]> Zhao Yanbai Git Server - kernel.git/commitdiff
在发送读硬盘命令前和wait的时候关中断,解决硬盘中断快于wait的问题
authoracevest <zhaoyanbai@126.com>
Thu, 18 Nov 2021 09:13:19 +0000 (17:13 +0800)
committeracevest <zhaoyanbai@126.com>
Thu, 18 Nov 2021 09:13:19 +0000 (17:13 +0800)
drivers/ata.c
drivers/ide.c
drivers/ide.h
include/wait.h
kernel/task_disk.c

index 156c7c747e13ffeccee6277b6794c5b9d692b1e0..344d5791ccfc0e4a1d834b462ed00dca2344bd1d 100644 (file)
@@ -50,7 +50,7 @@ void ata_read_identify(int dev) {  // 这里所用的dev是逻辑编号 ATA0、A
     // DECLARE_WAIT_QUEUE_HEAD(wq_head);
     // DECLARE_WAIT_QUEUE(wait, current);
     // add_wait_queue(&wq_head, &wait);
-    ide_pci_controller.task = current;
+    // ide_pci_controller.task = current;
 
     outb(0x00, REG_CTL(dev));
     outb(0x00 | ((dev & 0x01) << 4), REG_DEVICE(dev));  // 根据文档P113,这里不用指定bit5, bit7,直接指示DRIVE就行
@@ -58,15 +58,11 @@ void ata_read_identify(int dev) {  // 这里所用的dev是逻辑编号 ATA0、A
     unsigned long flags;
     irq_save(flags);
 
-    current->state = TASK_WAIT;
     outb(ATA_CMD_IDENTIFY, REG_CMD(dev));
+    wait_on_ide();
 
     irq_restore(flags);
 
-    schedule();
-
-    // del_wait_queue(&wq_head, &wait);
-
     insw(REG_DATA(dev), identify, SECT_SIZE / sizeof(u16));
 
     // 第49个word的第8个bit位表示是否支持DMA
index 14e6cbe91e66325e92efc779b99d6ae3c7b12374..781b28ec16678cd3f41331ca6dc5677e418e37bf 100644 (file)
@@ -537,6 +537,7 @@ void ata_read_identify(int dev);
 DECLARE_WAIT_QUEUE_HEAD(ide_wait_queue_head);
 
 void sleep_on_ide() { sleep_on(&ide_wait_queue_head); }
+void wait_on_ide() { wait_event(&ide_wait_queue_head, ide_pci_controller.done); }
 
 extern void *mbr_buf;
 uint8_t ata_pci_bus_status();
@@ -560,13 +561,16 @@ void ide_irq_handler(unsigned int irq, pt_regs_t *regs, void *devid) {
     }
 #endif
 
-    // wake_up(&ide_wait_queue_head);
+    ide_pci_controller.done = 1;
 
-    ide_pci_controller.task->state = TASK_RUNNING;
+    wake_up(&ide_wait_queue_head);
+
+    // ide_pci_controller.task->state = TASK_RUNNING;
 }
 
 void ide_init() {
     // memset((void *)&drv, 0, sizeof(drv));
+    memset(&ide_pci_controller, 0, sizeof(ide_pci_controller));
 
     request_irq(0x0E, ide_irq_handler, "hard", "IDE");
 
index 62979d14751535ec8f8a71542c5d143670b7ec25..46df6c09ed413267406e6fe47f18a1e8e106a321 100644 (file)
@@ -178,6 +178,8 @@ typedef struct _ide_pci_controller {
     // 这里应该改成一个请求链表
     // 先简单实现
     task_union *task;
+    int done;
 } ide_pci_controller_t;
 
-void sleep_on_ide();
\ No newline at end of file
+void sleep_on_ide();
+void wait_on_ide();
\ No newline at end of file
index 7fe371a9538890f92085a899252300c4eafa9ce4..616634edacb23783b1c14d128f6602db970bc240 100644 (file)
@@ -40,17 +40,18 @@ void __end_wait(wait_queue_head_t *head, wait_queue_t *wq);
 void sleep_on(wait_queue_head_t *head);
 void wake_up(wait_queue_head_t *head);
 
-#define __wait_event(head, condition)        \
-    do {                                     \
-        DECLARE_WAIT_QUEUE(__wait, current); \
-        while (1) {                          \
-            __do_wait(head, wa, TASK_WAIT);  \
-            if ((condition)) {               \
-                break;                       \
-            }                                \
-            schedule();                      \
-        }                                    \
-        __end_wait(head, &__wait);           \
+unsigned long schedule();
+#define __wait_event(head, condition)            \
+    do {                                         \
+        DECLARE_WAIT_QUEUE(__wait, current);     \
+        while (1) {                              \
+            __do_wait(head, &__wait, TASK_WAIT); \
+            if ((condition)) {                   \
+                break;                           \
+            }                                    \
+            schedule();                          \
+        }                                        \
+        __end_wait(head, &__wait);               \
     } while (0)
 
 #define wait_event(head, condition)          \
index 5ba8cbba661d802032642935f43e9cd260e17c74..02ca8cbd40f2ecb9268bba41a0f1f69574232089 100644 (file)
@@ -8,11 +8,61 @@
  */
 
 #include <sched.h>
+#include <wait.h>
+#if 0
+
+typedef enum {
+    DISK_REQ_IDENTIFY,
+    DISK_REQ_READ,
+} disk_request_cmd_t;
+
+typedef struct disk_request {
+    uint64_t pos;                // 扇区号
+    uint16_t count;              // 扇区数
+    void *buf;                   // 到的缓冲区
+    disk_request_cmd_t command;  // 命令
+    wait_queue_head_t wait;      // 等待队列
+    // 驱动器完全有可能在进程在进程睡眠到等待队列前返回数据并执行唤醒操作
+    // 这时等待队列上无进程,就相当于不执行任何操作
+    // 然后进程再睡眠到等待队列上,就会造成永远无法唤醒该进程
+    // 因此要添加一个字段,标志驱动器已经对该请求做过唤醒操作
+    // 进程在睡眠前需要检查该字段
+    int done;
+} disk_request_t;
+
+void send_disk_request() {
+    disk_request_t r;
+    r.pos = 0;
+    r.count = 1;
+    r.buf = kmalloc(512, 0);
+    r.command = DISK_REQ_IDENTIFY;
+    INIT_LIST_HEAD(&r.wait.task_list);
+    r.done = 0;
+
+    list_add_tail(&wq->task_list, &head->task_list);
+
+    // 发送命令
+    //....
+
+    unsigned long flags;
+    irq_save(flags);
+    if (0 == r.done) {  // 驱动器还没完成
+        set_current_state(TASK_WAIT);
+        irq_restore(flags);
+        // 就算在schedule前驱动器触发中断也没有问题
+        // 因为该进程已经加到等待队列上了
+        // 所以它一定以唤醒该进程
+        schedule();
+    } else {  // 驱动器已经完成
+        irq_restore(flags);
+    }
+}
+#endif
 
 void disk_task_entry() {
     while (1) {
-       // TODO
-       asm("hlt;");
-        //schedule();
+        // TODO
+        asm("hlt;");
+        // schedule();
     }
 }