]> Zhao Yanbai Git Server - kernel.git/commitdiff
测试SATA中断
authoracevest <zhaoyanbai@126.com>
Mon, 19 Jan 2026 11:19:32 +0000 (19:19 +0800)
committeracevest <zhaoyanbai@126.com>
Mon, 19 Jan 2026 11:19:32 +0000 (19:19 +0800)
drivers/ahci.c
drivers/ahci.h
drivers/sata.c
include/apic.h
kernel/ap.c
kernel/apic.c

index 4ea8f2c1b26ecc4b8fa859622ce99ca5d9dc0043..834095973de81346c3516df5f85ff8a7b0f410bc 100644 (file)
@@ -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() {
index 9852e57bf33c3f8cc5a77bcede66e4bea5d881ee..b7e140520df8b9d28eee153a94f7d2b7a38785f6 100644 (file)
@@ -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
index a1755d2fdf02175e17aa0b88efa7efc473df5063..e0c73762e8725200c18524670e306ccb0b1b8204 100644 (file)
@@ -15,6 +15,8 @@
 #include <string.h>
 #include <system.h>
 
+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};
index fcc856356b704ceaeca9bf934c5df78948904c37..a808bb2e3a74dfc842e2310acd59c9794b8a4695 100644 (file)
@@ -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();
index f2a79aa4e1b7e9e892a8f60bb083848305d968f9..a2bd36e7f1ed2e8fee850763bc6c2036d21aaf15 100644 (file)
@@ -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() {
index f23ee7f552208e13f0848bb0167268bb23483a26..a92310de19c43c56a950ba403519befd293fdfc4 100644 (file)
@@ -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
 }