From: acevest Date: Tue, 24 Sep 2024 14:16:39 +0000 (+0800) Subject: 移除硬盘中断的后半部处理逻辑 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/doc/mdoc.7.txt?a=commitdiff_plain;h=07fb28fafe14d389b7a40bba5907aeaeb4ec13bf;p=kernel.git 移除硬盘中断的后半部处理逻辑 --- diff --git a/boot/cmdline.c b/boot/cmdline.c index b698e4c..dfb8c8b 100644 --- a/boot/cmdline.c +++ b/boot/cmdline.c @@ -39,12 +39,12 @@ void parse_cmdline(const char *cmdline) { assert(value[0] == 'h' && value[1] == 'd'); assert(value[2] >= 'a' && value[2] <= 'd'); - int disk_drv_no = value[2] - 'a'; + int disk_drvid = value[2] - 'a'; - uint32_t part_no = atoi(value + 3); - assert(part_no >= 1); + uint32_t partid = atoi(value + 3); + assert(partid >= 1); - system.root_dev = MAKE_DISK_DEV(disk_drv_no, part_no); + system.root_dev = MAKE_DISK_DEV(disk_drvid, partid); printk("root device %s [0x%08x]\n", value, system.root_dev); get_value("delay", value); diff --git a/drivers/ata.c b/drivers/ata.c index cf250fb..1904a6e 100644 --- a/drivers/ata.c +++ b/drivers/ata.c @@ -155,12 +155,13 @@ extern unsigned int IDE_CHL1_CTL_BASE; void ide_ata_init() { printk("IDE %04X %04X %04X %04X\n", IDE_CHL0_CMD_BASE, IDE_CHL1_CMD_BASE, IDE_CHL0_CTL_BASE, IDE_CHL1_CTL_BASE); for (int i = 0; i < MAX_IDE_DRIVE_CNT; i++) { - int drv_no = i; - int channel = drv_no >> 1; + int drvid = i; + int channel = drvid >> 1; memset(ide_drives + i, 0, sizeof(ide_drive_t)); - ide_drive_t *drv = ide_drives + drv_no; - drv->drv_no = drv_no; + ide_drive_t *drv = ide_drives + drvid; + drv->drvid = drvid; + drv->channel = channel; drv->ide_pci_controller = ide_pci_controller + channel; // https://wiki.osdev.org/ATA_PIO_Mode @@ -196,12 +197,12 @@ void ide_ata_init() { // 3. 等到status的DRQ位或ERR位设置 uint8_t status = 0; const char *ide_drive_type = "NONE"; - if (ata_read_identify(drv_no, 1, &status, identify)) { + if (ata_read_identify(drvid, 1, &status, identify)) { drv->present = 1; drv->type = IDE_DRIVE_TYPE_ATA; ide_drive_type = "ATA"; } else { - if (ata_read_identify_packet(drv_no, 1, &status, identify)) { + if (ata_read_identify_packet(drvid, 1, &status, identify)) { // printk("ATAPI DEVICE\n"); drv->present = 1; drv->type = IDE_DRIVE_TYPE_ATAPI; @@ -225,7 +226,7 @@ void ide_ata_init() { continue; } - // insl(REG_DATA(drv_no), identify, SECT_SIZE / sizeof(uint32_t)); + // insl(REG_DATA(drvid), identify, SECT_SIZE / sizeof(uint32_t)); // Bit 15: 0 表示 ATA 设备,1 表示 ATAPI 设备。 // Bit 14-8: 保留。 @@ -324,8 +325,8 @@ void ide_ata_init() { } for (int i = 0; i < MAX_IDE_DRIVE_CNT; i++) { - int drv_no = i; - ide_drive_t *drv = ide_drives + drv_no; + int drvid = i; + ide_drive_t *drv = ide_drives + drvid; if (drv->present) { assert(drv->dma == 1); // assert(drv->lba48 == 1); @@ -346,14 +347,25 @@ void ide_disk_read(dev_t dev, uint32_t sect_nr, uint32_t count, bbuffer_t *b) { } void tmp_ide_disk_read(dev_t dev, uint32_t sect_nr, uint32_t count, char *buf) { - disk_request_t r; - r.dev = dev; - r.command = DISK_REQ_READ; - r.pos = sect_nr; - r.count = count; - r.buf = buf; - r.bb = NULL; - send_disk_request(&r); + int ret = 0; + int retry = 3; + while (retry--) { + disk_request_t r; + r.dev = dev; + r.command = DISK_REQ_READ; + r.pos = sect_nr; + r.count = count; + r.buf = buf; + r.bb = NULL; + ret = send_disk_request(&r); + if (ret == 0) { + break; + } + } + + if (ret != 0) { + panic("read disk error"); + } } // mbr_ext_offset: 在MBR中的扩展分区记录里的偏移地址 @@ -361,13 +373,13 @@ void tmp_ide_disk_read(dev_t dev, uint32_t sect_nr, uint32_t count, char *buf) { void read_partition_table(ide_drive_t *drv, uint32_t mbr_ext_offset, uint64_t lba_partition_table, int depth) { // disk_request_t r; char *sect = kmalloc(SECT_SIZE, 0); - + memset(sect, 0xAA, SECT_SIZE); #if 1 - // part_no == 0 代表整块硬盘 - tmp_ide_disk_read(MAKE_DISK_DEV(drv->drv_no, 0), lba_partition_table, 1, sect); + // partid == 0 代表整块硬盘 + tmp_ide_disk_read(MAKE_DISK_DEV(drv->drvid, 0), lba_partition_table, 1, sect); #else - // part_no == 0 代表整块硬盘 - r.dev = MAKE_DISK_DEV(drv->drv_no, 0); + // partid == 0 代表整块硬盘 + r.dev = MAKE_DISK_DEV(drv->drvid, 0); r.command = DISK_REQ_READ; r.pos = lba_partition_table; r.count = 1; @@ -447,7 +459,7 @@ void ide_read_partions() { continue; } - printk("read ide drive %u\n", drv->drv_no); + printk("read ide drive %u\n", drv->drvid); read_partition_table(drv, 0, 0, 0); printk("--------------\n"); } @@ -495,6 +507,11 @@ void ata_dma_read_ext(int drvid, uint64_t pos, uint16_t count, void *dest) { assert(((dest_paddr + size - (size == 0 ? 0 : 1)) & _64K) == (dest_paddr & _64K)); #endif + uint8_t pci_status = inb(ide_ctrl->bus_status); + if (pci_status & PCI_IDE_STATUS_ACT) { + panic("Bus master IDE active"); + } + ide_ctrl->prdt[0].phys_addr = dest_paddr; ide_ctrl->prdt[0].byte_count = size; ide_ctrl->prdt[0].reserved = 0; diff --git a/drivers/ide.c b/drivers/ide.c index 2f955f5..c9d9193 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -134,14 +134,30 @@ void ide_irq_handler(unsigned int irq, pt_regs_t *regs, void *devid) { // printk("ide irq %d handler pci status: 0x%02x\n", irq, ata_pci_bus_status()); int channel = irq == ide_pci_controller[0].irq_line ? 0 : 1; +#if 0 // printk("ide[%d] irq %d handler\n", channel, irq); ide_pci_controller_t *ide_ctrl = ide_pci_controller + channel; + atomic_inc(&ide_ctrl->irq_cnt); ata_dma_stop(channel); add_irq_bh_handler(ide_irq_bh_handler, (void *)channel); +#endif + + const int drvid = (channel << 1); // 虚拟一个 + ide_pci_controller_t *ide_ctrl = ide_pci_controller + channel; + ide_ctrl->status = inb(REG_STATUS(drvid)); + ide_ctrl->pci_status = inb(ide_ctrl->bus_status); + + // 之前这里是用up()来唤醒磁盘任务 + // 但在中断的底半处理,不应该切换任务,因为会引起irq里的reenter问题,导致不能再进底半处理,也无法切换任务 + // 所以就移除了up()里的 schedule() + // 后来就改用完成量来通知磁盘任务,就不存在这个问题了 + + // complete会唤醒进程,但不会立即重新调度进程 + complete(&ide_ctrl->intr_complete); } unsigned int IDE_CHL0_CMD_BASE = 0x1F0; @@ -202,6 +218,9 @@ void ide_pci_init(pci_device_t *pci) { ide_pci_controller[i].bus_prdt = iobase + PCI_IDE_PRDT; ide_pci_controller[i].prdt = (prdte_t *)page2va(alloc_one_page(0)); + ide_pci_controller[i].status = 0; + ide_pci_controller[i].pci_status = 0; + ide_pci_controller[i].pci = pci; unsigned int irq_line = pci_read_config_byte(pci_cmd(pci, PCI_INTRLINE)); @@ -287,13 +306,13 @@ ide_drive_t *ide_get_drive(dev_t dev) { int major = DEV_MAJOR(dev); int minor = DEV_MINOR(dev); - int drv_no = (minor & 0xFFFF) >> 8; + int drvid = (minor & 0xFFFF) >> 8; assert(major == DEV_MAJOR_DISK); assert(minor >= 0); - assert(drv_no < MAX_IDE_DRIVE_CNT); + assert(drvid < MAX_IDE_DRIVE_CNT); - ide_drive_t *drv = ide_drives + drv_no; + ide_drive_t *drv = ide_drives + drvid; return drv; } diff --git a/drivers/ide.h b/drivers/ide.h index d79ba2e..c230c34 100644 --- a/drivers/ide.h +++ b/drivers/ide.h @@ -9,8 +9,10 @@ #pragma once +#include #include #include +#include #include #include #include @@ -178,6 +180,10 @@ typedef struct _ide_pci_controller { prdte_t *prdt; + // + uint8_t status; + uint8_t pci_status; + // 提出请求的任务用这个字段互斥地添加请求到request_queue // 同时也和disk任务互斥 mutex_t request_mutex; @@ -204,7 +210,9 @@ extern ide_pci_controller_t ide_pci_controller[NR_IDE_CONTROLLER]; typedef struct _ide_drive { int type; int present; - int drv_no; + int drvid; + int channel; + int dma; // 是否支持DMA int lba48; // 是否支持LBA48 uint64_t max_lba; diff --git a/include/disk.h b/include/disk.h index c63d184..90fc202 100644 --- a/include/disk.h +++ b/include/disk.h @@ -29,6 +29,8 @@ typedef struct disk_request { disk_request_cmd_t command; // 命令 list_head_t list; semaphore_t sem; + + int ret; } disk_request_t; typedef struct { @@ -39,4 +41,4 @@ typedef struct { semaphore_t sem; } disk_request_queue_t; -void send_disk_request(disk_request_t *r); +int send_disk_request(disk_request_t *r); diff --git a/include/fs.h b/include/fs.h index b96b7ee..5db8166 100644 --- a/include/fs.h +++ b/include/fs.h @@ -35,7 +35,7 @@ #define DEV_MINOR_MASK ((1UL << DEV_MAJOR_BITS) - 1) #define MAKE_DEV(major, minor) ((major) << DEV_MAJOR_BITS | minor) -#define MAKE_DISK_DEV(drv_no, part_no) MAKE_DEV(DEV_MAJOR_DISK, (((drv_no) & 0x03) << 8) | (((part_no) & 0xFF) << 0)) +#define MAKE_DISK_DEV(drvid, partid) MAKE_DEV(DEV_MAJOR_DISK, (((drvid) & 0x03) << 8) | (((partid) & 0xFF) << 0)) #define DEV_MAJOR(dev) ((unsigned int)((dev) >> DEV_MAJOR_BITS)) #define DEV_MINOR(dev) ((unsigned int)((dev) & DEV_MINOR_MASK)) diff --git a/kernel/task_disk.c b/kernel/task_disk.c index b5525ae..60d1ca3 100644 --- a/kernel/task_disk.c +++ b/kernel/task_disk.c @@ -13,10 +13,10 @@ #include void ata_read_identify(int drv, int disable_intr); -void ata_pio_read_data(int drv_no, int sect_cnt, void *dst); +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); -void send_disk_request(disk_request_t *r) { +int send_disk_request(disk_request_t *r) { if (NULL == r) { panic("null disk request"); } @@ -28,6 +28,8 @@ void send_disk_request(disk_request_t *r) { // 这个用来让task_disk唤醒自己 semaphore_init(&r->sem, 0); + r->ret = 0; + // 校验pos,和pos+count是否大于硬盘返回的最大LBA48 // ... @@ -57,6 +59,8 @@ void send_disk_request(disk_request_t *r) { // 等待被task_disk唤醒 down(&r->sem); + + return r->ret; } void disk_task_entry(void *arg) { @@ -87,7 +91,7 @@ void disk_task_entry(void *arg) { mutex_unlock(&ide_ctrl->request_mutex); ide_drive_t *drv = ide_get_drive(r->dev); - int drv_no = drv->drv_no; + int drvid = drv->drvid; if (drv->present == 0) { panic("disk not present"); } @@ -95,7 +99,7 @@ void disk_task_entry(void *arg) { int part_id = DEV_MINOR((r->dev)) & 0xFF; assert(part_id < MAX_DISK_PARTIONS); - assert(MAKE_DISK_DEV(drv_no, part_id) == r->dev); + 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); @@ -106,31 +110,31 @@ void disk_task_entry(void *arg) { panic("INVARG"); } - const bool pio_mode = true; + 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", drv_no); + printk("try to read disk drive %u identify\n", drvid); assert(r->count == 1); - ata_read_identify(drv_no, 0); + 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 drv_no %u pos %u count %u bb %x\n", drv_no, (uint32_t)pos, r->count, r->bb); + // 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(drv_no, pos, r->count, 100, r->bb->data); + ata_pio_read_ext(drvid, pos, r->count, 100, r->bb->data); } else { - ata_pio_read_ext(drv_no, pos, r->count, 100, r->buf); + ata_pio_read_ext(drvid, pos, r->count, 100, r->buf); } } else { if (r->bb != 0) { - ata_dma_read_ext(drv_no, pos, r->count, r->bb->data); + ata_dma_read_ext(drvid, pos, r->count, r->bb->data); } else { - ata_dma_read_ext(drv_no, pos, r->count, r->buf); + ata_dma_read_ext(drvid, pos, r->count, r->buf); } } break; @@ -139,14 +143,20 @@ void disk_task_entry(void *arg) { 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(drv_no, 1, r->buf); + ata_pio_read_data(drvid, 1, r->buf); } if (r->bb != 0) { @@ -154,6 +164,8 @@ void disk_task_entry(void *arg) { complete(&r->bb->io_done); } + r->ret = ret; + // 唤醒等待该请求的进程 up(&(r->sem)); }