From a8d3fa418ba5f9b9e786b16bd82b596e7e7a4e2e Mon Sep 17 00:00:00 2001 From: acevest Date: Sun, 25 Jan 2026 16:19:52 +0800 Subject: [PATCH] =?utf8?q?disk=E8=BF=9B=E7=A8=8B=E6=94=AF=E6=8C=81?= =?utf8?q?=E5=A4=84=E7=90=86=E7=A1=AC=E7=9B=98=E8=AF=BB=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/ahci.c | 2 + drivers/sata.c | 51 ++++++++---- drivers/sata.h | 11 ++- include/disk.h | 13 ++- include/printk.h | 5 +- kernel/ap.c | 5 ++ kernel/task_disk.c | 200 +++++++++++++-------------------------------- kernel/task_init.c | 5 +- 8 files changed, 120 insertions(+), 172 deletions(-) diff --git a/drivers/ahci.c b/drivers/ahci.c index 65a8a2b..087be6a 100644 --- a/drivers/ahci.c +++ b/drivers/ahci.c @@ -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); diff --git a/drivers/sata.c b/drivers/sata.c index ff495a7..2f959ab 100644 --- a/drivers/sata.c +++ b/drivers/sata.c @@ -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) { diff --git a/drivers/sata.h b/drivers/sata.h index 9cd8a75..db9c173 100644 --- a/drivers/sata.h +++ b/drivers/sata.h @@ -11,6 +11,7 @@ #include #include +#include #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); diff --git a/include/disk.h b/include/disk.h index a0dd42f..63078d5 100644 --- a/include/disk.h +++ b/include/disk.h @@ -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任务睡眠和被唤醒用 diff --git a/include/printk.h b/include/printk.h index 90f21e9..338ea7f 100644 --- a/include/printk.h +++ b/include/printk.h @@ -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, }; diff --git a/kernel/ap.c b/kernel/ap.c index a2bd36e..23bcfc4 100644 --- a/kernel/ap.c +++ b/kernel/ap.c @@ -15,6 +15,7 @@ #include #include #include +#include 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(); diff --git a/kernel/task_disk.c b/kernel/task_disk.c index f3ffcfd..680c6a1 100644 --- a/kernel/task_disk.c +++ b/kernel/task_disk.c @@ -2,176 +2,90 @@ * ------------------------------------------------------------------------ * 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 #include -#include -#include - -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 +#include +// #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"); + } } } diff --git a/kernel/task_init.c b/kernel/task_init.c index 2dab08b..88d6724 100644 --- a/kernel/task_init.c +++ b/kernel/task_init.c @@ -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); -- 2.47.0