ahci.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. #include "ahci.h"
  2. #include <common/kprint.h>
  3. #include <mm/slab.h>
  4. #include <syscall/syscall.h>
  5. #include <syscall/syscall_num.h>
  6. #include <sched/sched.h>
  7. #include <common/string.h>
  8. #include <common/block.h>
  9. #include <filesystem/MBR.h>
  10. #include <debug/bug.h>
  11. struct pci_device_structure_header_t *ahci_devs[MAX_AHCI_DEVICES];
  12. struct block_device_request_queue ahci_req_queue;
  13. struct blk_gendisk ahci_gendisk0 = {0}; // 暂时硬性指定一个ahci_device
  14. static int __first_port = -1; // 临时用于存储 ahci控制器的第一个可用端口 的变量
  15. static uint32_t count_ahci_devices = 0;
  16. static uint64_t ahci_port_base_vaddr; // 端口映射base addr
  17. static uint64_t ahci_port_base_phys_addr; // 端口映射的物理基地址(ahci控制器的参数的地址都是物理地址)
  18. static void start_cmd(HBA_PORT *port);
  19. static void stop_cmd(HBA_PORT *port);
  20. static void port_rebase(HBA_PORT *port, int portno);
  21. static long ahci_query_disk();
  22. // Find a free command list slot
  23. static int ahci_find_cmdslot(HBA_PORT *port);
  24. // 计算HBA_MEM的虚拟内存地址
  25. #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)))
  26. long ahci_open();
  27. long ahci_close();
  28. static long ahci_ioctl(long cmd, long arg);
  29. static long ahci_transfer(struct blk_gendisk *gd, long cmd, uint64_t base_addr, uint64_t count, uint64_t buf);
  30. struct block_device_operation ahci_operation =
  31. {
  32. .open = ahci_open,
  33. .close = ahci_close,
  34. .ioctl = ahci_ioctl,
  35. .transfer = ahci_transfer,
  36. };
  37. /**
  38. * @brief ahci驱动器在block_device中的私有数据结构体
  39. *
  40. */
  41. struct ahci_blk_private_data
  42. {
  43. uint16_t ahci_ctrl_num; // ahci控制器号
  44. uint16_t ahci_port_num; // ahci端口号
  45. struct MBR_disk_partition_table_t *part_table; // 分区表
  46. };
  47. /**
  48. * @brief 申请ahci设备的私有信息结构体
  49. *
  50. * @return struct ahci_blk_private_data* 申请到的私有信息结构体
  51. */
  52. static struct ahci_blk_private_data *__alloc_private_data()
  53. {
  54. struct ahci_blk_private_data *data = (struct ahci_blk_private_data *)kzalloc(sizeof(struct ahci_blk_private_data), 0);
  55. data->part_table = (struct MBR_disk_partition_table_t *)kzalloc(512, 0);
  56. return data;
  57. }
  58. /**
  59. * @brief 释放ahci设备的分区的私有信息结构体
  60. *
  61. * @param pdata 待释放的结构体
  62. * @return int 错误码
  63. */
  64. static int __release_private_data(struct ahci_blk_private_data *pdata)
  65. {
  66. kfree(pdata->part_table);
  67. kfree(pdata);
  68. return 0;
  69. }
  70. /**
  71. * @brief 初始化gendisk结构体(暂时只支持1个gendisk)
  72. *
  73. */
  74. static int ahci_init_gendisk()
  75. {
  76. memset(&ahci_gendisk0, 0, sizeof(ahci_gendisk0));
  77. strcpy(ahci_gendisk0.disk_name, "ahci0");
  78. ahci_gendisk0.flags = BLK_GF_AHCI;
  79. ahci_gendisk0.fops = &ahci_operation;
  80. mutex_init(&ahci_gendisk0.open_mutex);
  81. ahci_gendisk0.request_queue = &ahci_req_queue;
  82. // 为存储分区结构,分配内存空间
  83. ahci_gendisk0.private_data = __alloc_private_data();
  84. // 读取分区表
  85. // 暂时假设全都是MBR分区表的
  86. // todo: 支持GPT
  87. ((struct ahci_blk_private_data *)ahci_gendisk0.private_data)->ahci_ctrl_num = 0;
  88. ((struct ahci_blk_private_data *)ahci_gendisk0.private_data)->ahci_port_num = __first_port;
  89. MBR_read_partition_table(&ahci_gendisk0, ((struct ahci_blk_private_data *)ahci_gendisk0.private_data)->part_table);
  90. struct MBR_disk_partition_table_t *ptable = ((struct ahci_blk_private_data *)ahci_gendisk0.private_data)->part_table;
  91. // 求出可用分区数量
  92. for (int i = 0; i < 4; ++i)
  93. {
  94. // 分区可用
  95. if (ptable->DPTE[i].type != 0)
  96. ++ahci_gendisk0.part_cnt;
  97. }
  98. if (ahci_gendisk0.part_cnt)
  99. {
  100. // 分配分区结构体数组的空间
  101. ahci_gendisk0.partition = (struct block_device *)kzalloc(ahci_gendisk0.part_cnt * sizeof(struct block_device), 0);
  102. int cnt = 0;
  103. // 循环遍历每个分区
  104. for (int i = 0; i < 4; ++i)
  105. {
  106. // 分区可用
  107. if (ptable->DPTE[i].type != 0)
  108. {
  109. // 初始化分区结构体
  110. ahci_gendisk0.partition[cnt].bd_disk = &ahci_gendisk0;
  111. ahci_gendisk0.partition[cnt].bd_partno = cnt;
  112. ahci_gendisk0.partition[cnt].bd_queue = &ahci_req_queue;
  113. ahci_gendisk0.partition[cnt].bd_sectors_num = ptable->DPTE[i].total_sectors;
  114. ahci_gendisk0.partition[cnt].bd_start_sector = ptable->DPTE[i].starting_sector;
  115. ahci_gendisk0.partition[cnt].bd_superblock = NULL; // 挂载文件系统时才会初始化superblock
  116. ahci_gendisk0.partition[cnt].bd_start_LBA = ptable->DPTE[i].starting_LBA;
  117. ++cnt;
  118. }
  119. }
  120. }
  121. return 0;
  122. };
  123. /**
  124. * @brief 初始化ahci模块
  125. *
  126. */
  127. void ahci_init()
  128. {
  129. kinfo("Initializing AHCI...");
  130. pci_get_device_structure(0x1, 0x6, ahci_devs, &count_ahci_devices);
  131. if (count_ahci_devices == 0)
  132. {
  133. kwarn("There is no AHCI device found on this computer!");
  134. return;
  135. }
  136. // 映射ABAR
  137. kdebug("phys_2_virt(ahci_devs[0])= %#018lx", (ahci_devs[0]));
  138. 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);
  139. uint32_t bar5 = ((struct pci_device_structure_general_device_t *)(ahci_devs[0]))->BAR5;
  140. mm_map_phys_addr(AHCI_MAPPING_BASE, (ul)(bar5)&PAGE_2M_MASK, PAGE_2M_SIZE, PAGE_KERNEL_PAGE | PAGE_PWT | PAGE_PCD, false);
  141. kdebug("ABAR mapped!");
  142. for (int i = 0; i < count_ahci_devices; ++i)
  143. {
  144. // 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);
  145. // 赋值HBA_MEM结构体
  146. ahci_devices[i].dev_struct = ahci_devs[i];
  147. ahci_devices[i].hba_mem = (HBA_MEM *)(cal_HBA_MEM_VIRT_ADDR(i));
  148. kdebug("ahci_devices[i].hba_mem = %#018lx", (ul)ahci_devices[i].hba_mem);
  149. }
  150. // todo: 支持多个ahci控制器。
  151. ahci_port_base_vaddr = (uint64_t)kmalloc(1048576, 0);
  152. kdebug("ahci_port_base_vaddr=%#018lx", ahci_port_base_vaddr);
  153. ahci_probe_port(0);
  154. // 初始化请求队列
  155. ahci_req_queue.in_service = NULL;
  156. wait_queue_init(&ahci_req_queue.wait_queue_list, NULL);
  157. ahci_req_queue.request_count = 0;
  158. BUG_ON(ahci_init_gendisk() != 0);
  159. kinfo("AHCI initialized.");
  160. }
  161. // Check device type
  162. static int check_type(HBA_PORT *port)
  163. {
  164. uint32_t ssts = port->ssts;
  165. uint8_t ipm = (ssts >> 8) & 0x0F;
  166. uint8_t det = ssts & 0x0F;
  167. if (det != HBA_PORT_DET_PRESENT) // Check drive status
  168. return AHCI_DEV_NULL;
  169. if (ipm != HBA_PORT_IPM_ACTIVE)
  170. return AHCI_DEV_NULL;
  171. switch (port->sig)
  172. {
  173. case SATA_SIG_ATAPI:
  174. return AHCI_DEV_SATAPI;
  175. case SATA_SIG_SEMB:
  176. return AHCI_DEV_SEMB;
  177. case SATA_SIG_PM:
  178. return AHCI_DEV_PM;
  179. default:
  180. return AHCI_DEV_SATA;
  181. }
  182. }
  183. /**
  184. * @brief 检测端口连接的设备的类型
  185. *
  186. * @param device_num ahci控制器号
  187. */
  188. static void ahci_probe_port(const uint32_t device_num)
  189. {
  190. HBA_MEM *abar = ahci_devices[device_num].hba_mem;
  191. uint32_t pi = abar->pi;
  192. for (int i = 0; i < 32; ++i, (pi >>= 1))
  193. {
  194. if (pi & 1)
  195. {
  196. uint dt = check_type(&abar->ports[i]);
  197. ahci_devices[i].type = dt;
  198. switch (dt)
  199. {
  200. case AHCI_DEV_SATA:
  201. kdebug("SATA drive found at port %d", i);
  202. goto found;
  203. case AHCI_DEV_SATAPI:
  204. kdebug("SATAPI drive found at port %d", i);
  205. goto found;
  206. case AHCI_DEV_SEMB:
  207. kdebug("SEMB drive found at port %d", i);
  208. goto found;
  209. case AHCI_DEV_PM:
  210. kdebug("PM drive found at port %d", i);
  211. goto found;
  212. found:;
  213. port_rebase(&ahci_devices[0].hba_mem->ports[i], i);
  214. if (__first_port == -1)
  215. __first_port = i;
  216. break;
  217. default:
  218. kdebug("No drive found at port %d", i);
  219. break;
  220. }
  221. }
  222. }
  223. }
  224. // Start command engine
  225. static void start_cmd(HBA_PORT *port)
  226. {
  227. // Wait until CR (bit15) is cleared
  228. while ((port->cmd) & HBA_PxCMD_CR)
  229. ;
  230. // Set FRE (bit4) and ST (bit0)
  231. port->cmd |= HBA_PxCMD_FRE;
  232. port->cmd |= HBA_PxCMD_ST;
  233. }
  234. // Stop command engine
  235. static void stop_cmd(HBA_PORT *port)
  236. {
  237. // Clear ST (bit0)
  238. port->cmd &= ~HBA_PxCMD_ST;
  239. // Clear FRE (bit4)
  240. port->cmd &= ~HBA_PxCMD_FRE;
  241. // Wait until FR (bit14), CR (bit15) are cleared
  242. while (1)
  243. {
  244. if (port->cmd & HBA_PxCMD_FR)
  245. continue;
  246. if (port->cmd & HBA_PxCMD_CR)
  247. continue;
  248. break;
  249. }
  250. }
  251. static void port_rebase(HBA_PORT *port, int portno)
  252. {
  253. // Before rebasing Port memory space, OS must wait for current pending commands to finish
  254. // and tell HBA to stop receiving FIS from the port. Otherwise an accidently incoming FIS may be
  255. // written into a partially configured memory area.
  256. stop_cmd(port); // Stop command engine
  257. // Command list offset: 1K*portno
  258. // Command list entry size = 32
  259. // Command list entry maxim count = 32
  260. // Command list maxim size = 32*32 = 1K per port
  261. port->clb = virt_2_phys(ahci_port_base_vaddr + (portno << 10));
  262. memset((void *)(phys_2_virt(port->clb)), 0, 1024);
  263. // FIS offset: 32K+256*portno
  264. // FIS entry size = 256 bytes per port
  265. port->fb = virt_2_phys(ahci_port_base_vaddr + (32 << 10) + (portno << 8));
  266. memset((void *)(phys_2_virt(port->fb)), 0, 256);
  267. // Command table offset: 40K + 8K*portno
  268. // Command table size = 256*32 = 8K per port
  269. HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)(phys_2_virt(port->clb));
  270. for (int i = 0; i < 32; ++i)
  271. {
  272. cmdheader[i].prdtl = 8; // 8 prdt entries per command table
  273. // 256 bytes per command table, 64+16+48+16*8
  274. // Command table offset: 40K + 8K*portno + cmdheader_index*256
  275. cmdheader[i].ctba = virt_2_phys((ahci_port_base_vaddr + (40 << 10) + (portno << 13) + (i << 8)));
  276. memset((void *)phys_2_virt(cmdheader[i].ctba), 0, 256);
  277. }
  278. start_cmd(port); // Start command engine
  279. }
  280. /**
  281. * @brief read data from SATA device using 48bit LBA address
  282. *
  283. * @param port HBA PORT
  284. * @param startl low 32bits of start addr
  285. * @param starth high 32bits of start addr
  286. * @param count total sectors to read
  287. * @param buf buffer
  288. * @return true done
  289. * @return false failed
  290. */
  291. static bool ahci_read(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count, uint64_t buf)
  292. {
  293. port->is = (uint32_t)-1; // Clear pending interrupt bits
  294. int spin = 0; // Spin lock timeout counter
  295. int slot = ahci_find_cmdslot(port);
  296. if (slot == -1)
  297. return E_NOEMPTYSLOT;
  298. HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)phys_2_virt(port->clb);
  299. cmdheader += slot;
  300. cmdheader->cfl = sizeof(FIS_REG_H2D) / sizeof(uint32_t); // Command FIS size
  301. cmdheader->w = 0; // Read from device
  302. cmdheader->prdtl = (uint16_t)((count - 1) >> 4) + 1; // PRDT entries count
  303. HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)phys_2_virt(cmdheader->ctba);
  304. memset(cmdtbl, 0, sizeof(HBA_CMD_TBL) + (cmdheader->prdtl - 1) * sizeof(HBA_PRDT_ENTRY));
  305. // 8K bytes (16 sectors) per PRDT
  306. int i;
  307. for (i = 0; i < cmdheader->prdtl - 1; ++i)
  308. {
  309. cmdtbl->prdt_entry[i].dba = virt_2_phys(buf);
  310. cmdtbl->prdt_entry[i].dbc = 8 * 1024 - 1; // 8K bytes (this value should always be set to 1 less than the actual value)
  311. cmdtbl->prdt_entry[i].i = 1;
  312. buf += 4 * 1024; // 4K uint16_ts
  313. count -= 16; // 16 sectors
  314. }
  315. // Last entry
  316. cmdtbl->prdt_entry[i].dba = virt_2_phys(buf);
  317. cmdtbl->prdt_entry[i].dbc = (count << 9) - 1; // 512 bytes per sector
  318. cmdtbl->prdt_entry[i].i = 1;
  319. // Setup command
  320. FIS_REG_H2D *cmdfis = (FIS_REG_H2D *)(&cmdtbl->cfis);
  321. cmdfis->fis_type = FIS_TYPE_REG_H2D;
  322. cmdfis->c = 1; // Command
  323. cmdfis->command = AHCI_CMD_READ_DMA_EXT;
  324. cmdfis->lba0 = (uint8_t)startl;
  325. cmdfis->lba1 = (uint8_t)(startl >> 8);
  326. cmdfis->lba2 = (uint8_t)(startl >> 16);
  327. cmdfis->device = 1 << 6; // LBA mode
  328. cmdfis->lba3 = (uint8_t)(startl >> 24);
  329. cmdfis->lba4 = (uint8_t)starth;
  330. cmdfis->lba5 = (uint8_t)(starth >> 8);
  331. cmdfis->countl = count & 0xFF;
  332. cmdfis->counth = (count >> 8) & 0xFF;
  333. // The below loop waits until the port is no longer busy before issuing a new command
  334. while ((port->tfd & (AHCI_DEV_BUSY | AHCI_DEV_DRQ)) && spin < 1000000)
  335. {
  336. spin++;
  337. }
  338. if (spin == 1000000)
  339. {
  340. kerror("Port is hung");
  341. return E_PORT_HUNG;
  342. }
  343. port->ci = 1 << slot; // Issue command
  344. current_pcb->flags |= PF_NEED_SCHED;
  345. sched();
  346. int retval = AHCI_SUCCESS;
  347. // Wait for completion
  348. while (1)
  349. {
  350. // In some longer duration reads, it may be helpful to spin on the DPS bit
  351. // in the PxIS port field as well (1 << 5)
  352. if ((port->ci & (1 << slot)) == 0)
  353. break;
  354. if (port->is & HBA_PxIS_TFES) // Task file error
  355. {
  356. kerror("Read disk error");
  357. retval = E_TASK_FILE_ERROR;
  358. break;
  359. }
  360. }
  361. // Check again
  362. if (port->is & HBA_PxIS_TFES)
  363. {
  364. kerror("Read disk error");
  365. retval = E_TASK_FILE_ERROR;
  366. }
  367. enter_syscall_int(SYS_AHCI_END_REQ, 0, 0, 0, 0, 0, 0, 0, 0);
  368. return retval;
  369. }
  370. static bool ahci_write(HBA_PORT *port, uint32_t startl, uint32_t starth, uint32_t count,
  371. uint64_t buf)
  372. {
  373. // kdebug("ahci write");
  374. port->is = 0xffff; // Clear pending interrupt bits
  375. int slot = ahci_find_cmdslot(port);
  376. if (slot == -1)
  377. return E_NOEMPTYSLOT;
  378. HBA_CMD_HEADER *cmdheader = (HBA_CMD_HEADER *)phys_2_virt(port->clb);
  379. cmdheader += slot;
  380. cmdheader->cfl = sizeof(FIS_REG_H2D) / sizeof(uint32_t); // Command FIS size
  381. cmdheader->w = 1;
  382. cmdheader->c = 1;
  383. cmdheader->p = 1;
  384. cmdheader->prdtl = (uint16_t)((count - 1) >> 4) + 1; // PRDT entries count
  385. HBA_CMD_TBL *cmdtbl = (HBA_CMD_TBL *)phys_2_virt(cmdheader->ctba);
  386. memset(cmdtbl, 0, sizeof(HBA_CMD_TBL) + (cmdheader->prdtl - 1) * sizeof(HBA_PRDT_ENTRY));
  387. int i = 0;
  388. for (i = 0; i < cmdheader->prdtl - 1; ++i)
  389. {
  390. cmdtbl->prdt_entry[i].dba = virt_2_phys(buf);
  391. cmdtbl->prdt_entry[i].dbc = 8 * 1024 - 1; // 8K bytes
  392. cmdtbl->prdt_entry[i].i = 0;
  393. buf += 4 * 1024; // 4K words
  394. count -= 16; // 16 sectors
  395. }
  396. cmdtbl->prdt_entry[i].dba = virt_2_phys(buf);
  397. cmdtbl->prdt_entry[i].dbc = count << 9; // 512 bytes per sector
  398. cmdtbl->prdt_entry[i].i = 0;
  399. FIS_REG_H2D *cmdfis = (FIS_REG_H2D *)(&cmdtbl->cfis);
  400. cmdfis->fis_type = FIS_TYPE_REG_H2D;
  401. cmdfis->c = 1; // Command
  402. cmdfis->command = AHCI_CMD_WRITE_DMA_EXT;
  403. cmdfis->lba0 = (uint8_t)startl;
  404. cmdfis->lba1 = (uint8_t)(startl >> 8);
  405. cmdfis->lba2 = (uint8_t)(startl >> 16);
  406. cmdfis->lba3 = (uint8_t)(startl >> 24);
  407. cmdfis->lba4 = (uint8_t)starth;
  408. cmdfis->lba5 = (uint8_t)(starth >> 8);
  409. cmdfis->device = 1 << 6; // LBA mode
  410. cmdfis->countl = count & 0xff;
  411. cmdfis->counth = count >> 8;
  412. // printk("[slot]{%d}", slot);
  413. port->ci = 1; // Issue command
  414. current_pcb->flags |= PF_NEED_SCHED;
  415. sched();
  416. int retval = AHCI_SUCCESS;
  417. while (1)
  418. {
  419. // In some longer duration reads, it may be helpful to spin on the DPS bit
  420. // in the PxIS port field as well (1 << 5)
  421. if ((port->ci & (1 << slot)) == 0)
  422. break;
  423. if (port->is & HBA_PxIS_TFES)
  424. { // Task file error
  425. kerror("Write disk error");
  426. retval = E_TASK_FILE_ERROR;
  427. break;
  428. }
  429. }
  430. if (port->is & HBA_PxIS_TFES)
  431. {
  432. kerror("Write disk error");
  433. retval = E_TASK_FILE_ERROR;
  434. }
  435. // kdebug("ahci write retval=%d", retval);
  436. enter_syscall_int(SYS_AHCI_END_REQ, 0, 0, 0, 0, 0, 0, 0, 0);
  437. return retval;
  438. }
  439. // Find a free command list slot
  440. static int ahci_find_cmdslot(HBA_PORT *port)
  441. {
  442. // If not set in SACT and CI, the slot is free
  443. uint32_t slots = (port->sact | port->ci);
  444. int num_of_cmd_clots = (ahci_devices[0].hba_mem->cap & 0x0f00) >> 8; // bit 12-8
  445. for (int i = 0; i < num_of_cmd_clots; i++)
  446. {
  447. if ((slots & 1) == 0)
  448. return i;
  449. slots >>= 1;
  450. }
  451. kerror("Cannot find free command list entry");
  452. return -1;
  453. }
  454. long ahci_open()
  455. {
  456. return 0;
  457. }
  458. long ahci_close()
  459. {
  460. return 0;
  461. }
  462. /**
  463. * @brief 创建ahci磁盘请求包
  464. *
  465. * @param cmd 控制命令
  466. * @param base_addr 48位LBA地址
  467. * @param count total sectors to read
  468. * @param buf 缓冲区线性地址
  469. * @param ahci_ctrl_num ahci控制器号
  470. * @param port_num ahci控制器端口号
  471. * @return struct block_device_request_packet*
  472. */
  473. static struct ahci_request_packet_t *ahci_make_request(long cmd, uint64_t base_addr, uint64_t count, uint64_t buffer, uint8_t ahci_ctrl_num, uint8_t port_num)
  474. {
  475. struct ahci_request_packet_t *pack = (struct ahci_request_packet_t *)kmalloc(sizeof(struct ahci_request_packet_t), 0);
  476. wait_queue_init(&pack->blk_pak.wait_queue, current_pcb);
  477. pack->blk_pak.device_type = BLK_TYPE_AHCI;
  478. // 由于ahci不需要中断即可读取磁盘,因此end handler为空
  479. switch (cmd)
  480. {
  481. case AHCI_CMD_READ_DMA_EXT:
  482. pack->blk_pak.end_handler = NULL;
  483. pack->blk_pak.cmd = AHCI_CMD_READ_DMA_EXT;
  484. break;
  485. case AHCI_CMD_WRITE_DMA_EXT:
  486. pack->blk_pak.end_handler = NULL;
  487. pack->blk_pak.cmd = AHCI_CMD_WRITE_DMA_EXT;
  488. break;
  489. default:
  490. pack->blk_pak.end_handler = NULL;
  491. pack->blk_pak.cmd = cmd;
  492. break;
  493. }
  494. pack->blk_pak.LBA_start = base_addr;
  495. pack->blk_pak.count = count;
  496. pack->blk_pak.buffer_vaddr = buffer;
  497. pack->ahci_ctrl_num = ahci_ctrl_num;
  498. pack->port_num = port_num;
  499. return pack;
  500. }
  501. /**
  502. * @brief 结束磁盘请求
  503. *
  504. */
  505. void ahci_end_request()
  506. {
  507. ahci_req_queue.in_service->wait_queue.pcb->state = PROC_RUNNING;
  508. // ahci_req_queue.in_service->wait_queue.pcb->flags |= PF_NEED_SCHED;
  509. // current_pcb->flags |= PF_NEED_SCHED;
  510. kfree((uint64_t *)ahci_req_queue.in_service);
  511. ahci_req_queue.in_service = NULL;
  512. // 进行下一轮的磁盘请求 (由于未实现单独的io调度器,这里会造成长时间的io等待)
  513. if (ahci_req_queue.request_count > 0)
  514. ahci_query_disk();
  515. }
  516. static long ahci_query_disk()
  517. {
  518. wait_queue_node_t *wait_queue_tmp = container_of(list_next(&ahci_req_queue.wait_queue_list.wait_list), wait_queue_node_t, wait_list);
  519. struct ahci_request_packet_t *pack = (struct ahci_request_packet_t *)container_of(wait_queue_tmp, struct block_device_request_packet, wait_queue);
  520. ahci_req_queue.in_service = (struct block_device_request_packet *)pack;
  521. list_del(&(ahci_req_queue.in_service->wait_queue.wait_list));
  522. --ahci_req_queue.request_count;
  523. // kdebug("ahci_query_disk");
  524. long ret_val = 0;
  525. switch (pack->blk_pak.cmd)
  526. {
  527. case AHCI_CMD_READ_DMA_EXT:
  528. ret_val = ahci_read(&(ahci_devices[pack->ahci_ctrl_num].hba_mem->ports[pack->port_num]), pack->blk_pak.LBA_start & 0xFFFFFFFF, ((pack->blk_pak.LBA_start) >> 32) & 0xFFFFFFFF, pack->blk_pak.count, pack->blk_pak.buffer_vaddr);
  529. break;
  530. case AHCI_CMD_WRITE_DMA_EXT:
  531. ret_val = ahci_write(&(ahci_devices[pack->ahci_ctrl_num].hba_mem->ports[pack->port_num]), pack->blk_pak.LBA_start & 0xFFFFFFFF, ((pack->blk_pak.LBA_start) >> 32) & 0xFFFFFFFF, pack->blk_pak.count, pack->blk_pak.buffer_vaddr);
  532. break;
  533. default:
  534. kerror("Unsupport ahci command: %#05lx", pack->blk_pak.cmd);
  535. ret_val = E_UNSUPPORTED_CMD;
  536. break;
  537. }
  538. // kdebug("ahci_query_disk: retval=%d", ret_val);
  539. // ahci_end_request();
  540. return ret_val;
  541. }
  542. /**
  543. * @brief 将请求包提交到io队列
  544. *
  545. * @param pack
  546. */
  547. static void ahci_submit(struct ahci_request_packet_t *pack)
  548. {
  549. list_append(&(ahci_req_queue.wait_queue_list.wait_list), &(pack->blk_pak.wait_queue.wait_list));
  550. ++ahci_req_queue.request_count;
  551. if (ahci_req_queue.in_service == NULL) // 当前没有正在请求的io包,立即执行磁盘请求
  552. ahci_query_disk();
  553. }
  554. /**
  555. * @brief ahci驱动程序的传输函数
  556. *
  557. * @param gd 磁盘设备结构体
  558. * @param cmd 控制命令
  559. * @param base_addr 48位LBA地址
  560. * @param count total sectors to read
  561. * @param buf 缓冲区线性地址
  562. * @return long
  563. */
  564. static long ahci_transfer(struct blk_gendisk *gd, long cmd, uint64_t base_addr, uint64_t count, uint64_t buf)
  565. {
  566. struct ahci_request_packet_t *pack = NULL;
  567. struct ahci_blk_private_data *pdata = (struct ahci_blk_private_data *)gd->private_data;
  568. if (cmd == AHCI_CMD_READ_DMA_EXT || cmd == AHCI_CMD_WRITE_DMA_EXT)
  569. {
  570. pack = ahci_make_request(cmd, base_addr, count, buf, pdata->ahci_ctrl_num, pdata->ahci_port_num);
  571. ahci_submit(pack);
  572. }
  573. else
  574. return E_UNSUPPORTED_CMD;
  575. return AHCI_SUCCESS;
  576. }
  577. /**
  578. * @brief todo: io控制器函数
  579. *
  580. * @param cmd 命令
  581. * @param arg 参数
  582. * @return long
  583. */
  584. static long ahci_ioctl(long cmd, long arg)
  585. {
  586. return 0;
  587. }