From 5bf9f06ae17417b07db8a9c5a58ca970ace30ea2 Mon Sep 17 00:00:00 2001 From: acevest Date: Mon, 19 Jan 2026 19:19:32 +0800 Subject: [PATCH] =?utf8?q?=E6=B5=8B=E8=AF=95SATA=E4=B8=AD=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/ahci.c | 6 ++---- drivers/ahci.h | 18 ++++++++++++++++++ drivers/sata.c | 37 +++++++++++++++++++++++++++++++++++++ include/apic.h | 2 ++ kernel/ap.c | 4 ++-- kernel/apic.c | 25 +++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 6 deletions(-) diff --git a/drivers/ahci.c b/drivers/ahci.c index 4ea8f2c..8340959 100644 --- a/drivers/ahci.c +++ b/drivers/ahci.c @@ -74,6 +74,8 @@ void init_ahci_device(pci_device_t* pci, int index) { hba->global_hba_control |= AHCI_ENABLE; + hba->global_hba_control |= AHCI_INTERRUPT_ENABLE; + uint32_t cap = hba->capability; int num_ports = (cap & 0x1F) + 1; @@ -168,10 +170,6 @@ void init_ahci_device(pci_device_t* pci, int index) { } } } - - // TODO - // 开启ahci的global_hba_control的interrupt enable位 - hba->global_hba_control |= AHCI_INTERRUPT_ENABLE; } void init_ahci() { diff --git a/drivers/ahci.h b/drivers/ahci.h index 9852e57..b7e1405 100644 --- a/drivers/ahci.h +++ b/drivers/ahci.h @@ -23,6 +23,24 @@ const static int AHCI_DEVICE_SATAPI = 4; const static int AHCI_FIS_TYPE_REG_H2D = 0x27; const static int AHCI_FIS_TYPE_REG_D2H = 0x34; +const static uint32_t AHCI_INTERRUPT_ENABLE_DHRS = (1U << 0); // device to host fis interrupt enable +const static uint32_t AHCI_INTERRUPT_ENABLE_PSE = (1U << 1); // pio setup fis interrupt enable +const static uint32_t AHCI_INTERRUPT_ENABLE_DSE = (1U << 2); // DMA setup fis interrupt enable +const static uint32_t AHCI_INTERRUPT_ENABLE_SDBE = (1U << 3); // set device bits interrupt enable +const static uint32_t AHCI_INTERRUPT_ENABLE_UFE = (1U << 4); // unknown fis interrupt enable +const static uint32_t AHCI_INTERRUPT_ENABLE_DPE = (1U << 5); // descriptor process error interrupt enable +const static uint32_t AHCI_INTERRUPT_ENABLE_PCE = (1U << 6); // port change error interrupt enable +const static uint32_t AHCI_INTERRUPT_ENABLE_DMPE = (1U << 7); // device mechanical presence enable +const static uint32_t AHCI_INTERRUPT_ENABLE_PRCE = (1U << 22); // phyrdy change interrupt enable +const static uint32_t AHCI_INTERRUPT_ENABLE_IPME = (1U << 23); // incorrect port multiplier interrupt enable +const static uint32_t AHCI_INTERRUPT_ENABLE_OFE = (1U << 24); // overflow error interrupt enable +const static uint32_t AHCI_INTERRUPT_ENABLE_INFE = (1U << 26); // interface non-fatal error enable +const static uint32_t AHCI_INTERRUPT_ENABLE_IFE = (1U << 27); // interface fatal error enable +const static uint32_t AHCI_INTERRUPT_ENABLE_HBDE = (1U << 28); // host bus data error enable +const static uint32_t AHCI_INTERRUPT_ENABLE_HBFE = (1U << 29); // host bus fatal error enable +const static uint32_t AHCI_INTERRUPT_ENABLE_TFEE = (1U << 30); // task file error enable +const static uint32_t AHCI_INTERRUPT_ENABLE_CPDE = (1U << 31); // cold presence detect enable + typedef struct { uint8_t fis_type; uint8_t pmport : 4; // port multiplier diff --git a/drivers/sata.c b/drivers/sata.c index a1755d2..e0c7376 100644 --- a/drivers/sata.c +++ b/drivers/sata.c @@ -15,6 +15,8 @@ #include #include +int sata_irq_triggered = 0; + void init_sata_device(ahci_hba_t* hba, ahci_port_t* port, int index) { assert(hba != NULL); assert(port != NULL); @@ -107,6 +109,8 @@ void init_sata_device(ahci_hba_t* hba, ahci_port_t* port, int index) { // 写1清0 port->interrupt_status = port->interrupt_status; + port->interrupt_enable = AHCI_INTERRUPT_ENABLE_DHRS; + asm("sti"); // port->cmd_issue = 1 << 0; @@ -188,6 +192,39 @@ void init_sata_device(ahci_hba_t* hba, ahci_port_t* port, int index) { sata_read_identify_string(identify, 27, 46, s); printk("HD Model: %s\n", s); + + // while (!sata_irq_triggered) { + // // asm("sti"); + // asm("pause"); + // } + + // 1. 等待端口空闲(确保上一条命令完全完成) + while (port->cmd_issue & 1) { + // 命令位仍被置位,等待清除 + } + while (port->sata_active & 1) { + // 等待active位清除 + } + + memset(fis, 0, sizeof(ahci_fis_reg_h2d_t)); + fis->fis_type = AHCI_FIS_TYPE_REG_H2D; + fis->c = 1; + fis->command = SATA_CMD_IDENTIFY; + fis->device = SATA_DEVICE_LBA; + + sata->cmd_list0->cfl = sizeof(ahci_fis_reg_h2d_t) / sizeof(uint32_t); + sata->cmd_list0->prdtl = 1; + sata->cmd_list0->w = 0; // read + sata->cmd_list0->a = 0; // ata device + sata->cmd_list0->prd_byte_count = 0; + // 清除中断状态 + // 写1清0 + port->interrupt_status = port->interrupt_status; + + port->interrupt_enable = AHCI_INTERRUPT_ENABLE_DHRS; + + // + port->cmd_issue = 1 << 0; } sata_device_t sata_devices[MAX_SATA_DEVICES] = {0}; diff --git a/include/apic.h b/include/apic.h index fcc8563..a808bb2 100644 --- a/include/apic.h +++ b/include/apic.h @@ -201,3 +201,5 @@ typedef union ioapic_rte ioapic_rte_t; uint64_t ioapic_rte_read(uint32_t index); void ioapic_rte_write(uint32_t index, uint64_t v); + +void ioapic_eoi(); diff --git a/kernel/ap.c b/kernel/ap.c index f2a79aa..a2bd36e 100644 --- a/kernel/ap.c +++ b/kernel/ap.c @@ -240,7 +240,7 @@ void do_ap_pit_irq_handler() { ap_pit_ticks++; - system.lapic->write(LAPIC_EOI, 0); + ioapic_eoi(); } void do_ap_no_irq_handler() { @@ -254,7 +254,7 @@ void do_ap_lapic_irq_handler() { ap_lapic_ticks++; - system.lapic->write(LAPIC_EOI, 0); + ioapic_eoi(); } void _system_monitor() { diff --git a/kernel/apic.c b/kernel/apic.c index f23ee7f..a92310d 100644 --- a/kernel/apic.c +++ b/kernel/apic.c @@ -270,6 +270,17 @@ void ioapic_enable() { iounmap(rcba_virt_base); } +void ioapic_eoi() { + system.lapic->write(LAPIC_EOI, 0); +} + +extern int sata_irq_triggered; +void sata0_irq_handler() { + printk("SATA#0 IRQ\n"); + sata_irq_triggered = 1; + ioapic_eoi(); +} + void ioapic_init() { // 把IO APIC映射进地址空间 ioapic_map.phys_base = system.ioapic_addr; @@ -335,6 +346,20 @@ void ioapic_init() { rte.destination = 0; ioapic_rte_write(IOAPIC_RTE(1), rte.value); irq_set_chip(0x01, &ioapic_chip); + + // + int irq = 0x0B; // 11 + rte.value = 0; + rte.vector = 0x20 + irq; + rte.delivery_mode = IOAPIC_DELIVERY_MODE_FIXED; + rte.destination_mode = IOAPIC_PHYSICAL_DESTINATION; + rte.trigger_mode = IOAPIC_TRIGGER_MODE_EDGE; + rte.mask = IOAPIC_INT_UNMASKED; + rte.destination = 0; + ioapic_rte_write(IOAPIC_RTE(irq), rte.value); + irq_set_chip(irq, &ioapic_chip); + + request_irq(irq, sata0_irq_handler, "SATA#0", "SATA#0"); #endif } -- 2.47.0