I'm trying to initialize an NVMe SSD on a 32-bit PowerPC board just enough to issue the identity command. I don't have an operating system.
These are the steps I've taken:
- Disable dcache
- Find the SDD
- Get bar0, strip off the last nybble, and use that as the control area address (a volatile struct)
- Allocate some memory for the admin completion and submission queues: 16*64 bytes for submission, 256 bytes for completion. That's 16 entries for both
- Set AQA in the control area to
ENDIAN_FLIP((16<<16)|16)
because I have 16 entries for each
- Zero out the queues with memset
- Set ASQ and ACQ to their respective addresses (Endian flipped)
- Ensure EN in CSTS is not enabled by comparing it bitwise with
0x01000000
- Enable controller by setting CC to
0x01000000
- Wait for CSTS to notify it's enabled. This works so far
- Ensure CSTS doesn't contain fatal error flag. Works
- Allocate a 4096kb memory block for identify controller response
- Form submission entry from struct:
.cdw0 = ENDIAN_FLIP(0x00000006)//identify command
.prp1 = ENDIAN_FLIP(block_address_32bit)//loading 32-bit address into 64-bit space
.cdw10 = ENDIAN_FLIP(0x00000001)//identify controller
- Copy struct to submission queue[0]
- Increment tail doorbell register locally (from 0 to 1)
- set tail doorbell register in NVMe control area to
ENDIAN_FLIP(local_tail_doorbell_counter)
- Check that CSTS doesn't have fatal flag. FAILS HERE: CSTS returns
0x03000000
, which means NVMe controller is enabled and a fatal error has occurred
Is there any idea on what's gone wrong, or what I could do to find better error information?
I've been reading the spec, and it seems like I'm doing everything right :/