Program I/O APIC; got one RTC interrupt
This commit is contained in:
parent
d49f9e32cd
commit
58d685a15b
@ -52,13 +52,23 @@ struct apic
|
|||||||
ApicRegister divide_configuration;
|
ApicRegister divide_configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct IoApicRegisters
|
||||||
|
{
|
||||||
|
ApicRegister address;
|
||||||
|
ApicRegister data;
|
||||||
|
}
|
||||||
|
|
||||||
private static __gshared ApicRegisters * apic_registers;
|
private static __gshared ApicRegisters * apic_registers;
|
||||||
|
private static __gshared IoApicRegisters * io_apic_registers;
|
||||||
|
|
||||||
public static void initialize()
|
public static void initialize()
|
||||||
{
|
{
|
||||||
apic_registers = cast(ApicRegisters *)acpi.apic_address;
|
apic_registers = cast(ApicRegisters *)acpi.apic_address;
|
||||||
|
io_apic_registers = cast(IoApicRegisters *)0xFEC0_0000u;
|
||||||
hurl.map(cast(ulong)apic_registers, cast(ulong)apic_registers,
|
hurl.map(cast(ulong)apic_registers, cast(ulong)apic_registers,
|
||||||
PT_WRITABLE | PT_WRITE_THROUGH | PT_DISABLE_CACHE | PT_NO_EXECUTE);
|
PT_WRITABLE | PT_WRITE_THROUGH | PT_DISABLE_CACHE | PT_NO_EXECUTE);
|
||||||
|
hurl.map(cast(ulong)io_apic_registers, cast(ulong)io_apic_registers,
|
||||||
|
PT_WRITABLE | PT_WRITE_THROUGH | PT_DISABLE_CACHE | PT_NO_EXECUTE);
|
||||||
klog.writefln("LAPIC ID: 0x%08x", apic_registers.lapic_id.value);
|
klog.writefln("LAPIC ID: 0x%08x", apic_registers.lapic_id.value);
|
||||||
klog.writefln("LAPIC version: 0x%08x", apic_registers.lapic_version.value);
|
klog.writefln("LAPIC version: 0x%08x", apic_registers.lapic_version.value);
|
||||||
/* Enable local APIC to receive interrupts and set spurious interrupt
|
/* Enable local APIC to receive interrupts and set spurious interrupt
|
||||||
@ -68,6 +78,19 @@ struct apic
|
|||||||
apic_registers.lvt_lint[0].value = idt.INT_LAPIC_LINT0;
|
apic_registers.lvt_lint[0].value = idt.INT_LAPIC_LINT0;
|
||||||
apic_registers.lvt_lint[1].value = idt.INT_LAPIC_LINT1;
|
apic_registers.lvt_lint[1].value = idt.INT_LAPIC_LINT1;
|
||||||
apic_registers.divide_configuration.value = 3u;
|
apic_registers.divide_configuration.value = 3u;
|
||||||
|
for (size_t i = 0u; i < 24u; i++)
|
||||||
|
{
|
||||||
|
configure_io_apic_irq(i, i + 0x40u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void configure_io_apic_irq(size_t io_apic_irq, size_t interrupt_id)
|
||||||
|
{
|
||||||
|
ulong entry = interrupt_id;
|
||||||
|
io_apic_registers.address.value = cast(uint)(0x10u + io_apic_irq * 2u);
|
||||||
|
io_apic_registers.data.value = entry & 0xFFFF_FFFFu;
|
||||||
|
io_apic_registers.address.value = cast(uint)(0x10u + io_apic_irq * 2u + 1u);
|
||||||
|
io_apic_registers.data.value = entry >> 32u;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void eoi()
|
private static void eoi()
|
||||||
|
@ -21,6 +21,7 @@ import hulk.pic;
|
|||||||
import hulk.acpi;
|
import hulk.acpi;
|
||||||
import hulk.apic;
|
import hulk.apic;
|
||||||
import hulk.rtc;
|
import hulk.rtc;
|
||||||
|
import hulk.pit;
|
||||||
|
|
||||||
extern extern(C) __gshared ubyte _hulk_bss_size;
|
extern extern(C) __gshared ubyte _hulk_bss_size;
|
||||||
|
|
||||||
@ -75,6 +76,7 @@ void hulk_start()
|
|||||||
acpi.initialize(hulk_header.bootinfo.acpi_xsdt_phys);
|
acpi.initialize(hulk_header.bootinfo.acpi_xsdt_phys);
|
||||||
apic.initialize();
|
apic.initialize();
|
||||||
rtc.initialize();
|
rtc.initialize();
|
||||||
|
pit.initialize();
|
||||||
sti();
|
sti();
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -13,8 +13,8 @@ import hulk.rtc;
|
|||||||
|
|
||||||
struct idt
|
struct idt
|
||||||
{
|
{
|
||||||
/* IRQ 0 is interrupt 32 (0x20). */
|
/* The I/O APIC is configured to map IRQ 0 to interrupt 64 (0x40). */
|
||||||
public static enum ulong INT_RTC = 0x28u; /* IRQ 8 */
|
public static enum ulong INT_RTC = 0x48u; /* IRQ 8 */
|
||||||
|
|
||||||
public static enum ulong INT_LAPIC_TIMER = 0x70u;
|
public static enum ulong INT_LAPIC_TIMER = 0x70u;
|
||||||
public static enum ulong INT_LAPIC_LINT0 = 0x71u;
|
public static enum ulong INT_LAPIC_LINT0 = 0x71u;
|
||||||
|
42
src/hulk/pit.d
Normal file
42
src/hulk/pit.d
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* PIT (Programmable Interval Timer) functionality.
|
||||||
|
*/
|
||||||
|
module hulk.pit;
|
||||||
|
|
||||||
|
import hulk.cpu;
|
||||||
|
import hulk.klog;
|
||||||
|
|
||||||
|
struct pit
|
||||||
|
{
|
||||||
|
/** PIT input frequency in 1/1000 Hz. */
|
||||||
|
private enum ulong PIT_FREQUENCY_1000HZ = 1_193_181_667u;
|
||||||
|
private enum ulong TARGET_INTERRUPT_HZ = 100u;
|
||||||
|
private enum ulong TARGET_INTERRUPT_1000HZ = TARGET_INTERRUPT_HZ * 1000u;
|
||||||
|
private enum ulong PIT_DIVIDER = (PIT_FREQUENCY_1000HZ + TARGET_INTERRUPT_1000HZ / 2u) / TARGET_INTERRUPT_1000HZ;
|
||||||
|
|
||||||
|
/** PIT channel 0 I/O port. */
|
||||||
|
private enum ubyte PORT_CH_0 = 0x40u;
|
||||||
|
/** PIT channel 1 I/O port. */
|
||||||
|
private enum ubyte PORT_CH_1 = 0x41u;
|
||||||
|
/** PIT channel 2 I/O port. */
|
||||||
|
private enum ubyte PORT_CH_2 = 0x42u;
|
||||||
|
/** PIT mode/command register I/O port. */
|
||||||
|
private enum ubyte PORT_MC = 0x43u;
|
||||||
|
|
||||||
|
private enum ubyte MC_CH_0 = 0x00u;
|
||||||
|
private enum ubyte MC_LO_HI = 0x30u;
|
||||||
|
private enum ubyte MC_RATE_GENERATOR = 0x04u;
|
||||||
|
private enum ubyte MC_BINARY = 0x00u;
|
||||||
|
|
||||||
|
public static void initialize()
|
||||||
|
{
|
||||||
|
out8(PORT_MC, MC_CH_0 | MC_LO_HI | MC_RATE_GENERATOR | MC_BINARY);
|
||||||
|
out8(PORT_CH_0, PIT_DIVIDER & 0xFFu);
|
||||||
|
out8(PORT_CH_0, PIT_DIVIDER >> 8u);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isr()
|
||||||
|
{
|
||||||
|
klog.writefln("PIT ISR");
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user