Browse Source

wip drivers

master
Mathieu Serandour 12 months ago
parent
commit
7bd4d1284a
  1. 4
      kernel/acpi/acpi.c
  2. 2
      kernel/acpi/acpi.h
  3. 19
      kernel/acpi/lai.c
  4. 47
      kernel/drivers/driver.h
  5. 103
      kernel/drivers/pcie/pcie.c
  6. 41
      kernel/drivers/pcie/pcie.h
  7. 140
      kernel/drivers/pcie/scan.c
  8. 2
      kernel/drivers/pcie/scan.h
  9. 4
      kernel/drivers/ps2kb.c
  10. 18
      kernel/drivers/terminal/terminal.c
  11. 4
      kernel/drivers/terminal/video.c
  12. 4
      kernel/entry.c
  13. 55
      kernel/int/apic.c
  14. 17
      kernel/int/pic.c
  15. 2
      kernel/lib/panic.c
  16. 5
      kernel/memory/heap.c

4
kernel/acpi/acpi.c

@ -24,7 +24,7 @@ static void* apic_config_base, *hpet_config_space;
// defined in pcie/scan.c
extern struct PCIE_Descriptor pcie_descriptor;
static const struct XSDT* xsdt;
static struct XSDT* xsdt;
static bool __ATTR_PURE__ checksum(const void* table, size_t size) {
@ -42,7 +42,7 @@ static void parse_hpet(const struct HPET* table);
static void parse_fadt(const struct ACPISDTHeader* table);
static void parse_pcie(const struct PCIETable* table);
const struct XSDT* get_xsdt_location(void) {
struct XSDT* get_xsdt_location(void) {
return xsdt;
}

2
kernel/acpi/acpi.h

@ -5,6 +5,6 @@
read RSDP, XSDP, MADT, FADT
*/
void read_acpi_tables(const void* rsdp_location);
const struct XSDT* get_xsdt_location(void);
struct XSDT* get_xsdt_location(void);
void map_acpi_mmios(void);

19
kernel/acpi/lai.c

@ -1,11 +1,15 @@
#include <lai/host.h>
// this file impelments the functions needed
// by the LAI library
#include "acpitables.h"
#include "acpi.h"
#include "../lib/panic.h"
#include "../lib/logging.h"
#include "../lib/sprintf.h"
#include "../memory/heap.h"
#include "acpitables.h"
// this file impelments the functions needed
// by the LAI library
// OS-specific functions.
void *laihost_malloc(size_t s) {
@ -33,17 +37,18 @@ void laihost_panic(const char* msg) {
// only called early:
void *laihost_scan(char * name, size_t c) {
const struct XSDT* xsdt = get_xsdt_location();
struct XSDT* xsdt = get_xsdt_location();
size_t n_entries = (xsdt->header.length - sizeof(xsdt->header)) / sizeof(void*);
const uint32_t* raw = (uint32_t*)name;
uint32_t* raw = (uint32_t*)name;
for(size_t i = 0; i < n_entries; i++) {
const struct ACPISDTHeader* table = xsdt->entries[i];
struct ACPISDTHeader* table = xsdt->entries[i];
if(*raw == table->signature.raw)
return table;
if(c-- == 0)
return table;
}
// no such table

47
kernel/drivers/driver.h

@ -0,0 +1,47 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdatomic.h>
typedef atomic_bool lock_t;
#define DRIVER_STATE_UNINITIALIZED 0
#define DRIVER_STATE_OK 1
#define DRIVER_STATE_FAULT 2
typedef struct {
void* addr;
size_t size;
} resource_t;
typedef struct {
void(* install)(driver_t*);
void(* remove) (void);
const char* name;
uint32_t status;
lock_t lock;
// things like pci BARs,
// hpet registers space, ...
resource_t* iores;
// can be NULL
struct pcie_device* device;
const driver_t* parent;
void* data;
size_t data_len;
} driver_t;
void register_driver(driver_t* dr);
void remove_all_drivers(void);

103
kernel/drivers/pcie/pcie.c

@ -1,6 +1,8 @@
#include "pcie.h"
#include "scan.h"
#include "../nvme.h"
#include "../../lib/logging.h"
#include "../../lib/assert.h"
#include "../../memory/paging.h"
@ -9,10 +11,107 @@
static struct pcie_dev* devices = NULL;
static unsigned n_devices = 0;
// array of drivers
// should be the same size as the
// device array.
// device[i] corresponds to drivers[i]
// if drivers[i] = NULL, device[i] doesn't
// have an installed driver
static struct driver** drivers = NULL;
// at shutdown
static void pcie_shutdown(void);
////__attribute__((pure))
static inline struct resource get_bar_resource(
struct PCIE_config_space* cs,
unsigned i)
{
volatile uint64_t* bar_reg = (uint64_t*)&cs->bar[i];
uint64_t val = *bar_reg;
*bar_reg = ~0llu;
unsigned size = (unsigned) ~*bar_reg + 1;
*bar_reg = val;
return (struct resource) {
.addr = (void *)val,
.size = size,
};
}
// alloc the structure and fill with
// basic info
static struct driver* create_driver_data(
struct device* dev)
{
struct driver* dr = malloc(sizeof(struct driver));
dr->dev = dev;
dr->status = DRIVER_STATE_UNINITIALIZED;
return dr;
}
// recognize compatible drivers
// and set them up
static void setup_drivers(void) {
drivers = malloc(n_devices * sizeof(void *));
for(int i = 0; i < n_devices; i++) {
struct pcie_dev* dev = &devices[i];
// only one driver is supported right now....
if(dev->info.classcode == 1) {
// mass storage drive
if(dev->info.subclasscode == 8) {
// yey! we found an nvme device!
struct driver* dr = create_driver_data(dev);
drivers[i] = dr;
if(vme_install(drivers[i])) {
dev->driver = dr;
log_info("installed driver %u",
dr->driver_name);
}
else {
dr->status = DRIVER_STATE_FAULT;
panic("couldn't install NVMe driver!!");
}
}
}
}
}
void pcie_init(void) {
log_debug("init pcie...");
devices = pcie_scan(&n_devices);
atshutdown(pcie_shutdown);
}
static void free_device(struct pcie_dev* dev) {
assert(dev);
assert(dev->name);
void pcie_init_devices(void) {
}
free(dev->name);
}
static void pcie_shutdown(void) {
for(int i = 0; i < n_devices; i++) {
free_device(devices+i);
}
n_devices = 0;
free(devices);
}

41
kernel/drivers/pcie/pcie.h

@ -6,8 +6,6 @@
#include "../../lib/assert.h"
void pcie_init(void);
void pcie_init_devices(void);
typedef void (*driver_init_fun)(void* config_space);
@ -46,8 +44,9 @@ static_assert_equals(sizeof(pcie_path_t), 8);
struct pcie_dev {
struct resource bars[3];
struct resource* resources;
struct dev_info info;
const char* name;
void* config_space;
@ -57,18 +56,36 @@ struct pcie_dev {
};
struct driver {
driver_init_fun install;
driver_callback remove;
const char* driver_name;
uint32_t status;
struct resource data;
struct pcie_driver {
const struct pcie_device* dev;
};
struct PCIE_config_space {
volatile uint16_t vendorID;
volatile uint16_t deviceID;
uint16_t unused0;
uint16_t unused1;
volatile uint8_t revID;
volatile uint8_t progIF;
volatile uint8_t subclasscode;
volatile uint8_t classcode;
uint16_t reserved3;
volatile uint16_t header_type;
volatile uint8_t BIST;
volatile uint32_t bar[6];
volatile uint32_t cardbud_cis_ptr;
volatile uint16_t subsystemID;
volatile uint16_t subsystem_vendorID;
volatile uint32_t expansion_base;
volatile uint8_t capabilities;
uint8_t reserved0[3];
uint32_t reserved1;
volatile uint8_t interrupt_line;
volatile uint8_t interrupt_pin;
uint16_t reserved5[2];
} __packed;
/**
* PCIE drivers interfaces:

140
kernel/drivers/pcie/scan.c

@ -1,5 +1,6 @@
#include "scan.h"
#include "pcie.h"
#include "../../lib/logging.h"
#include "../../lib/dump.h"
#include "../../lib/assert.h"
@ -8,30 +9,6 @@
#include "../../lib/string.h"
struct PCIE_config_space {
volatile uint16_t vendorID;
volatile uint16_t deviceID;
uint16_t unused0;
uint16_t unused1;
volatile uint8_t revID;
volatile uint8_t progIF;
volatile uint8_t subclasscode;
volatile uint8_t classcode;
volatile uint32_t infos;
volatile uint64_t bar[3];
volatile uint32_t cardbud_cis_ptr;
volatile uint16_t subsystemID;
volatile uint16_t subsystem_vendorID;
volatile uint32_t expansion_base;
volatile uint8_t capabilities;
uint8_t reserved0[3];
uint32_t reserved1;
volatile uint8_t interrupt_line;
volatile uint8_t interrupt_pin;
uint16_t reserved2[2];
};
struct PCIE_Descriptor pcie_descriptor = {0};
@ -53,28 +30,6 @@ struct early_device_desc head_node = {.next = NULL};
struct early_device_desc* current = &head_node;
////__attribute__((pure))
static struct resource get_bar_resource(
struct PCIE_config_space* cs,
unsigned i)
{
volatile uint64_t* bar_reg = (uint64_t*)&cs->bar[i];
uint64_t val = *bar_reg;
*bar_reg = ~0llu;
unsigned size = ~ *bar_reg + 1;
*bar_reg = val;
return (struct resource) {
.addr = (void *)val,
.size = size,
};
}
//__attribute__((pure))
static struct PCIE_config_space*
get_config_space_base(unsigned bus_group,
@ -86,13 +41,13 @@ static struct PCIE_config_space*
assert(bus_group < pcie_descriptor.size);
assert(bus_group == 0);
struct PCIE_busgroup* group_desc = &pcie_descriptor.array[bus_group];
return 0;
/*
return group_desc->address + (
(bus - group_desc->start_bus) << 20
| device << 15
| func << 12);
*/
}
@ -102,10 +57,10 @@ static int __attribute__((pure))
unsigned device,
unsigned func)
{
// struct PCIE_config_space* config_space =
// get_config_space_base(bus_group, bus,device,func);
return 8086;
//return config_space->vendorID;
struct PCIE_config_space* config_space =
get_config_space_base(bus_group, bus,device,func);
//return 8086;
return config_space->vendorID;
}
@ -115,14 +70,21 @@ static void insert(
unsigned device,
unsigned func)
{
/*
struct PCIE_config_space* config_space =
get_config_space_base(bus_group,
bus,
device,
func)
/*
->next = malloc(sizeof(struct early_device_desc));
func);
if((config_space->header_type & 0x7f) != 0 ||
config_space->classcode == 06)
return;
// the device is a bridge,
// we won't do anything with it anyway
current->next = malloc(sizeof(struct early_device_desc));
current = current->next;
current->next = NULL;
@ -132,10 +94,8 @@ static void insert(
current->device = device;
current->function = func;
current->config_space = config_space;
*/
asm volatile("nop");
//printf("%2x:%2x:%2x.%2x - %lx", bus_group, bus, device, func);
//n_found_devices++;
n_found_devices++;
}
@ -237,16 +197,18 @@ static void create_array(void) {
{
struct PCIE_config_space* cs = device->config_space;
assert(i++ < n_found_devices);
assert(i++ < n_found_devices);
char* name_buffer = malloc(32);
sprintf(name_buffer, "dev%u", i);
*ptr++ = (struct pcie_dev) {
.bars = {
0,//get_bar_resource(cs, 0),
0,//get_bar_resource(cs, 1),
0,//get_bar_resource(cs, 2),
},
.resources = NULL,
.driver = NULL,
.config_space = cs,
.driver = NULL,
.name = name_buffer,
.info = (struct dev_info) {
.vendorID = cs->vendorID,
.deviceID = cs->deviceID,
@ -255,6 +217,7 @@ static void create_array(void) {
.progIF = cs->progIF,
.revID = cs->revID,
},
.path = (pcie_path_t) {
.domain = device->domain,
.bus = device->bus,
@ -262,8 +225,6 @@ static void create_array(void) {
.func = device->function,
},
};
free(device);
}
@ -303,47 +264,14 @@ static void identity_unmap_possible_config_spaces(void) {
*/
struct pcie_dev* pcie_scan(unsigned* size) {
log_debug("scanning pcie devices...");
log_debug("%u PCIE bus groups found", pcie_descriptor.size);
identity_map_possible_config_spaces();
log_debug("identity_map_possible_config_spaces()", pcie_descriptor.size);
//scan_devices();
log_debug("devices scanned", pcie_descriptor.size);
//create_array();
//log_debug("memory shit done", pcie_descriptor.size);
for(unsigned i = 0; i < n_found_devices; i++) {
log_warn("%2x:%2x:%2x: %2x:%2x:%2x, rev %2x, "
"vendor 0x%4x",
found_devices[i].path.bus,
found_devices[i].path.device,
found_devices[i].path.func,
found_devices[i].info.classcode,
found_devices[i].info.subclasscode,
found_devices[i].info.progIF,
found_devices[i].info.revID,
found_devices[i].info.vendorID
);
}
scan_devices();
create_array();
// identity_unmap_possible_config_spaces();
log_info("found %u PCI Express devices", n_found_devices);
identity_unmap_possible_config_spaces();
*size = n_found_devices;
return found_devices;
}

2
kernel/drivers/pcie/scan.h

@ -22,7 +22,7 @@ static_assert_equals(sizeof(struct PCIE_busgroup), 16);
#define PCIE_SUPPORTED_SEGMENT_GROUPS 2
struct PCIE_Descriptor {
size_t size;
struct PCIE_busgroup array[PCIE_SUPPORTED_SEGMENT_GROUPS];
struct PCIE_busgroup array[2];
// we only handle PCIE devices with only 4 segment groups max
};

4
kernel/drivers/ps2kb.c

@ -132,6 +132,8 @@ static void process_byte(uint8_t b) {
static void __attribute__((interrupt)) irq_handler(void* r) {
(void) r;
uint8_t status = inb(0x64);
// sometimes, interrupts
@ -146,7 +148,7 @@ static void __attribute__((interrupt)) irq_handler(void* r) {
void ps2kb_init(void) {
log_debug("init ps/2 keyboard...");
set_irq_handler(17, irq_handler);
set_irq_handler(33, irq_handler);
unsigned status = inb(0x64);
if(status & 0xc0) {

18
kernel/drivers/terminal/terminal.c

@ -83,7 +83,7 @@ static char* stream_buffer = NULL;
// should execute in an IRQ
void terminal_update(void) {
return;
static unsigned update_cur_line = 0;
//static unsigned update_cur_line = 0;
@ -96,11 +96,6 @@ void terminal_update(void) {
}
void terminal_remove(void) {
apic_delete_timer(timerID);
}
void terminal_install_early(void) {
set_terminal_handler(empty_terminal_handler);
@ -148,7 +143,7 @@ void terminal_install_early(void) {
// finish intallation when memory
// is well initialized
void terminal_install_late(void) {
//timerID = apic_create_timer(terminal_update, UPDATE_PERIOD_MS);
timerID = apic_create_timer(terminal_update, UPDATE_PERIOD_MS);
@ -160,6 +155,15 @@ void terminal_install_late(void) {
terminal_clear();
}
void terminal_remove(void) {
bmp_free(charmap);
free(char_buffer);
free(stream_buffer);
if(timerID != INVALID_TIMER_ID)
apic_remove_timer(timerID);
}
void terminal_clear(void) {

4
kernel/drivers/terminal/video.c

@ -3,11 +3,13 @@
// for initialization
#include <stivale2.h>
#include "../../memory/heap.h"
#include "../../lib/string.h"
#include "../../lib/logging.h"
//#include "../memory/heap.h"
#include "../../lib/common.h"
#include "../../lib/assert.h"
#include "video.h"
#include "terminal.h"

4
kernel/entry.c

@ -147,13 +147,13 @@ void _start(struct stivale2_struct *stivale2_struct) {
const struct stivale2_struct_tag_memmap* memmap_tag;
const struct stivale2_struct_tag_framebuffer* framebuffer_tag;
const struct stivale2_struct_tag_rsdp* rsdp_tag_ptr;
const struct stivale2_struct_tag_boot_volume* boot_volume_tag;
//const struct stivale2_struct_tag_boot_volume* boot_volume_tag;
term_str_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_TERMINAL_ID);
memmap_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_MEMMAP_ID);
framebuffer_tag = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID);
rsdp_tag_ptr = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_RSDP_ID);
boot_volume_tag = stivale2_get_tag(stivale2_struct, 0x9b4358364c19ee62);
//boot_volume_tag = stivale2_get_tag(stivale2_struct, 0x9b4358364c19ee62);
// term_str_tag == NULL is not a blocking

55
kernel/int/apic.c

@ -62,40 +62,69 @@ static uint64_t apic_timer_clock_count = 0;
// 1 ms
#define CLOCK_FREQUENCY 1
struct timer {
typedef struct {
unsigned period;
unsigned counter;
void (*func)(void);
};
char exists;
} timer_t;
// realloc(NULL, s) ~ malloc(s)
static struct timer* timers = NULL;
timer_t* timers = NULL;
static unsigned n_timers = 0;
static unsigned buffsize = 0;
static void timers_realloc(void) {
if(n_timers == 0) {
// performs a free
buffsize = 0;
}
if(n_timers > buffsize)
buffsize *= 2;
else if(n_timers < buffsize / 2)
buffsize /= 2;
timers = realloc(timers, buffsize*sizeof(timer_t));
}
unsigned apic_create_timer(void (*fun)(void), int millisecs) {
unsigned id = n_timers++;
if(n_timers > buffsize) {
buffsize *= 2;
timers = realloc(timers, buffsize);
}
timers_realloc();
timers[id].counter = 0;
timers[id].period = millisecs * CLOCK_FREQUENCY;
timers[id].func = fun;
timers[id].func = fun;
timers[id].exists = 1;
return id;
}
int apic_delete_timer(unsigned id) {
if(id >= n_timers)
return 0;
n_timers--;
timers[id].exists = 0;
memmove(timers+id, timers+id+1, (n_timers - id) * sizeof(struct timer));
if(n_timers < buffsize/2) {
buffsize /= 2;
timers = realloc(timers, buffsize);
// check if we can free the end of the list
// end of the list:
// timers[timer_end -> n_timers-1].exist = 0
char timer_end = 0;
for(int i = 0; i < n_timers; i++) {
if(timers[i].exists)
timer_end = i+1;
}
if(timer_end != timer_end) {
n_timers = timer_end;
timers_realloc();
}
return 1;

17
kernel/int/pic.c

@ -40,27 +40,17 @@ static uint16_t mask = 0xff;
void pic_init(void) {
log_debug("init PIC...");
outb(0x80, 0);
// 0x343
// 34*2=68
// mask all interrupts
// if already initialized
outb(PIC1_DATA, 0xff);
outb(PIC2_DATA, 0xff);
_cli();
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
// starts the initialization sequence (in cascade mode)
io_wait();
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
io_wait();
outb(PIC1_DATA, 16);
outb(PIC1_DATA, 32);
// ICW2: Master PIC vector offset
io_wait();
outb(PIC2_DATA, 24);
outb(PIC2_DATA, 40);
// ICW2: Slave PIC vector offset
io_wait();
outb(PIC1_DATA, 4);
@ -80,6 +70,7 @@ void pic_init(void) {
outb(PIC1_DATA, 0xff);
outb(PIC2_DATA, 0xff);
_sti();
}

2
kernel/lib/panic.c

@ -24,7 +24,7 @@ static inline __attribute__((always_inline)) void stack_trace(void) {
break;
void* rip = *(ptr+1);
if(!is_kernel_memory(rip)) {
if(!is_kernel_memory((uint64_t)rip)) {
//maybe it is an exception error code
rip = *(ptr+2);

5
kernel/memory/heap.c

@ -354,6 +354,11 @@ static void realloc_shrink(seg_header* header, size_t size) {
void* realloc(void* ptr, size_t size) {
if(ptr == NULL)
return malloc(size);
if(size == 0) {
free(ptr);
return NULL;
}
seg_header* header = ptr - sizeof(seg_header);
if(size <= header->size) {// no need to move

Loading…
Cancel
Save