144 lines
5.3 KiB
C
144 lines
5.3 KiB
C
#pragma once
|
|
|
|
#include "stdint.h"
|
|
#include "stdbool.h"
|
|
#include "stddef.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define SATA_SIG_ATA 0x00000101 // SATA drive
|
|
#define SATA_SIG_ATAPI 0xEB140101 // SATAPI drive
|
|
#define SATA_SIG_SEMB 0xC33C0101 // Enclosure management bridge
|
|
#define SATA_SIG_PM 0x96690101 // Port multiplier
|
|
|
|
#define AHCI_DEV_NULL 0
|
|
#define AHCI_DEV_SATA 1
|
|
#define AHCI_DEV_SEMB 2
|
|
#define AHCI_DEV_PM 3
|
|
#define AHCI_DEV_SATAPI 4
|
|
|
|
#define HBA_PORT_IPM_ACTIVE 1
|
|
#define HBA_PORT_DET_PRESENT 3
|
|
|
|
// Register FIS - Host to Device
|
|
#define FIS_TYPE_REG_H2D 0x27
|
|
#define ATA_CMD_READ_DMA_EXT 0x25
|
|
#define ATA_CMD_WRITE_DMA_EXT 0x35
|
|
|
|
typedef volatile struct tagHBA_PORT {
|
|
uint32_t clb; // 0x00, Command list base address, 1K-byte aligned
|
|
uint32_t clbu; // 0x04, Command list base address upper 32 bits
|
|
uint32_t fb; // 0x08, FIS base address, 256-byte aligned
|
|
uint32_t fbu; // 0x0C, FIS base address upper 32 bits
|
|
uint32_t is; // 0x10, Interrupt status
|
|
uint32_t ie; // 0x14, Interrupt enable
|
|
uint32_t cmd; // 0x18, Command and status
|
|
uint32_t rsv0; // 0x1C, Reserved
|
|
uint32_t tfd; // 0x20, Task file data
|
|
uint32_t sig; // 0x24, Signature
|
|
uint32_t ssts; // 0x28, SATA status (SCR0:SStatus)
|
|
uint32_t sctl; // 0x2C, SATA control (SCR2:SControl)
|
|
uint32_t serr; // 0x30, SATA error (SCR1:SError)
|
|
uint32_t sact; // 0x34, SATA active (SCR3:SActive)
|
|
uint32_t ci; // 0x38, Command issue
|
|
uint32_t sntf; // 0x3C, SATA notification (SCR4:SNotification)
|
|
uint32_t fbs; // 0x40, FIS-based switch control
|
|
uint32_t rsv1[11]; // 0x44 ~ 0x6F, Reserved
|
|
uint32_t vendor[4]; // 0x70 ~ 0x7F, vendor specific
|
|
} HBA_PORT;
|
|
|
|
typedef volatile struct tagHBA_MEM {
|
|
uint32_t cap; // 0x00 - 0x03, Host capability
|
|
uint32_t ghc; // 0x04 - 0x07, Global host control
|
|
uint32_t is; // 0x08 - 0x0B, Interrupt status
|
|
uint32_t pi; // 0x0C - 0x0F, Port implemented
|
|
uint32_t vs; // 0x10 - 0x13, Version
|
|
uint32_t ccc_ctl; // 0x14 - 0x17, Command completion coalescing control
|
|
uint32_t ccc_pts; // 0x18 - 0x1B, Command completion coalescing ports
|
|
uint32_t em_loc; // 0x1C - 0x1F, Enclosure management location
|
|
uint32_t em_ctl; // 0x20 - 0x23, Enclosure management control
|
|
uint32_t cap2; // 0x24 - 0x27, Host capabilities extended
|
|
uint32_t bohc; // 0x28 - 0x2B, BIOS/OS handoff control and status
|
|
uint8_t rsv[0xA0-0x2C];
|
|
uint8_t vendor[0x100-0xA0];
|
|
HBA_PORT ports[32]; // 0x100 ~ 0x10FF, Port control registers
|
|
} HBA_MEM;
|
|
|
|
typedef struct tagHBA_CMD_HEADER {
|
|
uint8_t cfl:5; // Command FIS length in DWORDS, 2 ~ 16
|
|
uint8_t a:1; // ATAPI
|
|
uint8_t w:1; // Write, 1: H2D, 0: D2H
|
|
uint8_t p:1; // Prefetchable
|
|
uint8_t r:1; // Reset
|
|
uint8_t b:1; // BIST
|
|
uint8_t c:1; // Clear busy upon R_OK
|
|
uint8_t rsv0:1; // Reserved
|
|
uint8_t pmp:4; // Port multiplier port
|
|
uint16_t prdtl; // Physical region descriptor table length in entries
|
|
volatile uint32_t prdbc; // Physical region descriptor byte count transferred
|
|
uint32_t ctba; // Command table descriptor base address
|
|
uint32_t ctbau; // Command table descriptor base address upper 32 bits
|
|
uint32_t rsv1[4]; // Reserved
|
|
} HBA_CMD_HEADER;
|
|
|
|
typedef struct tagHBA_PRDT_ENTRY {
|
|
uint32_t dba; // Data base address
|
|
uint32_t dbau; // Data base address upper 32 bits
|
|
uint32_t rsv0; // Reserved
|
|
uint32_t dbc:22; // Byte count, 4M max
|
|
uint32_t rsv1:9; // Reserved
|
|
uint32_t i:1; // Interrupt on completion
|
|
} HBA_PRDT_ENTRY;
|
|
|
|
typedef struct tagHBA_CMD_TABLE {
|
|
uint8_t cfis[64]; // Command FIS
|
|
uint8_t acmd[16]; // ATAPI command, 12 or 16 bytes
|
|
uint8_t rsv[48]; // Reserved
|
|
HBA_PRDT_ENTRY prdt_entry[1]; // Physical region descriptor table entries, 0 ~ 65535
|
|
} HBA_CMD_TABLE;
|
|
|
|
typedef struct tagFIS_REG_H2D {
|
|
uint8_t fis_type; // FIS_TYPE_REG_H2D
|
|
uint8_t pmport:4; // Port multiplier
|
|
uint8_t rsv0:3; // Reserved
|
|
uint8_t c:1; // 1: Command, 0: Control
|
|
uint8_t command; // Command register
|
|
uint8_t featurel; // Feature register, 7:0
|
|
uint8_t lba0; // LBA low register, 7:0
|
|
uint8_t lba1; // LBA mid register, 15:8
|
|
uint8_t lba2; // LBA high register, 23:16
|
|
uint8_t device; // Device register
|
|
uint8_t lba3; // LBA register, 31:24
|
|
uint8_t lba4; // LBA register, 39:32
|
|
uint8_t lba5; // LBA register, 47:40
|
|
uint8_t featureh; // Feature register, 15:8
|
|
uint8_t countl; // Count register, 7:0
|
|
uint8_t counth; // Count register, 15:8
|
|
uint8_t icc; // Isochronous command completion
|
|
uint8_t control; // Control register
|
|
uint8_t rsv1[4]; // Reserved
|
|
} FIS_REG_H2D;
|
|
|
|
typedef struct ahci_device {
|
|
uint8_t bus;
|
|
uint8_t slot;
|
|
uint8_t func;
|
|
uint64_t abar_phys;
|
|
HBA_MEM *hba_mem;
|
|
int active_port;
|
|
bool initialized;
|
|
uint64_t sector_count;
|
|
} ahci_device_t;
|
|
|
|
extern ahci_device_t g_ahci;
|
|
|
|
int ahci_detect_and_init(void);
|
|
int ahci_read_sectors(uint64_t lba, uint32_t count, void *buf);
|
|
int ahci_write_sectors(uint64_t lba, uint32_t count, const void *buf);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|