Further parse AHCI information.

Send an IDENTIFY command to each drive and set up a hook to handle
interrupts.
This commit is contained in:
Drew Galbraith 2023-06-12 19:20:51 -07:00
parent 4e1888bd24
commit 0f0e39d1e9
25 changed files with 721 additions and 90 deletions

View file

@ -7,7 +7,7 @@
#include "common/port.h"
#include "debug/debug.h"
#define APIC_DEBUG 0
#define APIC_DEBUG 1
namespace {
@ -17,6 +17,7 @@ namespace {
const uint64_t kEoiOffset = 0xB0;
// FIXME: parse these from madt.
constexpr uint64_t kLApicBase = 0xFEE0'0000;
constexpr uint64_t kIoApicAddr = 0xFEC0'0000;
constexpr uint64_t kIoApicData = 0xFEC0'0010;
@ -88,7 +89,6 @@ void InspectApic() {
dbgln("TPR: %x", GetLocalReg(0x80));
dbgln("APR: %x", GetLocalReg(0x90));
dbgln("PPR: %x", GetLocalReg(0xA0));
dbgln("RRD: %x", GetLocalReg(0xC0));
dbgln("LDR: %x", GetLocalReg(0xD0));
dbgln("DFR: %x", GetLocalReg(0xE0));
dbgln("SIV: %x", GetLocalReg(0xF0));
@ -119,10 +119,22 @@ void EnableApic() {
SetIoEntry(0x14, 0x20);
// Skip Keyboard for now.
// SetIoEntry(0x12, 0x21);
// TODO: This also works with the interrupt numbers provided by the MADT
// I need to do further investigation on the difference in this case and
// also how to find a declarative spec for where the PCI Lines are mapped.
// PCI Line 1-4
// FIXME: These should be level triggered according to spec I believe
// but because we handle the interrupt outside of the kernel it is tricky
// to wait to send the end of interrupt message.
// Because of this leave them as edge triggered and send EOI immediately.
SetIoEntry(0x30, 0x30);
SetIoEntry(0x32, 0x31);
SetIoEntry(0x34, 0x32);
SetIoEntry(0x36, 0x33);
InspectApic();
}
void SignalEOI() {
// Value doesn't matter.
WriteLocalReg(kEoiOffset, 0x1);
}
void SignalEOI() { WriteLocalReg(kEoiOffset, 0x0); }

View file

@ -138,11 +138,44 @@ extern "C" void interrupt_timer(InterruptFrame*) {
gScheduler->Preempt();
}
RefPtr<Port> pci1_port;
extern "C" void isr_pci1();
extern "C" void interrupt_pci1(InterruptFrame*) {
dbgln("Interrupt PCI line 1");
pci1_port->Write({});
SignalEOI();
}
extern "C" void isr_pci2();
extern "C" void interrupt_pci2(InterruptFrame*) {
dbgln("Interrupt PCI line 2");
SignalEOI();
}
extern "C" void isr_pci3();
extern "C" void interrupt_pci3(InterruptFrame*) {
dbgln("Interrupt PCI line 3");
SignalEOI();
}
extern "C" void isr_pci4();
extern "C" void interrupt_pci4(InterruptFrame*) {
dbgln("Interrupt PCI line 4");
SignalEOI();
}
void InitIdt() {
gIdt[0] = CreateDescriptor(isr_divide_by_zero);
gIdt[13] = CreateDescriptor(isr_protection_fault);
gIdt[14] = CreateDescriptor(isr_page_fault);
gIdt[32] = CreateDescriptor(isr_timer);
gIdt[0x20] = CreateDescriptor(isr_timer);
gIdt[0x30] = CreateDescriptor(isr_pci1);
gIdt[0x31] = CreateDescriptor(isr_pci2);
gIdt[0x32] = CreateDescriptor(isr_pci3);
gIdt[0x33] = CreateDescriptor(isr_pci4);
InterruptDescriptorTablePointer idtp{
.size = sizeof(gIdt),
.base = reinterpret_cast<uint64_t>(gIdt),
@ -151,3 +184,5 @@ void InitIdt() {
EnableApic();
}
void RegisterPciPort(const RefPtr<Port>& port) { pci1_port = port; }

View file

@ -1,3 +1,8 @@
#pragma once
#include "lib/ref_ptr.h"
#include "object/port.h"
void InitIdt();
void RegisterPciPort(const RefPtr<Port>& port);