ATA/ATAPI using DMA: Difference between revisions

Added an order of sending DMA commands
[unchecked revision][unchecked revision]
(added comment about ISA DMA)
(Added an order of sending DMA commands)
 
(7 intermediate revisions by 6 users not shown)
Line 2:
 
It is very important to understand that there are several different types of DMA on a machine. The DMA that is used for ATA drives is called PCI Busmastering DMA. It is very fast. It is completely different from ISA DMA, which is limited to 4MB per second. Anything you may have read about 8bit or 16bit DMA channels 0 through 7, <b>does not apply to disk DMA at all.</b>
ATA singleword DMA, ATA multiword DMA, UDMA, and [[ADMA]] are all PCI Busmastering DMA types.
 
==UDMA==
 
From the point of view of the OS, there is only a tiny difference between "regular" (Single/Multiword) DMA and any of the UDMA modes.
Most of the actual differences involve precislyprecisely how, and how fast, data is transferred between the disk drive and the disk controller. OS software has no direct control over that part of the process. The driver software issues exactly the same commands, in exactly the same way, for all the DMA methods (except ADMA).
 
The only control the rest of the system has, lies in the initialization of the disk drive and disk controller to mutually compatible DMA modes, during bootup. This will hopefully always be done correctly by the BIOS.
Line 17:
===Verifying CRC errors===
 
Read the PCI Configuration Space worduint16_t at offset 6 (Device Status) to get the error code.
 
==The PRD Table==
 
You must set up at least one Physical Region Descriptor Table (PRDT) in memory per ATA bus, which contains some number of Physical Region Descriptors (PRDs).
(The PRDT must be dworduint32_t aligned, contiguous in physical memory, and cannot cross a 64K boundary.)
Then you need to store the physical address of the current PRDT in the Bus Master Register, of the Bus Mastering ATA Disk Controller on the PCI bus (see below).
 
===PRD setup===
 
Half of each DMA transfer is encoded in one qworduint64_t PRD entry (8 bytes) in the table.
(Why is it only half of a DMA transfer? Because the PRD does not contain any information about which LBAs to read from/write to the disk.
That information is sent in an entirely separate way to the proper disk -- see below.)
 
The low dworduint32_t is a [b]'''physical[/b]''' memory address of a data buffer. (Keep in mind on 64 bit systems that this address must fit in a dworduint32_t!)
The next worduint16_t is a [b]'''byte[/b]''' count (not a sector count!) of the transfer size (64K maximum per PRD transfer).
A byte count of 0 means 64K. The next worduint16_t is reserved (should be 0) except for the MSB. If the MSB is set, that indicates that this PRD is the last entry in the PRDT, and the entire set of transfers is complete.
The data buffers cannot cross a 64K boundary, and must be contiguous in physical memory (ie. they can't be "virtual" data buffers).
The byte count on the data buffers must match the number of sectors transferred by the disk. If not, the controller will error out in various ways.
Line 47:
0x0 Command (byte)
0x2 Status (byte)
0x4-0x7 PRDT Address (dworduint32_t)
(Secondary ATA bus)
0x8 Command (byte)
0xA Status (byte)
0xC-0xF PRDT Address (dworduint32_t)
</pre>
 
Line 61:
Also, the controller does not remember how far it got in the PRDT. That information is lost, if the OS does not save it. The bit must be cleared when a transfer completes.
 
Bit 3 (value = 8) is the Read/Write bit. This bit is a huge problem. The disk controller does not automatically detect whether the next disk operation is a read or write. You have to <i>tell</i> it, in advance, by setting this bit. Note that when reading from the disk, you must set this bit to 1, and clear it when writing to the disk. You must first stop DMA transfers (by clearing bit 0) before you can change the Read/Write bit! Please note all the bad consequences of clearing bit 0, above! The controller loses its place in the PRDT.
Bit 3 (value = 8) is the Read/Write bit.
This bit is a huge problem. The disk controller does not automatically detect whether the next disk operation is a read or write. You have to <i>tell</i> it, in advance, by setting this bit. You must first stop DMA transfers (by clearing bit 0) before you can change the Read/Write bit! Please note all the bad consequences of clearing bit 0, above! The controller loses its place in the PRDT.
 
In essence, this means that each PRDT must consist exclusively of either read or write entries. You set the Read/Write bit in advance, then "use up" the entire PRDT -- before you can do the opposite operation.
Line 85 ⟶ 84:
For ATA, for each PRD entry in the PRDT, the driver must issue a Read/Write DMA command to the disk; specifying a StartLBA and a sector count.
 
When the drive completes each command it sends an IRQ (possibly also when transfer in progress), to let the driver know that it is ready to transfer the next batch of data to/from the disk controller. The driver should then read the Bus Master Register Status byte.
 
The formats of the commands are precisely the same as for the 28 and 48 bit PIO mode Read and Write commands, except for the value sent to the "Command" IO Port.
Line 103 ⟶ 102:
For any error except a UDMA CRC error, it is recommended to do a Software Reset on the bus, in order to force all the devices to take the bus out of DMA mode.
 
==Standard Order of Sending Commands==
 
* Prepare a PRDT in system memory.
* Send the '''physical''' PRDT address to the Bus Master PRDT Register.
* Set the direction of the data transfer by setting the Read/Write bit in the Bus Master Command Register.
* Clear the Error and Interrupt bit in the Bus Master Status Register.
* Select the drive.
* Send the LBA and sector count to their respective ports.
* Send the DMA transfer command to the ATA controller.
* Set the Start/Stop bit on the Bus Master Command Register.
* When an interrupt arrives (after the transfer is complete), respond by resetting the Start/Stop bit.
* Read the controller and drive status to determine if the transfer completed successfully.
==Comments==
 
==See Also==
===Articles===
* [[ADMA]]
* [[DMA]]
===External Links===
* [http://bos.asmhackers.net/docs/ata/docs/29860001.pdf Intel manual with DMA / UDMA / PCI configuration space details]
Anonymous user