parent
54a5e96722
commit
0fbd91d599
|
@ -17,7 +17,7 @@ void kputs(const s8 *szString);
|
|||
void kputch(const s8 Character);
|
||||
void kclear(void);
|
||||
void kprint(const s8 *szString);
|
||||
void kputi(s32 Number);
|
||||
void kputi(s64 Number);
|
||||
void kprintf(const s8 *Format, ...);
|
||||
void kdump(u8 *bData, u32 Length);
|
||||
void kprint_hex(u64 Number);
|
||||
|
|
|
@ -9,8 +9,12 @@
|
|||
#define APIC_GET32(field) (*((u32*)(g_APIC.LAPIC + field)))
|
||||
#define APIC_SET32A(field, value) do { APIC_SET32(field, value); ASSERT(APIC_GET32(field) == (value));} while(0)
|
||||
|
||||
#define APIC_CALIBRATION_SAMPLES 8
|
||||
struct {
|
||||
void *LAPIC;
|
||||
volatile u32 CalibrationCounter;
|
||||
volatile u32 CalibrationSamples[APIC_CALIBRATION_SAMPLES];
|
||||
u32 BusSpeed;
|
||||
} g_APIC;
|
||||
|
||||
void apic_eoi(void)
|
||||
|
@ -26,8 +30,26 @@ void apic_spurious_interrupt(T_ISR_REGISTERS Registers)
|
|||
void apic_timer_interrupt(T_ISR_REGISTERS Registers)
|
||||
{
|
||||
kprintf("ohai\n");
|
||||
apic_eoi();
|
||||
}
|
||||
|
||||
void apic_calibration_interrupt(T_ISR_REGISTERS Registers)
|
||||
{
|
||||
u32 Sample = APIC_GET32(APIC_TimerCCR);
|
||||
if (g_APIC.CalibrationCounter >= APIC_CALIBRATION_SAMPLES)
|
||||
{
|
||||
koutb(0x20, 0x20);
|
||||
return;
|
||||
}
|
||||
g_APIC.CalibrationSamples[g_APIC.CalibrationCounter] = Sample;
|
||||
g_APIC.CalibrationCounter++;
|
||||
|
||||
// is the APIC timer 0? well shit.
|
||||
if (Sample == 0)
|
||||
PANIC("APIC Calibration look reached null timer value. Too many saples?");
|
||||
|
||||
koutb(0x20, 0x20);
|
||||
}
|
||||
|
||||
void apic_enable_lapic(void)
|
||||
{
|
||||
|
@ -46,6 +68,10 @@ void apic_enable_lapic(void)
|
|||
kprintf("[i] LAPIC will be @0x%x.\n", Virtual);
|
||||
paging_map_page(Virtual, 0xFEE00000);
|
||||
|
||||
// prepare interrupts ..
|
||||
interrupts_setup_isr(39, (void *)apic_spurious_interrupt, E_INTERRUPTS_RING0);
|
||||
interrupts_setup_isr(200, (void *)apic_timer_interrupt, E_INTERRUPTS_RING0);
|
||||
|
||||
g_APIC.LAPIC = (void *)Virtual;
|
||||
|
||||
// reset APIC to a kinda known state
|
||||
|
@ -53,47 +79,52 @@ void apic_enable_lapic(void)
|
|||
APIC_SET32(APIC_LDR, (APIC_GET32(APIC_LDR)&0x00FFFFFF)|1);
|
||||
APIC_SET32A(APIC_LVTTimer, 0x10000); // mask bit
|
||||
APIC_SET32A(APIC_LVTPerformanceCounter, 4 << 8); // NMI bit
|
||||
APIC_SET32A(APIC_LVTLINT0, 0x10000); // mask bit
|
||||
APIC_SET32A(APIC_LVTLINT0, 0x10000); // mask vit
|
||||
APIC_SET32A(APIC_LVTLINT1, 0x10000); // mask bit
|
||||
APIC_SET32A(APIC_TPR, 0); // task priority = 0 (accept all)
|
||||
|
||||
// prepare interrupts ..
|
||||
interrupts_setup_isr(39, (void *)apic_spurious_interrupt, E_INTERRUPTS_RING0);
|
||||
interrupts_setup_isr(32, (void *)apic_timer_interrupt, E_INTERRUPTS_RING0);
|
||||
|
||||
APIC_SET32A(APIC_SVR, 39 | 0x100); // spurious interrupt + sw enable bit
|
||||
APIC_SET32A(APIC_LVTTimer, 32); // apic timer interrupt
|
||||
APIC_SET32A(APIC_LVTTimer, 0x1000); // mask bit
|
||||
APIC_SET32A(APIC_TimerDCR, 0x03); // timer divider = bus speed / 16
|
||||
|
||||
kprintf("[i] LAPIC ready to calibrate timer.\n");
|
||||
|
||||
// calibration time! let's use the PIT
|
||||
koutb(0x61, kinb(0x61) | 0xFD); // disable speaker
|
||||
koutb(0x43, 0xB2); // one shot, channel 2
|
||||
// let's unmask IRQ0 only
|
||||
koutb(0x21, 0xFE);
|
||||
koutb(0xA1, 0xFF);
|
||||
|
||||
// to setup a 100Hz loop, wee need a divider of...
|
||||
// 1193180 / 100 Hz = 11931 = 0x2e9b
|
||||
koutb(0x42, 0x9b); // write low byte
|
||||
kinb(0x60); // wait a bit
|
||||
koutb(0x42, 0x2e); // write high bte
|
||||
// let's make LINT0 trigger an extINT (yay PIC-time)
|
||||
APIC_SET32(APIC_LVTLINT0, 0x8700);
|
||||
|
||||
// now we are ready to fire the PIT timer
|
||||
kprintf("[i] Firing PIT for calibration...\n");
|
||||
u8 Temporary = kinb(0x61) & 0xFE;
|
||||
koutb(0x61, Temporary); // gate low
|
||||
koutb(0x61, Temporary | 1); // gate high
|
||||
// don't forget to actually fire the APIC timer at the same time...
|
||||
// let's start the APIC timer and zero the calibration counter
|
||||
APIC_SET32(APIC_TimerICR, 0xFFFFFFFF);
|
||||
// for(;;)
|
||||
// {
|
||||
// kprintf("APIC: %x\n", APIC_GET32(APIC_TimerICR));
|
||||
// }
|
||||
g_APIC.CalibrationCounter = 0;
|
||||
|
||||
// wait for the PIT counter to reach zero...
|
||||
while (!(kinb(0x61) & 0x020));
|
||||
// disable APIC timer
|
||||
// now let's program the PIT to run a channel0 (IRQ0) timer with a 100Hz loop
|
||||
interrupts_setup_isr(32, (void *)apic_calibration_interrupt, E_INTERRUPTS_RING0);
|
||||
koutb(0x43, 0x36);
|
||||
koutb(0x40, 0x0B);
|
||||
koutb(0x40, 0xE9);
|
||||
|
||||
// the timer is now running!
|
||||
while (g_APIC.CalibrationCounter < APIC_CALIBRATION_SAMPLES) {};
|
||||
|
||||
// enough samples, let's clean up
|
||||
kprintf("[i] Calibration loop finished.\n");
|
||||
koutb(0x21, 0xFF);
|
||||
koutb(0x21, 0xFF);
|
||||
APIC_SET32(APIC_LVTLINT0, 0x1000); // mask bit
|
||||
APIC_SET32(APIC_LVTTimer, 0x10000); // mask bit
|
||||
kprintf("[i] Timer reached zero, APIC Timer @%x.\n", APIC_GET32(APIC_TimerICR));
|
||||
interrupts_setup_isr(32, (void *)apic_timer_interrupt, E_INTERRUPTS_RING0);
|
||||
|
||||
u64 Average = 0;
|
||||
for (u32 i = 0; i < APIC_CALIBRATION_SAMPLES -1; i++)
|
||||
Average += (g_APIC.CalibrationSamples[i] - g_APIC.CalibrationSamples[i + 1]);
|
||||
|
||||
Average /= (APIC_CALIBRATION_SAMPLES - 1);
|
||||
g_APIC.BusSpeed = (Average * 16 * 50)/(1000000);
|
||||
kprintf("[i] Bus speed %iMHz.\n", g_APIC.BusSpeed);
|
||||
}
|
||||
|
||||
#undef APIC_SET
|
|
@ -119,26 +119,40 @@ void interrupts_remap_pic(void)
|
|||
{
|
||||
// remap the PIC IRQ's to 0x20-0x27 and 0x28-0x2F
|
||||
|
||||
// save masks
|
||||
u8 MaskMaster = kinb(0x21);
|
||||
u8 MaskSlave = kinb(0xA1);
|
||||
|
||||
koutb(0x20, 0x11); // start initialization sequence
|
||||
kio_wait();
|
||||
koutb(0xA0, 0x11); // - " -
|
||||
kio_wait();
|
||||
|
||||
koutb(0x21, 0x20); // master from 0x20
|
||||
kio_wait();
|
||||
koutb(0xA1, 0x28); // slave from 0x28
|
||||
kio_wait();
|
||||
koutb(0x21, 0x04); // slave PIC at IRQ2
|
||||
kio_wait();
|
||||
koutb(0xA1, 0x02); // cascade
|
||||
kio_wait();
|
||||
koutb(0x21, 0x01); // 8086 mode
|
||||
kio_wait();
|
||||
koutb(0xA1, 0x01); // 8086 mode
|
||||
kio_wait();
|
||||
|
||||
// restore masks
|
||||
koutb(0x21, MaskMaster);
|
||||
koutb(0xA1, MaskSlave);
|
||||
// set masks to accept no IRQs
|
||||
koutb(0x21, 0xFF);
|
||||
kio_wait();
|
||||
koutb(0xA1, 0xFF);
|
||||
kio_wait();
|
||||
}
|
||||
|
||||
#define GENERIC_IRQ_DEF(i) void interrupts_irq##i##_isr(void) { kprintf("[w] OOPS: Unhandled IRQ"#i"\n"); }
|
||||
void interrupts_eoi_pic(u8 IRQ)
|
||||
{
|
||||
if (IRQ > 7)
|
||||
koutb(0xA0, 0x20);
|
||||
|
||||
koutb(0x20, 0x20);
|
||||
}
|
||||
|
||||
#define GENERIC_IRQ_DEF(i) void interrupts_irq##i##_isr(void) { kprintf("[w] OOPS: Unhandled IRQ"#i"\n"); interrupts_eoi_pic(i); }
|
||||
#define GENERIC_IRQ_BIND(i) interrupts_setup_isr(0x20 + i, (void *)interrupts_irq##i##_isr, E_INTERRUPTS_RING0)
|
||||
PPHAX_DO16(GENERIC_IRQ_DEF);
|
||||
|
||||
|
|
|
@ -95,8 +95,8 @@ void kmain_newstack(void)
|
|||
interrupts_init_simple();
|
||||
exceptions_init_simple();
|
||||
apic_enable_lapic();
|
||||
for (;;) {}
|
||||
heap_init_simple();
|
||||
|
||||
// enable FPU/SSE...
|
||||
__asm__ volatile(
|
||||
"movq %cr0, %rax;"
|
||||
|
|
|
@ -58,14 +58,14 @@ void kio_wait(void)
|
|||
__asm__ volatile("jmp 1f;1:jmp 1f;1:");
|
||||
}
|
||||
|
||||
void kputi(s32 Number)
|
||||
void kputi(s64 Number)
|
||||
{
|
||||
s32 Sign, i;
|
||||
s64 Sign, i;
|
||||
|
||||
if ((Sign = Number) < 0)
|
||||
Number = -Number;
|
||||
|
||||
u8 szString[11];
|
||||
u8 szString[21];
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
|
@ -106,10 +106,10 @@ void kprintf(const s8 *szFormat, ...)
|
|||
kputs(va_arg(ap, s8*));
|
||||
break;
|
||||
case 'i':
|
||||
kputi(va_arg(ap, s32));
|
||||
kputi(va_arg(ap, s64));
|
||||
break;
|
||||
case 'u':
|
||||
kputi(va_arg(ap, u32));
|
||||
kputi(va_arg(ap, u64));
|
||||
break;
|
||||
case 'm': //dump
|
||||
; u8 *szString = va_arg(ap, u8*); //stupid gcc bug
|
||||
|
|
Loading…
Reference in New Issue