Add pit and rtc modules
This commit is contained in:
parent
b1a8f8d348
commit
676fd17bf5
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");
|
||||
}
|
||||
}
|
56
src/hulk/rtc.d
Normal file
56
src/hulk/rtc.d
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* RTC (Real-Time Clock) functionality.
|
||||
*/
|
||||
module hulk.rtc;
|
||||
|
||||
import hulk.cpu;
|
||||
import hulk.klog;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user