diff options
Diffstat (limited to 'sys/include/sys/driver.h')
-rw-r--r-- | sys/include/sys/driver.h | 69 |
1 files changed, 68 insertions, 1 deletions
diff --git a/sys/include/sys/driver.h b/sys/include/sys/driver.h index 05c40fa..e10021a 100644 --- a/sys/include/sys/driver.h +++ b/sys/include/sys/driver.h @@ -31,27 +31,94 @@ #define _SYS_DRIVER_H_ #include <sys/cdefs.h> +#include <sys/proc.h> +#include <sys/types.h> #if defined(_KERNEL) +/* Variable driver data */ +struct driver_var { + uint8_t deferred : 1; +}; + struct driver { int(*init)(void); + const char *name; + struct driver_var *data; }; +extern struct proc g_proc0; + +/* Early (high priority) drivers */ extern char __drivers_init_start[]; extern char __drivers_init_end[]; -#define DRIVER_EXPORT(INIT) \ +/* Deferred (low priority) drivers */ +extern char __driversd_init_start[]; +extern char __driversd_init_end[]; + +#define DRIVER_EXPORT(INIT, NAME) \ + static struct driver_var __driver_var = { \ + .deferred = 0 \ + }; \ + \ __attribute__((used, section(".drivers"))) \ static struct driver __driver_desc = { \ .init = INIT, \ + .data = &__driver_var, \ + .name = NAME \ } +/* + * Some drivers are not required to start up + * early for proper system operation and may + * be deferred to start at a later time. + * + * Examples of such (deferrable) drivers include code + * that waits for I/O (e.g., disks, network cards, + * et cetera). This allows for faster boot times + * as only *required* drivers are started before + * everything else. + * + * Drivers that wish to be deferred may export themselves + * via the DRIVER_DEFER() macro. The DRIVER_DEFERRED() + * macro gives the value of 1 if the current driver + * context has yet to be initialized. The driver may + * use this to defer requests for I/O. + */ +#define DRIVER_DEFER(INIT, NAME) \ + static struct driver_var __driver_var = { \ + .deferred = 1 \ + }; \ + \ + __attribute__((used, section(".drivers.defer"))) \ + static struct driver __driver_desc = { \ + .init = INIT, \ + .data = &__driver_var, \ + .name = NAME \ + } + +#define DRIVER_DEFERRED() __driver_var.deferred + #define DRIVERS_INIT() \ for (struct driver *__d = (struct driver *)__drivers_init_start; \ (uintptr_t)__d < (uintptr_t)__drivers_init_end; ++__d) \ { \ + if (driver_blacklist_check((__d)->name)) { \ + continue; \ + } \ __d->init(); \ } + +#define DRIVERS_SCHED() \ + spawn(&g_proc0, __driver_init_td, NULL, 0, NULL) + +/* Driver blacklist framework */ +int driver_blacklist(const char *name); +int driver_blacklist_check(const char *name); +void driver_blacklist_init(void); + +void __driver_init_td(void); + #endif /* _KERNEL */ #endif /* !_SYS_DRIVER_H_ */ |