feat: taken qsort from PDCLIB, Sorting drivers. Generic driver

structure. Driver ranking
This commit is contained in:
2021-03-07 14:43:35 +01:00
parent 01efc5e98a
commit f6e720bad9
11 changed files with 255 additions and 44 deletions

View File

@@ -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,
);

View File

@@ -13,6 +13,7 @@
#ifdef ENABLE_PCIPP
#include <drivers/pci_devices.h>
#include <libc/sort.h>
#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

View File

@@ -11,10 +11,15 @@
#include <attributes.h>
#define PCI_CLASS_MASS_STORAGE 0x01
#define PCI_CLASS_BRIDGE 0x06
// class MASS STORAGE 1
// 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)));

View File

@@ -9,6 +9,7 @@
#include <tasks/task.h>
#include <tasks/locking.h>
#include <attributes.h>
#include <libc/sort.h>
#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);

View File

@@ -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();

View File

@@ -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
);

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

129
kernel/libc/sort.c Normal file
View File

@@ -0,0 +1,129 @@
//
// Created by rick on 06-03-21.
//
#include "sort.h"
#include "libc.h"
#include <types.h>
// 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;
}
}
}
}

11
kernel/libc/sort.h Normal file
View File

@@ -0,0 +1,11 @@
//
// Created by rick on 06-03-21.
//
#ifndef NEW_KERNEL_SORT_H
#define NEW_KERNEL_SORT_H
#include <types.h>
void qsort(void *base, size_t num, size_t size, int (*compar)(const void *, const void *));
#endif //NEW_KERNEL_SORT_H