From 3e67f42912c91593843c0184bde6436754fb3979 Mon Sep 17 00:00:00 2001 From: acevest Date: Sun, 22 Sep 2024 12:11:33 +0800 Subject: [PATCH] =?utf8?q?=E4=BF=AE=E5=A4=8D=E5=BD=93PCI=E7=9A=84IDE=20Con?= =?utf8?q?troller=E6=8C=87=E5=AE=9A=E4=BA=86=E4=B8=AD=E6=96=AD=E5=8F=B7?= =?utf8?q?=E6=97=B6=E8=80=8C=E5=86=85=E6=A0=B8=E5=9B=A0=E4=B8=BA=E4=BD=BF?= =?utf8?q?=E7=94=A8=E4=BA=86=E9=BB=98=E8=AE=A4=E7=9A=84=E7=A1=AC=E7=9B=98?= =?utf8?q?=E4=B8=AD=E6=96=AD=E5=8F=B7=E5=AF=BC=E8=87=B4=E6=94=B6=E4=B8=8D?= =?utf8?q?=E5=88=B0=E7=A1=AC=E7=9B=98=E4=B8=AD=E6=96=AD=E7=9A=84=E9=97=AE?= =?utf8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/ide.c | 94 ++++++++++++++++++++++++++++--------------------- drivers/ide.h | 2 ++ kernel/system.c | 5 +-- 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/drivers/ide.c b/drivers/ide.c index 1bd2658..de5c35c 100644 --- a/drivers/ide.c +++ b/drivers/ide.c @@ -105,6 +105,45 @@ SATA(Serial ATA)于2002年推出后,原有的ATA改名为PATA(并行高 // 随着SATA技术的出现,之前所有的ATA就被称为PATA ide_pci_controller_t ide_pci_controller[NR_IDE_CONTROLLER]; +void ata_dma_stop(int channel); + +void ide_irq_bh_handler(void *arg) { + int channel = (int)arg; + + // 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, + atomic_read(&(ide_ctrl->request_cnt)), ide_ctrl->irq_cnt, ide_ctrl->consumed_cnt); + + // 之前这里是用up()来唤醒磁盘任务 + // 但在中断的底半处理,不应该切换任务,因为会引起irq里的reenter问题,导致不能再进底半处理,也无法切换任务 + // 所以就移除了up()里的 schedule() + // 后来就改用完成量来通知磁盘任务,就不存在这个问题了 + + // complete会唤醒进程,但不会立即重新调度进程 + complete(&ide_ctrl->intr_complete); +} + +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; + + 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); +} + unsigned int IDE_CHL0_CMD_BASE = 0x1F0; unsigned int IDE_CHL1_CMD_BASE = 0x170; @@ -164,6 +203,14 @@ void ide_pci_init(pci_device_t *pci) { ide_pci_controller[i].prdt = (prdte_t *)page2va(alloc_one_page(0)); ide_pci_controller[i].pci = pci; + + unsigned int irq_line = pci_read_config_byte(pci_cmd(pci, PCI_INTRLINE)); + assert(irq_line <= 15); + if (irq_line == 0) { + ide_pci_controller[i].irq_line = 14 + i; + } else { + ide_pci_controller[i].irq_line = irq_line; + } } IDE_CHL0_CMD_BASE = pci->bars[0] ? (pci->bars[0] & 0xFFFFFFFE) : IDE_CHL0_CMD_BASE; @@ -172,6 +219,12 @@ void ide_pci_init(pci_device_t *pci) { IDE_CHL1_CMD_BASE = pci->bars[2] ? (pci->bars[2] & 0xFFFFFFFE) : IDE_CHL1_CMD_BASE; IDE_CHL1_CTL_BASE = pci->bars[3] ? (pci->bars[3] & 0xFFFFFFFE) : IDE_CHL1_CTL_BASE; + for (int i = 0; i < NR_IDE_CONTROLLER; i++) { + int irq = ide_pci_controller[i].irq_line; + open_irq(irq); + request_irq(irq, ide_irq_handler, "hard", "IDE"); + } + printd("ide channel 0: cmd %04x ctl %04x\n", IDE_CHL0_CMD_BASE, IDE_CHL0_CTL_BASE); printd("ide channel 1: cmd %04x ctl %04x\n", IDE_CHL1_CMD_BASE, IDE_CHL1_CTL_BASE); } @@ -219,43 +272,6 @@ extern void *mbr_buf; uint8_t ata_pci_bus_status(); -void ata_dma_stop(int channel); -void ide_irq_bh_handler(void *arg) { - int channel = (int)arg; - - // 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, - atomic_read(&(ide_ctrl->request_cnt)), ide_ctrl->irq_cnt, ide_ctrl->consumed_cnt); - - // 之前这里是用up()来唤醒磁盘任务 - // 但在中断的底半处理,不应该切换任务,因为会引起irq里的reenter问题,导致不能再进底半处理,也无法切换任务 - // 所以就移除了up()里的 schedule() - // 后来就改用完成量来通知磁盘任务,就不存在这个问题了 - - // complete会唤醒进程,但不会立即重新调度进程 - complete(&ide_ctrl->intr_complete); -} - -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, (void *)channel); -} - void ide_ata_init(); void ide_init() { memset(ide_pci_controller, 0, sizeof(ide_pci_controller[0]) * NR_IDE_CONTROLLER); @@ -263,10 +279,6 @@ void ide_init() { // 读PCI里 IDE相关寄存器的配置 init_pci_controller(0x0101); - request_irq(0x0E, ide_irq_handler, "hard", "IDE"); - - request_irq(0x0F, ide_irq_handler, "hard", "IDE"); - // 读IDE 硬盘的identity ide_ata_init(); } diff --git a/drivers/ide.h b/drivers/ide.h index 2c599eb..8cf5125 100644 --- a/drivers/ide.h +++ b/drivers/ide.h @@ -190,6 +190,8 @@ typedef struct _ide_pci_controller { atomic_t request_cnt; atomic_t irq_cnt; atomic_t consumed_cnt; + + int irq_line; } ide_pci_controller_t; #define NR_IDE_CONTROLLER 2 diff --git a/kernel/system.c b/kernel/system.c index 1717762..eab8ccb 100644 --- a/kernel/system.c +++ b/kernel/system.c @@ -151,8 +151,9 @@ void setup_irqs() { // 打开支持的中断 open_irq(IRQ_CLOCK); open_irq(IRQ_KEYBOARD); - open_irq(IRQ_DISK); - open_irq(15); + // open_irq(IRQ_DISK); + // open_irq(15); + // open_irq(10); } void boot_irq_handler(); -- 2.44.0