AHCI: Difference between revisions

252 bytes added ,  29 days ago
m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Add links for PCI and IDE.)
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(One intermediate revision by the same user not shown)
Line 24:
Following code defines different kinds of FIS specified in Serial ATA Revision 3.0.
 
<sourcesyntaxhighlight lang="c">
typedef enum
{
Line 36:
FIS_TYPE_DEV_BITS = 0xA1, // Set device bits FIS - device to host
} FIS_TYPE;
</syntaxhighlight>
</source>
 
'''2) Register FIS – Host to Device'''
Line 42:
A host to device register FIS is used by the host to send command or control to a device. As illustrated in the following data structure, it contains the IDE registers such as command, LBA, device, feature, count and control. An ATA command is constructed in this structure and issued to the device. All reserved fields in an FIS should be cleared to zero.
 
<sourcesyntaxhighlight lang="c">
typedef struct tagFIS_REG_H2D
{
Line 76:
uint8_t rsv1[4]; // Reserved
} FIS_REG_H2D;
</syntaxhighlight>
</source>
 
'''3) Register FIS – Device to Host'''
Line 82:
A device to host register FIS is used by the device to notify the host that some ATA register has changed. It contains the updated task files such as status, error and other registers.
 
<sourcesyntaxhighlight lang="c">
typedef struct tagFIS_REG_D2H
{
Line 116:
uint8_t rsv4[4]; // Reserved
} FIS_REG_D2H;
</syntaxhighlight>
</source>
 
'''4) Data FIS – Bidirectional'''
Line 122:
This FIS is used by the host or device to send data payload. The data size can be varied.
 
<sourcesyntaxhighlight lang="c">
typedef struct tagFIS_DATA
{
Line 136:
uint32_t data[1]; // Payload
} FIS_DATA;
</syntaxhighlight>
</source>
 
'''5) PIO Setup – Device to Host'''
Line 142:
This FIS is used by the device to tell the host that it’s about to send or ready to receive a PIO data payload.
 
<sourcesyntaxhighlight lang="c">
typedef struct tagFIS_PIO_SETUP
{
Line 179:
uint8_t rsv4[2]; // Reserved
} FIS_PIO_SETUP;
</syntaxhighlight>
</source>
 
'''6) DMA Setup – Device to Host'''
 
<sourcesyntaxhighlight lang="c">
typedef struct tagFIS_DMA_SETUP
{
Line 215:
} FIS_DMA_SETUP;
</syntaxhighlight>
</source>
 
'''7) Example'''
Line 223:
To issue an ATA Identify command to the device, the FIS is constructed at follows.
 
<sourcesyntaxhighlight lang="c">
FIS_REG_H2D fis;
memset(&fis, 0, sizeof(FIS_REG_H2D));
Line 230:
fis.device = 0; // Master device
fis.c = 1; // Write command register
</syntaxhighlight>
</source>
 
After the device receives this FIS and successfully read the 256 words data into its internal buffer, it sends a PIO Setup FIS – Device to Host to tell the host that it’s ready to transfer data and the data size (FIS_PIO_SETUP.tc).
Line 258:
[[Image:HBA_registers.jpg‎]]
 
<sourcesyntaxhighlight lang="c">
typedef volatile struct tagHBA_MEM
{
Line 306:
uint32_t vendor[4]; // 0x70 ~ 0x7F, vendor specific
} HBA_PORT;
</syntaxhighlight>
</source>
 
This memory area should be configured as uncacheable as they are memory mapped hardware registers, not normal prefetchable RAM. For the same reason, the data structures are declared as "volatile" to prevent the compiler from over optimizing the code.
Line 322:
Data FIS – Device to Host is not copied to this structure. Data payload is sent and received through PRDT (Physical Region Descriptor Table) in Command List, as will be introduced later.
 
<sourcesyntaxhighlight lang="c">
typedef volatile struct tagHBA_FIS
{
Line 346:
uint8_t rsv[0x100-0xA0];
} HBA_FIS;
</syntaxhighlight>
</source>
 
'''4) Command List'''
Line 358:
[[Image:Command_list.jpg‎]]
 
<sourcesyntaxhighlight lang="c">
typedef struct tagHBA_CMD_HEADER
{
Line 386:
uint32_t rsv1[4]; // Reserved
} HBA_CMD_HEADER;
</syntaxhighlight>
</source>
 
'''5) Command Table and Physical Region Descriptor Table'''
Line 398:
[[Image:Command_table.jpg‎]]
 
<sourcesyntaxhighlight lang="c">
typedef struct tagHBA_CMD_TBL
{
Line 425:
uint32_t i:1; // Interrupt on completion
} HBA_PRDT_ENTRY;
</syntaxhighlight>
</source>
 
== Detect attached SATA devices ==
Line 439:
There are four kinds of SATA devices, and their signatures are defined as below. The Port Signature register (HBA_PORT.sig) contains the device signature, just read this register to find which kind of device is attached at the port. Some buggy AHCI controllers may not set the Signature register correctly. The most reliable way is to judge from the Identify data read back from the device.
 
<sourcesyntaxhighlight lang="c">
#define SATA_SIG_ATA 0x00000101 // SATA drive
#define SATA_SIG_ATAPI 0xEB140101 // SATAPI drive
Line 516:
}
}
</syntaxhighlight>
</source>
 
== AHCI port memory space initialization ==
Line 526:
The following example assumes that the HBA has 32 ports implemented and each port contains 32 command slots, and will allocate 8 PRDTs for each command slot. (Note: unlike in the above struct definitions, this is using 8 instead of 1)
 
<sourcesyntaxhighlight lang="c">
#define AHCI_BASE 0x400000 // 4M
 
Line 600:
 
}
</syntaxhighlight>
</source>
 
== AHCI & ATAPI ==
Line 610:
The code example shows how to read "count" sectors from sector offset "starth:startl" to "buf" with LBA48 mode from HBA "port". Every PRDT entry contains 8K bytes data payload at most.
 
<sourcesyntaxhighlight lang="c">
#define ATA_DEV_BUSY 0x80
#define ATA_DEV_DRQ 0x08
Line 716:
return -1;
}
</syntaxhighlight>
</source>
 
== Checklist ==