erythros/System/Drivers/Pci.HC

98 lines
No EOL
2.7 KiB
HolyC

#define PCI_INTH_MAX 16
U64 @pci_int_handler[PCI_INTH_MAX];
class @pci_info
{
U16 vendor_id;
U16 device_id;
U16 command;
U16 status;
U32 _class;
U32 bar[6];
U32 cap_pointer;
};
class @pci_cap
{
U8 cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */
U8 cap_next; /* Generic PCI field: next ptr. */
U8 cap_len; /* Generic PCI field: capability length */
U8 cfg_type; /* Identifies the structure. */
U8 bar; /* Where to find it. */
U8 padding[3]; /* Pad to full dword. */
U32 offset; /* Offset within bar. */
U32 length; /* Length of the structure, in bytes. */
};
U0 @get_pci_info(I64 i, @pci_info* pci)
{
I64 j;
pci->vendor_id = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x0) & 0xFFFF;
pci->device_id = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x0) >> 16;
pci->command = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x4) & 0xFFFF;
pci->status = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x4) >> 16;
pci->_class = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x8) >> 24;
for (j = 0; j < 6; j++)
pci->bar[j] = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], 0x10 + (0x04 * j));
}
U0 @get_pci_cap(I64 i, @pci_cap* cap, I64 idx)
{
I64 base = 0x40 + (idx * 16);
U32 u32;
u32 = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base);
cap->cap_vndr = u32.u8[0];
cap->cap_next = u32.u8[1];
cap->cap_len = u32.u8[2];
cap->cfg_type = u32.u8[3];
u32 = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base + 0x04);
cap->bar = u32.u8[0];
cap->offset = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base + 0x08);
cap->length = PCIReadU32(i.u8[2], i.u8[1], i.u8[0], base + 0x0c);
}
U0 @pci_reroute_interrupts(I64 base, I64 cpu)
{
I64 i;
U8* da = dev.uncached_alias + IOAPIC_REG;
U32* _d = dev.uncached_alias + IOAPIC_DATA;
for (i = 0; i < 4; i++) {
*da = IOREDTAB + i * 2 + 1;
*_d = dev.mp_apic_ids[cpu] << 24;
*da = IOREDTAB + i * 2;
*_d = 0x4000 + base + i;
}
}
I64 @pci_register_int_handler(U64 handler)
{
if (!handler)
return -1;
I64 i = 0;
while (@pci_int_handler[i])
i++;
if (i > PCI_INTH_MAX - 1)
return -1;
@pci_int_handler[i] = handler;
return 0;
}
interrupt U0 @pci_interrupt_handler()
{
I64 i;
for (i = 0; i < PCI_INTH_MAX; i++)
if (@pci_int_handler[i])
Call(@pci_int_handler[i]);
*(dev.uncached_alias + LAPIC_EOI)(U32*) = 0;
}
MemSet(&@pci_int_handler, NULL, sizeof(U64) * PCI_INTH_MAX);
IntEntrySet(0x40, &@pci_interrupt_handler, IDTET_IRQ);
IntEntrySet(0x41, &@pci_interrupt_handler, IDTET_IRQ);
IntEntrySet(0x42, &@pci_interrupt_handler, IDTET_IRQ);
IntEntrySet(0x43, &@pci_interrupt_handler, IDTET_IRQ);
@pci_reroute_interrupts(0x40, 0);
"pci ";