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