diff --git a/kernel/drivers/ide.c b/kernel/drivers/ide.c index b24ae6a..80999fc 100644 --- a/kernel/drivers/ide.c +++ b/kernel/drivers/ide.c @@ -674,13 +674,13 @@ uint8_t ide_access(uint8_t direction, uint8_t drive, uint32_t lba, uint8_t numse PCI_DRIVER( .name = "pci-ide", .description = "Default PCI IDE Driver", - .order = 0xFF, // let other block_dev_drivers precede if they can - .pci_use_subclass = true, + .rank = 10000, // let other block_dev_drivers precede if they can .validatable = true, .initialisable = true, - .pci_class = PCI_CLASS_MASS_STORAGE, - .pci_subclass = PCI_SUB_CLASS_IDE, - + .match.class = PCI_CLASS_MASS_STORAGE, + .match.subclass = PCI_SUB_CLASS_IDE, + .mask.class = true, + .mask.subclass = true, .validate = ide_pci_validate, .initialize = ide_pci_initialize, ); diff --git a/kernel/drivers/pci.c b/kernel/drivers/pci.c index a0c6eac..a52095e 100644 --- a/kernel/drivers/pci.c +++ b/kernel/drivers/pci.c @@ -13,6 +13,7 @@ #ifdef ENABLE_PCIPP #include +#include #endif @@ -34,17 +35,6 @@ #define MASK_BAR_IOSPACE 0xFFFFFFFC #define MASK_BAR_MEMSPACE 0xFFFFFFF0 -const struct pci_driver pci_internal_secondary_bus = { - .name = "pci-secondary-bus", - .description = "A PCI bus connected to the primary bus", - .order = 0, - .pci_class = 0x06, - .pci_subclass = 0x04, - .pci_use_subclass = true, - .validate = NULL, - .initialize = NULL, -}; - //const pci_driver *pci_drivers[MAX_PCI_DRIVERS]; extern struct pci_driver __start_pci_driver[]; extern struct pci_driver __stop_pci_driver[]; @@ -55,6 +45,13 @@ pci_device pci_devices[MAX_PCI_DEVICES]; void pci_check_bus(uint8_t bus); +uint8_t used pci_secondary_bus_use(const pci_device *device) { + uint8_t secondary_bus = pci_config_read_byte(device->bus, device->slot, device->func, + PCI_CONFIG_SECONDARY_BUS_NUMBER); + pci_check_bus(secondary_bus); + return PCI_USE_OK; +} + uint32_t pci_config_address(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) { return PCI_CONFIG_ENABLE | ((uint32_t) bus << PCI_CONFIG_SHIFT_BUS_NUMBER) @@ -124,32 +121,35 @@ uint8_t pci_get_header_type(uint8_t bus, uint8_t slot, uint8_t func) { } void pci_pick_driver(pci_device *device) { - // check special drivers - // PCI Secondary bus - if (device->class == pci_internal_secondary_bus.pci_class && - device->subclass == pci_internal_secondary_bus.pci_subclass) { - uint8_t secondary_bus = pci_config_read_byte(device->bus, device->slot, device->func, - PCI_CONFIG_SECONDARY_BUS_NUMBER); - device->pci_driver = &pci_internal_secondary_bus; - pci_check_bus(secondary_bus); - return; - } - - // use normal drivers for (size_t i = 0; i < NUM_DRIVERS; ++i) { - if (DRIVER(i) == NULL) { + struct pci_driver *driver = DRIVER(i); + if (driver == NULL) { continue; } - if (device->class != DRIVER(i)->pci_class) { + if (driver->mask.class && driver->match.class != device->class) { continue; } - if (DRIVER(i)->pci_use_subclass && device->subclass != DRIVER(i)->pci_subclass) { + if (driver->mask.subclass && driver->match.subclass != device->subclass) { continue; } - if (!DRIVER(i)->validatable) { + if (driver->mask.interface && driver->match.interface != device->programInterface) { continue; } - if (DRIVER(i)->validate(device) != PCI_VALIDATE_OK) { + if (driver->mask.vendor && driver->match.vendor != device->vendorId) { + continue; + } + if (driver->mask.device && driver->match.device != device->deviceId) { + continue; + } + if (driver->direct_use) { + if (driver->use(device) != PCI_USE_OK) { + continue; + } + } else if (driver->validatable) { + if (driver->validate(device) != PCI_VALIDATE_OK) { + continue; + } + } else { continue; } device->pci_driver = DRIVER(i); @@ -192,8 +192,19 @@ void pci_check_bus(uint8_t bus) { } } +int pci_driver_compare(const void* a, const void* b) { + int rank_a = ((struct pci_driver *) a)->rank; + int rank_b = ((struct pci_driver *) b)->rank; + if (rank_a > rank_b) { + return 1; + } else if (rank_a < rank_b) { + return -1; + } + return 0; +} + void pci_sort_drivers() { - // todo + qsort(DRIVER(0), NUM_DRIVERS, sizeof(struct pci_driver), pci_driver_compare); } void pci_scan() { @@ -373,4 +384,17 @@ void pci_init_bar(pci_device *device, uint8_t bar_index) { bar->present = 1; } +// internal drivers +PCI_DRIVER( + .name = "pci-secondary-bus", + .description = "A PCI bus connected to the primary bus", + .rank = 0, // internal driver for PCI bus + .match.class = PCI_CLASS_BRIDGE, + .match.subclass = PCI_SUB_CLASS_PCI_PCI_BRIDGE_4, + .mask.class = true, + .mask.subclass = true, + .direct_use = true, + .use = pci_secondary_bus_use, +); + // todo https://wiki.osdev.org/Universal_Serial_Bus if i dare \ No newline at end of file diff --git a/kernel/drivers/pci.h b/kernel/drivers/pci.h index ab6052e..ba4f4d2 100644 --- a/kernel/drivers/pci.h +++ b/kernel/drivers/pci.h @@ -10,10 +10,15 @@ #include #include -#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_CLASS_BRIDGE 0x06 -// class MASS STORAGE 1 -#define PCI_SUB_CLASS_IDE 0x01 +// class MASS STORAGE 0x01 +#define PCI_SUB_CLASS_IDE 0x01 + +// class BRIDGE 0x06 +#define PCI_SUB_CLASS_PCI_PCI_BRIDGE_4 0x04 +#define PCI_SUB_CLASS_PCI_PCI_BRIDGE_9 0x09 #define PCI_REGISTER_OK 0 #define PCI_REGISTER_ERR_FULL (-1) @@ -24,6 +29,9 @@ #define PCI_INIT_OK 0 #define PCI_INIT_FAIL 1 +#define PCI_USE_OK 0 +#define PCI_USE_FAIL 1 + #define PCI_HEADER_TYPE_MULTI_FUNC 0x80 #define PCI_HEADER_TYPE_ENDPOINT 0x00 #define PCI_HEADER_TYPE_PCI_PCI_BRIDGE 0x01 @@ -79,6 +87,8 @@ typedef struct pci_device pci_device; +typedef uint8_t (*pci_driver_use)(const pci_device *); + typedef uint8_t (*pci_driver_validate)(const pci_device *); typedef uint8_t (*pci_driver_initialize)(pci_device *); @@ -86,14 +96,27 @@ typedef uint8_t (*pci_driver_initialize)(pci_device *); struct pci_driver { const char *name; const char *description; - uint8_t order; - uint8_t pci_class; - uint8_t pci_subclass; + uint16_t rank; struct { - bool pci_use_subclass: 1; + uint8_t class; + uint8_t subclass; + uint8_t interface; + uint16_t vendor; + uint16_t device; + } match; + struct { + bool class: 1; + bool subclass: 1; + bool interface: 1; + bool vendor: 1; + bool device: 1; + } mask; + struct { + bool direct_use: 1; bool validatable: 1; bool initialisable: 1; }; + pci_driver_use use; pci_driver_validate validate; pci_driver_initialize initialize; } __attribute__((__aligned__(STRUCT_ALIGNMENT))); diff --git a/kernel/fs/blockdev.c b/kernel/fs/blockdev.c index 5712746..c486b27 100644 --- a/kernel/fs/blockdev.c +++ b/kernel/fs/blockdev.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "blockdev.h" #define MAX_BLOCK_DEVS 64 @@ -79,6 +80,21 @@ void block_dev_scan() { } } +int block_dev_driver_comp(const void *a, const void *b) { + int rank_a = ((struct block_dev_driver *) a)->rank; + int rank_b = ((struct block_dev_driver *) b)->rank; + if (rank_a > rank_b) { + return 1; + } else if (rank_a < rank_b) { + return -1; + } + return 0; +} + +void block_dev_pre_init() { + qsort(DRIVER(0), NUM_DRIVERS, sizeof(struct block_dev_driver), block_dev_driver_comp); +} + void noreturn block_dev_task(void *data) { while (true) { semaphore_wait(block_semaphore); diff --git a/kernel/fs/blockdev.h b/kernel/fs/blockdev.h index 1e18af6..26ae7f4 100644 --- a/kernel/fs/blockdev.h +++ b/kernel/fs/blockdev.h @@ -34,6 +34,7 @@ typedef uint8_t (*block_device_access)(const block_device *device, uint8_t direc struct block_dev_driver { char name[16]; + uint16_t rank; struct { uint8_t root_only: 1; } flags; @@ -64,6 +65,8 @@ uint8_t block_dev_register(block_device *device); void block_dev_free(block_device *device); +void block_dev_pre_init(); + void block_dev_start_task(); void block_dev_print_info(); diff --git a/kernel/fs/fat.c b/kernel/fs/fat.c index a594e68..61361eb 100644 --- a/kernel/fs/fat.c +++ b/kernel/fs/fat.c @@ -195,6 +195,7 @@ get_fat_table_value(uint8_t fat_type, const uint8_t *fat_table, uint32_t active_ BLOCK_DEV_DRIVER( .name = "fat", + .rank = 10000, .check_device = fat_check_device, .free_device = NULL, // todo ); diff --git a/kernel/fs/mbr.c b/kernel/fs/mbr.c index 82e43e9..e1dd45a 100644 --- a/kernel/fs/mbr.c +++ b/kernel/fs/mbr.c @@ -102,6 +102,7 @@ void mbr_read_from_ide(uint8_t ide_drive) { BLOCK_DEV_DRIVER( .name = "mbr", + .rank = 100, .flags.root_only = 1, .check_device = mbr_check_device, .free_device = NULL, // todo diff --git a/kernel/kernel.c b/kernel/kernel.c index 17a3ebf..f1b07e7 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -60,6 +60,9 @@ void noreturn used kmain(multiboot_info_t *multiboot_info, uint32_t mb_name) { // identify cpu cpuidx_print_info(); + // pre init drivers + block_dev_pre_init(); + // enable interrupts __asm__ __volatile__("sti"); // start the timer diff --git a/kernel/libc/libc.c b/kernel/libc/libc.c index 9251bcd..32e9261 100644 --- a/kernel/libc/libc.c +++ b/kernel/libc/libc.c @@ -30,8 +30,8 @@ int abs(int val) { } // next stolen form https://www.techiedelight.com/implement-itoa-function-in-c/ -// inline function to swap two numbers -void swap(char *x, char *y) { +// inline function to swapc two numbers +void swapc(char *x, char *y) { char t = *x; *x = *y; *y = t; @@ -40,7 +40,7 @@ void swap(char *x, char *y) { // function to reverse buffer[i..j] char *reverse(char *buffer, int i, int j) { while (i < j) - swap(&buffer[i++], &buffer[j--]); + swapc(&buffer[i++], &buffer[j--]); return buffer; } diff --git a/kernel/libc/sort.c b/kernel/libc/sort.c new file mode 100644 index 0000000..580e8cb --- /dev/null +++ b/kernel/libc/sort.c @@ -0,0 +1,129 @@ +// +// Created by rick on 06-03-21. +// + +#include "sort.h" +#include "libc.h" +#include + +// taken from https://github.com/DevSolar/pdclib/blob/master/functions/stdlib/qsort.c + +/* This implementation is taken from Paul Edward's PDPCLIB. + Original code is credited to Raymond Gardner, Englewood CO. + Minor mods are credited to Paul Edwards. + Some reformatting and simplification done by Martin Baute. + All code is still Public Domain. +*/ + +static inline void memswp(uint8_t *i, uint8_t *j, size_t size) { + uint8_t tmp[size]; + memcpy(tmp, j, size); + memcpy(j, i, size); + memcpy(i, tmp, size); +} + +/* For small sets, insertion sort is faster than quicksort. + T is the threshold below which insertion sort will be used. + Must be 3 or larger. +*/ +#define T 7 + +/* Macros for handling the QSort stack */ +#define PREPARE_STACK void * stack[STACKSIZE]; void ** stackptr = stack +#define PUSH(base, limit) stackptr[0] = base; stackptr[1] = limit; stackptr += 2 +#define POP(base, limit) stackptr -= 2; (base) = stackptr[0]; (limit) = stackptr[1] +/* TODO: Stack usage is log2( nmemb ) (minus what T shaves off the worst case). + Worst-case nmemb is platform dependent and should probably be + configured through _PDCLIB_config.h. +*/ +#define STACKSIZE 64 + +void qsort(void *base, size_t nmemb, size_t size, int ( *compar )(const void *, const void *)) { + void *i; + void *j; + size_t thresh = T * size; + void *base_ = base; + void *limit = base_ + nmemb * size; + PREPARE_STACK; + + for (;;) { + if ((size_t) (limit - base_) > thresh) /* QSort for more than T elements. */ + { + /* We work from second to last - first will be pivot element. */ + i = base_ + size; + j = limit - size; + /* We swap first with middle element, then sort that with second + and last element so that eventually first element is the median + of the three - avoiding pathological pivots. + TODO: Instead of middle element, chose one randomly. + */ + memswp(((((size_t) (limit - base_)) / size) / 2) * size + base_, base_, size); + + if (compar(i, j) > 0) { + memswp(i, j, size); + } + + if (compar(base_, j) > 0) { + memswp(base_, j, size); + } + + if (compar(i, base_) > 0) { + memswp(i, base_, size); + } + + /* Now we have the median for pivot element, entering main Quicksort. */ + for (;;) { + do { + /* move i right until *i >= pivot */ + i += size; + } while (compar(i, base_) < 0); + + do { + /* move j left until *j <= pivot */ + j -= size; + } while (compar(j, base_) > 0); + + if (i > j) { + /* break loop if pointers crossed */ + break; + } + + /* else swap elements, keep scanning */ + memswp(i, j, size); + } + + /* move pivot into correct place */ + memswp(base_, j, size); + + /* larger subfile base / limit to stack, sort smaller */ + if (j - base_ > limit - i) { + /* left is larger */ + PUSH(base_, j); + base_ = i; + } else { + /* right is larger */ + PUSH(i, limit); + limit = j; + } + } else /* insertion sort for less than T elements */ + { + for (j = base_, i = j + size; i < limit; j = i, i += size) { + for (; compar(j, j + size) > 0; j -= size) { + memswp(j, j + size, size); + + if (j == base_) { + break; + } + } + } + + if (stackptr != stack) /* if any entries on stack */ + { + POP(base_, limit); + } else /* else stack empty, done */ + { + break; + } + } + } +} diff --git a/kernel/libc/sort.h b/kernel/libc/sort.h new file mode 100644 index 0000000..5add42e --- /dev/null +++ b/kernel/libc/sort.h @@ -0,0 +1,11 @@ +// +// Created by rick on 06-03-21. +// + +#ifndef NEW_KERNEL_SORT_H +#define NEW_KERNEL_SORT_H +#include + +void qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *)); + +#endif //NEW_KERNEL_SORT_H