]> Zhao Yanbai Git Server - kernel.git/commitdiff
支持IDE Primary Secondary两个通道同时读硬盘
authoracevest <zhaoyanbai@126.com>
Mon, 5 Jun 2023 06:01:50 +0000 (14:01 +0800)
committeracevest <zhaoyanbai@126.com>
Mon, 5 Jun 2023 06:01:50 +0000 (14:01 +0800)
12 files changed:
drivers/ata.c
drivers/ide.c
drivers/ide.h
drivers/keyboard.c
include/atomic.h
include/disk.h
include/printk.h
kernel/clock.c
kernel/irq.c
kernel/setup.c
kernel/task_disk.c
kernel/task_root.c

index e7422e116f303aa001453afa9e99ca2b9978e95d..30cf4d2ad1112bb387ce6e8cb965cc6c24838bcf 100644 (file)
@@ -15,8 +15,6 @@
 #include <string.h>
 #include <system.h>
 
-extern ide_pci_controller_t ide_pci_controller[];
-
 ide_drive_t ide_drives[MAX_IDE_DRIVE_CNT];
 
 #define ATA_TIMEOUT 10  // 10次时钟中断
@@ -75,15 +73,11 @@ void ata_read_identity_string(const uint16_t *identify, int bgn, int end, char *
 void ide_ata_init() {
     for (int i = 0; i < MAX_IDE_DRIVE_CNT; i++) {
         int drv_no = i;
+        int channel = drv_no >> 1;
         memset(ide_drives + i, 0, sizeof(ide_drive_t));
 
         ide_drive_t *drv = ide_drives + drv_no;
-
-        INIT_MUTEX(&drv->request_mutex);
-
-        drv->request_queue.count = 0;
-        INIT_LIST_HEAD(&drv->request_queue.list);
-        semaphore_init(&drv->request_queue.sem, 0);
+        drv->ide_pci_controller = ide_pci_controller + channel;
 
         // https://wiki.osdev.org/ATA_PIO_Mode
         // To use the IDENTIFY command, select a target drive by sending 0xA0 for the master drive, or 0xB0 for the
@@ -263,10 +257,10 @@ void ata_dma_read_ext(int drv, uint64_t pos, uint16_t count, void *dest) {
 
     int channel = (drv >> 1) & 0x01;
     assert(channel == 0 || channel == 1);
-    ide_pci_controller_t *pci = ide_pci_controller + channel;
+    ide_pci_controller_t *ide_ctrl = ide_pci_controller + channel;
 
     // 停止DMA
-    outb(PCI_IDE_CMD_STOP, pci->bus_cmd);
+    outb(PCI_IDE_CMD_STOP, ide_ctrl->bus_cmd);
 
     // 配置描述符表
     unsigned long dest_paddr = va2pa(dest);
@@ -276,19 +270,19 @@ void ata_dma_read_ext(int drv, uint64_t pos, uint16_t count, void *dest) {
     const uint32_t _64K = 1 << 16;
     assert(((dest_paddr + size) & _64K) == (dest_paddr & _64K));
 
-    pci->prdt[0].phys_addr = dest_paddr;
-    pci->prdt[0].byte_count = size;
-    pci->prdt[0].reserved = 0;
-    pci->prdt[0].eot = 1;
-    outl(va2pa(pci->prdt), pci->bus_prdt);
+    ide_ctrl->prdt[0].phys_addr = dest_paddr;
+    ide_ctrl->prdt[0].byte_count = size;
+    ide_ctrl->prdt[0].reserved = 0;
+    ide_ctrl->prdt[0].eot = 1;
+    outl(va2pa(ide_ctrl->prdt), ide_ctrl->bus_prdt);
 
-    // printk("paddr: %x prdt: %x %x prdte %x %x\n", dest_paddr, pci->prdt,
-    // va2pa(pci->prdt),
-    //        pci->prdt[0].phys_addr, *(((unsigned int *)pci->prdt) + 1));
+    // printk("paddr: %x prdt: %x %x prdte %x %x\n", dest_paddr, ide_ctrl->prdt,
+    // va2pa(ide_ctrl->prdt),
+    //        ide_ctrl->prdt[0].phys_addr, *(((unsigned int *)ide_ctrl->prdt) + 1));
 
     // 清除中断位和错误位
     // 这里清除的方式是是设置1后清除
-    outb(PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, pci->bus_status);
+    outb(PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, ide_ctrl->bus_status);
 
     // 不再设置nIEN,DMA需要中断
     outb(0x00, REG_CTL(drv));
@@ -328,26 +322,26 @@ void ata_dma_read_ext(int drv, uint64_t pos, uint16_t count, void *dest) {
     // 在qemu中用DMA的方式读数据就会读不到数据,而只触是发中断,然后寄存器(Bus Master IDE Status
     // Register)的值会一直是5 也就是INTERRUPT和和ACTIVE位是1,正常应该是4,也就是只有INTERRUPT位为1
     // 在bochs中则加不加这一句不会有影响,都能正常读到数据
-    unsigned int v = pci_read_config_word(pci_cmd(pci->pci, PCI_COMMAND));
+    unsigned int v = pci_read_config_word(pci_cmd(ide_ctrl->pci, PCI_COMMAND));
     // printk(" ide pci command %04x\n", v);
-    pci_write_config_word(v | PCI_COMMAND_MASTER, pci_cmd(pci->pci, PCI_COMMAND));
-    // pci_write_config_word(v, pci_cmd(pci->pci, PCI_COMMAND));
+    pci_write_config_word(v | PCI_COMMAND_MASTER, pci_cmd(ide_ctrl->pci, PCI_COMMAND));
+    // pci_write_config_word(v, pci_cmd(ide_ctrl->pci, PCI_COMMAND));
 
     // 指定DMA操作为读取硬盘操作,内核用DMA读取,对硬盘而言是写出
     // 并设置DMA的开始位,开始DMA
-    outb(PCI_IDE_CMD_WRITE | PCI_IDE_CMD_START, pci->bus_cmd);
+    outb(PCI_IDE_CMD_WRITE | PCI_IDE_CMD_START, ide_ctrl->bus_cmd);
 }
 
 // TODO
 int ata_dma_stop(int channel) {
-    ide_pci_controller_t *pci = ide_pci_controller + channel;
+    ide_pci_controller_t *ide_ctrl = ide_pci_controller + channel;
 
-    uint8_t x = inb(pci->bus_cmd);
+    uint8_t x = inb(ide_ctrl->bus_cmd);
     x &= ~PCI_IDE_CMD_START;
-    outb(x, pci->bus_cmd);
+    outb(x, ide_ctrl->bus_cmd);
 
-    uint8_t status = inb(pci->bus_status);
-    outb(status | PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, pci->bus_status);
+    uint8_t status = inb(ide_ctrl->bus_status);
+    outb(status | PCI_IDE_STATUS_INTR | PCI_IDE_STATUS_ERR, ide_ctrl->bus_status);
 
     // TODO
     if (status & PCI_IDE_STATUS_ERR) {
index 837eb00625948f1162ef178cf7821320647ce663..32c8fb2b46cb63525071f3f8d0dd0d49825ac7bc 100644 (file)
@@ -35,6 +35,16 @@ void ide_pci_init(pci_device_t *pci) {
     unsigned int iobase = pci_read_config_long(pci_cmd(pci, PCI_BAR4));
 
     for (int i = 0; i < NR_IDE_CONTROLLER; i++) {
+        INIT_MUTEX(&ide_pci_controller[i].request_mutex);
+        ide_pci_controller[i].request_queue.count = 0;
+        INIT_LIST_HEAD(&ide_pci_controller[i].request_queue.list);
+        semaphore_init(&ide_pci_controller[i].request_queue.sem, 0);
+        semaphore_init(&ide_pci_controller[i].disk_intr_sem, 0);
+
+        ide_pci_controller[i].request_cnt = 0;
+        ide_pci_controller[i].irq_cnt = 0;
+        ide_pci_controller[i].consumed_cnt = 0;
+
         iobase += i * 8;  // secondary channel 需要加8
         printd("ide pci Base IO Address Register %08x\n", iobase);
         iobase &= 0xFFFC;  // 最低为0是内存地址为1是端口地址
@@ -103,40 +113,42 @@ void init_pci_controller(unsigned int classcode) {
     }
 }
 
-extern semaphore_t disk_intr_sem;
-
 extern void *mbr_buf;
-extern uint32_t disk_request_cnt;
-extern uint32_t disk_handled_cnt;
 
 uint8_t ata_pci_bus_status();
 
-volatile uint32_t disk_inter_cnt = 0;
-
 void ata_dma_stop(int channel);
 void ide_irq_bh_handler(void *arg) {
-    disk_inter_cnt++;
-
     int channel = (int)arg;
 
-    // printl(MPL_IDE, "disk req %u consumed %u irq %u", disk_request_cnt, disk_handled_cnt, disk_inter_cnt);
-    printlxy(MPL_IDE, MPO_IDE, "disk irq %u req %u consumed %u ", disk_inter_cnt, disk_request_cnt, disk_handled_cnt);
+    // printk("channel %08x\n", channel);
+    assert(channel <= 1);
+    assert(channel >= 0);
+
+    ide_pci_controller_t *ide_ctrl = ide_pci_controller + channel;
+    // printlxy(MPL_IDE, MPO_IDE, "disk irq %u req %u consumed %u ", disk_inter_cnt, disk_request_cnt,
+    // disk_handled_cnt);
+
+    printlxy(MPL_IDE0 + channel, MPO_IDE, "IDE%d req %u irq %u consumed %u", channel, ide_ctrl->request_cnt,
+             ide_ctrl->irq_cnt, ide_ctrl->consumed_cnt);
 
     // up里不会立即重新调度进程
-    up(&disk_intr_sem);
+    up(&ide_ctrl->disk_intr_sem);
 }
 
 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 == 14 ? 0 : 1;
+
+    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, &channel);
+    add_irq_bh_handler(ide_irq_bh_handler, (void *)channel);
 }
 
-void ide1_irq_handler(unsigned int irq, pt_regs_t *regs, void *devid) { panic("ide 0"); }
-
 void ide_ata_init();
 void ide_init() {
     memset(ide_pci_controller, 0, sizeof(ide_pci_controller[0]) * NR_IDE_CONTROLLER);
index 1a63a920c2b7268aa1a2b38e8e1c570c7eff0c3c..148d63e161c62c6839b47645d1cf95e250067625 100644 (file)
@@ -9,6 +9,7 @@
 
 #pragma once
 
+#include <atomic.h>
 #include <disk.h>
 #include <pci.h>
 #include <semaphore.h>
@@ -177,13 +178,23 @@ typedef struct _ide_pci_controller {
 
     prdte_t *prdt;
 
-    // 这里应该改成一个请求链表
-    // 先简单实现
-    task_union *task;
-    int done;
+    // 提出请求的任务用这个字段互斥地添加请求到request_queue
+    // 同时也和disk任务互斥
+    semaphore_t request_mutex;
+    // 请求队列
+    disk_request_queue_t request_queue;
+
+    // task disk与中断函数之间的信号量
+    // 初始化成0
+    semaphore_t disk_intr_sem;
+
+    atomic_t request_cnt;
+    atomic_t irq_cnt;
+    atomic_t consumed_cnt;
 } ide_pci_controller_t;
 
 #define NR_IDE_CONTROLLER 2
+extern ide_pci_controller_t ide_pci_controller[NR_IDE_CONTROLLER];
 
 typedef struct _ide_drive {
     int present;
@@ -191,9 +202,7 @@ typedef struct _ide_drive {
     uint64_t lba48;
     uint64_t max_lba;
 
-    semaphore_t request_mutex;
-
-    disk_request_queue_t request_queue;
+    ide_pci_controller_t *ide_pci_controller;
 } ide_drive_t;
 
 #define MAX_IDE_DRIVE_CNT 4
index e26b6f58502e329240f76116bdfd11361c9181e6..c3451b188995a7dea19a9396e2e55b1e9aaf50af 100644 (file)
@@ -77,7 +77,7 @@ extern void tty_switch_to_next();
 void kbd_debug(uint8_t scan_code) {
     static unsigned long kbd_cnt = 0;
     // printl(MPL_KEYBOARD, "keyboard irq: %d scan code %02x", kbd_cnt++, scan_code);
-    printlxy(MPL_IRQ, MPO_KEYBOARD, "keyboard irq: %d %02x", kbd_cnt++, scan_code);
+    printlxy(MPL_IRQ, MPO_KEYBOARD, "KBD irq: %d %02x", kbd_cnt++, scan_code);
 
     if (scan_code == 0x01) {  // Esc
         // reboot();
index 63f5168a903b3842a743d884be6c3dd47c7b5c0a..4afeb373c36fb7a9fd04b1e4d30d53eeebcd309a 100644 (file)
@@ -9,6 +9,10 @@
 
 #pragma once
 
+#include <types.h>
+
+typedef uint32_t atomic_t;
+
 #define atomic_inc(x) __sync_add_and_fetch((x), 1)
 #define atomic_dec(x) __sync_sub_and_fetch((x), 1)
 #define atomic_add(x, y) __sync_add_and_fetch((x), (y))
index d5423493e745f642c0255c1fdaceeb1371bd7a49..920fb48bba2db8385d5754d9b2f87bc512d09921 100644 (file)
@@ -39,8 +39,10 @@ typedef struct disk_request {
 
 typedef struct {
     uint32_t count;
-    semaphore_t sem;
     list_head_t list;
+
+    // 供disk任务睡眠和被唤醒用
+    semaphore_t sem;
 } disk_request_queue_t;
 
 void send_disk_request(disk_request_t *r);
index 5b2908cb90dbfd30be4f29fc7ec590908e427d76..001d5d4839ba6d7a6bfc97df21a2ede2d7a7265d 100644 (file)
@@ -29,7 +29,8 @@ int printlo(unsigned int line, unsigned int offset, const char *fmtstr, ...);
 enum {
     MPL_TITLE,
     MPL_IRQ,
-    MPL_IDE,
+    MPL_IDE0,
+    MPL_IDE1,
     MPL_CURRENT,
     MPL_TEST,
     MPL_DEBUG,
index 438386a5e876a557e4eb8407710d4db763c5cb7e..3cf9330dfb805cf12ff5c5d7ed6c88c0ee859147 100644 (file)
@@ -28,7 +28,7 @@ void clk_bh_handler(void *arg);
 void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) {
     // if (jiffies % 100 == 0) {
     // printl(MPL_CLOCK, "clock irq: %d", jiffies);
-    printlxy(MPL_IRQ, MPO_CLOCK, "clock irq: %d", jiffies);
+    printlxy(MPL_IRQ, MPO_CLOCK, "CLK irq: %d", jiffies);
     // }
 
     jiffies++;
index b8286940e213640a6b097438f35021e367e84760..ff2d26585b2b355e103cfb13b592955271e7c1c5 100644 (file)
@@ -99,7 +99,7 @@ __attribute__((regparm(1))) void irq_handler(pt_regs_t *regs) {
 #if 1
     unsigned long esp;
     asm("movl %%esp, %%eax" : "=a"(esp));
-    printl(MPL_CURRENT, "current %08x %s cr3 %08x reenter %d esp %08x ticks %u", current, current->name, current->cr3,
+    printl(MPL_CURRENT, "current %08x %-6s cr3 %08x reenter %d esp %08x ticks %u", current, current->name, current->cr3,
            reenter, esp, current->ticks);
 #endif
 
index 8b2aa57c99216511bae9704fb167a9f4449414b9..c8fad041ed3f3fbc2da7eb8a8125e294f638347f 100644 (file)
@@ -80,7 +80,7 @@ void setup_kernel() {
     boot_delay(DEFAULT_BOOT_DELAY_TICKS);
 
     extern tty_t *const monitor_tty;
-    tty_switch(monitor_tty);
+    // tty_switch(monitor_tty);
 
     boot_delay(DEFAULT_BOOT_DELAY_TICKS);
 
index 741a933c094639beb26bffccae83a7eba89dccc5..d53cd8d221f14d3e84116f5b75f276db6f21afbc 100644 (file)
 #include <ide.h>
 #include <sched.h>
 
-// task disk与中断函数之间的信号量
-semaphore_t disk_intr_sem;
-
-// task disk 之间发送命令的互斥量
-DECLARE_MUTEX(disk_cmd_mutex);
-
-void disk_init() { semaphore_init(&disk_intr_sem, 0); }
-
-volatile uint32_t disk_request_cnt = 0;
-volatile uint32_t disk_handled_cnt = 0;
+void disk_init() {
+    // ...
+}
 
 void send_disk_request(disk_request_t *r) {
     if (NULL == r) {
@@ -51,55 +44,51 @@ void send_disk_request(disk_request_t *r) {
         panic("disk DMA read cross 64K");
     }
 
-    mutex_lock(&drv->request_mutex);
-    disk_request_cnt++;
-    list_add_tail(&r->list, &drv->request_queue.list);
-    mutex_unlock(&drv->request_mutex);
+    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->request_queue.sem);
+    up(&drv->ide_pci_controller->request_queue.sem);
 
     // 等待被task_disk唤醒
     down(&r->sem);
 }
 
-void disk_task_entry(int arg) {
+void disk_task_entry(void *arg) {
     int r_cnt = 0;
     while (1) {
-        // 如果要改造成每个drive对应一个内核任务的话
-        // 就要注意共享disk_intr_sem的问题
-        // 目前只支持drv_no == 0
-        int drv_no = arg;
-        ide_drive_t *drv = ide_drives + drv_no;
-        if (drv->present == 0) {
-            panic("disk not present");
-        }
+        int channel = (int)arg;
+        ide_pci_controller_t *ide_ctrl = ide_pci_controller + channel;
 
         // 为了在DEBUG时看到RUNNING
-        for (int i = 0; i < 3; i++) {
+        for (int i = 0; i < 1; i++) {
             asm("hlt;");
         }
 
         // printk("wait request for hard disk %d\n", drv_no);
-        down(&drv->request_queue.sem);
+        down(&ide_ctrl->request_queue.sem);
         // printk("hard disk %d\n", drv_no);
 
-        mutex_lock(&drv->request_mutex);
+        mutex_lock(&ide_ctrl->request_mutex);
         disk_request_t *r;
-        r = list_first_entry(&drv->request_queue.list, disk_request_t, list);
+        r = list_first_entry(&ide_ctrl->request_queue.list, disk_request_t, list);
         if (NULL == r) {
             panic("no disk request");
         }
 
         list_del(&r->list);
-        disk_handled_cnt++;
-        mutex_unlock(&drv->request_mutex);
-
-        // 目前这个disk_cmd_mutex是用于两个通道四个DRIVE之间互斥
-        // 目前还不确定两个通道之间能否同时执行
-        // 后续要把disk分成两个进程,分别负责channel 0 1
-        // 这里再视情况改写
-        mutex_lock(&disk_cmd_mutex);
+        atomic_inc(&ide_ctrl->consumed_cnt);
+        mutex_unlock(&ide_ctrl->request_mutex);
+
+        // TODO dev -> drv
+        int drv_no = r->dev;
+        ide_drive_t *drv = ide_drives + drv_no;
+        if (drv->present == 0) {
+            panic("disk not present");
+        }
+
         switch (r->command) {
         case DISK_REQ_IDENTIFY:
             assert(r->count == 1);
@@ -117,8 +106,8 @@ void disk_task_entry(int arg) {
         }
 
         // 等待硬盘中断
-        down(&disk_intr_sem);
-        mutex_unlock(&disk_cmd_mutex);
+        down(&ide_ctrl->disk_intr_sem);
+
         // 读数据
         if (DISK_REQ_IDENTIFY == r->command) {
             void ata_read_data(int drv_no, int sect_cnt, void *dst);
index cece7406b890f5401e2ca757185367ac4be153e9..6028d411c455742f5031367cff30d5567e0034c9 100644 (file)
@@ -97,7 +97,7 @@ u16 disk_buf1[256];
 u16 disk_buf2[256];
 
 void taskA_entry() {
-    current->priority = 9;
+    current->priority = 7;
 
     while (1) {
         sysc_wait(7);
@@ -122,10 +122,10 @@ void taskA_entry() {
 }
 
 void taskB_entry() {
-    current->priority = 9;
+    current->priority = 13;
 
     while (1) {
-        sysc_wait(10);
+        sysc_wait(7);
 
         uint64_t sect_nr = get_next_deubug_sect_nr();
         memset(disk_buf2, 0, 512);
@@ -136,7 +136,7 @@ void taskB_entry() {
         r.count = 1;
         r.buf = disk_buf2;
         send_disk_request(&r);
-        // verify_hd_data(sect_nr, disk_buf2, current->name);
+        verify_hd_data(sect_nr, disk_buf2, current->name);
 
         for (int i = 0; i < 1; i++) {
             asm("hlt;");
@@ -171,8 +171,8 @@ void root_task_entry() {
     disk_init();
 
     kernel_task("init", init_task_entry, NULL);
-    kernel_task("disk/0", disk_task_entry, (void *)0);
-    kernel_task("disk/2", disk_task_entry, (void *)2);
+    kernel_task("ide/0", disk_task_entry, (void *)0);
+    kernel_task("ide/1", disk_task_entry, (void *)1);
     kernel_task("user", user_task_entry, NULL);
 
     // for (int i = 0; i < 100; i++) {