]> Zhao Yanbai Git Server - kernel.git/commitdiff
移除硬盘中断的后半部处理逻辑
authoracevest <zhaoyanbai@126.com>
Tue, 24 Sep 2024 14:16:39 +0000 (22:16 +0800)
committeracevest <zhaoyanbai@126.com>
Tue, 24 Sep 2024 14:16:39 +0000 (22:16 +0800)
boot/cmdline.c
drivers/ata.c
drivers/ide.c
drivers/ide.h
include/disk.h
include/fs.h
kernel/task_disk.c

index b698e4c0b1e111f8e0753b63e1f12edae0e8407d..dfb8c8bca6728ed70f67831feaf99bc691e6b85e 100644 (file)
@@ -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);
index cf250fb5da3140018a081e99873012d9b8b6b067..1904a6e3bf3bcbab9c653982aee64b2056987995 100644 (file)
@@ -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;
index 2f955f509b13e3f611289d7ca4716c4b21bda862..c9d9193f4dea13267ede3e16fa039238e6d2e0dd 100644 (file)
@@ -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;
 }
index d79ba2eb0f25f424af49aa36acb17b486eb2a94a..c230c34e2d28f780a0b0a253b0f84bc33a1a2fa6 100644 (file)
@@ -9,8 +9,10 @@
 
 #pragma once
 
+#include <ata.h>
 #include <atomic.h>
 #include <disk.h>
+#include <io.h>
 #include <pci.h>
 #include <semaphore.h>
 #include <system.h>
@@ -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;
index c63d184eaa1317bb5f1889fc8d8d0f1df4271a88..90fc202056e66ca22ae26cd9401a4ca0aa4700e0 100644 (file)
@@ -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);
index b96b7eee3f3fe8cd02b05f24740e72bdfaca48e8..5db8166d85a930a60d9785c59d0829e735dde426 100644 (file)
@@ -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))
index b5525ae821b0e6e0fcca9609d56cd56d1b7729e6..60d1ca30a0ebd075bd9e1e7e0670ef3d99dae989 100644 (file)
 #include <sched.h>
 
 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));
     }