More work on APIC.
parent
05b3631004
commit
54a5e96722
|
@ -115,7 +115,7 @@ hdd.img: kernel.bin
|
|||
|
||||
emulate-nohdd-debug: kernel.bin
|
||||
@echo "[i] Starting GDB..."
|
||||
@echo -e "target remote localhost:1234\n" > gdbcommands
|
||||
@echo -e "file kernel.bin\ntarget remote localhost:1234\n" > gdbcommands
|
||||
@terminal -x /bin/bash -c "sleep 1 && gdb -x gdbcommands && rm gdbcommands" &
|
||||
@echo "[i] Starting QEmu..."
|
||||
@qemu-system-x86_64 --no-kvm -S -gdb tcp::1234 -d int -smp 4 -kernel ../Loader/loader.bin -initrd kernel.bin
|
||||
|
|
|
@ -16,6 +16,25 @@ x(7); \
|
|||
x(8); \
|
||||
x(9); \
|
||||
|
||||
//Do something 10 times
|
||||
#define PPHAX_DO16(x) \
|
||||
x(0); \
|
||||
x(1); \
|
||||
x(2); \
|
||||
x(3); \
|
||||
x(4); \
|
||||
x(5); \
|
||||
x(6); \
|
||||
x(7); \
|
||||
x(8); \
|
||||
x(9); \
|
||||
x(10); \
|
||||
x(11); \
|
||||
x(12); \
|
||||
x(13); \
|
||||
x(14); \
|
||||
x(15); \
|
||||
|
||||
//Do something 256 times
|
||||
#define PPHAX_DO256(x) \
|
||||
x(0); \
|
||||
|
|
|
@ -132,31 +132,31 @@ CPCIDevice::CPCIDevice(u16 Bus, u16 Device)
|
|||
u32 Value = ConfigRead(0, i);
|
||||
((u32 *)&m_Header)[i/4] = Value;
|
||||
}
|
||||
kprintf(" VID: %h, PID: %h\n", m_Header.VendorID, m_Header.ProductID);
|
||||
kprintf(" Type: ");
|
||||
switch (m_Header.HeaderType)
|
||||
{
|
||||
case 0x00:
|
||||
kprintf("Generic Device\n");
|
||||
break;
|
||||
case 0x01:
|
||||
kprintf("PCI-PCI Bridge\n");
|
||||
break;
|
||||
case 0x02:
|
||||
kprintf("CardBus Bridge\n");
|
||||
break;
|
||||
default:
|
||||
kprintf("Unknown.\n");
|
||||
break;
|
||||
}
|
||||
// kprintf(" VID: %h, PID: %h\n", m_Header.VendorID, m_Header.ProductID);
|
||||
// kprintf(" Type: ");
|
||||
// switch (m_Header.HeaderType)
|
||||
// {
|
||||
// case 0x00:
|
||||
// kprintf("Generic Device\n");
|
||||
// break;
|
||||
// case 0x01:
|
||||
// kprintf("PCI-PCI Bridge\n");
|
||||
// break;
|
||||
// case 0x02:
|
||||
// kprintf("CardBus Bridge\n");
|
||||
// break;
|
||||
// default:
|
||||
// kprintf("Unknown.\n");
|
||||
// break;
|
||||
// }
|
||||
|
||||
kprintf(" Info: ");
|
||||
const s8 *VendorName, *ProductName, *ProductDescription;
|
||||
if (CPCIManager::DBGetVendor(m_Header.VendorID, &VendorName))
|
||||
kprintf("%s", VendorName);
|
||||
if (CPCIManager::DBGetProduct(m_Header.VendorID, m_Header.ProductID, &ProductName, &ProductDescription))
|
||||
kprintf(" %s %s", ProductName, ProductDescription);
|
||||
kprintf("\n");
|
||||
// kprintf(" Info: ");
|
||||
// const s8 *VendorName, *ProductName, *ProductDescription;
|
||||
// if (CPCIManager::DBGetVendor(m_Header.VendorID, &VendorName))
|
||||
// kprintf("%s", VendorName);
|
||||
// if (CPCIManager::DBGetProduct(m_Header.VendorID, m_Header.ProductID, &ProductName, &ProductDescription))
|
||||
// kprintf(" %s %s", ProductName, ProductDescription);
|
||||
// kprintf("\n");
|
||||
|
||||
switch (m_Header.HeaderType)
|
||||
{
|
||||
|
@ -173,11 +173,11 @@ CPCIDevice::CPCIDevice(u16 Bus, u16 Device)
|
|||
if (Value == 0)
|
||||
continue;
|
||||
|
||||
kprintf(" BAR%i: ", i);
|
||||
// kprintf(" BAR%i: ", i);
|
||||
if (Value & 1)
|
||||
{
|
||||
kprintf("I/O ");
|
||||
kprintf("Value: %x\n", Value);
|
||||
// kprintf("I/O ");
|
||||
// kprintf("Value: %x\n", Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -186,13 +186,13 @@ CPCIDevice::CPCIDevice(u16 Bus, u16 Device)
|
|||
kprintf(" non 32-bit, ignoring.\n");
|
||||
continue;
|
||||
}
|
||||
kprintf("Memory ");
|
||||
kprintf("Value: %x ", Value);
|
||||
// kprintf("Memory ");
|
||||
// kprintf("Value: %x ", Value);
|
||||
ConfigWrite(0, 0x10 + (i * 4), 0xFFFFFFFF);
|
||||
u32 NewValue = ConfigRead(0, 0x10 + (i * 4));
|
||||
// u32 NewValue = ConfigRead(0, 0x10 + (i * 4));
|
||||
ConfigWrite(0, 0x10 + (i * 4), Value);
|
||||
u32 Size = ~(NewValue & ~(0b1111)) + 1;
|
||||
kprintf("Size: %x (%ik)\n", Size, Size/1024);
|
||||
// u32 Size = ~(NewValue & ~(0b1111)) + 1;
|
||||
// kprintf("Size: %x (%ik)\n", Size, Size/1024);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -2,11 +2,33 @@
|
|||
#include "Tier0/system.h"
|
||||
#include "Tier0/kstdio.h"
|
||||
#include "Tier0/paging.h"
|
||||
#include "Tier0/interrupts.h"
|
||||
#include "Tier0/panic.h"
|
||||
|
||||
#define APIC_SET32(field, value) do { *((u32 *)(g_APIC.LAPIC + field)) = (value);} while(0)
|
||||
#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)
|
||||
|
||||
struct {
|
||||
T_APIC_LAPIC *APIC;
|
||||
void *LAPIC;
|
||||
} g_APIC;
|
||||
|
||||
void apic_eoi(void)
|
||||
{
|
||||
APIC_SET32(APIC_EOI, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void apic_spurious_interrupt(T_ISR_REGISTERS Registers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void apic_timer_interrupt(T_ISR_REGISTERS Registers)
|
||||
{
|
||||
kprintf("ohai\n");
|
||||
}
|
||||
|
||||
|
||||
void apic_enable_lapic(void)
|
||||
{
|
||||
u64 APICMSR = system_msr_get(0x1B);
|
||||
|
@ -16,13 +38,62 @@ void apic_enable_lapic(void)
|
|||
else
|
||||
{
|
||||
kprintf("[i] APIC enable flag not set in APIC MSR. Trying to set it...\n");
|
||||
APICMSR |= (1 << 22);
|
||||
APICMSR |= (1 << 11);
|
||||
system_msr_set(0x1B, APICMSR);
|
||||
}
|
||||
|
||||
u64 Virtual = paging_minivmm_allocate();
|
||||
kprintf("[i] LAPIC will be @0x%x.\n", Virtual);
|
||||
paging_map_page(Virtual, 0xFEE00000);
|
||||
|
||||
g_APIC.APIC = (T_APIC_LAPIC *)Virtual;
|
||||
|
||||
g_APIC.LAPIC = (void *)Virtual;
|
||||
|
||||
// reset APIC to a kinda known state
|
||||
APIC_SET32A(APIC_DFR, 0xFFFFFFFF);
|
||||
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_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_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
|
||||
|
||||
// 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
|
||||
|
||||
// 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...
|
||||
APIC_SET32(APIC_TimerICR, 0xFFFFFFFF);
|
||||
// for(;;)
|
||||
// {
|
||||
// kprintf("APIC: %x\n", APIC_GET32(APIC_TimerICR));
|
||||
// }
|
||||
|
||||
// wait for the PIT counter to reach zero...
|
||||
while (!(kinb(0x61) & 0x020));
|
||||
// disable APIC timer
|
||||
APIC_SET32(APIC_LVTTimer, 0x10000); // mask bit
|
||||
kprintf("[i] Timer reached zero, APIC Timer @%x.\n", APIC_GET32(APIC_TimerICR));
|
||||
}
|
||||
|
||||
#undef APIC_SET
|
|
@ -46,6 +46,9 @@ void exceptions_floating_point_isr(T_ISR_REGISTERS Registers)
|
|||
void exceptions_general_protection_isr(T_ISR_REGISTERS_ERR Registers)
|
||||
{
|
||||
T_ISR_REGISTERS NoErr;
|
||||
kprintf("general protection fault %x.\n", Registers.Error);
|
||||
__asm__ __volatile__("cli;");
|
||||
for (;;)
|
||||
RERR_TO_R(Registers, NoErr);
|
||||
PANIC_EX("General protection fault in kernel task.", NoErr);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "Tier0/paging.h"
|
||||
#include "Tier0/kstdio.h"
|
||||
#include "Tier0/pic.h"
|
||||
#include "preprocessor_hacks.h"
|
||||
|
||||
struct {
|
||||
// IDT
|
||||
|
@ -113,10 +114,46 @@ void interrupts_setup_isr(u8 Interrupt, void *Handler, \
|
|||
*((u32*)&g_idt_entries[Interrupt]) = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
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
|
||||
koutb(0xA0, 0x11); // - " -
|
||||
|
||||
koutb(0x21, 0x20); // master from 0x20
|
||||
koutb(0xA1, 0x28); // slave from 0x28
|
||||
koutb(0x21, 0x04); // slave PIC at IRQ2
|
||||
koutb(0xA1, 0x02); // cascade
|
||||
koutb(0x21, 0x01); // 8086 mode
|
||||
koutb(0xA1, 0x01); // 8086 mode
|
||||
|
||||
// restore masks
|
||||
koutb(0x21, MaskMaster);
|
||||
koutb(0xA1, MaskSlave);
|
||||
}
|
||||
|
||||
#define GENERIC_IRQ_DEF(i) void interrupts_irq##i##_isr(void) { kprintf("[w] OOPS: Unhandled IRQ"#i"\n"); }
|
||||
#define GENERIC_IRQ_BIND(i) interrupts_setup_isr(0x20 + i, (void *)interrupts_irq##i##_isr, E_INTERRUPTS_RING0)
|
||||
PPHAX_DO16(GENERIC_IRQ_DEF);
|
||||
|
||||
void interrupts_init_simple(void)
|
||||
{
|
||||
interrupts_init_idt();
|
||||
interrupts_lidt();
|
||||
interrupts_remap_pic();
|
||||
|
||||
// generic IRQ handlers
|
||||
PPHAX_DO16(GENERIC_IRQ_BIND);
|
||||
|
||||
// enable hardware interrupts
|
||||
__asm__ __volatile__("sti;");
|
||||
kprintf("[i] Hardware interrupts enabled.\n");
|
||||
}
|
||||
/*
|
||||
void interrupts_irq_finish(u8 IRQ)
|
||||
|
|
Loading…
Reference in New Issue