From 778eec2582f605bd889f3d113ee66e0cc79f97a5 Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 23 Oct 2019 18:21:42 +0300 Subject: [PATCH] Add AHCI PCI IRQ handling --- include/sys/amd64/hw/ide/ahci.h | 2 ++ include/sys/amd64/hw/irq.h | 2 ++ sys/amd64/hw/apic.c | 6 ------ sys/amd64/hw/ide/ahci.c | 29 +++++++++++++++++++++++++++++ sys/amd64/hw/ide/ide.c | 2 -- sys/amd64/hw/irq.c | 16 +++++++++++++++- sys/amd64/hw/pci/ahci.c | 8 ++++++++ sys/amd64/kernel.c | 8 ++++++-- 8 files changed, 62 insertions(+), 11 deletions(-) diff --git a/include/sys/amd64/hw/ide/ahci.h b/include/sys/amd64/hw/ide/ahci.h index 3d82f46..f681d6b 100644 --- a/include/sys/amd64/hw/ide/ahci.h +++ b/include/sys/amd64/hw/ide/ahci.h @@ -220,6 +220,8 @@ struct ahci_command_table_entry { #define AHCI_PORT_CMD_LIST(p) (struct ahci_command_header *) MM_VIRTUALIZE(((uintptr_t) (p)->p_clbu << 32) | ((p)->p_clb)) #define AHCI_CMD_TABLE_ENTRY(l, i) (struct ahci_command_table_entry *) MM_VIRTUALIZE(((uintptr_t) (l)[i].ctbau << 32) | ((l)[i].ctba)) +int ahci_irq(void); + // TODO: accept block device instead of port registers void ahci_sata_read(struct ahci_port_registers *port, void *buf, uint32_t nsect, uint64_t lba); diff --git a/include/sys/amd64/hw/irq.h b/include/sys/amd64/hw/irq.h index 25a49fc..ca7e390 100644 --- a/include/sys/amd64/hw/irq.h +++ b/include/sys/amd64/hw/irq.h @@ -1,4 +1,5 @@ #pragma once +#include "sys/amd64/hw/pci/pci.h" #include "sys/types.h" #define IRQ_LEG_KEYBOARD 1 @@ -8,6 +9,7 @@ typedef int (*irq_handler_t) (void); int irq_add_handler(uint8_t gsi, irq_handler_t handler); int irq_add_leg_handler(uint8_t leg_irq, irq_handler_t handler); +int irq_add_pci_handler(pci_addr_t addr, uint8_t pin, irq_handler_t handler); void irq_enable_ioapic_mode(void); void irq_init(void); diff --git a/sys/amd64/hw/apic.c b/sys/amd64/hw/apic.c index 0c329a9..78c059e 100644 --- a/sys/amd64/hw/apic.c +++ b/sys/amd64/hw/apic.c @@ -117,8 +117,6 @@ void amd64_acpi_smp(struct acpi_madt *madt) { offset += ent_hdr->length; } - - amd64_smp_init(); } #endif @@ -173,8 +171,4 @@ void amd64_apic_init(void) { #endif amd64_timer_init(); - - extern mm_space_t mm_kernel; - // Initialization finished, can unmap 0 -> 0 mapping now - mm_kernel[0] = 0; } diff --git a/sys/amd64/hw/ide/ahci.c b/sys/amd64/hw/ide/ahci.c index c8d9c29..471afe8 100644 --- a/sys/amd64/hw/ide/ahci.c +++ b/sys/amd64/hw/ide/ahci.c @@ -22,6 +22,29 @@ static int ahci_alloc_cmd(struct ahci_port_registers *port) { return -1; } +struct ahci_registers *controller0 = NULL; + +static void ahci_irq_port(struct ahci_port_registers *port) { + if (port->p_is & (1 << 0)) { + // TODO: integrate this with reading code + } + + port->p_is = 0; +} + +int ahci_irq(void) { + if (controller0->is) { + for (size_t port = 0; port < 32; ++port) { + ahci_irq_port(&controller0->ports[port]); + controller0->is &= ~(1 << port); + } + + return 0; + } + + return -1; +} + void ahci_sata_read(struct ahci_port_registers *port, void *buf, uint32_t nsect, uint64_t lba) { port->p_is = -1; @@ -227,6 +250,9 @@ void ahci_port_init(uint8_t n, struct ahci_port_registers *port) { case AHCI_PORT_SIG_SATA: ahci_sata_port_init(port); ahci_sata_port_identify(port); + + // Enable IRQs + port->p_ie |= (1 << 0); break; default: kdebug("Skipping unknown drive type\n"); @@ -272,4 +298,7 @@ void ahci_init(struct ahci_registers *regs) { ahci_port_init(i, port); } } + + // Enable HBA interrupts + regs->ghc |= 1 << 1; } diff --git a/sys/amd64/hw/ide/ide.c b/sys/amd64/hw/ide/ide.c index f9ca324..ffd2635 100644 --- a/sys/amd64/hw/ide/ide.c +++ b/sys/amd64/hw/ide/ide.c @@ -284,8 +284,6 @@ int ide_ata_read_pio(struct ide_device *dev, void *buf, size_t nsect, uint64_t l return 0; } -static char test_buf[65536 * 2] __attribute__((aligned(65536))); - void ide_init(struct ide_controller *ide) { // Initialize from PCI IDE information: BARs ide->channels[0].base = ide->bar0; diff --git a/sys/amd64/hw/irq.c b/sys/amd64/hw/irq.c index 73d14f9..5ec3ce6 100644 --- a/sys/amd64/hw/irq.c +++ b/sys/amd64/hw/irq.c @@ -7,7 +7,7 @@ #include "sys/panic.h" #include "sys/debug.h" -#define IRQ_MAX 16 // Maximum assignable IRQ vectors +#define IRQ_MAX 32 // Maximum assignable IRQ vectors #define IRQ_MAX_HANDLERS 4 // Maximum handlers per IRQ vector (sharing) static irq_handler_t handlers[IRQ_MAX * IRQ_MAX_HANDLERS] = {0}; @@ -87,6 +87,20 @@ int irq_add_leg_handler(uint8_t leg_irq, irq_handler_t handler) { } } +int irq_add_pci_handler(pci_addr_t addr, uint8_t pin, irq_handler_t handler) { + _assert(pin < 4); + uint32_t irq_route = amd64_pci_pin_irq_route(PCI_BUS(addr), PCI_DEV(addr), PCI_FUNC(addr), pin); + _assert(irq_route != PCI_IRQ_INVALID); + + if (irq_route == PCI_IRQ_NO_ROUTE) { + panic("TODO: allocate PCI IRQ routes\n"); + } + + kdebug("Assigning handler to " PCI_FMTADDR " INT%c# -> GSI%d", PCI_VAADDR(addr), pin + 'A', irq_route); + + return irq_add_handler(irq_route, handler); +} + void irq_enable_ioapic_mode(void) { ioapic_available = 1; // Copy current table diff --git a/sys/amd64/hw/pci/ahci.c b/sys/amd64/hw/pci/ahci.c index 4a7ca91..af648b3 100644 --- a/sys/amd64/hw/pci/ahci.c +++ b/sys/amd64/hw/pci/ahci.c @@ -1,6 +1,7 @@ #include "sys/amd64/hw/pci/ahci.h" #include "sys/amd64/hw/ide/ahci.h" #include "sys/amd64/hw/ide/ata.h" +#include "sys/amd64/hw/irq.h" #include "sys/amd64/mm/phys.h" #include "sys/assert.h" #include "sys/string.h" @@ -13,6 +14,8 @@ static struct pci_ahci ahci; void pci_ahci_init(pci_addr_t addr) { kdebug("Initializing AHCI controller at " PCI_FMTADDR "\n", PCI_VAADDR(addr)); + uint32_t irq = pci_config_read_dword(addr, 0x3C); + ahci.addr = addr; ahci.abar_phys = pci_config_read_dword(addr, 0x24); ahci.regs = (struct ahci_registers *) MM_VIRTUALIZE(ahci.abar_phys); @@ -20,4 +23,9 @@ void pci_ahci_init(pci_addr_t addr) { kdebug("AHCI registers: %p\n", ahci.regs); ahci_init(ahci.regs); + + uint8_t int_pin = ((irq >> 8) & 0xFF); + if (int_pin) { + irq_add_pci_handler(addr, int_pin - 1, ahci_irq); + } } diff --git a/sys/amd64/kernel.c b/sys/amd64/kernel.c index cab67f4..a7bfc15 100644 --- a/sys/amd64/kernel.c +++ b/sys/amd64/kernel.c @@ -4,6 +4,7 @@ #include "sys/amd64/syscall.h" #include "sys/amd64/hw/idt.h" #include "sys/amd64/mm/mm.h" +#include "sys/amd64/smp/smp.h" #include "sys/amd64/mm/phys.h" #include "sys/amd64/hw/acpi.h" #include "sys/amd64/hw/apic.h" @@ -31,11 +32,14 @@ void kernel_main(struct amd64_loader_data *data) { amd64_mm_init(data); amd64_acpi_init(); - pci_init(); - extern void sched_init(void); sched_init(); amd64_apic_init(); + pci_init(); + +#if defined(AMD64_SMP) + amd64_smp_init(); +#endif amd64_syscall_init();