Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by yucarp »

So I have been trying to read data from a virtual SATA drive through sending commands but although I receive D2H FIS, the buffer is empty. The specification specifies that if the data transfer is done there is a D2H FIS. I receive PIO setup FIS and D2H FIS when sending IDENTIFY_DEVICE and it works fine as far as I can tell. Here is what I try to do:

Construct the command header
Construct the physical region descriptor table
Set the related command issue bit
And read the data.

I know that waiting is important on real devices but since I am on QEMU and I don't want to clutter the log I didn't wait by polling some specific bits. Here is the QEMU log:

EDIT: I forgot the put the code, how silly of me #-o https://github.com/yucarp/cutesugaros/b ... les/ahci.c

Code: Select all

ahci_start_dma ahci(0x55f33ed0b5b0)[2]: start dma
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000000
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000000
ahci_populate_sglist ahci(0x55f33ed0b5b0)[2]
ahci_dma_rw_buf ahci(0x55f33ed0b5b0)[2] len=0x8000
ahci_cmd_done ahci(0x55f33ed0b5b0)[2]: cmd done
ahci_trigger_irq ahci(0x55f33ed0b5b0)[2]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000000
ahci_check_irq ahci(0x55f33ed0b5b0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f33ed0b5b0): lower irq
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000001
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000001
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000001
ahci_mem_write ahci(0x55f33ed0b5b0): write4 @ 0x210: 0x0000000000000001
ahci_port_write ahci(0x55f33ed0b5b0)[2]: port write [reg:PxIS] @ 0x10: 0x00000001
ahci_check_irq ahci(0x55f33ed0b5b0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f33ed0b5b0): lower irq
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000000
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000000
ahci_mem_write ahci(0x55f33ed0b5b0): write4 @ 0x238: 0x0000000000000001
ahci_port_write ahci(0x55f33ed0b5b0)[2]: port write [reg:PxCI] @ 0x38: 0x00000001
ahci_start_dma ahci(0x55f33ed0b5b0)[2]: start dma
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000000
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000000
ahci_populate_sglist ahci(0x55f33ed0b5b0)[2]
ahci_dma_rw_buf ahci(0x55f33ed0b5b0)[2] len=0x8000
ahci_cmd_done ahci(0x55f33ed0b5b0)[2]: cmd done
ahci_trigger_irq ahci(0x55f33ed0b5b0)[2]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000000
ahci_check_irq ahci(0x55f33ed0b5b0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f33ed0b5b0): lower irq
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000001
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000001
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000001
ahci_mem_write ahci(0x55f33ed0b5b0): write4 @ 0x210: 0x0000000000000001
ahci_port_write ahci(0x55f33ed0b5b0)[2]: port write [reg:PxIS] @ 0x10: 0x00000001
ahci_check_irq ahci(0x55f33ed0b5b0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f33ed0b5b0): lower irq
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000000
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000000
ahci_mem_write ahci(0x55f33ed0b5b0): write4 @ 0x238: 0x0000000000000001
ahci_port_write ahci(0x55f33ed0b5b0)[2]: port write [reg:PxCI] @ 0x38: 0x00000001
ahci_start_dma ahci(0x55f33ed0b5b0)[2]: start dma
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000000
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000000
ahci_populate_sglist ahci(0x55f33ed0b5b0)[2]
ahci_dma_rw_buf ahci(0x55f33ed0b5b0)[2] len=0x8000
ahci_cmd_done ahci(0x55f33ed0b5b0)[2]: cmd done
ahci_trigger_irq ahci(0x55f33ed0b5b0)[2]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000000
ahci_check_irq ahci(0x55f33ed0b5b0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f33ed0b5b0): lower irq
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000001
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000001
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000001
ahci_mem_write ahci(0x55f33ed0b5b0): write4 @ 0x210: 0x0000000000000001
ahci_port_write ahci(0x55f33ed0b5b0)[2]: port write [reg:PxIS] @ 0x10: 0x00000001
ahci_check_irq ahci(0x55f33ed0b5b0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f33ed0b5b0): lower irq
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000000
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000000
ahci_mem_write ahci(0x55f33ed0b5b0): write4 @ 0x238: 0x0000000000000001
ahci_port_write ahci(0x55f33ed0b5b0)[2]: port write [reg:PxCI] @ 0x38: 0x00000001
ahci_start_dma ahci(0x55f33ed0b5b0)[2]: start dma
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000000
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000000
ahci_populate_sglist ahci(0x55f33ed0b5b0)[2]
ahci_dma_rw_buf ahci(0x55f33ed0b5b0)[2] len=0x8000
ahci_cmd_done ahci(0x55f33ed0b5b0)[2]: cmd done
ahci_trigger_irq ahci(0x55f33ed0b5b0)[2]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000000
ahci_check_irq ahci(0x55f33ed0b5b0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f33ed0b5b0): lower irq
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000001
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000001
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000001
ahci_mem_write ahci(0x55f33ed0b5b0): write4 @ 0x210: 0x0000000000000001
ahci_port_write ahci(0x55f33ed0b5b0)[2]: port write [reg:PxIS] @ 0x10: 0x00000001
ahci_check_irq ahci(0x55f33ed0b5b0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f33ed0b5b0): lower irq
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000000
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000000
ahci_mem_write ahci(0x55f33ed0b5b0): write4 @ 0x238: 0x0000000000000001
ahci_port_write ahci(0x55f33ed0b5b0)[2]: port write [reg:PxCI] @ 0x38: 0x00000001
ahci_start_dma ahci(0x55f33ed0b5b0)[2]: start dma
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000000
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000000
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000000
ahci_populate_sglist ahci(0x55f33ed0b5b0)[2]
ahci_dma_rw_buf ahci(0x55f33ed0b5b0)[2] len=0x8000
ahci_cmd_done ahci(0x55f33ed0b5b0)[2]: cmd done
ahci_trigger_irq ahci(0x55f33ed0b5b0)[2]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000000
ahci_check_irq ahci(0x55f33ed0b5b0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f33ed0b5b0): lower irq
ahci_port_read ahci(0x55f33ed0b5b0)[2]: port read [reg:PxIS] @ 0x10: 0x00000001
ahci_mem_read_32 ahci(0x55f33ed0b5b0): mem read @ 0x210: 0x00000001
ahci_mem_read ahci(0x55f33ed0b5b0): read4 @ 0x210: 0x0000000000000001
ahci_mem_write ahci(0x55f33ed0b5b0): write4 @ 0x210: 0x0000000000000001
ahci_port_write ahci(0x55f33ed0b5b0)[2]: port write [reg:PxIS] @ 0x10: 0x00000001
ahci_check_irq ahci(0x55f33ed0b5b0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55f33ed0b5b0): lower irq
Octocontrabass
Member
Member
Posts: 6249
Joined: Mon Mar 25, 2013 7:01 pm

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by Octocontrabass »

