/// <summary> /// Parses the MADT /// </summary> /// <param name="madt">The MADT</param> private static void parseMADT(MADT *madt) { m_madt = madt; LocalApic.SetLocalControllerAddress(madt->LocalControllerAddress); m_intSourceOverrides = new ISAOverride[16]; for (uint i = 0; i < 16; i++) { m_intSourceOverrides[i].GSI = i; m_intSourceOverrides[i].Polarity = IOApic.IOAPIC_REDIR_POLARITY_HIGH; m_intSourceOverrides[i].Trigger = IOApic.IOAPIC_REDIR_TRIGGER_EDGE; } // After the flags field, the rest of the table contains a variable length of records uint current = (uint)madt + (uint)sizeof(MADT); uint end = current + madt->Header.Length - (uint)sizeof(MADT); while (current < end) { ApicEntryHeader * header = (ApicEntryHeader *)current; ApicEntryHeaderType type = (ApicEntryHeaderType)header->Type; switch (type) { case ApicEntryHeaderType.LOCAL_APIC: ApicLocalApic *localAPIC = (ApicLocalApic *)(current + sizeof(ApicEntryHeader)); Console.Write("[ACPI] Found CPU "); Console.WriteNum(localAPIC->ProcessorID); Console.Write('\n'); break; case ApicEntryHeaderType.IO_APIC: ApicIOApic *IOApicStruct = (ApicIOApic *)(current + sizeof(ApicEntryHeader)); Console.Write("[ACPI] Found IO APIC at "); Console.WriteHex(IOApicStruct->IOAPICAddress); Console.Write('\n'); IOApic IOApic = new IOApic(IOApicStruct->IOAPIC_ID, (void *)IOApicStruct->IOAPICAddress, IOApicStruct->GlobalSystemInterruptBase); IOApicManager.Add(IOApic); break; case ApicEntryHeaderType.INTERRUPT_SOURCE_OVERRIDE: ApicInterruptSourceOverride *intSourceOverride = (ApicInterruptSourceOverride *)(current + sizeof(ApicEntryHeader)); m_intSourceOverrides[intSourceOverride->IRQSource].GSI = intSourceOverride->GlobalSystemInterrupt; m_intSourceOverrides[intSourceOverride->IRQSource].Polarity = (uint)(intSourceOverride->Flags & 0x3); m_intSourceOverrides[intSourceOverride->IRQSource].Trigger = (uint)((intSourceOverride->Flags >> 2) & 0x3); break; } current += header->Length; } }
/// <summary> /// IRQ handler /// </summary> /// <param name="regsPtr">Pointer to registers</param> public static unsafe void Handler(Regs *regsPtr) { int irqNum = regsPtr->IntNum; if (handlers[irqNum] != null) { // Loop through handlers to see who has sent interrupt for (int i = 0; i < IRQ_MAX_SHARING; i++) { if (handlers[irqNum][i] == null || handlers[irqNum][i]()) { break; } } } LocalApic.SendEOI(); }