]> Zhao Yanbai Git Server - kernel.git/commitdiff
disk进程支持处理硬盘读请求
authoracevest <zhaoyanbai@126.com>
Sun, 25 Jan 2026 08:19:52 +0000 (16:19 +0800)
committeracevest <zhaoyanbai@126.com>
Sun, 25 Jan 2026 08:19:52 +0000 (16:19 +0800)
drivers/ahci.c
drivers/sata.c
drivers/sata.h
include/disk.h
include/printk.h
kernel/ap.c
kernel/task_disk.c
kernel/task_init.c

index 65a8a2b6ba210cea81cd0278f023b9abea9d661c..087be6a8cf342ee03675c552cfe052155ecb0991 100644 (file)
@@ -174,6 +174,8 @@ void init_ahci_device(pci_device_t* pci, int index) {
 }
 
 void init_ahci() {
+    void init_disk_request_queue();
+    init_disk_request_queue();
     // progif
     // 0x01 AHCI
     pci_init_device(0x0106, 0x01, init_ahci_device);
index ff495a789dfee6203586835f3a558cb611b5dd1a..2f959abda68bcd14561206cc508dee4944ad11b2 100644 (file)
@@ -26,7 +26,7 @@ void init_sata_device(ahci_hba_t* hba, ahci_port_t* port, int port_index) {
 
     assert(hba != NULL);
     assert(port != NULL);
-    assert(port_index >= 0 && port_index < MAX_SATA_DEVICES);
+    assert(port_index >= 0 && port_index < AHCI_PORT_COUNT);
     assert(index >= 0 && index < MAX_SATA_DEVICES);
 
     sata_device_t* sata = sata_devices + index;
@@ -36,6 +36,8 @@ void init_sata_device(ahci_hba_t* hba, ahci_port_t* port, int port_index) {
     sata->index = index;
     sata->port_index = port_index;
 
+    init_completion(&sata->completion);
+
     printk("ahci port clb %08x fb %08x sata_status 0x%08X signature %08X\n", port->cmd_list_base, port->fis_base,
            port->sata_status, port->signature);
 
@@ -74,10 +76,6 @@ void init_sata_device(ahci_hba_t* hba, ahci_port_t* port, int port_index) {
     sata->cmd_table_vaddr = (ahci_cmd_table_t*)ioremap(sata->cmd_table_paddr, PAGE_SIZE);
     memset((void*)sata->cmd_table_vaddr, 0, PAGE_SIZE);
 
-    sata->data_paddr = (paddr_t)page2pa(alloc_one_page(0));
-    sata->data_vaddr = (vaddr_t)ioremap(sata->data_paddr, PAGE_SIZE);
-    memset((void*)sata->data_vaddr, 0, PAGE_SIZE);
-
     memset((void*)cmd_list, 0, sizeof(ahci_cmd_header_t));
     cmd_list[0].cfl = 0;
     cmd_list[0].a = 0;
@@ -106,9 +104,9 @@ void init_sata_device(ahci_hba_t* hba, ahci_port_t* port, int port_index) {
 
     max_sata_devices += 1;
 
-    memset(sector, 0xCC, 512);
-    sata_dma_read(sata, 0, 1, (paddr_t)va2pa(sector));
-    printk("sector %08x\n", (uint32_t*)sector);
+    // memset(sector, 0xCC, 512);
+    // sata_dma_read(sata, 0, 1, (paddr_t)va2pa(sector));
+    // printk("sector %08x\n", (uint32_t*)sector);
 }
 
 void sata_irq_handler(unsigned int irq, pt_regs_t* regs, void* dev_id) {
@@ -130,6 +128,8 @@ void sata_irq_handler(unsigned int irq, pt_regs_t* regs, void* dev_id) {
             //
         }
 
+        complete(&sata->completion);
+
         port->interrupt_status = interrupt_status;
     }
 
@@ -161,7 +161,7 @@ int sata_wait_ready(sata_device_t* sata) {
     return -1;
 }
 
-int sata_dma_read(sata_device_t* sata, uint64_t lba, uint32_t sectors, paddr_t paddr) {
+int sata_dma_read(sata_device_t* sata, uint64_t lba, uint32_t sectors, vaddr_t vaddr) {
     assert(sata != NULL);
     assert(sectors <= 4);
     assert(lba + sectors <= sata->max_lba);
@@ -177,7 +177,7 @@ int sata_dma_read(sata_device_t* sata, uint64_t lba, uint32_t sectors, paddr_t p
     }
 
     //
-    sata->prdte0->data_base = paddr;
+    sata->prdte0->data_base = va2pa(vaddr);
     sata->prdte0->data_byte_count = (bytes - 1) | 1;
     sata->prdte0->ioc = 1;
 
@@ -222,7 +222,12 @@ int sata_dma_read(sata_device_t* sata, uint64_t lba, uint32_t sectors, paddr_t p
 
 void sata_identify(sata_device_t* sata) {
     assert(sata != NULL);
-    sata->prdte0->data_base = sata->data_paddr;
+
+    paddr_t data_paddr = (paddr_t)page2pa(alloc_one_page(0));
+    vaddr_t data_vaddr = (vaddr_t)ioremap(data_paddr, PAGE_SIZE);
+    memset((void*)data_vaddr, 0, PAGE_SIZE);
+
+    sata->prdte0->data_base = data_paddr;
     sata->prdte0->data_byte_count = (512 - 1) | 1;
     sata->prdte0->ioc = 0;
 
@@ -238,7 +243,7 @@ void sata_identify(sata_device_t* sata) {
     sata->cmd_list0->prdtl = 1;
     sata->cmd_list0->w = 0;  // read
     sata->cmd_list0->a = 0;  // ata device
-    sata->cmd_list0->c = 1;
+    sata->cmd_list0->c = 1;  // 自动清除BSY位
     sata->cmd_list0->prd_byte_count = 0;
 
     // 清除中断状态
@@ -247,39 +252,45 @@ void sata_identify(sata_device_t* sata) {
     assert(port != NULL);
     port->interrupt_status = port->interrupt_status;
 
+#if 0
     //
     port->interrupt_enable = AHCI_INTERRUPT_ENABLE_DHRS;
+#endif
 
     //
     port->cmd_issue = 1 << 0;
 
     uint32_t timeout = 1000000;
     while (timeout--) {
+        if ((port->cmd_issue) & (1 << 0) == 0) {
+            break;
+        }
+        // 不启用中断也仍然会设置
         if (port->interrupt_status & 1) {
             printk("SATA INTERRUPT STATUS: %08x\n", port->interrupt_status);
             // 清除本次请求产生的中断
-            port->interrupt_status = 1;
+            port->interrupt_status = port->interrupt_status;
             break;
         }
         if (port->sata_error) {
             printk("SATA ERROR: %08x\n", port->sata_error);
-            return;
+            goto end;
         }
         asm("pause");
     }
 
     if (timeout == 0) {
         printk("SATA TIMEOUT\n");
-        return;
+        goto end;
     }
 
     if (sata->cmd_list0->prd_byte_count != 512) {
         printk("SATA PRD BYTE COUNT: %08x\n", sata->cmd_list0->prd_byte_count);
-        return;
+        goto end;
     }
 
-    printk("identify data %08x\n", sata->data_vaddr);
-    uint16_t* identify = (uint16_t*)sata->data_vaddr;
+    printk("identify data %08x\n", data_vaddr);
+    uint16_t* identify = (uint16_t*)data_vaddr;
 
     // 第49个word的第8个bit位表示是否支持DMA
     // 第83个word的第10个bit位表示是否支持LBA48,为1表示支持。
@@ -334,6 +345,10 @@ void sata_identify(sata_device_t* sata) {
 
     sata_read_identify_string(identify, 27, 46, s);
     printk("HD Model: %s\n", s);
+
+end:
+    iounmap(data_vaddr);
+    free_pages((unsigned long)pa2va(data_paddr));
 }
 
 void sata_read_identify_string(const uint16_t* identify, int bgn, int end, char* buf) {
index 9cd8a7528f74918fe62092d42b44ce3d5c33f5f0..db9c1736f8e6fbe1b84f6f8795d81937043e2204 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <ahci.h>
 #include <types.h>
+#include <completion.h>
 
 #define SATA_SIGNATURE_ATA 0x00000101
 #define SATA_SIGNATURE_ATAPI 0xEB140101
@@ -48,6 +49,8 @@ typedef struct {
     int lba48;  // 是否支持lba48
     uint64_t max_lba;
 
+    completion_t completion;
+
     // 虽然有32个cmd header,但只用第0个
     ahci_cmd_header_t* cmd_list_base_vaddr;
     vaddr_t fis_base_vaddr;
@@ -60,9 +63,9 @@ typedef struct {
     paddr_t prdte_paddr;
     vaddr_t prdte_vaddr;
 
-    // 分配一个数据页
-    paddr_t data_paddr;
-    vaddr_t data_vaddr;
+    // // 分配一个数据页
+    // paddr_t data_paddr;
+    // vaddr_t data_vaddr;
 
     // 第0个cmd header
     ahci_cmd_header_t* cmd_list0;
@@ -74,7 +77,7 @@ typedef struct {
 
 extern sata_device_t sata_devices[MAX_SATA_DEVICES];
 
-int sata_dma_read(sata_device_t* sata, uint64_t lba, uint32_t sectors, paddr_t paddr);
+int sata_dma_read(sata_device_t* sata, uint64_t lba, uint32_t sectors, vaddr_t vaddr);
 
 void sata_read_identify_string(const uint16_t* identify, int bgn, int end, char* buf);
 
index a0dd42f82bfb502a91686943c20974e8801f8570..63078d584d59969fd878fffbf388c934506526ea 100644 (file)
@@ -28,13 +28,22 @@ typedef struct disk_request {
     bbuffer_t* bb;
     disk_request_cmd_t command;  // 命令
     list_head_t list;
-    semaphore_t sem;
+    // semaphore_t r_sem;
+
+    completion_t completion;
 
     int ret;
 } disk_request_t;
 
 typedef struct {
-    uint32_t count;
+    uint64_t req_count;
+    uint64_t completed_count;
+
+    uint32_t count;  // TODO remove
+    uint32_t pending_count;
+
+    //
+    mutex_t mutex;
     list_head_t list;
 
     // 供disk任务睡眠和被唤醒用
index 90f21e9cbf9f1b6dc554a9cad0598e1d332996fb..338ea7f1d7b1c9a2a155d406d9307c1b27e5a9a1 100644 (file)
@@ -50,8 +50,9 @@ enum {
 // monitor print offset
 enum {
     MPO_HPET = 1,
-    MPO_AP_CLOCK = 28,
-    MPO_KEYBOARD = 48,
+    MPO_AP_CLOCK = 20,
+    MPO_DISK = 36,
+    MPO_KEYBOARD = 54,
     MPO_IDE = 1,
 };
 
index a2bd36e7f1ed2e8fee850763bc6c2036d21aaf15..23bcfc43f55cd89dedef1c72327dad97e3acd584 100644 (file)
@@ -15,6 +15,7 @@
 #include <msr.h>
 #include <cpuid.h>
 #include <hpet.h>
+#include <disk.h>
 
 extern pde_t* ap_pre_pgd;
 
@@ -271,6 +272,10 @@ void _system_monitor() {
     //
     printlxy(MPL_IRQ, MPO_AP_CLOCK, "AP: %lu", ap_lapic_ticks);
 
+    extern disk_request_queue_t disk_request_queue;
+    disk_request_queue_t* drq = &disk_request_queue;
+    printlxy(MPL_IRQ, MPO_DISK, "DISK: %lu/%u/%lu", drq->req_count, drq->pending_count, drq->completed_count);
+
     //
     void print_all_tasks();
     print_all_tasks();
index f3ffcfd7f0c85667cd0a16a452177e8ca05f5e67..680c6a1973b0f596faba86d90940a43caf1b1371 100644 (file)
  * ------------------------------------------------------------------------
  *   File Name: task_disk.c
  *      Author: Zhao Yanbai
- *              2021-11-15 12:19:00 Monday CST
+ *              2026-01-25 09:53:51 Sunday CST
  * Description: none
  * ------------------------------------------------------------------------
  */
 
-#include <completion.h>
 #include <disk.h>
-#include <ide.h>
-#include <sched.h>
-
-void ata_read_identify(int drv, int disable_intr);
-void ata_pio_read_data(int drvid, int sect_cnt, void* dst);
-void ata_dma_read_ext(int drv, uint64_t pos, uint16_t count, void* dest);
-
-int send_disk_request(disk_request_t* r) {
-#if DISABLE_IDE
-    return 0;
-#endif
-    if (NULL == r) {
-        panic("null disk request");
-    }
-
-    ide_drive_t* drv = ide_get_drive(r->dev);
-
-    assert(drv->present == 1);
-
-    // 这个用来让task_disk唤醒自己
-    semaphore_init(&r->sem, 0);
+#include <completion.h>
+#include <sata.h>
+// #include
 
-    r->ret = 0;
+disk_request_queue_t disk_request_queue;
 
-    // 校验pos,和pos+count是否大于硬盘返回的最大LBA48
-    // ...
+void init_disk_request_queue() {
+    INIT_LIST_HEAD(&disk_request_queue.list);
+    mutex_init(&disk_request_queue.mutex);
+    semaphore_init(&disk_request_queue.sem, 0);
+}
 
-    // 校验buffer是否跨64K
-    // 先不处理
+int send_disk_request(disk_request_t* req) {
+    assert(req != NULL);
+    assert(req->count != 0);
+    assert(req->buf != NULL);
 
-#if 1
     {
-        const uint32_t size = r->count * 512;
+        const uint32_t size = req->count * 512;
         const uint32_t _64K = 1 << 16;
-        assert(((((uint32_t)r->buf) & (_64K - 1)) + size) <= _64K);
+        assert(((((uint32_t)req->buf) & (_64K - 1)) + size) <= _64K);
     }
-#else
-    if (((uint32_t)r->buf & 0xFFFF0000) != (((uint32_t)(r->buf + r->count * 512 - 1)) & 0xFFFF0000)) {
-        printk("dma read addr %08x count %d\n", r->buf, r->count);
-        panic("disk DMA read cross 64K");
-    }
-#endif
 
-    mutex_lock(&drv->ide_pci_controller->request_mutex);
-    atomic_inc(&drv->ide_pci_controller->request_cnt);
-    list_add_tail(&r->list, &drv->ide_pci_controller->request_queue.list);
-    mutex_unlock(&drv->ide_pci_controller->request_mutex);
+    init_completion(&req->completion);
 
-    // 唤醒task_disk
-    up(&drv->ide_pci_controller->request_queue.sem);
+    //
+    mutex_lock(&disk_request_queue.mutex);
+    list_add_tail(&req->list, &disk_request_queue.list);
+    disk_request_queue.req_count++;
+    disk_request_queue.pending_count++;
+    mutex_unlock(&disk_request_queue.mutex);
 
-    // 等待被task_disk唤醒
-    down(&r->sem);
+    //
+    up(&disk_request_queue.sem);
 
-    return r->ret;
-}
+    //
+    wait_completion(&req->completion);
 
-void disk_task_entry(void* arg) {
-    int r_cnt = 0;
-    while (1) {
-        int channel = (int)arg;
-        ide_pci_controller_t* ide_ctrl = ide_pci_controller + channel;
-
-#if 1
-        // 为了在DEBUG时看到RUN
-        int cnt = 2;
-        for (int i = 0; i < cnt; i++) {
-            asm("hlt;");
-        }
-#endif
+    return 0;
+}
 
-        // printk("wait request for hard disk channel %d\n", channel);
-        down(&ide_ctrl->request_queue.sem);
-        // printk("hard disk channel %d\n", channel);
+void disk_request(disk_request_t* req) {
+    int minor = DEV_MINOR(req->dev);
+    printk("disk_request dev %x minor %d\n", req->dev, minor);
+    assert(minor == 0);  // 先简单支持
+    assert(req->command == DISK_REQ_READ);
 
-        mutex_lock(&ide_ctrl->request_mutex);
-        disk_request_t* r;
-        r = list_first_entry(&ide_ctrl->request_queue.list, disk_request_t, list);
-        if (NULL == r) {
-            panic("no disk request");
-        }
+    sata_device_t* sata = &sata_devices[0];
 
-        list_del(&r->list);
-        atomic_inc(&ide_ctrl->consumed_cnt);
-        mutex_unlock(&ide_ctrl->request_mutex);
+    //
+    init_completion(&sata->completion);
 
-        ide_drive_t* drv = ide_get_drive(r->dev);
-        int drvid = drv->drvid;
-        if (drv->present == 0) {
-            panic("disk not present");
-        }
-        assert(drv->present == 1);
-
-        int part_id = DEV_MINOR((r->dev)) & 0xFF;
-        assert(part_id < MAX_DISK_PARTIONS);
-        assert(MAKE_DISK_DEV(drvid, part_id) == r->dev);
-
-        uint64_t pos = r->pos + drv->partions[part_id].lba_start;
-        // printk("pos %lu partid %d lba end %lu\n", pos, part_id, drv->partions[part_id].lba_end);
-        // assert(pos < drv->partions[part_id].lba_end);
-        if ((pos >= drv->partions[part_id].lba_end)) {
-            printk("pos %lu partid %d lba %lu %lu\n", pos, part_id, drv->partions[part_id].lba_start,
-                   drv->partions[part_id].lba_end);
-            panic("INVARG");
-        }
+    sata_dma_read(sata, req->pos, req->count, (vaddr_t)req->buf);
 
-        const bool pio_mode = false;
-        init_completion(&ide_ctrl->intr_complete);
-
-        switch (r->command) {
-        case DISK_REQ_IDENTIFY:
-            printk("try to read disk drive %u identify\n", drvid);
-            assert(r->count == 1);
-            ata_read_identify(drvid, 0);
-            break;
-        case DISK_REQ_READ:
-            assert(r->count > 0);
-            assert(r->buf != NULL || r->bb->data != NULL);
-            // printk("DISK READ drvid %u pos %u count %u bb %x\n", drvid, (uint32_t)pos, r->count, r->bb);
-            if (pio_mode) {
-                int ata_pio_read_ext(int drvid, uint64_t pos, uint16_t count, int timeout, void* dest);
-                if (r->bb != 0) {
-                    ata_pio_read_ext(drvid, pos, r->count, 100, r->bb->data);
-                } else {
-                    ata_pio_read_ext(drvid, pos, r->count, 100, r->buf);
-                }
-            } else {
-                if (r->bb != 0) {
-                    ata_dma_read_ext(drvid, pos, r->count, r->bb->data);
-                } else {
-                    ata_dma_read_ext(drvid, pos, r->count, r->buf);
-                }
-            }
-            break;
-        default:
-            panic("invalid disk request command");
-            break;
-        }
+    wait_completion(&sata->completion);
+}
 
-        int ret = 0;
-        if (!pio_mode) {
-            // 等待硬盘中断
-            wait_completion(&ide_ctrl->intr_complete);
+void disk_task_entry() {
+    while (1) {
+        down(&disk_request_queue.sem);
 
-            if ((ide_ctrl->status & (ATA_STATUS_BSY | ATA_STATUS_BSY | ATA_STATUS_WF)) != 0) {
-                printk("IDE status %02X error for drv %u pos %lu count %u\n", ide_ctrl->status, drvid, pos, r->count);
-                ret = -1;
-            }
-        }
+        mutex_lock(&disk_request_queue.mutex);
+        assert(!list_empty(&disk_request_queue.list));
+        disk_request_t* req = list_first_entry(&disk_request_queue.list, disk_request_t, list);
+        list_del(&req->list);
+        disk_request_queue.pending_count--;
+        mutex_unlock(&disk_request_queue.mutex);
 
-        // 读数据
-        if (DISK_REQ_IDENTIFY == r->command) {
-            ata_pio_read_data(drvid, 1, r->buf);
-        }
+        //
+        disk_request(req);
 
-        if (r->bb != 0) {
-            r->bb->uptodate = 1;
-            complete(&r->bb->io_done);
-        }
+        //
+        complete(&req->completion);
 
-        r->ret = ret;
+        disk_request_queue.completed_count++;  // 不需要保护
 
-        // 唤醒等待该请求的进程
-        up(&(r->sem));
+        for (int i = 0; i < 123; i++) {
+            asm("hlt");
+        }
     }
 }
index 2dab08b028d1f2c23d89c24d8d21320aeca975f1..88d67248ea3d0b32a6a869740db97a86029aed0a 100644 (file)
@@ -195,9 +195,8 @@ void init_task_entry() {
 #endif
 
 #if 1
-#if !DISABLE_IDE
-    kernel_task("ide/1", disk_task_entry, (void*)1);
-#endif
+
+    kernel_task("disk", disk_task_entry, NULL);
     kernel_task("user", user_task_entry, NULL);
     kernel_task("tskA", taskA_entry, NULL);
     kernel_task("tskB", taskB_entry, NULL);