uh save this
This commit is contained in:
parent
516329d25c
commit
4334e21878
@ -8,7 +8,7 @@ lw_project(lcrash
|
|||||||
enable_language(ASM)
|
enable_language(ASM)
|
||||||
|
|
||||||
lw_add_executable(lcrashkern
|
lw_add_executable(lcrashkern
|
||||||
SOURCES main.c cmdline.c util.c lnxboot.c math.c debug/debug.c acpi/acpi.c efi/efi.c efi/guid.c efi/memmap.c gdb/gdb.c pci/pci.c mm/phys.c mm/kmalloc.c driver/sysbus.c
|
SOURCES main.c cmdline.c util.c lnxboot.c math.c debug/debug.c acpi/acpi.c efi/efi.c efi/guid.c efi/memmap.c gdb/gdb.c pci/pci.c mm/phys.c mm/kmalloc.c mm/virt.c driver/sysbus.c
|
||||||
)
|
)
|
||||||
add_executable(lcrashkernld IMPORTED)
|
add_executable(lcrashkernld IMPORTED)
|
||||||
set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld)
|
set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld)
|
||||||
|
@ -15,7 +15,7 @@ struct DebugExtendedDebugInformationBlock* DebugEDIB = 0;
|
|||||||
struct GdbDataBlock* DebugGDB = (struct GdbDataBlock*)0x100000;
|
struct GdbDataBlock* DebugGDB = (struct GdbDataBlock*)0x100000;
|
||||||
|
|
||||||
int DebugInitialize() {
|
int DebugInitialize() {
|
||||||
DebugEDIB = KernelHeapAlloc(sizeof(struct DebugExtendedDebugInformationBlock), 0);
|
DebugEDIB = KernelHeapAlloc(sizeof(struct DebugExtendedDebugInformationBlock), 1, 0);
|
||||||
if (DebugEDIB == 0) return -1;
|
if (DebugEDIB == 0) return -1;
|
||||||
|
|
||||||
DebugGDB->EDIB = DebugEDIB;
|
DebugGDB->EDIB = DebugEDIB;
|
||||||
|
@ -10,10 +10,10 @@ struct SysbusDevice* SysbusRootDevice = 0;
|
|||||||
* Create a new device description
|
* Create a new device description
|
||||||
*/
|
*/
|
||||||
struct SysbusDeviceDescription* SysbusCreateDeviceDescriptionInternal() {
|
struct SysbusDeviceDescription* SysbusCreateDeviceDescriptionInternal() {
|
||||||
struct SysbusDeviceDescription* Description = KernelHeapAlloc(sizeof(struct SysbusDeviceDescription), 0);
|
struct SysbusDeviceDescription* Description = KernelHeapAlloc(sizeof(struct SysbusDeviceDescription), 1, 0);
|
||||||
|
|
||||||
Description->DeviceName = 0;
|
Description->DeviceName = 0;
|
||||||
Description->Instances = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 0);
|
Description->Instances = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 1, 0);
|
||||||
Description->InstanceCount = 0;
|
Description->InstanceCount = 0;
|
||||||
Description->InstanceSlots = 4;
|
Description->InstanceSlots = 4;
|
||||||
Description->CreateDevice = 0;
|
Description->CreateDevice = 0;
|
||||||
@ -29,7 +29,7 @@ struct SysbusDeviceDescription* SysbusCreateDeviceDescriptionInternal() {
|
|||||||
void SysbusAttachChildDeviceInternal(struct SysbusDevice* Parent, struct SysbusDevice* Child) {
|
void SysbusAttachChildDeviceInternal(struct SysbusDevice* Parent, struct SysbusDevice* Child) {
|
||||||
// See if we need to grow the list
|
// See if we need to grow the list
|
||||||
if (Parent->ChildCount >= Parent->ChildSlots) {
|
if (Parent->ChildCount >= Parent->ChildSlots) {
|
||||||
struct SysbusDevice** NewList = KernelHeapAlloc(sizeof(struct SysbusDevice*) * Parent->ChildSlots * 2, 0);
|
struct SysbusDevice** NewList = KernelHeapAlloc(sizeof(struct SysbusDevice*) * Parent->ChildSlots * 2, 1, 0);
|
||||||
for (int i = 0; i < Parent->ChildCount; i++) {
|
for (int i = 0; i < Parent->ChildCount; i++) {
|
||||||
NewList[i] = Parent->Children[i];
|
NewList[i] = Parent->Children[i];
|
||||||
}
|
}
|
||||||
@ -59,12 +59,12 @@ struct SysbusDevice* SysbusCreateDeviceInternal(
|
|||||||
void* DeviceData,
|
void* DeviceData,
|
||||||
bool IsRootDevice
|
bool IsRootDevice
|
||||||
) {
|
) {
|
||||||
struct SysbusDevice* Device = KernelHeapAlloc(sizeof(struct SysbusDevice), 0);
|
struct SysbusDevice* Device = KernelHeapAlloc(sizeof(struct SysbusDevice), 1, 0);
|
||||||
Device->DeviceDescription = Description;
|
Device->DeviceDescription = Description;
|
||||||
Device->DeviceName = 0;
|
Device->DeviceName = 0;
|
||||||
Device->DeviceData = 0;
|
Device->DeviceData = 0;
|
||||||
Device->Parent = Parent;
|
Device->Parent = Parent;
|
||||||
Device->Children = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 0);
|
Device->Children = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 1, 0);
|
||||||
Device->ChildCount = 0;
|
Device->ChildCount = 0;
|
||||||
Device->ChildSlots = 4;
|
Device->ChildSlots = 4;
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ struct SysbusDevice* SysbusCreateDeviceInternal(
|
|||||||
|
|
||||||
// See if we need to grow the instance list
|
// See if we need to grow the instance list
|
||||||
if (Description->InstanceCount >= Description->InstanceSlots) {
|
if (Description->InstanceCount >= Description->InstanceSlots) {
|
||||||
struct SysbusDevice** NewList = KernelHeapAlloc(sizeof(struct SysbusDevice*) * Description->InstanceSlots * 2, 0);
|
struct SysbusDevice** NewList = KernelHeapAlloc(sizeof(struct SysbusDevice*) * Description->InstanceSlots * 2, 1, 0);
|
||||||
for (int i = 0; i < Description->InstanceCount; i++) {
|
for (int i = 0; i < Description->InstanceCount; i++) {
|
||||||
NewList[i] = Description->Instances[i];
|
NewList[i] = Description->Instances[i];
|
||||||
}
|
}
|
||||||
@ -122,7 +122,5 @@ void SysbusInitialize() {
|
|||||||
);
|
);
|
||||||
SysbusRootDevice->DeviceName = "Lcrash System Bus";
|
SysbusRootDevice->DeviceName = "Lcrash System Bus";
|
||||||
|
|
||||||
Panic("Failed to initialize system bus");
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <lcrash/cmdline.h>
|
#include <lcrash/cmdline.h>
|
||||||
#include <lcrash/debug/debug.h>
|
#include <lcrash/debug/debug.h>
|
||||||
#include <lcrash/driver/sysbus.h>
|
#include <lcrash/driver/sysbus.h>
|
||||||
|
#include <lcrash/mm/virt.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "lnxboot.h"
|
#include "lnxboot.h"
|
||||||
@ -38,6 +39,9 @@ void entry64(struct boot_params* BootParams) {
|
|||||||
// Initialize the extended debugging information block
|
// Initialize the extended debugging information block
|
||||||
if (DebugInitialize()) while (1) {}
|
if (DebugInitialize()) while (1) {}
|
||||||
|
|
||||||
|
// Initialize the virtual memory manager
|
||||||
|
VmemInitialize();
|
||||||
|
|
||||||
// Initialize the system bus
|
// Initialize the system bus
|
||||||
SysbusInitialize();
|
SysbusInitialize();
|
||||||
|
|
||||||
|
@ -136,11 +136,99 @@ int KernelHeapInitialize() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* KernelHeapAlloc(u32 Size, u32 Flags) {
|
/// Shamelessly copy pasted from function above
|
||||||
|
int KernelHeapGrow(struct KernelHeapZone* Zone, u32 Level, u32 Flags) {
|
||||||
|
// Allocate
|
||||||
|
struct PmemAllocation Block;
|
||||||
|
if (PmemAllocateBlock(1 << Level, &Block)) return -1;
|
||||||
|
|
||||||
|
// Make the frame block
|
||||||
|
struct KernelHeapBlock* FrameBlock = Block.Address;
|
||||||
|
FrameBlock->Prev = Zone->Last;
|
||||||
|
FrameBlock->PrevFree = Zone->LastFree;
|
||||||
|
FrameBlock->Size = sizeof(struct KernelHeapFrame);
|
||||||
|
FrameBlock->Free = false;
|
||||||
|
|
||||||
|
// Make the frame structure
|
||||||
|
struct KernelHeapFrame* Frame = Block.Address
|
||||||
|
+ sizeof(struct KernelHeapBlock);
|
||||||
|
Frame->Block = Block;
|
||||||
|
Frame->Size = 1 << Level;
|
||||||
|
Frame->NextFrame = 0;
|
||||||
|
Frame->PrevFrame = Zone->LastFrame;
|
||||||
|
|
||||||
|
// Make the root block
|
||||||
|
struct KernelHeapBlock* RootBlock = (struct KernelHeapBlock*)((void*)Frame + sizeof(struct KernelHeapFrame));
|
||||||
|
RootBlock->Prev = FrameBlock;
|
||||||
|
FrameBlock->Next = RootBlock;
|
||||||
|
FrameBlock->NextFree = RootBlock;
|
||||||
|
RootBlock->Next = 0;
|
||||||
|
RootBlock->PrevFree = Zone->LastFree;
|
||||||
|
RootBlock->NextFree = 0;
|
||||||
|
RootBlock->Free = true;
|
||||||
|
RootBlock->Size = (1 << Level)
|
||||||
|
- sizeof(struct KernelHeapBlock)
|
||||||
|
- sizeof(struct KernelHeapFrame)
|
||||||
|
- sizeof(struct KernelHeapBlock);
|
||||||
|
|
||||||
|
// Fill out the rest of the zone
|
||||||
|
Zone->LastFrame->NextFrame = Frame;
|
||||||
|
Zone->LastFrame = Frame;
|
||||||
|
Zone->Last->Next = FrameBlock;
|
||||||
|
for (struct KernelHeapBlock* Block = Zone->Last; Block != 0 && Block->NextFree == 0; Block = Block->Prev) Block->NextFree = RootBlock;
|
||||||
|
Zone->Last = RootBlock;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* KernelHeapAllocInternal(u32 Size, u32 Align, u32 Flags, u32 Iteration) {
|
||||||
|
u64 AlignMask = 0;
|
||||||
|
for (u32 i = 1; i < Align; i <<= 1) AlignMask |= i;
|
||||||
|
AlignMask = ~AlignMask;
|
||||||
|
|
||||||
// Find a free block
|
// Find a free block
|
||||||
for (struct KernelHeapZone* Zone = KernelHeapFirst; Zone != 0; Zone = Zone->Next) {
|
for (struct KernelHeapZone* Zone = KernelHeapFirst; Zone != 0; Zone = Zone->Next) {
|
||||||
for (struct KernelHeapBlock* Block = Zone->FirstFree; Block != 0; Block = Block->NextFree) {
|
for (struct KernelHeapBlock* Block = Zone->FirstFree; Block != 0; Block = Block->NextFree) {
|
||||||
if (Block->Size >= Size) {
|
if (Block->Size >= Size) {
|
||||||
|
u64 PaddingSize = 0;
|
||||||
|
if (Align > 1) {
|
||||||
|
// Align uses memory poorly
|
||||||
|
if (Block->Prev == 0) continue;
|
||||||
|
|
||||||
|
u64 BlockStart = (uptr)Block + sizeof(struct KernelHeapBlock);
|
||||||
|
u64 BlockEnd = BlockStart + Block->Size;
|
||||||
|
|
||||||
|
if (!(BlockStart < ((BlockStart + Align) & AlignMask) && BlockEnd > ((BlockStart + Align) & AlignMask))) continue;
|
||||||
|
|
||||||
|
PaddingSize = ((BlockStart + Align) & AlignMask) - BlockStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PaddingSize > 0) {
|
||||||
|
struct KernelHeapBlock* NewBlock = (struct KernelHeapBlock*)((void*)Block + PaddingSize);
|
||||||
|
NewBlock->Prev = Block->Prev;
|
||||||
|
NewBlock->Next = Block->Next;
|
||||||
|
NewBlock->PrevFree = Block->PrevFree;
|
||||||
|
NewBlock->NextFree = Block->NextFree;
|
||||||
|
NewBlock->Free = Block->Free;
|
||||||
|
NewBlock->Size = Block->Size - PaddingSize;
|
||||||
|
|
||||||
|
// This is incredibly slow
|
||||||
|
struct KernelHeapBlock* Next = Zone->First;
|
||||||
|
while (Next != 0) {
|
||||||
|
struct KernelHeapBlock* NextNext = Next->Next;
|
||||||
|
if (Next->Prev == Block) Next->Prev = NewBlock;
|
||||||
|
if (Next->Next == Block) Next->Next = NewBlock;
|
||||||
|
if (Next->PrevFree == Block) Next->PrevFree = NewBlock;
|
||||||
|
if (Next->NextFree == Block) Next->NextFree = NewBlock;
|
||||||
|
Next = NextNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GOD.
|
||||||
|
if (NewBlock->Prev != 0) NewBlock->Prev->Size += (uptr)Block + PaddingSize;
|
||||||
|
|
||||||
|
Block = NewBlock;
|
||||||
|
}
|
||||||
|
|
||||||
s64 SplitSize = (s64)Block->Size - Size - (sizeof(struct KernelHeapBlock) * 2) - 8;
|
s64 SplitSize = (s64)Block->Size - Size - (sizeof(struct KernelHeapBlock) * 2) - 8;
|
||||||
|
|
||||||
if (SplitSize > 0) {
|
if (SplitSize > 0) {
|
||||||
@ -179,7 +267,14 @@ void* KernelHeapAlloc(u32 Size, u32 Flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (Iteration < 3) {
|
||||||
|
KernelHeapGrow(KernelHeapLast, 20, 0);
|
||||||
|
return KernelHeapAllocInternal(Size, Align, Flags, Iteration + 1);
|
||||||
|
} else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* KernelHeapAlloc(u32 Size, u32 Align, u32 Flags) {
|
||||||
|
return KernelHeapAllocInternal(Size, Align, Flags, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelHeapFree(void* Address) {
|
void KernelHeapFree(void* Address) {
|
||||||
|
@ -10,7 +10,7 @@ int KernelHeapInitialize();
|
|||||||
/**
|
/**
|
||||||
* Allocate memory
|
* Allocate memory
|
||||||
*/
|
*/
|
||||||
void* KernelHeapAlloc(u32 Size, u32 Flags);
|
void* KernelHeapAlloc(u32 Size, u32 Align, u32 Flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free memory
|
* Free memory
|
||||||
|
74
lcrash/mm/virt.c
Normal file
74
lcrash/mm/virt.c
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include <lcrash/mm/virt.h>
|
||||||
|
|
||||||
|
#include <lcrash/mm/kmalloc.h>
|
||||||
|
#include <lcrash/debug/debug.h>
|
||||||
|
|
||||||
|
u64 (*VmemOriginalPML4)[512] = 0;
|
||||||
|
u64 (*VmemPML4)[512] = 0;
|
||||||
|
|
||||||
|
void VmemInitialize() {
|
||||||
|
// Copy control registers
|
||||||
|
u64 CR3;
|
||||||
|
asm ("mov %%cr3, %0" : "=r" (CR3));
|
||||||
|
|
||||||
|
u64 CR4;
|
||||||
|
asm ("mov %%cr4, %0" : "=r" (CR4));
|
||||||
|
|
||||||
|
if (CR4 & 0x800) Panic("5 Level paging not supported");
|
||||||
|
|
||||||
|
u64 (*OriginalPML4)[512] = (u64(*)[512])(CR3 & 0x0007fffffffff000);
|
||||||
|
u64 (*NewPML4)[512] = KernelHeapAlloc(sizeof(u64) * 512, 0x1000, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < 512; i++) {
|
||||||
|
if ((*OriginalPML4)[i] & 1) {
|
||||||
|
u64 (*OriginalPDPT)[512] = (u64(*)[512])(((*OriginalPML4)[i] & 0x0007fffffffff000));
|
||||||
|
u64 (*NewPDPT)[512] = KernelHeapAlloc(sizeof(u64) * 512, 0x1000, 0);
|
||||||
|
|
||||||
|
for (int j = 0; j < 512; j++) {
|
||||||
|
if ((*OriginalPDPT)[j] & 1) {
|
||||||
|
u64 (*OriginalPD)[512] = (u64(*)[512])(((*OriginalPDPT)[j] & 0x000ffffffffff000));
|
||||||
|
u64 (*NewPD)[512] = KernelHeapAlloc(sizeof(u64) * 512, 0x1000, 0);
|
||||||
|
|
||||||
|
for (int k = 0; k < 512; k++) {
|
||||||
|
if ((*OriginalPD)[k] & 1) {
|
||||||
|
u64 (*OriginalPT)[512] = (u64(*)[512])(((*OriginalPD)[k] & 0x000ffffffffff000));
|
||||||
|
u64 (*NewPT)[512] = KernelHeapAlloc(sizeof(u64) * 512, 0x1000, 0);
|
||||||
|
|
||||||
|
if ((s64)NewPT <= 0) Panic("Failed to allocate memory");
|
||||||
|
|
||||||
|
for (int l = 0; l < 512; l++) {
|
||||||
|
//if ((*OriginalPT)[l] & 1) {
|
||||||
|
// (*NewPT)[l] = (*OriginalPT)[l];
|
||||||
|
//} else (*NewPT)[l] = 0;*
|
||||||
|
(*NewPT)[l] = (*OriginalPT)[l] | 0x87;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewPT = (void*)((u64)OriginalPT | 0x87);
|
||||||
|
|
||||||
|
(*NewPD)[k] = (u64)NewPT;
|
||||||
|
} else (*NewPD)[k] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewPD = (void*)((uptr)NewPD | (((*OriginalPDPT)[j]) & ~0x0007fffffffff000));
|
||||||
|
|
||||||
|
(*NewPDPT)[j] = (u64)NewPD;
|
||||||
|
} else (*NewPDPT)[j] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewPDPT = (void*)((uptr)NewPDPT | (((*OriginalPML4)[i]) & ~0x0007fffffffff000));
|
||||||
|
|
||||||
|
(*NewPML4)[i] = (u64)NewPDPT;
|
||||||
|
} else (*NewPML4)[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save these
|
||||||
|
VmemOriginalPML4 = OriginalPML4;
|
||||||
|
VmemPML4 = NewPML4;
|
||||||
|
|
||||||
|
// Load our new page table
|
||||||
|
CR3 ^= (u64)VmemOriginalPML4;
|
||||||
|
CR3 |= ((u64)VmemPML4) & 0x0007fffffffff000;
|
||||||
|
asm volatile ("mov %q0, %%cr3" : : "r" (CR3));
|
||||||
|
|
||||||
|
Panic("FUCK");
|
||||||
|
}
|
5
lcrash/mm/virt.h
Normal file
5
lcrash/mm/virt.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <lcrash/types.h>
|
||||||
|
|
||||||
|
void VmemInitialize();
|
@ -2,22 +2,46 @@
|
|||||||
|
|
||||||
#include <lcrash/acpi/acpi.h>
|
#include <lcrash/acpi/acpi.h>
|
||||||
#include <lcrash/debug/debug.h>
|
#include <lcrash/debug/debug.h>
|
||||||
|
#include <lcrash/driver/sysbus.h>
|
||||||
|
|
||||||
bool PciIsPresent = false;
|
bool PciIsPresent = false;
|
||||||
bool PciSupportsECM = false;
|
bool PciSupportsECM = false;
|
||||||
|
|
||||||
void PciInitialize() {
|
void* PciBusses[256] = {};
|
||||||
// Try to figure out if we have PCIe
|
|
||||||
if (AcpiPresent()) {
|
|
||||||
struct AcpiMCFG* BridgeTable = AcpiGetTable("MCFG");
|
|
||||||
|
|
||||||
// Guess not
|
void PciScanDevice(u32 Bus, u32 Device) {
|
||||||
if (BridgeTable == NULL) goto nopcie;
|
struct PciConfigurationSpaceHeader* DeviceHeader = (struct PciConfigurationSpaceHeader*)(PciBusses[Bus] + Device * 0x800);
|
||||||
|
|
||||||
|
// Is a device connected here?
|
||||||
|
if (DeviceHeader->VendorID != 0xFFFF) {
|
||||||
while (1) {}
|
while (1) {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nopcie: Panic("Failed to initialize PCI");
|
void PciScanBus(u32 Bus) {
|
||||||
|
// Scan bus devices
|
||||||
|
for (int i = 0; i < 32; i++) PciScanDevice(Bus, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PciInitialize() {
|
||||||
|
// Try to figure out if we have PCIe
|
||||||
|
if (!AcpiPresent()) Panic("Failed to initialize PCI");
|
||||||
|
|
||||||
|
struct AcpiMCFG* BridgeTable = AcpiGetTable("MCFG");
|
||||||
|
|
||||||
|
// Guess not
|
||||||
|
if (BridgeTable == NULL) Panic("Failed to find PCI bridge table");
|
||||||
|
|
||||||
|
// Take our pcie bridges
|
||||||
|
s32 Length = (BridgeTable->Header.Length - 44) / 16;
|
||||||
|
for (int i = 0; i < Length; i++) {
|
||||||
|
for (int Bus = BridgeTable->Bridges[i].StartBus; Bus < BridgeTable->Bridges[i].EndBus; Bus++) {
|
||||||
|
PciBusses[Bus] = BridgeTable->Bridges[i].Address + (Bus - BridgeTable->Bridges[i].StartBus) * 0x100000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan the root bus
|
||||||
|
PciScanBus(0);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,28 @@
|
|||||||
|
|
||||||
#include <lcrash/types.h>
|
#include <lcrash/types.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bwaaaaaa, the many ways to touch PCI things
|
||||||
|
*/
|
||||||
|
struct [[gnu::packed]] PciConfigurationSpaceHeader {
|
||||||
|
u16 VendorID;
|
||||||
|
u16 DeviceID;
|
||||||
|
u16 Status;
|
||||||
|
u16 Command;
|
||||||
|
u8 RevisionID : 8;
|
||||||
|
u32 ClassCode : 24;
|
||||||
|
u8 CacheLineSize;
|
||||||
|
u8 MasterLatencyTimer;
|
||||||
|
u8 HeaderType;
|
||||||
|
u8 BIST;
|
||||||
|
u8 Reserved[0x20];
|
||||||
|
u8 CapabilitiesPointer;
|
||||||
|
u8 Reserved2[7];
|
||||||
|
u8 InterruptLine;
|
||||||
|
u8 InterruptPin;
|
||||||
|
u8 Reserved3[2];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the PCI code.
|
* Initialize the PCI code.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user