ahci.c 21 KB

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