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 <ata_types.h> 9 #include <bus/PCI.h> 10 #include <bus/SCSI.h> 11 #include <PCI_x86.h> 12 13 #ifdef __cplusplus 14 extern "C" { 15 #endif 16 17 #define AHCI_DEVICE_MODULE_NAME "busses/scsi/ahci/driver_v1" 18 #define AHCI_SIM_MODULE_NAME "busses/scsi/ahci/sim/driver_v1" 19 20 // RW1 = Write 1 to set bit (writing 0 is ignored) 21 // RWC = Write 1 to clear bit (writing 0 is ignored) 22 23 24 enum { 25 CAP_S64A = (1U << 31), // Supports 64-bit Addressing 26 CAP_SNCQ = (1 << 30), // Supports Native Command Queuing 27 CAP_SSNTF = (1 << 29), // Supports SNotification Register 28 CAP_SMPS = (1 << 28), // Supports Mechanical Presence Switch 29 CAP_SSS = (1 << 27), // Supports Staggered Spin-up 30 CAP_SALP = (1 << 26), // Supports Aggressive Link Power Management 31 CAP_SAL = (1 << 25), // Supports Activity LED 32 CAP_SCLO = (1 << 24), // Supports Command List Override 33 CAP_ISS_MASK = 0xf, // Interface Speed Support 34 CAP_ISS_SHIFT = 20, 35 CAP_SNZO = (1 << 19), // Supports Non-Zero DMA Offsets 36 CAP_SAM = (1 << 18), // Supports AHCI mode only 37 CAP_SPM = (1 << 17), // Supports Port Multiplier 38 CAP_FBSS = (1 << 16), // FIS-based Switching Supported 39 CAP_PMD = (1 << 15), // PIO Multiple DRQ Block 40 CAP_SSC = (1 << 14), // Slumber State Capable 41 CAP_PSC = (1 << 13), // Partial State Capable 42 CAP_NCS_MASK = 0x1f, // Number of Command Slots 43 // (zero-based number) 44 CAP_NCS_SHIFT = 8, 45 CAP_CCCS = (1 << 7), // Command Completion Coalescing Supported 46 CAP_EMS = (1 << 6), // Enclosure Management Supported 47 CAP_SXS = (1 << 5), // Supports External SATA 48 CAP_NP_MASK = 0x1f, // Number of Ports (zero-based number) 49 CAP_NP_SHIFT = 0, 50 }; 51 52 53 enum { 54 GHC_AE = (1U << 31), // AHCI Enable 55 GHC_MRSM = (1 << 2), // MSI Revert to Single Message 56 GHC_IE = (1 << 1), // Interrupt Enable 57 GHC_HR = (1 << 0), // HBA Reset **RW1** 58 }; 59 60 61 enum { 62 INT_CPD = (1 << 31), // Cold Port Detect Status/Enable 63 INT_TFE = (1 << 30), // Task File Error Status/Enable 64 INT_HBF = (1 << 29), // Host Bus Fatal Error Status/Enable 65 INT_HBD = (1 << 28), // Host Bus Data Error Status/Enable 66 INT_IF = (1 << 27), // Interface Fatal Error Status/Enable 67 INT_INF = (1 << 26), // Interface Non-fatal Error Status/Enable 68 INT_OF = (1 << 24), // Overflow Status/Enable 69 INT_IPM = (1 << 23), // Incorrect Port Multiplier Status/Enable 70 INT_PRC = (1 << 22), // PhyRdy Change Status/Enable 71 INT_DMP = (1 << 7), // Device Mechanical Presence Status/Enable 72 INT_PC = (1 << 6), // Port Change Interrupt Status/Enable 73 INT_DP = (1 << 5), // Descriptor Processed Interrupt/Enable 74 INT_UF = (1 << 4), // Unknown FIS Interrupt/Enable 75 INT_SDB = (1 << 3), // Set Device Bits Interrupt/Enable 76 INT_DS = (1 << 2), // DMA Setup FIS Interrupt/Enable 77 INT_PS = (1 << 1), // PIO Setup FIS Interrupt/Enable 78 INT_DHR = (1 << 0), // Device to Host Register FIS 79 // Interrupt/Enable 80 }; 81 82 83 // Serial ATA Status and control 84 #define HBA_PORT_IPM_MASK 0x00000f00 // Interface Power Management 85 #define SSTS_PORT_IPM_ACTIVE 0x00000100 // active state 86 #define SSTS_PORT_IPM_PARTIAL 0x00000200 // partial state 87 #define SSTS_PORT_IPM_SLUMBER 0x00000600 // slumber power management state 88 #define SSTS_PORT_IPM_DEVSLEEP 0x00000800 // devsleep power management state 89 #define SCTL_PORT_IPM_NORES 0x00000000 // no power restrictions 90 #define SCTL_PORT_IPM_NOPART 0x00000100 // no transitions to partial 91 #define SCTL_PORT_IPM_NOSLUM 0x00000200 // no transitions to slumber 92 93 #define HBA_PORT_SPD_MASK 0x000000f0 // Interface speed 94 95 #define HBA_PORT_DET_MASK 0x0000000f // Device Detection 96 #define SSTS_PORT_DET_NODEV 0x00000000 // no device detected 97 #define SSTS_PORT_DET_NOPHY 0x00000001 // device present but PHY not est. 98 #define SSTS_PORT_DET_PRESENT 0x00000003 // device present and PHY est. 99 #define SSTS_PORT_DET_OFFLINE 0x00000004 // device offline due to disabled 100 #define SCTL_PORT_DET_NOINIT 0x00000000 // no initalization request 101 #define SCTL_PORT_DET_INIT 0x00000001 // perform interface initalization 102 #define SCTL_PORT_DET_DISABLE 0x00000004 // disable phy 103 104 // Device signatures 105 #define SATA_SIG_ATA 0x00000101 // SATA drive 106 #define SATA_SIG_ATAPI 0xEB140101 // ATAPI drive 107 #define SATA_SIG_SEMB 0xC33C0101 // Enclosure management bridge 108 #define SATA_SIG_PM 0x96690101 // Port multiplier 109 110 typedef struct { 111 uint32 clb; // Command List Base Address 112 // (alignment 1024 byte) 113 uint32 clbu; // Command List Base Address Upper 32-Bits 114 uint32 fb; // FIS Base Address (alignment 256 byte) 115 uint32 fbu; // FIS Base Address Upper 32-Bits 116 uint32 is; // Interrupt Status **RWC** 117 uint32 ie; // Interrupt Enable 118 uint32 cmd; // Command and Status 119 uint32 res1; // Reserved 120 uint32 tfd; // Task File Data 121 uint32 sig; // Signature 122 uint32 ssts; // Serial ATA Status (SCR0: SStatus) 123 uint32 sctl; // Serial ATA Control (SCR2: SControl) 124 uint32 serr; // Serial ATA Error (SCR1: SError) **RWC** 125 uint32 sact; // Serial ATA Active (SCR3: SActive) **RW1** 126 uint32 ci; // Command Issue **RW1** 127 uint32 sntf; // SNotification 128 uint32 fbs; // FIS-based Switching Control 129 uint32 devslp; // Device Sleep 130 uint32 res[10]; // Reserved 131 uint32 vendor[4]; // Vendor Specific 132 } ahci_port; 133 134 135 enum { 136 PORT_CMD_ICC_ACTIVE = (1 << 28), // Interface Communication control 137 PORT_CMD_ICC_SLUMBER = (6 << 28), // Interface Communication control 138 PORT_CMD_ICC_MASK = (0xf<<28), // Interface Communication control 139 PORT_CMD_ATAPI = (1 << 24), // Device is ATAPI 140 PORT_CMD_CR = (1 << 15), // Command List Running (DMA active) 141 PORT_CMD_FR = (1 << 14), // FIS Receive Running 142 PORT_CMD_FRE = (1 << 4), // FIS Receive Enable 143 PORT_CMD_CLO = (1 << 3), // Command List Override 144 PORT_CMD_POD = (1 << 2), // Power On Device 145 PORT_CMD_SUD = (1 << 1), // Spin-up Device 146 PORT_CMD_ST = (1 << 0), // Start DMA 147 }; 148 149 150 enum { 151 PORT_INT_CPD = (1 << 31), // Cold Presence Detect Status/Enable 152 PORT_INT_TFE = (1 << 30), // Task File Error Status/Enable 153 PORT_INT_HBF = (1 << 29), // Host Bus Fatal Error Status/Enable 154 PORT_INT_HBD = (1 << 28), // Host Bus Data Error Status/Enable 155 PORT_INT_IF = (1 << 27), // Interface Fatal Error Status/Enable 156 PORT_INT_INF = (1 << 26), // Interface Non-fatal Error Status/Enable 157 PORT_INT_OF = (1 << 24), // Overflow Status/Enable 158 PORT_INT_IPM = (1 << 23), // Incorrect Port Multiplier Status/Enable 159 PORT_INT_PRC = (1 << 22), // PhyRdy Change Status/Enable 160 PORT_INT_DI = (1 << 7), // Device Interlock Status/Enable 161 PORT_INT_PC = (1 << 6), // Port Change Status/Enable 162 PORT_INT_DP = (1 << 5), // Descriptor Processed Interrupt 163 PORT_INT_UF = (1 << 4), // Unknown FIS Interrupt 164 PORT_INT_SDB = (1 << 3), // Set Device Bits FIS Interrupt 165 PORT_INT_DS = (1 << 2), // DMA Setup FIS Interrupt 166 PORT_INT_PS = (1 << 1), // PIO Setup FIS Interrupt 167 PORT_INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt 168 }; 169 170 #define PORT_INT_ERROR (PORT_INT_TFE | PORT_INT_HBF | PORT_INT_HBD \ 171 | PORT_INT_IF | PORT_INT_INF | PORT_INT_OF \ 172 | PORT_INT_IPM | PORT_INT_PRC | PORT_INT_PC \ 173 | PORT_INT_UF) 174 175 #define PORT_INT_MASK (PORT_INT_ERROR | PORT_INT_DP | PORT_INT_SDB \ 176 | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR) 177 178 enum { 179 PORT_FBS_DWE_SHIFT = 16, // Device With Error 180 PORT_FBS_DWE_MASK = 0xf, 181 PORT_FBS_ADO_SHIFT = 12, // Active Device Optimization 182 PORT_FBS_ADO_MASK = 0xf, 183 PORT_FBS_DEV_SHIFT = 8, // Device To Issue 184 PORT_FBS_DEV_MASK = 0xf, 185 PORT_FBS_SDE = 0x04, // Single Device Error 186 PORT_FBS_DEC = 0x02, // Device Error Clear 187 PORT_FBS_EN = 0x01, // Enable 188 }; 189 190 191 enum { 192 PORT_DEVSLP_DM_SHIFT = 25, // DITO Multiplier 193 PORT_DEVSLP_DM_MASK = 0xf, 194 PORT_DEVSLP_DITO_SHIFT = 15, // Device Sleep Idle Timeout 195 PORT_DEVSLP_DITO_MASK = 0x3ff, 196 PORT_DEVSLP_MDAT_SHIFT = 10, // Minimum Device Sleep Assertion Time 197 PORT_DEVSLP_MDAT_MASK = 0x1f, 198 PORT_DEVSLP_DETO_SHIFT = 2, // Device Sleep Exit Timeout 199 PORT_DEVSLP_DETO_MASK = 0xff, 200 PORT_DEVSLP_DSP = 0x02, // Device Sleep Present 201 PORT_DEVSLP_ADSE = 0x01, // Aggressive Device Sleep Enable 202 }; 203 204 205 enum { 206 CAP2_DESO = (1 << 5), // DevSleep Entrance from Slumber Only 207 CAP2_SADM = (1 << 4), // Supports Aggressive Device Sleep 208 // Management 209 CAP2_SDS = (1 << 3), // Supports Device Sleep 210 CAP2_APST = (1 << 2), // Automatic Partial to Slumber Transitions 211 CAP2_NVMP = (1 << 1), // NVMHCI Present 212 CAP2_BOH = (1 << 0), // BIOS/OS Handoff 213 }; 214 215 216 typedef struct { 217 uint32 cap; // Host Capabilities 218 uint32 ghc; // Global Host Control 219 uint32 is; // Interrupt Status 220 uint32 pi; // Ports Implemented 221 uint32 vs; // Version 222 uint32 ccc_ctl; // Command Completion Coalescing Control 223 uint32 ccc_ports; // Command Completion Coalsecing Ports 224 uint32 em_loc; // Enclosure Management Location 225 uint32 em_ctl; // Enclosure Management Control 226 uint32 cap2; // Host Capabilities Extended 227 uint32 bohc; // BIOS/OS Handoff Control and Status 228 uint32 res[29]; // Reserved 229 uint32 vendor[24]; // Vendor Specific registers 230 ahci_port port[32]; 231 } _PACKED ahci_hba; 232 233 234 typedef struct { 235 uint8 dsfis[0x1c]; // DMA Setup FIS 236 uint8 res1[0x04]; 237 uint8 psfis[0x14]; // PIO Setup FIS 238 uint8 res2[0x0c]; 239 uint8 rfis[0x14]; // D2H Register FIS 240 uint8 res3[0x04]; 241 uint8 sdbfis[0x08]; // Set Device Bits FIS 242 uint8 ufis[0x40]; // Unknown FIS 243 uint8 res4[0x60]; 244 } _PACKED fis; 245 246 247 typedef struct { 248 union { 249 struct { 250 uint16 cfl : 5; // command FIS length 251 uint16 a : 1; // ATAPI 252 uint16 w : 1; // Write 253 uint16 p : 1; // Prefetchable 254 uint16 r : 1; // Reset 255 uint16 b : 1; // Build In Self Test 256 uint16 c : 1; // Clear Busy upon R_OK 257 uint16 : 1; 258 uint16 pmp : 4; // Port Multiplier Port 259 uint16 prdtl; // physical region description table 260 // length; 261 } _PACKED; 262 uint32 prdtl_flags_cfl; 263 } _PACKED; 264 uint32 prdbc; // PRD Byte Count 265 uint32 ctba; // command table desciptor base address 266 // (alignment 128 byte) 267 uint32 ctbau; // command table desciptor base address upper 268 uint8 res1[0x10]; 269 } _PACKED command_list_entry; 270 271 #define COMMAND_LIST_ENTRY_COUNT 32 272 273 274 // Command FIS layout - Host to Device (H2D) 275 // 0 - FIS Type (0x27) 276 // 1 - C bit (0x80) 277 // 2 - Command 278 // 3 - Features 279 // 4 - Sector Number (LBA Low, bits 0-7) 280 // 5 - Cylinder Low (LBA Mid, bits 8-15) 281 // 6 - Cylinder High (LBA High, bits 16-23) 282 // 7 - Device / Head (for 28-bit LBA commands, bits 24-27) 283 // 8 - Sector Number expanded (LBA Low-previous, bits 24-31) 284 // 9 - Cylinder Low expanded (LBA Mid-previous, bits 32-39) 285 // 10 - Cylinder High expanded (LBA High-previous, bits 40-47) 286 // 11 - Features expanded 287 // 12 - Sector Count (Sector count, bits 0-7) 288 // 13 - Sector Count expanded (Sector count, bits 8-15) 289 // 14 - Reserved (0) 290 // 15 - Control 291 // 16 - Reserved (0) 292 // 17 - Reserved (0) 293 // 18 - Reserved (0) 294 // 19 - Reserved (0) 295 typedef struct { 296 uint8 cfis[0x40]; // command FIS 297 uint8 acmd[0x20]; // ATAPI command 298 uint8 res[0x20]; // reserved 299 } _PACKED command_table; 300 301 302 typedef struct { 303 uint32 dba; // Data Base Address (2-byte aligned) 304 uint32 dbau; // Data Base Address Upper 305 uint32 res; 306 uint32 dbc; // Bytecount (0-based, even, max 4MB) 307 #define DBC_I 0x80000000 /* Interrupt on completition */ 308 } _PACKED prd; 309 310 #define PRD_TABLE_ENTRY_COUNT 168 311 #define PRD_MAX_DATA_LENGTH 0x400000 /* 4 MB */ 312 313 314 typedef struct { 315 uint16 vendor; 316 uint16 device; 317 const char *name; 318 uint32 flags; 319 } device_info; 320 321 status_t get_device_info(uint16 vendorID, uint16 deviceID, const char **name, 322 uint32 *flags); 323 324 325 extern scsi_sim_interface gAHCISimInterface; 326 extern device_manager_info *gDeviceManager; 327 extern scsi_for_sim_interface *gSCSI; 328 extern pci_x86_module_info* gPCIx86Module; 329 330 331 #define MAX_SECTOR_LBA_28 ((1ull << 28) - 1) 332 #define MAX_SECTOR_LBA_48 ((1ull << 48) - 1) 333 334 335 #define LO32(val) ((uint32)(addr_t)(val)) 336 #define HI32(val) ((uint32)(((uint64)(addr_t)(val)) >> 32)) 337 #define ASSERT(expr) if (expr) {} else panic("%s", #expr) 338 339 #define PCI_VENDOR_INTEL 0x8086 340 #define PCI_VENDOR_JMICRON 0x197b 341 #define PCI_JMICRON_CONTROLLER_CONTROL_1 0x40 342 343 #ifdef __cplusplus 344 } 345 #endif 346 347 #ifdef __cplusplus 348 349 template <class T> 350 int count_bits_set(T value) 351 { 352 int count = 0; 353 for (T mask = 1; mask; mask <<= 1) 354 if (value & mask) 355 count++; 356 return count; 357 } 358 359 inline 360 status_t 361 wait_until_set(volatile uint32 *reg, uint32 bits, bigtime_t timeout) 362 { 363 int trys = (timeout + 9999) / 10000; 364 while (trys--) { 365 if (((*reg) & bits) == bits) 366 return B_OK; 367 snooze(10000); 368 } 369 return B_TIMED_OUT; 370 } 371 372 inline 373 status_t 374 wait_until_clear(volatile uint32 *reg, uint32 bits, bigtime_t timeout) 375 { 376 int trys = (timeout + 9999) / 10000; 377 while (trys--) { 378 if (((*reg) & bits) == 0) 379 return B_OK; 380 snooze(10000); 381 } 382 return B_TIMED_OUT; 383 } 384 385 #endif /* __cplusplus */ 386 387 #endif /* _AHCI_DEFS_H */ 388