Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a39341a83 | ||
|
|
42ab6f396d | ||
|
|
58d685a15b | ||
|
|
d49f9e32cd |
No files matched your search
+27
-5
@@ -52,31 +52,53 @@ 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
|
||||||
* vector to 0xFF. */
|
* vector to 0xFF. */
|
||||||
apic_registers.spurious_interrupt_vector.value = 0x1FFu;
|
apic_registers.spurious_interrupt_vector.value = 0x1FFu;
|
||||||
apic_registers.lvt_timer.value = idt.EXCEPTION_LAPIC_TIMER | PERIODIC_MODE;
|
// apic_registers.lvt_timer.value = idt.INT_LAPIC_TIMER | PERIODIC_MODE;
|
||||||
apic_registers.lvt_lint[0].value = idt.EXCEPTION_LAPIC_LINT0;
|
apic_registers.lvt_timer.value = idt.INT_LAPIC_TIMER;
|
||||||
apic_registers.lvt_lint[1].value = idt.EXCEPTION_LAPIC_LINT1;
|
apic_registers.lvt_lint[0].value = idt.INT_LAPIC_LINT0;
|
||||||
apic_registers.divide_configuration.value = 3u;
|
apic_registers.lvt_lint[1].value = idt.INT_LAPIC_LINT1;
|
||||||
|
// apic_registers.divide_configuration.value = 3u;
|
||||||
|
configure_io_apic_irq(8u, 0x48u);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void eoi()
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void eoi()
|
||||||
{
|
{
|
||||||
apic_registers.eoi.value = 0u;
|
apic_registers.eoi.value = 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void isr(ulong vector)
|
public static void isr(ulong vector)
|
||||||
{
|
{
|
||||||
|
klog.writefln("APIC ISR 0x%x", vector);
|
||||||
eoi();
|
eoi();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,8 @@ import ldc.llvmasm;
|
|||||||
import hulk.pic;
|
import hulk.pic;
|
||||||
import hulk.acpi;
|
import hulk.acpi;
|
||||||
import hulk.apic;
|
import hulk.apic;
|
||||||
|
import hulk.rtc;
|
||||||
|
import hulk.pit;
|
||||||
|
|
||||||
extern extern(C) __gshared ubyte _hulk_bss_size;
|
extern extern(C) __gshared ubyte _hulk_bss_size;
|
||||||
|
|
||||||
@@ -73,6 +75,8 @@ void hulk_start()
|
|||||||
pic.initialize();
|
pic.initialize();
|
||||||
acpi.initialize(hulk_header.bootinfo.acpi_xsdt_phys);
|
acpi.initialize(hulk_header.bootinfo.acpi_xsdt_phys);
|
||||||
apic.initialize();
|
apic.initialize();
|
||||||
|
rtc.initialize();
|
||||||
|
pit.initialize();
|
||||||
sti();
|
sti();
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
|
|||||||
+18
-7
@@ -9,12 +9,16 @@ import hulk.fb;
|
|||||||
import hulk.console;
|
import hulk.console;
|
||||||
import hulk.klog;
|
import hulk.klog;
|
||||||
import hulk.apic;
|
import hulk.apic;
|
||||||
|
import hulk.rtc;
|
||||||
|
|
||||||
struct idt
|
struct idt
|
||||||
{
|
{
|
||||||
public static enum ulong EXCEPTION_LAPIC_TIMER = 0x70u;
|
/* The I/O APIC is configured to map IRQ 0 to interrupt 64 (0x40). */
|
||||||
public static enum ulong EXCEPTION_LAPIC_LINT0 = 0x71u;
|
public static enum ulong INT_RTC = 0x48u; /* IRQ 8 */
|
||||||
public static enum ulong EXCEPTION_LAPIC_LINT1 = 0x72u;
|
|
||||||
|
public static enum ulong INT_LAPIC_TIMER = 0x70u;
|
||||||
|
public static enum ulong INT_LAPIC_LINT0 = 0x71u;
|
||||||
|
public static enum ulong INT_LAPIC_LINT1 = 0x72u;
|
||||||
|
|
||||||
struct idtr_t
|
struct idtr_t
|
||||||
{
|
{
|
||||||
@@ -99,12 +103,19 @@ struct idt
|
|||||||
|
|
||||||
public extern(C) void isr(ulong vector, ulong arg)
|
public extern(C) void isr(ulong vector, ulong arg)
|
||||||
{
|
{
|
||||||
if ((idt.EXCEPTION_LAPIC_TIMER <= vector) && (vector <= idt.EXCEPTION_LAPIC_LINT1))
|
switch (vector)
|
||||||
{
|
{
|
||||||
|
case idt.INT_RTC:
|
||||||
|
rtc.isr();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case idt.INT_LAPIC_TIMER:
|
||||||
|
case idt.INT_LAPIC_LINT0:
|
||||||
|
case idt.INT_LAPIC_LINT1:
|
||||||
apic.isr(vector);
|
apic.isr(vector);
|
||||||
}
|
break;
|
||||||
else
|
|
||||||
{
|
default:
|
||||||
console.clear();
|
console.clear();
|
||||||
fb.clear(0xFF8000u);
|
fb.clear(0xFF8000u);
|
||||||
klog.writefln("ISR %u, 0x%x", vector, arg);
|
klog.writefln("ISR %u, 0x%x", vector, arg);
|
||||||
|
|||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* RTC (Real-Time Clock) functionality.
|
||||||
|
*/
|
||||||
|
module hulk.rtc;
|
||||||
|
|
||||||
|
import hulk.cpu;
|
||||||
|
import hulk.klog;
|
||||||
|
import hulk.apic;
|
||||||
|
|
||||||
|
struct rtc
|
||||||
|
{
|
||||||
|
private enum ubyte PORT_SELECT = 0x70u;
|
||||||
|
private enum ubyte PORT_DATA = 0x71u;
|
||||||
|
|
||||||
|
private enum ubyte DISABLE_NMI = 0x80u;
|
||||||
|
|
||||||
|
private enum ubyte SR_A = 0xAu;
|
||||||
|
private enum ubyte SR_B = 0xBu;
|
||||||
|
private enum ubyte SR_C = 0xCu;
|
||||||
|
|
||||||
|
private enum ubyte SR_B_ENABLE_IRQ = 0x40u;
|
||||||
|
|
||||||
|
public static void initialize()
|
||||||
|
{
|
||||||
|
/* Enable IRQ 8 to receive RTC interrupts. */
|
||||||
|
out8(PORT_SELECT, DISABLE_NMI | SR_B);
|
||||||
|
ubyte sr_b = in8(PORT_DATA);
|
||||||
|
out8(PORT_SELECT, DISABLE_NMI | SR_B);
|
||||||
|
out8(PORT_DATA, sr_b | SR_B_ENABLE_IRQ);
|
||||||
|
|
||||||
|
out8(PORT_SELECT, DISABLE_NMI | SR_A);
|
||||||
|
klog.writefln("SR_A = 0x%x", in8(PORT_DATA));
|
||||||
|
|
||||||
|
/* Send EOI to enable more RTC interrupts and re-enable NMIs. */
|
||||||
|
eoi();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void eoi()
|
||||||
|
{
|
||||||
|
/* Read from status register C to clear the interrupt. */
|
||||||
|
out8(PORT_SELECT, SR_C);
|
||||||
|
in8(PORT_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isr()
|
||||||
|
{
|
||||||
|
static __gshared ulong count;
|
||||||
|
static __gshared ulong seconds;
|
||||||
|
count++;
|
||||||
|
if ((count % 1024) == 0u)
|
||||||
|
{
|
||||||
|
seconds++;
|
||||||
|
klog.writefln("Seconds: %u", seconds);
|
||||||
|
}
|
||||||
|
eoi();
|
||||||
|
apic.eoi();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user