feature (drivers): implemented driver registration and lookup
This commit is contained in:
parent
a904629abd
commit
74aa1a4e4d
|
@ -5,10 +5,12 @@
|
||||||
|
|
||||||
#include <utils/stdtypes.h>
|
#include <utils/stdtypes.h>
|
||||||
#include <utils/bitmap.h>
|
#include <utils/bitmap.h>
|
||||||
|
#include <utils/hashmap.h>
|
||||||
#include <drivers/builtin/elf/elf.h>
|
#include <drivers/builtin/elf/elf.h>
|
||||||
|
|
||||||
#define DRIVER_MANAGER_CHUNK_SIZE 64
|
#define DRIVER_MANAGER_CHUNK_SIZE 64
|
||||||
#define DRIVER_MEMORY_REGION_SIZE 0x100000000 // 4 GB
|
#define DRIVER_MANAGER_HASHMAP_SIZE 128
|
||||||
|
#define DRIVER_MEMORY_REGION_SIZE 0x100000000 // 4 GB
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DRIVER_TRANSPORT_PCI,
|
DRIVER_TRANSPORT_PCI,
|
||||||
|
@ -55,13 +57,13 @@ typedef struct {
|
||||||
uint8_t subclass;
|
uint8_t subclass;
|
||||||
uint8_t progif;
|
uint8_t progif;
|
||||||
uint16_t num_device_ids;
|
uint16_t num_device_ids;
|
||||||
driver_config_device_id_T device_ids;
|
driver_config_device_id_T device_ids[];
|
||||||
} __attribute__((packed)) driver_config_pci_T;
|
} __attribute__((packed)) driver_config_pci_T;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t min_version;
|
uint8_t min_version;
|
||||||
uint16_t num_device_ids;
|
uint16_t num_device_ids;
|
||||||
driver_config_device_id_T device_ids;
|
driver_config_device_id_T device_ids[];
|
||||||
} __attribute__((packed)) driver_config_usb_T;
|
} __attribute__((packed)) driver_config_usb_T;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -94,6 +96,10 @@ struct driver_manager_chunk_T {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
driver_manager_chunk_T* driver_pool;
|
driver_manager_chunk_T* driver_pool;
|
||||||
|
hashmap_T lookup_table_pci;
|
||||||
|
hashmap_T lookup_table_usb;
|
||||||
|
hashmap_T lookup_table_fs_gpt;
|
||||||
|
hashmap_T lookup_table_fs_mbr;
|
||||||
} driver_manager_T;
|
} driver_manager_T;
|
||||||
|
|
||||||
void driver_manager_init ();
|
void driver_manager_init ();
|
||||||
|
|
|
@ -97,5 +97,10 @@ void kmain(boot_info_T boot_info) {
|
||||||
void (*drv_test)() = entry;
|
void (*drv_test)() = entry;
|
||||||
drv_test();
|
drv_test();
|
||||||
|
|
||||||
|
driver_T* resolved = driver_lookup_pci_device(0x886, 0x2920);
|
||||||
|
|
||||||
|
DEBUG("driver: 0x%x", drv);
|
||||||
|
DEBUG("resolved: 0x%x", resolved);
|
||||||
|
|
||||||
CORE_HALT_FOREVER
|
CORE_HALT_FOREVER
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,19 @@ void nx_drv_pci_config(driver_config_pci_T* config) {
|
||||||
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
|
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
|
||||||
if (driver == NULL) return;
|
if (driver == NULL) return;
|
||||||
|
|
||||||
|
driver_init(driver, DRIVER_TRANSPORT_PCI, (conf_U)config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx_drv_usb_config(driver_config_usb_T* config) {
|
void nx_drv_usb_config(driver_config_usb_T* config) {
|
||||||
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
|
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
|
||||||
if (driver == NULL) return;
|
if (driver == NULL) return;
|
||||||
|
|
||||||
|
driver_init(driver, DRIVER_TRANSPORT_USB, (conf_U)config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nx_drv_fs_config(driver_config_fs_T* config) {
|
void nx_drv_fs_config(driver_config_fs_T* config) {
|
||||||
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
|
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
|
||||||
if (driver == NULL) return;
|
if (driver == NULL) return;
|
||||||
|
|
||||||
|
driver_init(driver, DRIVER_TRANSPORT_FS, (conf_U)config);
|
||||||
}
|
}
|
|
@ -10,7 +10,11 @@
|
||||||
driver_manager_T g_driver_manager;
|
driver_manager_T g_driver_manager;
|
||||||
|
|
||||||
void driver_manager_init() {
|
void driver_manager_init() {
|
||||||
g_driver_manager.driver_pool = driver_manager_chunk_alloc(NULL);
|
g_driver_manager.driver_pool = driver_manager_chunk_alloc(NULL);
|
||||||
|
g_driver_manager.lookup_table_pci = hashmap_create(DRIVER_MANAGER_HASHMAP_SIZE);
|
||||||
|
g_driver_manager.lookup_table_usb = hashmap_create(DRIVER_MANAGER_HASHMAP_SIZE);
|
||||||
|
g_driver_manager.lookup_table_fs_gpt = hashmap_create(DRIVER_MANAGER_HASHMAP_SIZE);
|
||||||
|
g_driver_manager.lookup_table_fs_mbr = hashmap_create(DRIVER_MANAGER_HASHMAP_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_manager_chunk_T* driver_manager_chunk_alloc(driver_manager_chunk_T* prev) {
|
driver_manager_chunk_T* driver_manager_chunk_alloc(driver_manager_chunk_T* prev) {
|
||||||
|
@ -47,8 +51,89 @@ driver_T* driver_find_fs_mbr(uint8_t type) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void driver_init(driver_T* driver, driver_transport_protocol_E protocol, conf_U conf) {
|
void driver_init_pci(driver_T* driver, driver_config_pci_T* conf) {
|
||||||
|
for (int i = 0; i < conf->num_device_ids; i++) {
|
||||||
|
driver_config_device_id_T* device_id = &conf->device_ids[i];
|
||||||
|
|
||||||
|
hashmap_T* level_2 = hashmap_lookup(&g_driver_manager.lookup_table_pci, device_id->vendor_id);
|
||||||
|
if (level_2 == NULL) {
|
||||||
|
level_2 = memory_allocate(sizeof(hashmap_T));
|
||||||
|
hashmap_insert(&g_driver_manager.lookup_table_pci, device_id->vendor_id, level_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* entry = hashmap_lookup(level_2, device_id->device_id);
|
||||||
|
if (entry != NULL) {
|
||||||
|
log(LOG_WARNING, "Failed to register driver for pci device %xw:%xw (there is already a driver registered)", device_id->vendor_id, device_id->device_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
hashmap_insert(level_2, device_id->device_id, driver);
|
||||||
|
log(LOG_INFO, "Registered driver for pci device %xw:%xw", device_id->vendor_id, device_id->device_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver_init_usb(driver_T* driver, driver_config_usb_T* conf) {
|
||||||
|
for (int i = 0; i < conf->num_device_ids; i++) {
|
||||||
|
driver_config_device_id_T* device_id = &conf->device_ids[i];
|
||||||
|
|
||||||
|
hashmap_T* level_2 = hashmap_lookup(&g_driver_manager.lookup_table_usb, device_id->vendor_id);
|
||||||
|
if (level_2 == NULL) {
|
||||||
|
level_2 = memory_allocate(sizeof(hashmap_T));
|
||||||
|
hashmap_insert(&g_driver_manager.lookup_table_usb, device_id->vendor_id, level_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* entry = hashmap_lookup(level_2, device_id->device_id);
|
||||||
|
if (entry != NULL) {
|
||||||
|
log(LOG_WARNING, "Failed to register driver for usb device %xw:%xw (there is already a driver registered)", device_id->vendor_id, device_id->device_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
hashmap_insert(level_2, device_id->device_id, driver);
|
||||||
|
log(LOG_INFO, "Registered driver for usb device %xw:%xw", device_id->vendor_id, device_id->device_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver_init_fs_gpt(driver_T* driver, uint8_t gpt_guid[16]) {
|
||||||
|
uint64_t gpt_hash = ((uint64_t*)gpt_guid)[0] ^ ((uint64_t*)gpt_guid)[1];
|
||||||
|
|
||||||
|
if (hashmap_lookup(&g_driver_manager.lookup_table_fs_gpt, gpt_hash) != NULL) {
|
||||||
|
log(LOG_WARNING, "Failed to register driver for gpt file system: %xb%xb%xb%xb-%xb%xb-%xb%xb-%xb%xb-%xb%xb%xb%xb%xb%xb (there is already a driver registered)",
|
||||||
|
gpt_guid[0x0], gpt_guid[0x1], gpt_guid[0x2], gpt_guid[0x3],
|
||||||
|
gpt_guid[0x4], gpt_guid[0x5], gpt_guid[0x6], gpt_guid[0x7],
|
||||||
|
gpt_guid[0x8], gpt_guid[0x9], gpt_guid[0xA], gpt_guid[0xB],
|
||||||
|
gpt_guid[0xC], gpt_guid[0xD], gpt_guid[0xE], gpt_guid[0xF]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashmap_insert(&g_driver_manager.lookup_table_fs_gpt, gpt_hash, driver);
|
||||||
|
|
||||||
|
log(LOG_INFO, "Registered driver for gpt file system: %xb%xb%xb%xb-%xb%xb-%xb%xb-%xb%xb-%xb%xb%xb%xb%xb%xb",
|
||||||
|
gpt_guid[0x0], gpt_guid[0x1], gpt_guid[0x2], gpt_guid[0x3],
|
||||||
|
gpt_guid[0x4], gpt_guid[0x5], gpt_guid[0x6], gpt_guid[0x7],
|
||||||
|
gpt_guid[0x8], gpt_guid[0x9], gpt_guid[0xA], gpt_guid[0xB],
|
||||||
|
gpt_guid[0xC], gpt_guid[0xD], gpt_guid[0xE], gpt_guid[0xF]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver_init_fs_mbr(driver_T* driver, uint8_t type) {
|
||||||
|
if (hashmap_lookup(&g_driver_manager.lookup_table_fs_gpt, type) != NULL) {
|
||||||
|
log(LOG_WARNING, "Failed to register driver for mbr file system: %xb (there is already a driver registered)", type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashmap_insert(&g_driver_manager.lookup_table_fs_gpt, type, driver);
|
||||||
|
|
||||||
|
log(LOG_INFO, "Registered driver for mbr file system: %xb", type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver_init_fs(driver_T* driver, driver_config_fs_T* conf) {
|
||||||
|
driver_init_fs_gpt(driver, conf->gpt_guid);
|
||||||
|
driver_init_fs_mbr(driver, conf->mbr_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver_init(driver_T* driver, driver_transport_protocol_E protocol, conf_U conf) {
|
||||||
|
switch (protocol) {
|
||||||
|
case DRIVER_TRANSPORT_PCI: driver_init_pci(driver, conf.pci);
|
||||||
|
case DRIVER_TRANSPORT_USB: driver_init_usb(driver, conf.usb);
|
||||||
|
case DRIVER_TRANSPORT_FS: driver_init_fs (driver, conf.fs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_T* driver_register(elf_executable_T* executable, uint8_t* buffer) {
|
driver_T* driver_register(elf_executable_T* executable, uint8_t* buffer) {
|
||||||
|
@ -90,19 +175,39 @@ driver_T* driver_register(elf_executable_T* executable, uint8_t* buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_T* driver_lookup_pci_device(uint16_t vendor_id, uint16_t device_id) {
|
driver_T* driver_lookup_pci_device(uint16_t vendor_id, uint16_t device_id) {
|
||||||
return NULL;
|
hashmap_T* level_2 = hashmap_lookup(&g_driver_manager.lookup_table_pci, vendor_id);
|
||||||
|
if (level_2 == NULL) return driver_find_pci_device(vendor_id, device_id);
|
||||||
|
|
||||||
|
driver_T* driver = hashmap_lookup(level_2, device_id);
|
||||||
|
if (driver == NULL) return driver_find_pci_device(vendor_id, device_id);
|
||||||
|
|
||||||
|
return driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_T* driver_lookup_usb_device(uint16_t vendor_id, uint16_t device_id) {
|
driver_T* driver_lookup_usb_device(uint16_t vendor_id, uint16_t device_id) {
|
||||||
return NULL;
|
hashmap_T* level_2 = hashmap_lookup(&g_driver_manager.lookup_table_usb, vendor_id);
|
||||||
|
if (level_2 == NULL) return driver_find_usb_device(vendor_id, device_id);
|
||||||
|
|
||||||
|
driver_T* driver = hashmap_lookup(level_2, device_id);
|
||||||
|
if (driver == NULL) return driver_find_usb_device(vendor_id, device_id);
|
||||||
|
|
||||||
|
return driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_T* driver_lookup_fs_gpt(uint8_t guid[16]) {
|
driver_T* driver_lookup_fs_gpt(uint8_t guid[16]) {
|
||||||
return NULL;
|
uint64_t gpt_hash = ((uint64_t*)guid)[0] ^ ((uint64_t*)guid)[1];
|
||||||
|
|
||||||
|
driver_T* driver = hashmap_lookup(&g_driver_manager.lookup_table_fs_gpt, gpt_hash);
|
||||||
|
if (driver == NULL) return driver_find_fs_gpt(guid);
|
||||||
|
|
||||||
|
return driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_T* driver_lookup_fs_mbr(uint8_t type) {
|
driver_T* driver_lookup_fs_mbr(uint8_t type) {
|
||||||
return NULL;
|
driver_T* driver = hashmap_lookup(&g_driver_manager.lookup_table_fs_gpt, type);
|
||||||
|
if (driver == NULL) return driver_find_fs_mbr(type);
|
||||||
|
|
||||||
|
return driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
driver_T* driver_lookup_by_address(void* address) {
|
driver_T* driver_lookup_by_address(void* address) {
|
||||||
|
|
Loading…
Reference in New Issue