From 516329d25cba4c0fa765557c8970c413d297620c Mon Sep 17 00:00:00 2001 From: xwashere Date: Fri, 19 Apr 2024 13:02:34 -0400 Subject: [PATCH] [lcrash] ADD: System bus subsystem --- lcrash/CMakeLists.txt | 2 +- lcrash/driver/sysbus.c | 128 +++++++++++++++++++++++++++++++++++++++++ lcrash/driver/sysbus.h | 102 ++++++++++++++++++++++++++++++++ lcrash/main.c | 4 ++ lcrash/pci/pci.c | 4 +- 5 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 lcrash/driver/sysbus.c diff --git a/lcrash/CMakeLists.txt b/lcrash/CMakeLists.txt index e814bde..2c7d495 100644 --- a/lcrash/CMakeLists.txt +++ b/lcrash/CMakeLists.txt @@ -8,7 +8,7 @@ lw_project(lcrash enable_language(ASM) 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 + 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 ) add_executable(lcrashkernld IMPORTED) set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld) diff --git a/lcrash/driver/sysbus.c b/lcrash/driver/sysbus.c new file mode 100644 index 0000000..7b610f7 --- /dev/null +++ b/lcrash/driver/sysbus.c @@ -0,0 +1,128 @@ +#include + +#include +#include + +struct SysbusDeviceDescription* SysbusRootDeviceDescription = 0; +struct SysbusDevice* SysbusRootDevice = 0; + +/** + * Create a new device description + */ +struct SysbusDeviceDescription* SysbusCreateDeviceDescriptionInternal() { + struct SysbusDeviceDescription* Description = KernelHeapAlloc(sizeof(struct SysbusDeviceDescription), 0); + + Description->DeviceName = 0; + Description->Instances = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 0); + Description->InstanceCount = 0; + Description->InstanceSlots = 4; + Description->CreateDevice = 0; + Description->DeleteDevice = 0; + Description->GetCapability = 0; + + return Description; +} + +/** + * Attach a device to another device + */ +void SysbusAttachChildDeviceInternal(struct SysbusDevice* Parent, struct SysbusDevice* Child) { + // See if we need to grow the list + if (Parent->ChildCount >= Parent->ChildSlots) { + struct SysbusDevice** NewList = KernelHeapAlloc(sizeof(struct SysbusDevice*) * Parent->ChildSlots * 2, 0); + for (int i = 0; i < Parent->ChildCount; i++) { + NewList[i] = Parent->Children[i]; + } + + KernelHeapFree(Parent->Children); + Parent->Children = NewList; + Parent->ChildSlots *= 2; + } + + // Add the child + Parent->Children[Parent->ChildCount++] = Child; + + return; +} + +/** + * Create a new device + * + * \param Description device description + * \param Parent parent device + * \param DeviceData device specific data + * \param IsRootDevice device has no parent + */ +struct SysbusDevice* SysbusCreateDeviceInternal( + struct SysbusDeviceDescription* Description, + struct SysbusDevice* Parent, + void* DeviceData, + bool IsRootDevice +) { + struct SysbusDevice* Device = KernelHeapAlloc(sizeof(struct SysbusDevice), 0); + Device->DeviceDescription = Description; + Device->DeviceName = 0; + Device->DeviceData = 0; + Device->Parent = Parent; + Device->Children = KernelHeapAlloc(sizeof(struct SysbusDevice*) * 4, 0); + Device->ChildCount = 0; + Device->ChildSlots = 4; + + // Attach to parent + if (Parent != NULL) SysbusAttachChildDeviceInternal(Parent, Device); + + // See if we need to grow the instance list + if (Description->InstanceCount >= Description->InstanceSlots) { + struct SysbusDevice** NewList = KernelHeapAlloc(sizeof(struct SysbusDevice*) * Description->InstanceSlots * 2, 0); + for (int i = 0; i < Description->InstanceCount; i++) { + NewList[i] = Description->Instances[i]; + } + + KernelHeapFree(Description->Instances); + Description->Instances = NewList; + Description->InstanceSlots *= 2; + } + + // Add us as an instance + Description->Instances[Description->InstanceCount++] = Device; + + return Device; +} + +struct SysbusDeviceDescription* SysbusCreateDeviceDescription() { + return SysbusCreateDeviceDescriptionInternal(); +} + +void SysbusDeleteDeviceDescription(struct SysbusDeviceDescription* Description) { + Panic("todo"); +} + +struct SysbusDevice* SysbusCreateDevice( + struct SysbusDeviceDescription* Description, + struct SysbusDevice* Parent, + void* Data +) { + return SysbusCreateDeviceInternal(Description, Parent, Data, false); +} + +void SysbusDeleteDevice(struct SysbusDevice* Device) { + Panic("todo"); +} + +void SysbusInitialize() { + // Create the sysbus root + SysbusRootDeviceDescription = SysbusCreateDeviceDescriptionInternal(); + SysbusRootDeviceDescription->DeviceName = "Lcrash System Bus"; + + SysbusRootDevice = SysbusCreateDeviceInternal( + SysbusRootDeviceDescription, + NULL, + NULL, + true + ); + SysbusRootDevice->DeviceName = "Lcrash System Bus"; + + Panic("Failed to initialize system bus"); + + return; +} diff --git a/lcrash/driver/sysbus.h b/lcrash/driver/sysbus.h index fd39686..388c5ba 100644 --- a/lcrash/driver/sysbus.h +++ b/lcrash/driver/sysbus.h @@ -82,3 +82,105 @@ * Removes the DEVICE from the DEVICE::DeviceDescription's instance list * Deallocates the DEVICE */ + +#include + +/** + * Structure that describes a specific device capablility + */ +struct SysbusDeviceCapability { + // Name of the device capability + const char* CapabilityName; +}; + +/** + * Structure that describes a device and allows them to hook the sysbus subsystem + */ +struct SysbusDeviceDescription { + /// Device name, this is only used for debugging + const c8* DeviceName; + + /// List of device instances + /// Do not hold pointers to this list + /// Managed by the sysbus subsystem. DRIVERS, DO NOT MODIFY THIS LIST. + struct SysbusDevice** Instances; + + /// Number of instances + /// Managed by the sysbus subsystem. DO NOT MODIFY THIS. + u32 InstanceCount; + + /// Instance array length + /// Managed by the sysbus subsysyem. DO NOT MODIFY THIS. + /// \internal + u32 InstanceSlots; + + /// Called by the sysbus subsystem when a device is created, use this to initialize a device + /// \returns 0 on success + s32 (*CreateDevice)(struct SysbusDevice*, void*); + + /// Called by the sysbus subsystem when a device is deleted, use this to deinitialize a device + /// \returns 0 on success + s32 (*DeleteDevice)(struct SysbusDevice* Device); + + /// Returns a capability specific structure if a capability is present, otherwise returns NULL + void* (*GetCapability)(struct SysbusDevice* Device, struct SysbusDeviceCapability* Capability); +}; + +/** + * Structure that describes an instace of a specific device + */ +struct SysbusDevice { + /// Pointer to the device type structure + const struct SysbusDeviceDescription* DeviceDescription; + + /// Name of the device + const c8* DeviceName; + + /// Device specific data + void* DeviceData; + + /// Parent device + /// Managed by the sysbus subsystem. DO NOT MODIFY THIS. + struct SysbusDevice* Parent; + + /// Child devices + /// Managed by the sysbus subsystem. DRIVERS, DO NOT MODIFY THIS LIST + /// Do not hold pointers to this list, it may be moved or resized as needed + struct SysbusDevice** Children; + + /// Number of children + /// Managed by the sysbus subsystem. DO NOT MODIFY THIS. + u32 ChildCount; + + /// Child array length + /// Managed by the sysbus subsysyem. DO NOT MODIFY THIS. + /// \internal + u32 ChildSlots; +}; + +/// Initialize the sysbus subsystem +void SysbusInitialize(); + +/** + * Create and return a sysbus device description + */ +struct SysbusDeviceDescription* SysbusCreateDeviceDescription(); + +/** + * Delete a sysbus device description + */ +void SysbusDeleteDeviceDescription(struct SysbusDeviceDescription* Description); + +/** + * Create a new device + */ +struct SysbusDevice* SysbusCreateDevice( + struct SysbusDeviceDescription* Description, + struct SysbusDevice* Parent, + void* Data +); + +/** + * Delete a device + */ +void SysbusDeleteDevice(struct SysbusDevice* Device); diff --git a/lcrash/main.c b/lcrash/main.c index 2421d75..235b582 100644 --- a/lcrash/main.c +++ b/lcrash/main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "types.h" #include "lnxboot.h" @@ -37,6 +38,9 @@ void entry64(struct boot_params* BootParams) { // Initialize the extended debugging information block if (DebugInitialize()) while (1) {} + // Initialize the system bus + SysbusInitialize(); + // Initialize EFI code if we had EFI EfiInitialize(); diff --git a/lcrash/pci/pci.c b/lcrash/pci/pci.c index 1d4d610..3d939e8 100644 --- a/lcrash/pci/pci.c +++ b/lcrash/pci/pci.c @@ -1,5 +1,7 @@ #include + #include +#include bool PciIsPresent = false; bool PciSupportsECM = false; @@ -15,7 +17,7 @@ void PciInitialize() { while (1) {} } -nopcie: while (1) {} +nopcie: Panic("Failed to initialize PCI"); return; }