yucarp wrote: Thu Apr 30, 2026 2:35 pmalthough I receive D2H FIS, the buffer is empty.
Does the D2H register FIS say that the command was successful?
yucarp wrote: Thu Apr 30, 2026 2:35 pmI receive PIO setup FIS and D2H FIS when sending IDENTIFY_DEVICE and it works fine as far as I can tell.
Does IDENTIFY DEVICE say that your drive supports READ DMA EXT?
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by yucarp »

Octocontrabass wrote: Thu Apr 30, 2026 7:41 pm Does the D2H register FIS say that the command was successful?
Does IDENTIFY DEVICE say that your drive supports READ DMA EXT?
!. The status and error register is the same with the identify command. (status: 0x50, error : 0x0) so it's probably successful
2. I tried issuing a READ_SECTOR command but I got the same result. Also the double bytes 60 and 61 is empty, so the device probably doesn't support LBA (I don't know how)
Octocontrabass
Member
Member
Posts: 6249
Joined: Mon Mar 25, 2013 7:01 pm

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by Octocontrabass »

yucarp wrote: Fri May 01, 2026 4:03 amAlso the double bytes 60 and 61 is empty, so the device probably doesn't support LBA (I don't know how)
LBA support is reported in word 49, but QEMU's virtual SATA drive should support LBA. Are you sure you're reading the correct part of the IDENTIFY DEVICE data? Are you sure you're receiving the IDENTIFY DEVICE data correctly?
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by yucarp »

Octocontrabass wrote: Fri May 01, 2026 10:12 am LBA support is reported in word 49, but QEMU's virtual SATA drive should support LBA. Are you sure you're reading the correct part of the IDENTIFY DEVICE data? Are you sure you're receiving the IDENTIFY DEVICE data correctly?
After checking the ATA manual, some values are seeming to be missing. It only has maximum LBA value and some reserved values. EDIT: Actually a lot of values are missing, I just read the wrong command output table...

Code: Select all

Num 3: 5800
 Num 4: 200
