lindows/lcrash/driver/sysbus.h

207 lines
5.9 KiB
C

#pragma once
/**
* The lcrash system bus is a root device which manages all other associated devices, and handles bookkeeping for other subsystems (e.g. classifying devices)
* The system bus supports device names to aid debuggers, however these names are otherwise meaningless and pointers to structures should be used instead
*
* Example device tree:
* /SYSBUS
* /PCI
* /PCI0000:00:00.0
* $ETHERNET
* /PCI0000:00:00.1
* $FRAMEBUF
* $TEXTBUF
* /ACPI:0
* $BATTERY
* /ACPI:1
* $SERIAL
* /COM:0
* $SERIAL
* /COM:1
* $SERIAL
*
* Device capabilities provide a way for devices to expose functionality without writing device specific code, a capability is defined by the following structure
* struct SysbusDeviceCapability {
* // Name of the device capability
* const char* CapabilityName;
* };
*
* Devices types are defined by the following structure:
* struct SysbusDeviceDescription {
* // Name of the device type
* const char* DeviceName;
*
* // == Instance Management ==
* // List of device instances
* struct SysbusDevice** Instances;
*
* // Device initialization code, returns 0 if ok
* int (*CreateDevice)(struct SysbusDevice* Device, void* Data);
*
* // Cleanup code for before a device is deleted, returns 0 if ok
* int (*DeleteDevice)(struct SysbusDevice* Device);
*
* // == Capablities ==
* // Returns a capability specific structure if a capability is present, otherwise returns NULL
* void* (*GetCapability)(struct SysbusDevice* Device, struct SysbusDeviceCapability* Capability);
* };
*
* Devices are stored in the following structure:
* struct SysbusDevice {
* // Pointer to the device type structure
* const struct SysbusDeviceDescription* DeviceDescription;
*
* // Name of the device
* const char* DeviceName;
*
* // Device specific data
* void* DeviceData;
*
* // Child devices
* struct SysbusDevice** Children;
* };
*
* Drivers can define a new device type by calling `struct SysbusDeviceDescription* SysbusCreateDeviceDescription()` which
* Allocates and returns a device description structure
*
* Drivers must free device types with `void SysbusDeleteDeviceDescription(struct SysbusDeviceDescription* DESCRIPTION)` which
* Deletes a DESCRIPTION's instances
* Deallocates a device DESCRIPTION structure
*
* Drivers can create a new device by calling `struct SysbusDevice* SysbusCreateDevice(struct SysbusDeviceDescription* DESCRIPTION, void* DATA)` which
* DEVICE = Allocate a device structure
* Initializes it by calling DESCRIPTION::CreateDevice(DEVICE, DATA)
* if ok then
* Adds the DEVICE to the DESCRIPTION's instance list
* Returns the DEVICE
* otherwise returns NULL
*
* Drivers must free devices with `void SysbusDeleteDevice(struct SysbusDevice* DEVICE)` which
* Uninitializes the DEVICE by calling DEVICE::DeviceDescription::DeleteDevice(DEVICE)
* Removes the DEVICE from the DEVICE::DeviceDescription's instance list
* Deallocates the DEVICE
*/
#include <lcrash/types.h>
/**
* 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);
/**
* Create a sysbus capability
*/
struct SysbusDeviceCapability* SysbusCreateCapability();
/**
* Delete a sysbus capability
*/
void SysbusDeleteCapability();
/**
* Get a sysbus capability
*/
void* SysbusGetCapability(struct SysbusDevice* Device, struct SysbusDeviceCapability* Capability);
/**
* Get the system bus device
*/
struct SysbusDevice* SysbusGetRootDevice();