ahci.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. #include "ahci.h"
  2. #include "../../../common/kprint.h"
  3. #include "../../../mm/slab.h"
  4. struct pci_device_structure_header_t *ahci_devs[MAX_AHCI_DEVICES];
  5. uint32_t count_ahci_devices = 0;
  6. uint64_t ahci_port_base_vaddr; // 端口映射base addr
  7. uint64_t ahci_port_base_phys_addr; // 端口映射的物理基地址(ahci控制器的参数的地址都是物理地址)
  8. static void start_cmd(HBA_PORT *port);
  9. static void stop_cmd(HBA_PORT *port);
  10. static void port_rebase(HBA_PORT *port, int portno);
  11. static long ahci_query_disk();
  12. // Find a free command list slot
  13. static int ahci_find_cmdslot(HBA_PORT *port);
  14. // 计算HBA_MEM的虚拟内存地址
  15. #define cal_HBA_MEM_VIRT_ADDR(device_num) (AHCI_MAPPING_BASE + (ul)(((struct pci_device_structure_general_device_t *)(ahci_devs[device_num]))->BAR5 - ((((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5) & PAGE_2M_MASK)))
  16. /**
  17. * @brief 初始化ahci模块
  18. *
  19. */
  20. void ahci_init()
  21. {
  22. kinfo("Initializing AHCI...");
  23. pci_get_device_structure(0x1, 0x6, ahci_devs, &count_ahci_devices);
  24. if (count_ahci_devices == 0)
  25. {
  26. kwarn("There is no AHCI device found on this computer!");
  27. return;
  28. }
  29. // 映射ABAR
  30. kdebug("phys_2_virt(ahci_devs[0])= %#018lx",(ahci_devs[0]));
  31. kdebug("((struct pci_device_structure_general_device_t *)phys_2_virt(ahci_devs[0])))->BAR5= %#018lx",((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5);
  32. uint32_t bar5 = ((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5;
  33. mm_map_phys_addr(AHCI_MAPPING_BASE, (ul)(bar5) & PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD);
  34. kdebug("ABAR mapped!");
  35. for (int i = 0; i < count_ahci_devices; ++i)
  36. {
  37. // kdebug("[%d] class_code=%d, sub_class=%d, progIF=%d, ABAR=%#010lx", i, ahci_devs[i]->Class_code, ahci_devs[i]->SubClass, ahci_devs[i]->ProgIF, ((struct pci_device_structure_general_device_t *)(ahci_devs[i]))->BAR5);
  38. // 赋值HBA_MEM结构体
  39. ahci_devices[i].dev_struct = ahci_devs[i];
  40. ahci_devices[i].hba_mem = (HBA_MEM *)(cal_HBA_MEM_VIRT_ADDR(i));
  41. kdebug("ahci_devices[i].hba_mem = %#018lx", (ul)ahci_devices[i].hba_mem);
  42. }
  43. // todo: 支持多个ahci控制器。
  44. ahci_port_base_vaddr = (uint64_t)kmalloc(1048576, 0);
  45. kdebug("ahci_port_base_vaddr=%#018lx", ahci_port_base_vaddr);
  46. ahci_probe_port(0);
  47. port_rebase(&ahci_devices[0].hba_mem->ports[0], 0);
  48. // 初始化请求队列
  49. ahci_req_queue.in_service = NULL;
  50. list_init(&(ahci_req_queue.queue_list));
  51. ahci_req_queue.request_count = 0;
  52. kinfo("AHCI initialized.");
  53. }
  54. // Check device type
  55. static int check_type(HBA_PORT *port)
  56. {
  57. uint32_t ssts = port->ssts;
  58. uint8_t ipm = (ssts >> 8) & 0x0F;
  59. uint8_t det = ssts & 0x0F;
  60. if (det != HBA_PORT_DET_PRESENT) // Check drive status
  61. return AHCI_DEV_NULL;
  62. if (ipm != HBA_PORT_IPM_ACTIVE)
  63. return AHCI_DEV_NULL;
  64. switch (port->sig)
  65. {
  66. case SATA_SIG_ATAPI:
  67. return AHCI_DEV_SATAPI;
  68. case SATA_SIG_SEMB:
  69. return AHCI_DEV_SEMB;
  70. case SATA_SIG_PM:
  71. return AHCI_DEV_PM;
  72. default:
  73. return AHCI_DEV_SATA;
  74. }
  75. }
  76. /**
  77. * @brief 检测端口连接的设备的类型
  78. *
  79. * @param device_num ahci控制器号
  80. */
  81. static void ahci_probe_port(const uint32_t device_num)
  82. {
  83. HBA_MEM *abar = ahci_devices[device_num].hba_mem;
  84. uint32_t pi = abar->pi;
  85. for (int i = 0; i < 32; ++i, (pi >>= 1))
  86. {
  87. if (pi & 1)
  88. {
  89. uint dt = check_type(&abar->ports[i]);
  90. ahci_devices[i].type = dt;
  91. if (dt == AHCI_DEV_SATA)
  92. {
  93. kdebug("SATA drive found at port %d", i);
  94. }
  95. else if (dt == AHCI_DEV_SATAPI)
  96. {
  97. kdebug("SATAPI drive found at port %d", i);
  98. }
  99. else if (dt == AHCI_DEV_SEMB)
  100. {
  101. kdebug("SEMB drive found at port %d", i);
  102. }
  103. else if (dt == AHCI_DEV_PM)
  104. {
  105. kdebug("PM drive found at port %d", i);
  106. }
  107. else
  108. {
  109. // kdebug("No drive found at port %d", i);
  110. }
  111. }
  112. }
  113. }
  114. // Start command engine
  115. static void start_cmd(HBA_PORT *port)
  116. {
  117. // Wait until CR (bit15) is cleared
  118. while ((port->cmd) & HBA_PxCMD_CR)
  119. ;
  120. // Set FRE (bit4) and ST (bit0)
  121. port->cmd |= HBA_PxCMD_FRE;
  122. port->cmd |= HBA_PxCMD_ST;
  123. }
  124. // Stop command engine
  125. static void stop_cmd(HBA_PORT *port)
  126. {
  127. // Clear ST (bit0)
  128. port->cmd &= ~HBA_PxCMD_ST;
  129. // Clear FRE (bit4)
  130. port->cmd &= ~HBA_PxCMD_FRE;
  131. // Wait until FR (bit14), CR (bit15) are cleared
  132. while (1)
  133. {
  134. if (port->cmd & HBA_PxCMD_FR)
  135. continue;
  136. if (port->cmd & HBA_PxCMD_CR)
  137. continue;
  138. break;
  139. }
  140. }
  141. static void port_rebase(HBA_PORT *port, int portno)
  142. {
  143. // Before rebasing Port memory space, OS must wait for current pending commands to finish
  144. // and tell HBA to stop receiving FIS from the port. Otherwise an accidently incoming FIS may be
  145. // written into a partially configured memory area.
  146. stop_cmd(port); // Stop command engine
  147. // Command list offset: 1K*portno
  148. // Command list entry size = 32
  149. // Command list entry maxim count = 32
  150. // Command list maxim size = 32*32 = 1K per port
  151. port->clb = virt_2_phys(ahci_port_base_vaddr + (portno << 10));
  152. memset((void *)(phys_2_virt(port->clb)), 0, 1024);
  153. // FIS offset: 32K+256*portno
  154. // FIS entry size = 256 bytes per port
  155. port->fb = virt_2_phys(ahci_port_base_vaddr + (32 << 10) + (portno << 8));
  156. memset((void *)(phys_2_virt(port->fb)), 0, 256);
  157. // Command table offset: 40K + 8K*portno
  158. // Command table size = 256*32 = 8K per port
  159. HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)(phys_2_virt(port->clb));
  160. for (int i = 0; i < 32; ++i)
  161. {
  162. cmdheader[i].prdtl = 8; // 8 prdt entries per command table
  163. // 256 bytes per command table, 64+16+48+16*8
  164. // Command table offset: 40K + 8K*portno + cmdheader_index*256
  165. cmdheader[i].ctba = virt_2_phys((ahci_port_base_vaddr + (40 << 10) + (portno << 13) + (i << 8)));
  166. memset((void *)phys_2_virt(cmdheader[i].ctba), 0, 256);
  167. }
  168. start_cmd(port); // Start command engine
  169. }
  170. /**
  171. * @brief read data from SATA device using 48bit LBA address
  172. *
  173. * @param port HBA PORT
  174. * @param startl low 32bits of start addr
  175. * @param starth high 32bits of start addr
  176. * @param count total sectors to read
  177. * @param buf buffer
  178. * @return true done
  179. * @return false failed
  180. */
  181. static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, uint64_t buf)
  182. {
  183. port->is = (uint32_t)-1; // Clear pending interrupt bits
  184. int spin = 0; // Spin lock timeout counter
  185. int slot = ahci_find_cmdslot(port);
  186. if (slot == -1)
  187. return E_NOEMPTYSLOT;
  188. HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)phys_2_virt(port->clb);
  189. cmdheader += slot;
  190. cmdheader->cfl = sizeof(FIS_REG_H2D) / sizeof(uint32_t); // Command FIS size
  191. cmdheader->w = 0; // Read from device
  192. cmdheader->prdtl = (uint16_t)((count - 1) >> 4) + 1; // PRDT entries count
  193. HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)phys_2_virt(cmdheader->ctba);
  194. memset(cmdtbl, 0, sizeof(HBA_CMD_TBL) + (cmdheader->prdtl - 1) * sizeof(HBA_PRDT_ENTRY));
  195. // 8K bytes (16 sectors) per PRDT
  196. int i;
  197. for (i = 0; i < cmdheader->prdtl - 1; ++i)
  198. {
  199. cmdtbl->prdt_entry[i].dba = virt_2_phys(buf);
  200. cmdtbl->prdt_entry[i].dbc = 8 * 1024 - 1; // 8K bytes (this value should always be set to 1 less than the actual value)
  201. cmdtbl->prdt_entry[i].i = 1;
  202. buf += 4 * 1024; // 4K uint16_ts
  203. count -= 16; // 16 sectors
  204. }
  205. // Last entry
  206. cmdtbl->prdt_entry[i].dba = virt_2_phys(buf);
  207. cmdtbl->prdt_entry[i].dbc = (count << 9) - 1; // 512 bytes per sector
  208. cmdtbl->prdt_entry[i].i = 1;
  209. // Setup command
  210. FIS_REG_H2D *cmdfis = (FIS_REG_H2D *)(&cmdtbl->cfis);
  211. cmdfis->fis_type = FIS_TYPE_REG_H2D;
  212. cmdfis->c = 1; // Command
  213. cmdfis->command = ATA_CMD_READ_DMA_EXT;
  214. cmdfis->lba0 = (uint8_t)startl;
  215. cmdfis->lba1 = (uint8_t)(startl >> 8);
  216. cmdfis->lba2 = (uint8_t)(startl >> 16);
  217. cmdfis->device = 1 << 6; // LBA mode
  218. cmdfis->lba3 = (uint8_t)(startl >> 24);
  219. cmdfis->lba4 = (uint8_t)starth;
  220. cmdfis->lba5 = (uint8_t)(starth >> 8);
  221. cmdfis->countl = count & 0xFF;
  222. cmdfis->counth = (count >> 8) & 0xFF;
  223. // The below loop waits until the port is no longer busy before issuing a new command
  224. while ((port->tfd & (ATA_DEV_BUSY | ATA_DEV_DRQ)) && spin < 1000000)
  225. {
  226. spin++;
  227. }
  228. if (spin == 1000000)
  229. {
  230. kerror("Port is hung");
  231. return E_PORT_HUNG;
  232. }
  233. kdebug("slot=%d", slot);
  234. port->ci = 1 << slot; // Issue command
  235. // Wait for completion
  236. while (1)
  237. {
  238. // In some longer duration reads, it may be helpful to spin on the DPS bit
  239. // in the PxIS port field as well (1 << 5)
  240. if ((port->ci & (1 << slot)) == 0)
  241. break;
  242. if (port->is & HBA_PxIS_TFES) // Task file error
  243. {
  244. kerror("Read disk error");
  245. return E_TASK_FILE_ERROR;
  246. }
  247. }
  248. // Check again
  249. if (port->is & HBA_PxIS_TFES)
  250. {
  251. kerror("Read disk error");
  252. return E_TASK_FILE_ERROR;
  253. }
  254. return AHCI_SUCCESS;
  255. }
  256. static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count,
  257. uint64_t buf)
  258. {
  259. port->is = 0xffff; // Clear pending interrupt bits
  260. int slot = ahci_find_cmdslot(port);
  261. if (slot == -1)
  262. return E_NOEMPTYSLOT;
  263. HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)phys_2_virt(port->clb);
  264. cmdheader += slot;
  265. cmdheader->cfl = sizeof(FIS_REG_H2D) / sizeof(uint32_t); // Command FIS size
  266. cmdheader->w = 1;
  267. cmdheader->c = 1;
  268. cmdheader->p = 1;
  269. cmdheader->prdtl = (uint16_t)((count - 1) >> 4) + 1; // PRDT entries count
  270. HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)phys_2_virt(cmdheader->ctba);
  271. memset(cmdtbl, 0, sizeof(HBA_CMD_TBL) + (cmdheader->prdtl - 1) * sizeof(HBA_PRDT_ENTRY));
  272. int i = 0;
  273. for (i = 0; i < cmdheader->prdtl - 1; ++i)
  274. {
  275. cmdtbl->prdt_entry[i].dba = virt_2_phys(buf);
  276. cmdtbl->prdt_entry[i].dbc = 8 * 1024 - 1; // 8K bytes
  277. cmdtbl->prdt_entry[i].i = 0;
  278. buf += 4 * 1024; // 4K words
  279. count -= 16; // 16 sectors
  280. }
  281. cmdtbl->prdt_entry[i].dba = virt_2_phys(buf);
  282. cmdtbl->prdt_entry[i].dbc = count << 9; // 512 bytes per sector
  283. cmdtbl->prdt_entry[i].i = 0;
  284. FIS_REG_H2D *cmdfis = (FIS_REG_H2D *)(&cmdtbl->cfis);
  285. cmdfis->fis_type = FIS_TYPE_REG_H2D;
  286. cmdfis->c = 1; // Command
  287. cmdfis->command = ATA_CMD_WRITE_DMA_EXT;
  288. cmdfis->lba0 = (uint8_t)startl;
  289. cmdfis->lba1 = (uint8_t)(startl >> 8);
  290. cmdfis->lba2 = (uint8_t)(startl >> 16);
  291. cmdfis->lba3 = (uint8_t)(startl >> 24);
  292. cmdfis->lba4 = (uint8_t)starth;
  293. cmdfis->lba5 = (uint8_t)(starth >> 8);
  294. cmdfis->device = 1 << 6; // LBA mode
  295. cmdfis->countl = count & 0xff;
  296. cmdfis->counth = count >> 8;
  297. // printk("[slot]{%d}", slot);
  298. port->ci = 1; // Issue command
  299. while (1)
  300. {
  301. // In some longer duration reads, it may be helpful to spin on the DPS bit
  302. // in the PxIS port field as well (1 << 5)
  303. if ((port->ci & (1 << slot)) == 0)
  304. break;
  305. if (port->is & HBA_PxIS_TFES)
  306. { // Task file error
  307. kerror("Write disk error");
  308. return E_TASK_FILE_ERROR;
  309. }
  310. }
  311. if (port->is & HBA_PxIS_TFES)
  312. {
  313. kerror("Write disk error");
  314. return E_TASK_FILE_ERROR;
  315. }
  316. return AHCI_SUCCESS;
  317. }
  318. // Find a free command list slot
  319. static int ahci_find_cmdslot(HBA_PORT *port)
  320. {
  321. // If not set in SACT and CI, the slot is free
  322. uint32_t slots = (port->sact | port->ci);
  323. int num_of_cmd_clots = (ahci_devices[0].hba_mem->cap & 0x0f00) >> 8; // bit 12-8
  324. for (int i = 0; i < num_of_cmd_clots; i++)
  325. {
  326. if ((slots & 1) == 0)
  327. return i;
  328. slots >>= 1;
  329. }
  330. kerror("Cannot find free command list entry");
  331. return -1;
  332. }
  333. long ahci_open()
  334. {
  335. return 0;
  336. }
  337. long ahci_close()
  338. {
  339. return 0;
  340. }
  341. /**
  342. * @brief 创建ahci磁盘请求包
  343. *
  344. * @param cmd 控制命令
  345. * @param base_addr 48位LBA地址
  346. * @param count total sectors to read
  347. * @param buf 缓冲区线性地址
  348. * @param ahci_ctrl_num ahci控制器号
  349. * @param port_num ahci控制器端口号
  350. * @return struct block_device_request_packet*
  351. */
  352. static struct block_device_request_packet *ahci_make_request(long cmd, uint64_t base_addr, uint64_t count, uint64_t buffer, uint8_t ahci_ctrl_num, uint8_t port_num)
  353. {
  354. struct block_device_request_packet *pack = (struct block_device_request_packet *)kmalloc(sizeof(struct block_device_request_packet), 0);
  355. list_init(&pack->list);
  356. // 由于ahci不需要中断即可读取磁盘,因此end handler为空
  357. switch (cmd)
  358. {
  359. case ATA_CMD_READ_DMA_EXT:
  360. pack->end_handler = NULL;
  361. pack->cmd = ATA_CMD_READ_DMA_EXT;
  362. break;
  363. case ATA_CMD_WRITE_DMA_EXT:
  364. pack->end_handler = NULL;
  365. pack->cmd = ATA_CMD_WRITE_DMA_EXT;
  366. break;
  367. default:
  368. pack->end_handler = NULL;
  369. pack->cmd = cmd;
  370. break;
  371. }
  372. pack->LBA_start = base_addr;
  373. pack->count = count;
  374. pack->buffer_vaddr = buffer;
  375. pack->ahci_ctrl_num = ahci_ctrl_num;
  376. pack->port_num = port_num;
  377. return pack;
  378. }
  379. /**
  380. * @brief 结束磁盘请求
  381. *
  382. */
  383. static void ahci_end_request()
  384. {
  385. kfree((uint64_t *)ahci_req_queue.in_service);
  386. ahci_req_queue.in_service = NULL;
  387. // 进行下一轮的磁盘请求 (由于未实现单独的io调度器,这里会造成长时间的io等待)
  388. if (ahci_req_queue.request_count > 0)
  389. ahci_query_disk();
  390. }
  391. static long ahci_query_disk()
  392. {
  393. struct block_device_request_packet *pack = container_of(list_next(&ahci_req_queue.queue_list), struct block_device_request_packet, list);
  394. ahci_req_queue.in_service = pack;
  395. list_del(&(ahci_req_queue.in_service->list));
  396. --ahci_req_queue.request_count;
  397. long ret_val;
  398. switch (pack->cmd)
  399. {
  400. case ATA_CMD_READ_DMA_EXT:
  401. ret_val = ahci_read(&(ahci_devices[pack->ahci_ctrl_num].hba_mem->ports[pack->port_num]), pack->LBA_start & 0xFFFFFFFF, ((pack->LBA_start) >> 32) & 0xFFFFFFFF, pack->count, pack->buffer_vaddr);
  402. break;
  403. case ATA_CMD_WRITE_DMA_EXT:
  404. ret_val = ahci_write(&(ahci_devices[pack->ahci_ctrl_num].hba_mem->ports[pack->port_num]), pack->LBA_start & 0xFFFFFFFF, ((pack->LBA_start) >> 32) & 0xFFFFFFFF, pack->count, pack->buffer_vaddr);
  405. break;
  406. default:
  407. kerror("Unsupport ahci command: %#05lx", pack->cmd);
  408. ret_val = E_UNSUPPORTED_CMD;
  409. break;
  410. }
  411. ahci_end_request();
  412. return ret_val;
  413. }
  414. /**
  415. * @brief 将请求包提交到io队列
  416. *
  417. * @param pack
  418. */
  419. static void ahci_submit(struct block_device_request_packet *pack)
  420. {
  421. list_append(&(ahci_req_queue.queue_list), &(pack->list));
  422. ++ahci_req_queue.request_count;
  423. if (ahci_req_queue.in_service == NULL) // 当前没有正在请求的io包,立即执行磁盘请求
  424. ahci_query_disk();
  425. }
  426. /**
  427. * @brief ahci驱动程序的传输函数
  428. *
  429. * @param cmd 控制命令
  430. * @param base_addr 48位LBA地址
  431. * @param count total sectors to read
  432. * @param buf 缓冲区线性地址
  433. * @param ahci_ctrl_num ahci控制器号
  434. * @param port_num ahci控制器端口号
  435. * @return long
  436. */
  437. static long ahci_transfer(long cmd, uint64_t base_addr, uint64_t count, uint64_t buf, uint8_t ahci_ctrl_num, uint8_t port_num)
  438. {
  439. struct block_device_request_packet *pack = NULL;
  440. if (cmd == ATA_CMD_READ_DMA_EXT || cmd == ATA_CMD_WRITE_DMA_EXT)
  441. {
  442. pack = ahci_make_request(cmd, base_addr, count, buf, ahci_ctrl_num, port_num);
  443. ahci_submit(pack);
  444. }
  445. else
  446. return E_UNSUPPORTED_CMD;
  447. return AHCI_SUCCESS;
  448. }
  449. /**
  450. * @brief todo: io控制器函数
  451. *
  452. * @param cmd 命令
  453. * @param arg 参数
  454. * @return long
  455. */
  456. static long ahci_ioctl(long cmd, long arg)
  457. {
  458. }
  459. struct block_device_operation ahci_operation =
  460. {
  461. .open = ahci_open,
  462. .close = ahci_close,
  463. .ioctl = ahci_ioctl,
  464. .transfer = ahci_transfer,
  465. };