From: Tulio A M Mendes Date: Fri, 13 Feb 2026 19:54:47 +0000 (-0300) Subject: feat: HAL Device Driver API — driver registry with probe/init/shutdown lifecycle X-Git-Url: https://projects.tadryanom.me/docs/static/git-favicon.png?a=commitdiff_plain;h=f57c5dbab9279512c6d923df720b0832e3c402ad;p=AdrOS.git feat: HAL Device Driver API — driver registry with probe/init/shutdown lifecycle - Add include/hal/driver.h: struct hal_driver with type, priority, ops (probe/init/shutdown) - Add src/kernel/driver.c: driver registry with hal_driver_register(), hal_drivers_init_all(), hal_drivers_shutdown_all(), hal_driver_find(), hal_driver_count() - Drivers init in priority order (insertion sort), shutdown in reverse - HAL_MAX_DRIVERS=32, 6 driver types: PLATFORM, CHAR, BLOCK, NET, DISPLAY, BUS - Framework ready for existing drivers to self-register (incremental migration) 20/20 smoke, cppcheck clean --- diff --git a/include/hal/driver.h b/include/hal/driver.h new file mode 100644 index 0000000..a9bb996 --- /dev/null +++ b/include/hal/driver.h @@ -0,0 +1,78 @@ +#ifndef HAL_DRIVER_H +#define HAL_DRIVER_H + +#include +#include + +/* + * HAL Device Driver Model + * + * Provides a unified registration and lifecycle interface for all + * hardware drivers, both platform-specific (x86 PS/2, PIT, LAPIC) + * and generic (ATA, E1000, VBE framebuffer). + * + * Architecture-dependent implementations register themselves at boot + * via hal_driver_register(). The kernel init code calls + * hal_drivers_init_all() to probe and initialise every registered + * driver in priority order. + */ + +/* Driver categories */ +enum hal_driver_type { + HAL_DRV_PLATFORM, /* arch-specific: PIT, PS/2, LAPIC, IOAPIC */ + HAL_DRV_CHAR, /* character devices: UART, keyboard, VGA text */ + HAL_DRV_BLOCK, /* block devices: ATA, virtio-blk */ + HAL_DRV_NET, /* network: E1000 */ + HAL_DRV_DISPLAY, /* display: VBE framebuffer */ + HAL_DRV_BUS, /* bus controllers: PCI */ + HAL_DRV_TYPE_COUNT +}; + +/* Driver operations table */ +struct hal_driver_ops { + int (*probe)(void); /* detect hardware; return 0 if present */ + int (*init)(void); /* initialise the driver; return 0 on success */ + void (*shutdown)(void); /* graceful shutdown / cleanup */ +}; + +/* Driver descriptor — typically declared as a const static in each driver */ +struct hal_driver { + const char* name; + enum hal_driver_type type; + int priority; /* lower = earlier init (0-99) */ + struct hal_driver_ops ops; +}; + +#define HAL_MAX_DRIVERS 32 + +/* + * Register a driver with the HAL subsystem. + * Must be called before hal_drivers_init_all(). + * Returns 0 on success, -1 if registry is full. + */ +int hal_driver_register(const struct hal_driver* drv); + +/* + * Probe and initialise all registered drivers in priority order. + * Called once during kernel boot. + * Returns the number of drivers successfully initialised. + */ +int hal_drivers_init_all(void); + +/* + * Shutdown all initialised drivers in reverse order. + */ +void hal_drivers_shutdown_all(void); + +/* + * Look up a registered driver by name. + * Returns NULL if not found. + */ +const struct hal_driver* hal_driver_find(const char* name); + +/* + * Return the number of registered drivers. + */ +int hal_driver_count(void); + +#endif /* HAL_DRIVER_H */ diff --git a/src/kernel/driver.c b/src/kernel/driver.c new file mode 100644 index 0000000..9cc5330 --- /dev/null +++ b/src/kernel/driver.c @@ -0,0 +1,94 @@ +/* + * HAL Device Driver Registry + * + * Maintains a table of registered drivers and provides lifecycle + * management (probe → init → shutdown) in priority order. + */ +#include "hal/driver.h" +#include "console.h" +#include "utils.h" + +static const struct hal_driver* drivers[HAL_MAX_DRIVERS]; +static int driver_count = 0; + +/* Track which drivers were successfully initialised (for shutdown order) */ +static int driver_inited[HAL_MAX_DRIVERS]; + +int hal_driver_register(const struct hal_driver* drv) { + if (!drv || !drv->name) return -1; + if (driver_count >= HAL_MAX_DRIVERS) { + kprintf("[DRV] registry full, cannot register '%s'\n", drv->name); + return -1; + } + drivers[driver_count] = drv; + driver_inited[driver_count] = 0; + driver_count++; + return 0; +} + +/* Simple insertion sort by priority (stable, in-place on the pointer array) */ +static void sort_drivers(void) { + for (int i = 1; i < driver_count; i++) { + const struct hal_driver* tmp = drivers[i]; + int j = i - 1; + while (j >= 0 && drivers[j]->priority > tmp->priority) { + drivers[j + 1] = drivers[j]; + j--; + } + drivers[j + 1] = tmp; + } +} + +int hal_drivers_init_all(void) { + sort_drivers(); + + int ok = 0; + for (int i = 0; i < driver_count; i++) { + const struct hal_driver* d = drivers[i]; + + /* Probe: skip if hardware not present */ + if (d->ops.probe) { + if (d->ops.probe() != 0) { + kprintf("[DRV] %s: not detected, skipping\n", d->name); + continue; + } + } + + /* Init */ + if (d->ops.init) { + int rc = d->ops.init(); + if (rc != 0) { + kprintf("[DRV] %s: init failed (%d)\n", d->name, rc); + continue; + } + } + + driver_inited[i] = 1; + ok++; + } + + return ok; +} + +void hal_drivers_shutdown_all(void) { + /* Shutdown in reverse priority order */ + for (int i = driver_count - 1; i >= 0; i--) { + if (driver_inited[i] && drivers[i]->ops.shutdown) { + drivers[i]->ops.shutdown(); + driver_inited[i] = 0; + } + } +} + +const struct hal_driver* hal_driver_find(const char* name) { + if (!name) return NULL; + for (int i = 0; i < driver_count; i++) { + if (strcmp(drivers[i]->name, name) == 0) + return drivers[i]; + } + return NULL; +} + +int hal_driver_count(void) { + return driver_count; +}