1 /* 2 * Copyright 2007, Marcus Overhagen. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _AHCI_DEFS_H 6 #define _AHCI_DEFS_H 7 8 #include <bus/PCI.h> 9 #include <bus/SCSI.h> 10 11 #ifdef __cplusplus 12 extern "C" { 13 #endif 14 15 #define AHCI_DEVICE_MODULE_NAME "busses/scsi/ahci/device_v1" 16 #define AHCI_SIM_MODULE_NAME "busses/scsi/ahci/sim/v1" 17 18 enum { 19 CAP_S64A = (1 << 31), // Supports 64-bit Addressing 20 CAP_SNCQ = (1 << 30), // Supports Native Command Queuing 21 CAP_SSNTF = (1 << 29), // Supports SNotification Register 22 CAP_SMPS = (1 << 28), // Supports Mechanical Presence Switch 23 CAP_SSS = (1 << 27), // Supports Staggered Spin-up 24 CAP_SALP = (1 << 26), // Supports Aggressive Link Power Management 25 CAP_SAL = (1 << 25), // Supports Activity LED 26 CAP_SCLO = (1 << 24), // Supports Command List Override 27 CAP_ISS_MASK = 0xf, // Interface Speed Support 28 CAP_ISS_SHIFT = 20, 29 CAP_SNZO = (1 << 19), // Supports Non-Zero DMA Offsets 30 CAP_SAM = (1 << 18), // Supports AHCI mode only 31 CAP_SPM = (1 << 17), // Supports Port Multiplier 32 CAP_FBSS = (1 << 16), // FIS-based Switching Supported 33 CAP_PMD = (1 << 15), // PIO Multiple DRQ Block 34 CAP_SSC = (1 << 14), // Slumber State Capable 35 CAP_PSC = (1 << 13), // Partial State Capable 36 CAP_NCS_MASK = 0x1f, // Number of Command Slots (zero-based number) 37 CAP_NCS_SHIFT = 8, 38 CAP_CCCS = (1 << 7), // Command Completion Coalescing Supported 39 CAP_EMS = (1 << 6), // Enclosure Management Supported 40 CAP_SXS = (1 << 5), // Supports External SATA 41 CAP_NP_MASK = 0x1f, // Number of Ports (zero-based number) 42 CAP_NP_SHIFT = 0, 43 }; 44 45 46 enum { 47 GHC_AE = (1 << 31), // AHCI Enable 48 GHC_MRSM = (1 << 2), // MSI Revert to Single Message 49 GHC_IE = (1 << 1), // Interrupt Enable 50 GHC_HR = (1 << 0), // HBA Reset 51 }; 52 53 54 enum { 55 INT_CPD = (1 << 31), // Cold Port Detect Status/Enable 56 INT_TFE = (1 << 30), // Task File Error Status/Enable 57 INT_HBF = (1 << 29), // Host Bus Fatal Error Status/Enable 58 INT_HBD = (1 << 28), // Host Bus Data Error Status/Enable 59 INT_IF = (1 << 27), // Interface Fatal Error Status/Enable 60 INT_INF = (1 << 26), // Interface Non-fatal Error Status/Enable 61 INT_OF = (1 << 24), // Overflow Status/Enable 62 INT_IPM = (1 << 23), // Incorrect Port Multiplier Status/Enable 63 INT_PRC = (1 << 22), // PhyRdy Change Status/Enable 64 INT_DMP = (1 << 7), // Device Mechanical Presence Status/Enable 65 INT_PC = (1 << 6), // Port Change Interrupt Status/Enable 66 INT_DP = (1 << 5), // Descriptor Processed Interrupt/Enable 67 INT_UF = (1 << 4), // Unknown FIS Interrupt/Enable 68 INT_SDB = (1 << 3), // Set Device Bits Interrupt/Enable 69 INT_DS = (1 << 2), // DMA Setup FIS Interrupt/Enable 70 INT_PS = (1 << 1), // PIO Setup FIS Interrupt/Enable 71 INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt/Enable 72 }; 73 74 75 typedef struct { 76 uint32 clb; // Command List Base Address (alignment 1024 byte) 77 uint32 clbu; // Command List Base Address Upper 32-Bits 78 uint32 fb; // FIS Base Address (alignment 256 byte) 79 uint32 fbu; // FIS Base Address Upper 32-Bits 80 uint32 is; // Interrupt Status 81 uint32 ie; // Interrupt Enable 82 uint32 cmd; // Command and Status 83 uint32 res1; // Reserved 84 uint32 tfd; // Task File Data 85 uint32 sig; // Signature 86 uint32 ssts; // Serial ATA Status (SCR0: SStatus) 87 uint32 sctl; // Serial ATA Control (SCR2: SControl) 88 uint32 serr; // Serial ATA Error (SCR1: SError) 89 uint32 sact; // Serial ATA Active (SCR3: SActive) 90 uint32 ci; // Command Issue 91 uint32 sntf; // SNotification 92 uint32 res2; // Reserved for FIS-based Switching Definition 93 uint32 res[11]; // Reserved 94 uint32 vendor[4]; // Vendor Specific 95 } _PACKED ahci_port; 96 97 98 enum { 99 PORT_CMD_ICC_ACTIVE = (1 << 28), // Interface Communication control 100 PORT_CMD_ICC_SLUMBER = (6 << 28), // Interface Communication control 101 PORT_CMD_ICC_MASK = (0xf<<28), // Interface Communication control 102 PORT_CMD_ATAPI = (1 << 24), // Device is ATAPI 103 PORT_CMD_CR = (1 << 15), // Command List Running (DMA active) 104 PORT_CMD_FR = (1 << 14), // FIS Receive Running 105 PORT_CMD_FER = (1 << 4), // FIS Receive Enable 106 PORT_CMD_CLO = (1 << 3), // Command List Override 107 PORT_CMD_POD = (1 << 2), // Power On Device 108 PORT_CMD_SUD = (1 << 1), // Spin-up Device 109 PORT_CMD_ST = (1 << 0), // Start DMA 110 }; 111 112 113 enum { 114 PORT_INT_CPD = (1 << 31), // Cold Presence Detect Status/Enable 115 PORT_INT_TFE = (1 << 30), // Task File Error Status/Enable 116 PORT_INT_HBF = (1 << 29), // Host Bus Fatal Error Status/Enable 117 PORT_INT_HBD = (1 << 28), // Host Bus Data Error Status/Enable 118 PORT_INT_IF = (1 << 27), // Interface Fatal Error Status/Enable 119 PORT_INT_INF = (1 << 26), // Interface Non-fatal Error Status/Enable 120 PORT_INT_OF = (1 << 24), // Overflow Status/Enable 121 PORT_INT_IPM = (1 << 23), // Incorrect Port Multiplier Status/Enable 122 PORT_INT_PRCE = (1 << 22), // PhyRdy Change Status/Enable 123 PORT_INT_DI = (1 << 7), // Device Interlock Status/Enable 124 PORT_INT_PC = (1 << 6), // Port Change Status/Enable 125 PORT_INT_DP = (1 << 5), // Descriptor Processed Interrupt 126 PORT_INT_UF = (1 << 4), // Unknown FIS Interrupt 127 PORT_INT_SDB = (1 << 3), // Set Device Bits FIS Interrupt 128 PORT_INT_DS = (1 << 2), // DMA Setup FIS Interrupt 129 PORT_INT_PS = (1 << 1), // PIO Setup FIS Interrupt 130 PORT_INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt 131 }; 132 133 #define PORT_INT_FATAL (PORT_INT_HBF | PORT_INT_IF | PORT_INT_IPM | PORT_INT_UF) 134 #define PORT_INT_ERROR (PORT_INT_TFE | PORT_INT_HBD) 135 #define PORT_INT_MASK (PORT_INT_FATAL | PORT_INT_ERROR | PORT_INT_DP |\ 136 PORT_INT_SDB | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR) 137 138 enum { 139 ATA_BSY = 0x80, 140 ATA_DRQ = 0x08, 141 ATA_ERR = 0x01, 142 }; 143 144 145 typedef struct { 146 uint32 cap; // Host Capabilities 147 uint32 ghc; // Global Host Control 148 uint32 is; // Interrupt Status 149 uint32 pi; // Ports Implemented 150 uint32 vs; // Version 151 uint32 ccc_ctl; // Command Completion Coalescing Control 152 uint32 ccc_ports; // Command Completion Coalsecing Ports 153 uint32 em_loc; // Enclosure Management Location 154 uint32 em_ctl; // Enclosure Management Control 155 uint32 res[31]; // Reserved 156 uint32 vendor[24]; // Vendor Specific registers 157 ahci_port port[32]; 158 } _PACKED ahci_hba; 159 160 161 typedef struct { 162 uint8 dsfis[0x1c]; // DMA Setup FIS 163 uint8 res1[0x04]; 164 uint8 psfis[0x14]; // PIO Setup FIS 165 uint8 res2[0x0c]; 166 uint8 rfis[0x14]; // D2H Register FIS 167 uint8 res3[0x04]; 168 uint8 sdbfis[0x08]; // Set Device Bits FIS 169 uint8 ufis[0x40]; // Unknown FIS 170 uint8 res4[0x60]; 171 } _PACKED fis; 172 173 174 typedef struct { 175 union { 176 struct { 177 uint16 cfl : 5; // command FIS length 178 uint16 a : 1; // ATAPI 179 uint16 w : 1; // Write 180 uint16 p : 1; // Prefetchable 181 uint16 r : 1; // Reset 182 uint16 b : 1; // Build In Self Test 183 uint16 c : 1; // Clear Busy upon R_OK 184 uint16 : 1; 185 uint16 pmp : 4; // Port Multiplier Port 186 uint16 prdtl; // physical region description table length; 187 } _PACKED; 188 uint32 prdtl_flags_cfl; 189 } _PACKED; 190 uint32 prdbc; // PRD Byte Count 191 uint32 ctba; // command table desciptor base address (alignment 128 byte) 192 uint32 ctbau; // command table desciptor base address upper 193 uint8 res1[0x10]; 194 } _PACKED command_list_entry; 195 196 #define COMMAND_LIST_ENTRY_COUNT 32 197 198 199 typedef struct { 200 uint8 cfis[0x40]; // command FIS 201 uint8 acmd[0x20]; // ATAPI command 202 uint8 res[0x20]; // reserved 203 } _PACKED command_table; 204 205 206 typedef struct { 207 uint32 dba; // Data Base Address (2-byte aligned) 208 uint32 dbau; // Data Base Address Upper 209 uint32 res; 210 uint32 dbc; // Bytecount (0-based, even, max 4MB) 211 #define DBC_I 0x80000000 /* Interrupt on completition */ 212 } _PACKED prd; 213 214 #define PRD_TABLE_ENTRY_COUNT 168 215 #define PRD_MAX_DATA_LENGTH 0x400000 /* 4 MB */ 216 217 218 typedef struct { 219 uint16 vendor; 220 uint16 device; 221 const char *name; 222 uint32 flags; 223 } device_info; 224 225 status_t get_device_info(uint16 vendorID, uint16 deviceID, const char **name, uint32 *flags); 226 227 228 extern scsi_sim_interface gAHCISimInterface; 229 extern device_manager_info *gDeviceManager; 230 extern pci_device_module_info *gPCI; 231 extern scsi_for_sim_interface *gSCSI; 232 233 #define LO32(val) ((uint32)(val)) 234 #define HI32(val) (((uint64)(val)) >> 32) 235 #define ASSERT(expr) if (expr) {} else panic(#expr) 236 237 #define PCI_VENDOR_INTEL 0x8086 238 #define PCI_VENDOR_JMICRON 0x197b 239 #define PCI_JMICRON_CONTROLLER_CONTROL_1 0x40 240 241 #ifdef __cplusplus 242 } 243 #endif 244 245 #ifdef __cplusplus 246 247 template <class T> 248 int count_bits_set(T value) 249 { 250 int count = 0; 251 for (T mask = 1; mask; mask <<= 1) 252 if (value & mask) 253 count++; 254 return count; 255 } 256 257 inline 258 status_t 259 wait_until_set(volatile uint32 *reg, uint32 bits, bigtime_t timeout) 260 { 261 int trys = (timeout + 9999) / 10000; 262 while (trys--) { 263 if (((*reg) & bits) == bits) 264 return B_OK; 265 snooze(10000); 266 } 267 return B_TIMED_OUT; 268 } 269 270 inline 271 status_t 272 wait_until_clear(volatile uint32 *reg, uint32 bits, bigtime_t timeout) 273 { 274 int trys = (timeout + 9999) / 10000; 275 while (trys--) { 276 if (((*reg) & bits) == 0) 277 return B_OK; 278 snooze(10000); 279 } 280 return B_TIMED_OUT; 281 } 282 283 #endif /* __cplusplus */ 284 285 #endif /* _AHCI_DEFS_H */ 286