feature (drivers): implemented driver registration and lookup

This commit is contained in:
antifallobst 2023-06-01 13:12:34 +02:00
parent a904629abd
commit 74aa1a4e4d
4 changed files with 131 additions and 10 deletions

View File

@ -5,10 +5,12 @@
#include <utils/stdtypes.h>
#include <utils/bitmap.h>
#include <utils/hashmap.h>
#include <drivers/builtin/elf/elf.h>
#define DRIVER_MANAGER_CHUNK_SIZE 64
#define DRIVER_MEMORY_REGION_SIZE 0x100000000 // 4 GB
#define DRIVER_MANAGER_CHUNK_SIZE 64
#define DRIVER_MANAGER_HASHMAP_SIZE 128
#define DRIVER_MEMORY_REGION_SIZE 0x100000000 // 4 GB
typedef enum {
DRIVER_TRANSPORT_PCI,
@ -55,13 +57,13 @@ typedef struct {
uint8_t subclass;
uint8_t progif;
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;
typedef struct {
uint8_t min_version;
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;
typedef struct {
@ -94,6 +96,10 @@ struct driver_manager_chunk_T {
typedef struct {
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;
void driver_manager_init ();

View File

@ -97,5 +97,10 @@ void kmain(boot_info_T boot_info) {
void (*drv_test)() = entry;
drv_test();
driver_T* resolved = driver_lookup_pci_device(0x886, 0x2920);
DEBUG("driver: 0x%x", drv);
DEBUG("resolved: 0x%x", resolved);
CORE_HALT_FOREVER
}

View File

@ -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());
if (driver == NULL) return;
driver_init(driver, DRIVER_TRANSPORT_PCI, (conf_U)config);
}
void nx_drv_usb_config(driver_config_usb_T* config) {
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
if (driver == NULL) return;
driver_init(driver, DRIVER_TRANSPORT_USB, (conf_U)config);
}
void nx_drv_fs_config(driver_config_fs_T* config) {
driver_T* driver = driver_lookup_by_address((void*)stack_get_caller());
if (driver == NULL) return;
driver_init(driver, DRIVER_TRANSPORT_FS, (conf_U)config);
}

View File

@ -10,7 +10,11 @@
driver_manager_T g_driver_manager;
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) {
@ -47,8 +51,89 @@ driver_T* driver_find_fs_mbr(uint8_t type) {
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) {
@ -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) {
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) {
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]) {
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) {
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) {