#ifndef _AHCI_DEFS_H
#define _AHCI_DEFS_H
#include <ata_types.h>
#include <bus/PCI.h>
#include <bus/SCSI.h>
#ifdef __cplusplus
extern "C" {
#endif
#define AHCI_DEVICE_MODULE_NAME "busses/scsi/ahci/driver_v1"
#define AHCI_SIM_MODULE_NAME "busses/scsi/ahci/sim/driver_v1"
enum {
CAP_S64A = (1U << 31),
CAP_SNCQ = (1 << 30),
CAP_SSNTF = (1 << 29),
CAP_SMPS = (1 << 28),
CAP_SSS = (1 << 27),
CAP_SALP = (1 << 26),
CAP_SAL = (1 << 25),
CAP_SCLO = (1 << 24),
CAP_ISS_MASK = 0xf,
CAP_ISS_SHIFT = 20,
CAP_SNZO = (1 << 19),
CAP_SAM = (1 << 18),
CAP_SPM = (1 << 17),
CAP_FBSS = (1 << 16),
CAP_PMD = (1 << 15),
CAP_SSC = (1 << 14),
CAP_PSC = (1 << 13),
CAP_NCS_MASK = 0x1f,
CAP_NCS_SHIFT = 8,
CAP_CCCS = (1 << 7),
CAP_EMS = (1 << 6),
CAP_SXS = (1 << 5),
CAP_NP_MASK = 0x1f,
CAP_NP_SHIFT = 0,
};
enum {
GHC_AE = (1U << 31),
GHC_MRSM = (1 << 2),
GHC_IE = (1 << 1),
GHC_HR = (1 << 0),
};
enum {
INT_CPD = (1 << 31),
INT_TFE = (1 << 30),
INT_HBF = (1 << 29),
INT_HBD = (1 << 28),
INT_IF = (1 << 27),
INT_INF = (1 << 26),
INT_OF = (1 << 24),
INT_IPM = (1 << 23),
INT_PRC = (1 << 22),
INT_DMP = (1 << 7),
INT_PC = (1 << 6),
INT_DP = (1 << 5),
INT_UF = (1 << 4),
INT_SDB = (1 << 3),
INT_DS = (1 << 2),
INT_PS = (1 << 1),
INT_DHR = (1 << 0),
};
#define HBA_PORT_IPM_MASK 0x00000f00
#define SSTS_PORT_IPM_ACTIVE 0x00000100
#define SSTS_PORT_IPM_PARTIAL 0x00000200
#define SSTS_PORT_IPM_SLUMBER 0x00000600
#define SSTS_PORT_IPM_DEVSLEEP 0x00000800
#define SCTL_PORT_IPM_NORES 0x00000000
#define SCTL_PORT_IPM_NOPART 0x00000100
#define SCTL_PORT_IPM_NOSLUM 0x00000200
#define HBA_PORT_SPD_MASK 0x000000f0
#define HBA_PORT_DET_MASK 0x0000000f
#define SSTS_PORT_DET_NODEV 0x00000000
#define SSTS_PORT_DET_NOPHY 0x00000001
#define SSTS_PORT_DET_PRESENT 0x00000003
#define SSTS_PORT_DET_OFFLINE 0x00000004
#define SCTL_PORT_DET_NOINIT 0x00000000
#define SCTL_PORT_DET_INIT 0x00000001
#define SCTL_PORT_DET_DISABLE 0x00000004
#define SATA_SIG_ATA 0x00000101
#define SATA_SIG_ATAPI 0xEB140101
#define SATA_SIG_SEMB 0xC33C0101
#define SATA_SIG_PM 0x96690101
typedef struct {
uint32 clb;
uint32 clbu;
uint32 fb;
uint32 fbu;
uint32 is;
uint32 ie;
uint32 cmd;
uint32 res1;
uint32 tfd;
uint32 sig;
uint32 ssts;
uint32 sctl;
uint32 serr;
uint32 sact;
uint32 ci;
uint32 sntf;
uint32 fbs;
uint32 devslp;
uint32 res[10];
uint32 vendor[4];
} ahci_port;
enum {
PORT_CMD_ICC_ACTIVE = (1 << 28),
PORT_CMD_ICC_SLUMBER = (6 << 28),
PORT_CMD_ICC_MASK = (0xf<<28),
PORT_CMD_ATAPI = (1 << 24),
PORT_CMD_CR = (1 << 15),
PORT_CMD_FR = (1 << 14),
PORT_CMD_FRE = (1 << 4),
PORT_CMD_CLO = (1 << 3),
PORT_CMD_POD = (1 << 2),
PORT_CMD_SUD = (1 << 1),
PORT_CMD_ST = (1 << 0),
};
enum {
PORT_INT_CPD = (1 << 31),
PORT_INT_TFE = (1 << 30),
PORT_INT_HBF = (1 << 29),
PORT_INT_HBD = (1 << 28),
PORT_INT_IF = (1 << 27),
PORT_INT_INF = (1 << 26),
PORT_INT_OF = (1 << 24),
PORT_INT_IPM = (1 << 23),
PORT_INT_PRC = (1 << 22),
PORT_INT_DI = (1 << 7),
PORT_INT_PC = (1 << 6),
PORT_INT_DP = (1 << 5),
PORT_INT_UF = (1 << 4),
PORT_INT_SDB = (1 << 3),
PORT_INT_DS = (1 << 2),
PORT_INT_PS = (1 << 1),
PORT_INT_DHR = (1 << 0),
};
#define PORT_INT_ERROR (PORT_INT_TFE | PORT_INT_HBF | PORT_INT_HBD \
| PORT_INT_IF | PORT_INT_INF | PORT_INT_OF \
| PORT_INT_IPM | PORT_INT_PRC | PORT_INT_PC \
| PORT_INT_UF)
#define PORT_INT_MASK (PORT_INT_ERROR | PORT_INT_DP | PORT_INT_SDB \
| PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR)
enum {
PORT_FBS_DWE_SHIFT = 16,
PORT_FBS_DWE_MASK = 0xf,
PORT_FBS_ADO_SHIFT = 12,
PORT_FBS_ADO_MASK = 0xf,
PORT_FBS_DEV_SHIFT = 8,
PORT_FBS_DEV_MASK = 0xf,
PORT_FBS_SDE = 0x04,
PORT_FBS_DEC = 0x02,
PORT_FBS_EN = 0x01,
};
enum {
PORT_DEVSLP_DM_SHIFT = 25,
PORT_DEVSLP_DM_MASK = 0xf,
PORT_DEVSLP_DITO_SHIFT = 15,
PORT_DEVSLP_DITO_MASK = 0x3ff,
PORT_DEVSLP_MDAT_SHIFT = 10,
PORT_DEVSLP_MDAT_MASK = 0x1f,
PORT_DEVSLP_DETO_SHIFT = 2,
PORT_DEVSLP_DETO_MASK = 0xff,
PORT_DEVSLP_DSP = 0x02,
PORT_DEVSLP_ADSE = 0x01,
};
enum {
CAP2_DESO = (1 << 5),
CAP2_SADM = (1 << 4),
CAP2_SDS = (1 << 3),
CAP2_APST = (1 << 2),
CAP2_NVMP = (1 << 1),
CAP2_BOH = (1 << 0),
};
typedef struct {
uint32 cap;
uint32 ghc;
uint32 is;
uint32 pi;
uint32 vs;
uint32 ccc_ctl;
uint32 ccc_ports;
uint32 em_loc;
uint32 em_ctl;
uint32 cap2;
uint32 bohc;
uint32 res[29];
uint32 vendor[24];
ahci_port port[32];
} _PACKED ahci_hba;
typedef struct {
uint8 dsfis[0x1c];
uint8 res1[0x04];
uint8 psfis[0x14];
uint8 res2[0x0c];
uint8 rfis[0x14];
uint8 res3[0x04];
uint8 sdbfis[0x08];
uint8 ufis[0x40];
uint8 res4[0x60];
} _PACKED fis;
typedef struct {
union {
struct {
uint16 cfl : 5;
uint16 a : 1;
uint16 w : 1;
uint16 p : 1;
uint16 r : 1;
uint16 b : 1;
uint16 c : 1;
uint16 : 1;
uint16 pmp : 4;
uint16 prdtl;
} _PACKED;
uint32 prdtl_flags_cfl;
} _PACKED;
uint32 prdbc;
uint32 ctba;
uint32 ctbau;
uint8 res1[0x10];
} _PACKED command_list_entry;
#define COMMAND_LIST_ENTRY_COUNT 32
typedef struct {
uint8 cfis[0x40];
uint8 acmd[0x20];
uint8 res[0x20];
} _PACKED command_table;
typedef struct {
uint32 dba;
uint32 dbau;
uint32 res;
uint32 dbc;
#define DBC_I 0x80000000
} _PACKED prd;
#define PRD_TABLE_ENTRY_COUNT 168
#define PRD_MAX_DATA_LENGTH 0x400000
typedef struct {
uint16 vendor;
uint16 device;
const char *name;
uint32 flags;
} device_info;
status_t get_device_info(uint16 vendorID, uint16 deviceID, const char **name,
uint32 *flags);
extern scsi_sim_interface gAHCISimInterface;
extern device_manager_info *gDeviceManager;
extern scsi_for_sim_interface *gSCSI;
#define MAX_SECTOR_LBA_28 ((1ull << 28) - 1)
#define MAX_SECTOR_LBA_48 ((1ull << 48) - 1)
#define LO32(val) ((uint32)(val))
#define HI32(val) ((uint32)(((uint64)(val)) >> 32))
#define PCI_VENDOR_INTEL 0x8086
#define PCI_VENDOR_JMICRON 0x197b
#define PCI_JMICRON_CONTROLLER_CONTROL_1 0x40
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
inline
status_t
wait_until_set(volatile uint32 *reg, uint32 bits, bigtime_t timeout)
{
int trys = (timeout + 9999) / 10000;
while (trys--) {
if (((*reg) & bits) == bits)
return B_OK;
snooze(10000);
}
return B_TIMED_OUT;
}
inline
status_t
wait_until_clear(volatile uint32 *reg, uint32 bits, bigtime_t timeout)
{
int trys = (timeout + 9999) / 10000;
while (trys--) {
if (((*reg) & bits) == 0)
return B_OK;
snooze(10000);
}
return B_TIMED_OUT;
}
#endif
#endif