From 40fd8225c1bb812e7fab51193c31094420150868 Mon Sep 17 00:00:00 2001 From: acevest Date: Sun, 25 Jan 2026 16:22:22 +0800 Subject: [PATCH] =?utf8?q?=E5=A4=87=E4=BB=BDtask=5Fdisk.c=E5=8E=9Fide?= =?utf8?q?=E7=9A=84=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- kernel/task_ide.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 kernel/task_ide.c diff --git a/kernel/task_ide.c b/kernel/task_ide.c new file mode 100644 index 0000000..6b549fb --- /dev/null +++ b/kernel/task_ide.c @@ -0,0 +1,179 @@ +/* + * ------------------------------------------------------------------------ + * File Name: task_disk.c + * Author: Zhao Yanbai + * 2021-11-15 12:19:00 Monday CST + * Description: none + * ------------------------------------------------------------------------ + */ + +#include +#include +#include +#include + +#if 0 +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); + + r->ret = 0; + + // 校验pos,和pos+count是否大于硬盘返回的最大LBA48 + // ... + + // 校验buffer是否跨64K + // 先不处理 + +#if 1 + { + const uint32_t size = r->count * 512; + const uint32_t _64K = 1 << 16; + assert(((((uint32_t)r->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); + + // 唤醒task_disk + up(&drv->ide_pci_controller->request_queue.sem); + + // 等待被task_disk唤醒 + down(&r->sem); + + return r->ret; +} + +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 + + // printk("wait request for hard disk channel %d\n", channel); + down(&ide_ctrl->request_queue.sem); + // printk("hard disk channel %d\n", channel); + + 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"); + } + + list_del(&r->list); + atomic_inc(&ide_ctrl->consumed_cnt); + mutex_unlock(&ide_ctrl->request_mutex); + + 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"); + } + + 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; + } + + int ret = 0; + if (!pio_mode) { + // 等待硬盘中断 + wait_completion(&ide_ctrl->intr_complete); + + 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; + } + } + + // 读数据 + if (DISK_REQ_IDENTIFY == r->command) { + ata_pio_read_data(drvid, 1, r->buf); + } + + if (r->bb != 0) { + r->bb->uptodate = 1; + complete(&r->bb->io_done); + } + + r->ret = ret; + + // 唤醒等待该请求的进程 + up(&(r->sem)); + } +} +#endif -- 2.47.0