1 #pragma once 2 3 #include <common/blk_types.h> 4 #include <driver/pci/pci.h> 5 #include <mm/mm.h> 6 7 /** 8 * @todo 加入io调度器(当操作系统实现了多进程之后要加入这个) 9 * 10 */ 11 #define AHCI_MAPPING_BASE SPECIAL_MEMOEY_MAPPING_VIRT_ADDR_BASE + AHCI_MAPPING_OFFSET 12 13 #define MAX_AHCI_DEVICES 100 14 15 #define HBA_PxCMD_ST 0x0001 16 #define HBA_PxCMD_FRE 0x0010 17 #define HBA_PxCMD_FR 0x4000 18 #define HBA_PxCMD_CR 0x8000 19 20 #define AHCI_DEV_BUSY 0x80 21 #define AHCI_DEV_DRQ 0x08 22 23 #define AHCI_CMD_READ_DMA_EXT 0x25 24 #define AHCI_CMD_WRITE_DMA_EXT 0x30 25 26 #define HBA_PxIS_TFES (1 << 30) /* TFES - Task File Error Status */ 27 28 #define AHCI_SUCCESS 0 // 请求成功 29 #define E_NOEMPTYSLOT 1 // 没有空闲的slot 30 #define E_PORT_HUNG 2 // 端口被挂起 31 #define E_TASK_FILE_ERROR 3 // 任务文件错误 32 #define E_UNSUPPORTED_CMD 4 // 不支持的命令 33 34 extern struct block_device_operation ahci_operation; 35 36 /** 37 * @brief 在SATA3.0规范中定义的Frame Information Structure类型 38 * 39 */ 40 typedef enum 41 { 42 FIS_TYPE_REG_H2D = 0x27, // Register FIS - host to device 43 FIS_TYPE_REG_D2H = 0x34, // Register FIS - device to host 44 FIS_TYPE_DMA_ACT = 0x39, // DMA activate FIS - device to host 45 FIS_TYPE_DMA_SETUP = 0x41, // DMA setup FIS - bidirectional 46 FIS_TYPE_DATA = 0x46, // Data FIS - bidirectional 47 FIS_TYPE_BIST = 0x58, // BIST activate FIS - bidirectional 48 FIS_TYPE_PIO_SETUP = 0x5F, // PIO setup FIS - device to host 49 FIS_TYPE_DEV_BITS = 0xA1, // Set device bits FIS - device to host 50 } FIS_TYPE; 51 52 /** 53 * @brief FIS_REG_H2D 被用于从主机向设备发送控制命令 54 * 注意:reserved bit应当被清零 55 */ 56 typedef struct tagFIS_REG_H2D 57 { 58 // DWORD 0 59 uint8_t fis_type; // FIS_TYPE_REG_H2D 60 61 uint8_t pmport : 4; // Port multiplier 62 uint8_t rsv0 : 3; // Reserved 63 uint8_t c : 1; // 1: Command, 0: Control 64 65 uint8_t command; // Command register 66 uint8_t featurel; // Feature register, 7:0 67 68 // DWORD 1 69 uint8_t lba0; // LBA low register, 7:0 70 uint8_t lba1; // LBA mid register, 15:8 71 uint8_t lba2; // LBA high register, 23:16 72 uint8_t device; // Device register 73 74 // DWORD 2 75 uint8_t lba3; // LBA register, 31:24 76 uint8_t lba4; // LBA register, 39:32 77 uint8_t lba5; // LBA register, 47:40 78 uint8_t featureh; // Feature register, 15:8 79 80 // DWORD 3 81 uint8_t countl; // Count register, 7:0 82 uint8_t counth; // Count register, 15:8 83 uint8_t icc; // Isochronous command completion 84 uint8_t control; // Control register 85 86 // DWORD 4 87 uint8_t rsv1[4]; // Reserved 88 } FIS_REG_H2D; 89 90 // A device to host register FIS is used by the device to notify the host that some ATA register has changed. 91 // It contains the updated task files such as status, error and other registers. 92 typedef struct tagFIS_REG_D2H 93 { 94 // DWORD 0 95 uint8_t fis_type; // FIS_TYPE_REG_D2H 96 97 uint8_t pmport : 4; // Port multiplier 98 uint8_t rsv0 : 2; // Reserved 99 uint8_t i : 1; // Interrupt bit 100 uint8_t rsv1 : 1; // Reserved 101 102 uint8_t status; // Status register 103 uint8_t error; // Error register 104 105 // DWORD 1 106 uint8_t lba0; // LBA low register, 7:0 107 uint8_t lba1; // LBA mid register, 15:8 108 uint8_t lba2; // LBA high register, 23:16 109 uint8_t device; // Device register 110 111 // DWORD 2 112 uint8_t lba3; // LBA register, 31:24 113 uint8_t lba4; // LBA register, 39:32 114 uint8_t lba5; // LBA register, 47:40 115 uint8_t rsv2; // Reserved 116 117 // DWORD 3 118 uint8_t countl; // Count register, 7:0 119 uint8_t counth; // Count register, 15:8 120 uint8_t rsv3[2]; // Reserved 121 122 // DWORD 4 123 uint8_t rsv4[4]; // Reserved 124 } FIS_REG_D2H; 125 126 // This FIS is used by the host or device to send data payload. The data size can be varied. 127 typedef struct tagFIS_DATA 128 { 129 // DWORD 0 130 uint8_t fis_type; // FIS_TYPE_DATA 131 132 uint8_t pmport : 4; // Port multiplier 133 uint8_t rsv0 : 4; // Reserved 134 135 uint8_t rsv1[2]; // Reserved 136 137 // DWORD 1 ~ N 138 uint32_t data[1]; // Payload 139 } FIS_DATA; 140 141 // This FIS is used by the device to tell the host that it’s about to send or ready to receive a PIO data payload. 142 typedef struct tagFIS_PIO_SETUP 143 { 144 // DWORD 0 145 uint8_t fis_type; // FIS_TYPE_PIO_SETUP 146 147 uint8_t pmport : 4; // Port multiplier 148 uint8_t rsv0 : 1; // Reserved 149 uint8_t d : 1; // Data transfer direction, 1 - device to host 150 uint8_t i : 1; // Interrupt bit 151 uint8_t rsv1 : 1; 152 153 uint8_t status; // Status register 154 uint8_t error; // Error register 155 156 // DWORD 1 157 uint8_t lba0; // LBA low register, 7:0 158 uint8_t lba1; // LBA mid register, 15:8 159 uint8_t lba2; // LBA high register, 23:16 160 uint8_t device; // Device register 161 162 // DWORD 2 163 uint8_t lba3; // LBA register, 31:24 164 uint8_t lba4; // LBA register, 39:32 165 uint8_t lba5; // LBA register, 47:40 166 uint8_t rsv2; // Reserved 167 168 // DWORD 3 169 uint8_t countl; // Count register, 7:0 170 uint8_t counth; // Count register, 15:8 171 uint8_t rsv3; // Reserved 172 uint8_t e_status; // New value of status register 173 174 // DWORD 4 175 uint16_t tc; // Transfer count 176 uint8_t rsv4[2]; // Reserved 177 } FIS_PIO_SETUP; 178 179 typedef struct tagFIS_DMA_SETUP 180 { 181 // DWORD 0 182 uint8_t fis_type; // FIS_TYPE_DMA_SETUP 183 184 uint8_t pmport : 4; // Port multiplier 185 uint8_t rsv0 : 1; // Reserved 186 uint8_t d : 1; // Data transfer direction, 1 - device to host 187 uint8_t i : 1; // Interrupt bit 188 uint8_t a : 1; // Auto-activate. Specifies if DMA Activate FIS is needed 189 190 uint8_t rsved[2]; // Reserved 191 192 // DWORD 1&2 193 194 uint64_t DMAbufferID; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory. 195 // SATA Spec says host specific and not in Spec. Trying AHCI spec might work. 196 197 // DWORD 3 198 uint32_t rsvd; // More reserved 199 200 // DWORD 4 201 uint32_t DMAbufOffset; // Byte offset into buffer. First 2 bits must be 0 202 203 // DWORD 5 204 uint32_t TransferCount; // Number of bytes to transfer. Bit 0 must be 0 205 206 // DWORD 6 207 uint32_t resvd; // Reserved 208 209 } FIS_DMA_SETUP; 210 211 typedef volatile struct tagHBA_PORT 212 { 213 uint64_t clb; // 0x00, command list base address, 1K-byte aligned 214 uint64_t fb; // 0x08, FIS base address, 256-byte aligned 215 uint32_t is; // 0x10, interrupt status 216 uint32_t ie; // 0x14, interrupt enable 217 uint32_t cmd; // 0x18, command and status 218 uint32_t rsv0; // 0x1C, Reserved 219 uint32_t tfd; // 0x20, task file data 220 uint32_t sig; // 0x24, signature 221 uint32_t ssts; // 0x28, SATA status (SCR0:SStatus) 222 uint32_t sctl; // 0x2C, SATA control (SCR2:SControl) 223 uint32_t serr; // 0x30, SATA error (SCR1:SError) 224 uint32_t sact; // 0x34, SATA active (SCR3:SActive) 225 uint32_t ci; // 0x38, command issue 226 uint32_t sntf; // 0x3C, SATA notification (SCR4:SNotification) 227 uint32_t fbs; // 0x40, FIS-based switch control 228 uint32_t rsv1[11]; // 0x44 ~ 0x6F, Reserved 229 uint32_t vendor[4]; // 0x70 ~ 0x7F, vendor specific 230 } HBA_PORT; 231 typedef volatile struct tagHBA_MEM 232 { 233 // 0x00 - 0x2B, Generic Host Control 234 uint32_t cap; // 0x00, Host capability 235 uint32_t ghc; // 0x04, Global host control 236 uint32_t is; // 0x08, Interrupt status 237 uint32_t pi; // 0x0C, Port implemented 238 uint32_t vs; // 0x10, Version 239 uint32_t ccc_ctl; // 0x14, Command completion coalescing control 240 uint32_t ccc_pts; // 0x18, Command completion coalescing ports 241 uint32_t em_loc; // 0x1C, Enclosure management location 242 uint32_t em_ctl; // 0x20, Enclosure management control 243 uint32_t cap2; // 0x24, Host capabilities extended 244 uint32_t bohc; // 0x28, BIOS/OS handoff control and status 245 246 // 0x2C - 0x9F, Reserved 247 uint8_t rsv[0xA0 - 0x2C]; 248 249 // 0xA0 - 0xFF, Vendor specific registers 250 uint8_t vendor[0x100 - 0xA0]; 251 252 // 0x100 - 0x10FF, Port control registers 253 HBA_PORT ports[32]; // 1 ~ 32 254 } HBA_MEM; 255 256 // There are four kinds of FIS which may be sent to the host by the device as indicated in the following structure declaration. 257 // 258 typedef volatile struct tagHBA_FIS 259 { 260 // 0x00 261 FIS_DMA_SETUP dsfis; // DMA Setup FIS 262 uint8_t pad0[4]; 263 264 // 0x20 265 FIS_PIO_SETUP psfis; // PIO Setup FIS 266 uint8_t pad1[12]; 267 268 // 0x40 269 FIS_REG_D2H rfis; // Register – Device to Host FIS 270 uint8_t pad2[4]; 271 272 // 0x58 273 // FIS_DEV_BITS sdbfis; // Set Device Bit FIS 274 275 // 0x60 276 uint8_t ufis[64]; 277 278 // 0xA0 279 uint8_t rsv[0x100 - 0xA0]; 280 } HBA_FIS; 281 282 typedef struct tagHBA_CMD_HEADER 283 { 284 // DW0 285 uint8_t cfl : 5; // Command FIS length in DWORDS, 2 ~ 16 286 uint8_t a : 1; // ATAPI 287 uint8_t w : 1; // Write, 1: H2D, 0: D2H 288 uint8_t p : 1; // Prefetchable 289 290 uint8_t r : 1; // Reset 291 uint8_t b : 1; // BIST 292 uint8_t c : 1; // Clear busy upon R_OK 293 uint8_t rsv0 : 1; // Reserved 294 uint8_t pmp : 4; // Port multiplier port 295 296 uint16_t prdtl; // Physical region descriptor table length in entries 297 298 // DW1 299 volatile uint32_t prdbc; // Physical region descriptor byte count transferred 300 301 // DW2, 3 302 uint64_t ctba; // Command table descriptor base address 303 304 // DW4 - 7 305 uint32_t rsv1[4]; // Reserved 306 } HBA_CMD_HEADER; 307 308 typedef struct tagHBA_PRDT_ENTRY 309 { 310 uint64_t dba; // Data base address 311 uint32_t rsv0; // Reserved 312 313 // DW3 314 uint32_t dbc : 22; // Byte count, 4M max 315 uint32_t rsv1 : 9; // Reserved 316 uint32_t i : 1; // Interrupt on completion 317 } HBA_PRDT_ENTRY; 318 319 typedef struct tagHBA_CMD_TBL 320 { 321 // 0x00 322 uint8_t cfis[64]; // Command FIS 323 324 // 0x40 325 uint8_t acmd[16]; // ATAPI command, 12 or 16 bytes 326 327 // 0x50 328 uint8_t rsv[48]; // Reserved 329 330 // 0x80 331 HBA_PRDT_ENTRY prdt_entry[1]; // Physical region descriptor table entries, 0 ~ 65535 332 } HBA_CMD_TBL; 333 334 struct ahci_device_t 335 { 336 uint32_t type; // 设备类型 337 struct pci_device_structure_header_t *dev_struct; 338 HBA_MEM *hba_mem; 339 } ahci_devices[MAX_AHCI_DEVICES]; 340 341 #define SATA_SIG_ATA 0x00000101 // SATA drive 342 #define SATA_SIG_ATAPI 0xEB140101 // SATAPI drive 343 #define SATA_SIG_SEMB 0xC33C0101 // Enclosure management bridge 344 #define SATA_SIG_PM 0x96690101 // Port multiplier 345 346 #define AHCI_DEV_NULL 0 347 #define AHCI_DEV_SATA 1 348 #define AHCI_DEV_SEMB 2 349 #define AHCI_DEV_PM 3 350 #define AHCI_DEV_SATAPI 4 351 352 #define HBA_PORT_IPM_ACTIVE 1 353 #define HBA_PORT_DET_PRESENT 3 354 355 struct ahci_request_packet_t 356 { 357 struct block_device_request_packet blk_pak; // 块设备请求包 358 uint8_t ahci_ctrl_num; // ahci控制器号, 默认应为0 359 uint8_t port_num; // ahci的设备端口号 360 }; 361 362 /** 363 * @brief 初始化ahci模块 364 * 365 */ 366 void ahci_init(); 367 368 /** 369 * @brief 检测端口连接的设备的类型 370 * 371 * @param device_num ahci设备号 372 */ 373 static void ahci_probe_port(const uint32_t device_num); 374 375 /** 376 * @brief read data from SATA device using 48bit LBA address 377 * 378 * @param port HBA PORT 379 * @param startl low 32bits of start addr 380 * @param starth high 32bits of start addr 381 * @param count total sectors to read 382 * @param buf buffer 383 * @return true done 384 * @return false failed 385 */ 386 static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, uint64_t buf); 387 388 /** 389 * @brief write data to SATA device using 48bit LBA address 390 * 391 * @param port HBA PORT 392 * @param startl low 32bits of start addr 393 * @param starth high 32bits of start addr 394 * @param count total sectors to read 395 * @param buf buffer 396 * @return true done 397 * @return false failed 398 */ 399 static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, 400 uint64_t buf); 401 402 void ahci_end_request();