297 lines
9.2 KiB
C
297 lines
9.2 KiB
C
#ifndef __AHCI_H__
|
||
#define __AHCI_H__
|
||
|
||
typedef enum
|
||
{
|
||
FIS_TYPE_REG_H2D = 0x27, // Register FIS - host to device
|
||
FIS_TYPE_REG_D2H = 0x34, // Register FIS - device to host
|
||
FIS_TYPE_DMA_ACT = 0x39, // DMA activate FIS - device to host
|
||
FIS_TYPE_DMA_SETUP = 0x41, // DMA setup FIS - bidirectional
|
||
FIS_TYPE_DATA = 0x46, // Data FIS - bidirectional
|
||
FIS_TYPE_BIST = 0x58, // BIST activate FIS - bidirectional
|
||
FIS_TYPE_PIO_SETUP = 0x5F, // PIO setup FIS - device to host
|
||
FIS_TYPE_DEV_BITS = 0xA1, // Set device bits FIS - device to host
|
||
} FIS_TYPE;
|
||
|
||
typedef volatile struct tagHBA_PORT
|
||
{
|
||
unsigned long clb; // 0x00, command list base address, 1K-byte aligned
|
||
unsigned long clbu; // 0x04, command list base address upper 32 bits
|
||
unsigned long fb; // 0x08, FIS base address, 256-byte aligned
|
||
unsigned long fbu; // 0x0C, FIS base address upper 32 bits
|
||
unsigned long is; // 0x10, interrupt status
|
||
unsigned long ie; // 0x14, interrupt enable
|
||
unsigned long cmd; // 0x18, command and status
|
||
unsigned long rsv0; // 0x1C, Reserved
|
||
unsigned long tfd; // 0x20, task file data
|
||
unsigned long sig; // 0x24, signature
|
||
unsigned long ssts; // 0x28, SATA status (SCR0:SStatus)
|
||
unsigned long sctl; // 0x2C, SATA control (SCR2:SControl)
|
||
unsigned long serr; // 0x30, SATA error (SCR1:SError)
|
||
unsigned long sact; // 0x34, SATA active (SCR3:SActive)
|
||
unsigned long ci; // 0x38, command issue
|
||
unsigned long sntf; // 0x3C, SATA notification (SCR4:SNotification)
|
||
unsigned long fbs; // 0x40, FIS-based switch control
|
||
unsigned long rsv1[11]; // 0x44 ~ 0x6F, Reserved
|
||
unsigned long vendor[4]; // 0x70 ~ 0x7F, vendor specific
|
||
} HBA_PORT;
|
||
|
||
typedef struct tagFIS_REG_H2D
|
||
{
|
||
// DWORD 0
|
||
unsigned char fis_type; // FIS_TYPE_REG_H2D
|
||
|
||
unsigned char pmport:4; // Port multiplier
|
||
unsigned char rsv0:3; // Reserved
|
||
unsigned char c:1; // 1: Command, 0: Control
|
||
|
||
unsigned char command; // Command register
|
||
unsigned char featurel; // Feature register, 7:0
|
||
|
||
// DWORD 1
|
||
unsigned char lba0; // LBA low register, 7:0
|
||
unsigned char lba1; // LBA mid register, 15:8
|
||
unsigned char lba2; // LBA high register, 23:16
|
||
unsigned char device; // Device register
|
||
|
||
// DWORD 2
|
||
unsigned char lba3; // LBA register, 31:24
|
||
unsigned char lba4; // LBA register, 39:32
|
||
unsigned char lba5; // LBA register, 47:40
|
||
unsigned char featureh; // Feature register, 15:8
|
||
|
||
// DWORD 3
|
||
unsigned char countl; // Count register, 7:0
|
||
unsigned char counth; // Count register, 15:8
|
||
unsigned char icc; // Isochronous command completion
|
||
unsigned char control; // Control register
|
||
|
||
// DWORD 4
|
||
unsigned char rsv1[4]; // Reserved
|
||
} FIS_REG_H2D;
|
||
|
||
typedef struct tagFIS_REG_D2H
|
||
{
|
||
// DWORD 0
|
||
unsigned char fis_type; // FIS_TYPE_REG_D2H
|
||
|
||
unsigned char pmport:4; // Port multiplier
|
||
unsigned char rsv0:2; // Reserved
|
||
unsigned char i:1; // Interrupt bit
|
||
unsigned char rsv1:1; // Reserved
|
||
|
||
unsigned char status; // Status register
|
||
unsigned char error; // Error register
|
||
|
||
// DWORD 1
|
||
unsigned char lba0; // LBA low register, 7:0
|
||
unsigned char lba1; // LBA mid register, 15:8
|
||
unsigned char lba2; // LBA high register, 23:16
|
||
unsigned char device; // Device register
|
||
|
||
// DWORD 2
|
||
unsigned char lba3; // LBA register, 31:24
|
||
unsigned char lba4; // LBA register, 39:32
|
||
unsigned char lba5; // LBA register, 47:40
|
||
unsigned char rsv2; // Reserved
|
||
|
||
// DWORD 3
|
||
unsigned char countl; // Count register, 7:0
|
||
unsigned char counth; // Count register, 15:8
|
||
unsigned char rsv3[2]; // Reserved
|
||
|
||
// DWORD 4
|
||
unsigned char rsv4[4]; // Reserved
|
||
} FIS_REG_D2H;
|
||
|
||
typedef struct tagFIS_DATA
|
||
{
|
||
// DWORD 0
|
||
unsigned char fis_type; // FIS_TYPE_DATA
|
||
|
||
unsigned char pmport:4; // Port multiplier
|
||
unsigned char rsv0:4; // Reserved
|
||
|
||
unsigned char rsv1[2]; // Reserved
|
||
|
||
// DWORD 1 ~ N
|
||
unsigned long data[1]; // Payload
|
||
} FIS_DATA;
|
||
|
||
typedef struct tagFIS_PIO_SETUP
|
||
{
|
||
// DWORD 0
|
||
unsigned char fis_type; // FIS_TYPE_PIO_SETUP
|
||
|
||
unsigned char pmport:4; // Port multiplier
|
||
unsigned char rsv0:1; // Reserved
|
||
unsigned char d:1; // Data transfer direction, 1 - device to host
|
||
unsigned char i:1; // Interrupt bit
|
||
unsigned char rsv1:1;
|
||
|
||
unsigned char status; // Status register
|
||
unsigned char error; // Error register
|
||
|
||
// DWORD 1
|
||
unsigned char lba0; // LBA low register, 7:0
|
||
unsigned char lba1; // LBA mid register, 15:8
|
||
unsigned char lba2; // LBA high register, 23:16
|
||
unsigned char device; // Device register
|
||
|
||
// DWORD 2
|
||
unsigned char lba3; // LBA register, 31:24
|
||
unsigned char lba4; // LBA register, 39:32
|
||
unsigned char lba5; // LBA register, 47:40
|
||
unsigned char rsv2; // Reserved
|
||
|
||
// DWORD 3
|
||
unsigned char countl; // Count register, 7:0
|
||
unsigned char counth; // Count register, 15:8
|
||
unsigned char rsv3; // Reserved
|
||
unsigned char e_status; // New value of status register
|
||
|
||
// DWORD 4
|
||
unsigned short tc; // Transfer count
|
||
unsigned char rsv4[2]; // Reserved
|
||
} FIS_PIO_SETUP;
|
||
|
||
typedef struct tagFIS_DMA_SETUP
|
||
{
|
||
// DWORD 0
|
||
unsigned char fis_type; // FIS_TYPE_DMA_SETUP
|
||
|
||
unsigned char pmport:4; // Port multiplier
|
||
unsigned char rsv0:1; // Reserved
|
||
unsigned char d:1; // Data transfer direction, 1 - device to host
|
||
unsigned char i:1; // Interrupt bit
|
||
unsigned char a:1; // Auto-activate. Specifies if DMA Activate FIS is needed
|
||
unsigned char rsved[2]; // Reserved
|
||
unsigned long long DMAbufferID; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory. SATA Spec says host specific and not in Spec. Trying AHCI spec might work.
|
||
unsigned long rsvd; //More reserved
|
||
unsigned long DMAbufOffset; //Byte offset into buffer. First 2 bits must be 0
|
||
unsigned long TransferCount; //Number of bytes to transfer. Bit 0 must be 0
|
||
unsigned long resvd; //Reserved
|
||
} FIS_DMA_SETUP;
|
||
|
||
typedef volatile struct tagHBA_MEM
|
||
{
|
||
// 0x00 - 0x2B, Generic Host Control
|
||
unsigned long cap; // 0x00, Host capability
|
||
unsigned long ghc; // 0x04, Global host control
|
||
unsigned long is; // 0x08, Interrupt status
|
||
unsigned long pi; // 0x0C, Port implemented
|
||
unsigned long vs; // 0x10, Version
|
||
unsigned long ccc_ctl; // 0x14, Command completion coalescing control
|
||
unsigned long ccc_pts; // 0x18, Command completion coalescing ports
|
||
unsigned long em_loc; // 0x1C, Enclosure management location
|
||
unsigned long em_ctl; // 0x20, Enclosure management control
|
||
unsigned long cap2; // 0x24, Host capabilities extended
|
||
unsigned long bohc; // 0x28, BIOS/OS handoff control and status
|
||
|
||
// 0x2C - 0x9F, Reserved
|
||
unsigned char rsv[0xA0-0x2C];
|
||
|
||
// 0xA0 - 0xFF, Vendor specific registers
|
||
unsigned char vendor[0x100-0xA0];
|
||
|
||
// 0x100 - 0x10FF, Port control registers
|
||
HBA_PORT ports[1]; // 1 ~ 32
|
||
} HBA_MEM;
|
||
/*
|
||
typedef volatile struct tagHBA_FIS
|
||
{
|
||
// 0x00
|
||
FIS_DMA_SETUP dsfis; // DMA Setup FIS
|
||
unsigned char pad0[4];
|
||
|
||
// 0x20
|
||
FIS_PIO_SETUP psfis; // PIO Setup FIS
|
||
unsigned char pad1[12];
|
||
|
||
// 0x40
|
||
FIS_REG_D2H rfis; // Register – Device to Host FIS
|
||
unsigned char pad2[4];
|
||
|
||
// 0x58
|
||
FIS_DEV_BITS sdbfis; // Set Device Bit FIS
|
||
|
||
// 0x60
|
||
unsigned char ufis[64];
|
||
|
||
// 0xA0
|
||
unsigned char rsv[0x100-0xA0];
|
||
} HBA_FIS;
|
||
*/
|
||
typedef struct tagHBA_CMD_HEADER
|
||
{
|
||
// DW0
|
||
unsigned char cfl:5; // Command FIS length in DWORDS, 2 ~ 16
|
||
unsigned char a:1; // ATAPI
|
||
unsigned char w:1; // Write, 1: H2D, 0: D2H
|
||
unsigned char p:1; // Prefetchable
|
||
|
||
unsigned char r:1; // Reset
|
||
unsigned char b:1; // BIST
|
||
unsigned char c:1; // Clear busy upon R_OK
|
||
unsigned char rsv0:1; // Reserved
|
||
unsigned char pmp:4; // Port multiplier port
|
||
|
||
unsigned short prdtl; // Physical region descriptor table length in entries
|
||
|
||
// DW1
|
||
volatile
|
||
unsigned long prdbc; // Physical region descriptor byte count transferred
|
||
|
||
// DW2, 3
|
||
unsigned long ctba; // Command table descriptor base address
|
||
unsigned long ctbau; // Command table descriptor base address upper 32 bits
|
||
|
||
// DW4 - 7
|
||
unsigned long rsv1[4]; // Reserved
|
||
} HBA_CMD_HEADER;
|
||
|
||
typedef struct tagHBA_PRDT_ENTRY
|
||
{
|
||
unsigned long dba; // Data base address
|
||
unsigned long dbau; // Data base address upper 32 bits
|
||
unsigned long rsv0; // Reserved
|
||
|
||
// DW3
|
||
unsigned long dbc:22; // Byte count, 4M max
|
||
unsigned long rsv1:9; // Reserved
|
||
unsigned long i:1; // Interrupt on completion
|
||
} HBA_PRDT_ENTRY;
|
||
|
||
typedef struct tagHBA_CMD_TBL
|
||
{
|
||
// 0x00
|
||
unsigned char cfis[64]; // Command FIS
|
||
|
||
// 0x40
|
||
unsigned char acmd[16]; // ATAPI command, 12 or 16 bytes
|
||
|
||
// 0x50
|
||
unsigned char rsv[48]; // Reserved
|
||
|
||
// 0x80
|
||
HBA_PRDT_ENTRY prdt_entry[1]; // Physical region descriptor table entries, 0 ~ 65535
|
||
} HBA_CMD_TBL;
|
||
|
||
struct ahci_slot_t {
|
||
unsigned long base;
|
||
unsigned long base_phys;
|
||
unsigned long prdt_base;
|
||
unsigned long prdt_base_phys;
|
||
int port;
|
||
};
|
||
|
||
struct ahci_device_t {
|
||
struct pci_device *pci_dev;
|
||
HBA_MEM *abar;
|
||
struct ahci_slot_t **devices;
|
||
int count;
|
||
};
|
||
extern void init_ahci();
|
||
extern int ahci_read_sectors(struct ahci_device_t *dev, int pt, unsigned long startl, unsigned long starth, unsigned long count, unsigned char *buf);
|
||
extern int ahci_write_sectors(struct ahci_device_t *dev, int pt, unsigned long startl, unsigned long starth, unsigned long count, unsigned char *buf);
|
||
#endif |