Num 12: 4034
Num 13: 50
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by yucarp »

KernelAllocateFrame returns physical addresses so yes, I am writing physical addresses and mapping them. I also tried to put the physical address of the buffer on the physical region descriptor table but the problem isn't solved.
Octocontrabass
Member
Member
Posts: 6249
Joined: Mon Mar 25, 2013 7:01 pm

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by Octocontrabass »

yucarp wrote: Fri May 01, 2026 1:12 pmKernelAllocateFrame returns physical addresses so yes, I am writing physical addresses and mapping them.
This line of code is writing a virtual address.
yucarp wrote: Fri May 01, 2026 1:12 pmI also tried to put the physical address of the buffer on the physical region descriptor table but the problem isn't solved.
There may be other places where you're mixing up physical and virtual addresses.
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by yucarp »

I checked a lot yet there isn't any places that I accidentally write a virtual address. You can see the new code here: https://github.com/yucarp/cutesugaros/b ... hci/ahci.c In fact, when I updated it to have a new address, the buffer had nothing. The error code is zero, so there isn't any error
Octocontrabass
Member
Member
Posts: 6249
Joined: Mon Mar 25, 2013 7:01 pm

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by Octocontrabass »

I see several places where you read physical addresses, but you've identity-mapped those so it should work for now (until you realize identity-mapping MMIO is a terrible idea).

Are you sure you haven't truncated any 64-bit addresses to 32 bits anywhere?

Your buffer is not volatile, so there may be a compiler optimization that assumes nothing ever writes to the buffer.
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by yucarp »

After mapping the addresses to higher half and marking the buffer as volatile the IDENTIFY_DEVICE started working. It even states that DMA and LBA is supported.

Code: Select all

Num 49: B00
However, when I try to issue a read command, no matter it's READ_SECTORS or READ_DMA_EXTENDED, I still get nothing.
Octocontrabass
Member
Member
Posts: 6249
Joined: Mon Mar 25, 2013 7:01 pm

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by Octocontrabass »

Given that IDENTIFY DEVICE and READ SECTORS should both work in exactly the same way, your should be able to use exactly the same code for both commands, and any problems are most likely caused by a difference between the code you use for each command.
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by yucarp »

Thanks I am finally able to use my AHCI controller. I didn't know that AHCI had so many nuances...
yucarp
Member
Member
Posts: 39
Joined: Fri Dec 05, 2025 5:19 pm
Libera.chat IRC: yucarp

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by yucarp »

Now the buffer is empty if lba1 is non-zero.

QEMU log:

Code: Select all

ahci_cmd_done ahci(0x55e473d93fa0)[0]: cmd done
ahci_trigger_irq ahci(0x55e473d93fa0)[0]: trigger irq +DHRS (0x00000001); irqstat: 0x00000000 --> 0x00000001; effective: 0x00000000
ahci_check_irq ahci(0x55e473d93fa0): check irq 0x00000000 --> 0x00000000
ahci_irq_lower ahci(0x55e473d93fa0): lower irq
ahci_port_read ahci(0x55e473d93fa0)[0]: port read [reg:PxTFD] @ 0x20: 0x00000050
ahci_mem_read_32 ahci(0x55e473d93fa0): mem read @ 0x120: 0x00000050
ahci_mem_read ahci(0x55e473d93fa0): read4 @ 0x120: 0x0000000000000050
ahci_port_read ahci(0x55e473d93fa0)[0]: port read [reg:PxCI] @ 0x38: 0x00000000
ahci_mem_read_32 ahci(0x55e473d93fa0): mem read @ 0x138: 0x00000000
ahci_mem_read ahci(0x55e473d93fa0): read4 @ 0x138: 0x0000000000000000
ahci_port_read ahci(0x55e473d93fa0)[0]: port read [reg:PxTFD] @ 0x20: 0x00000050
ahci_mem_read_32 ahci(0x55e473d93fa0): mem read @ 0x120: 0x00000050
ahci_mem_read ahci(0x55e473d93fa0): read4 @ 0x120: 0x0000000000000050
Octocontrabass
Member
Member
Posts: 6249
Joined: Mon Mar 25, 2013 7:01 pm

Re: Issuing READ_DMA_EXT doesn't work even though IDENTIFY_DEVICE works on SATA drive

Post by Octocontrabass »

yucarp wrote: Sat May 02, 2026 4:57 amNow the buffer is empty if lba1 is non-zero.
Are you sure the sector isn't empty?
Post Reply