Add AHCI PCI IRQ handling
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
+15
-1
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user