ahci.c 17 KB

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