I already implemented some subsystem of my kernel (without memory allocation, timer support, etc.). My build system allows to select, which drivers to compile with kernel - it append -DMODULE_mname_NUMBER=number to gcc parameters, so I can do checking if driver is compiled. It also supports GNU Grub modules, so GRUB can load for example LANG_en_GB_map or LANG_pl_PL_map to kernel and message driver (if compiled) can use it, so you can enable kernel messages during compile time and select language of kernel messages, when system is loading.
But.. There's no many device drivers. I have only module to support text video mode (writing a string to screen) and x86 driver. I cannot implement either keyboard support.
There's my x86 driver code:
Code: Select all
#include "x86.h"
#include "objects.h"
void do_after_modules_loaded(char (*handler)(void *,struct drivers*, int driver_count));
struct git_entry interrupts[256];
struct git_header int_info;
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
static int set_interrupt(int number, int csel, void *fnc)
{
interrupts[number].addr_lower = (int)fnc & 0xffff;
interrupts[number].addr_higher = ((int)fnc >> 16) & 0xffff;
interrupts[number].mesh = 0;
interrupts[number].flags = INT_DESC_BITS32 | INT_DESC_RING0 | INT_DESC_PRESENT;
interrupts[number].sel_number = csel;
return 1;
}
static struct driver_export_table robjects[] = {
{1, (struct api_version_export[]) {
{
"processor", 0, 0, 1,
1, (struct driver_symbol[]) {
{"create_ide", parameter_int, parameter_int parameter_int parameter_function, set_interrupt},
}
}
}
}
};
void(*print_fnc)(void *,const char *);
void *print_module_addr;
void real_keyboard_interrupt()
{
if (0 != print_fnc) {
print_fnc(print_module_addr, "PRZYCISK ");
}
}
extern void keyboard_interrupt(void);
extern void default_interrupt(void);
__asm__ (".global keyboard_interrupt\n"
"keyboard_interrupt:\n"
"cli\n"
"cld\n"
"pusha\n"
"call real_keyboard_interrupt\n"
"mov $32, %al\n"
"out %al, $160 \n"
"out %al, $32\n"
"popa\n"
"sti\n"
"iret");
__asm__ (".global default_interrupt\n"
"default_interrupt:\n"
"cli\n"
"pusha\n"
"mov $32, %al\n"
"out %al, $160\n"
"out %al, $32\n"
"popa\n"
"sti\n"
"iret");
static char init;
static char interrupts_init(void *mesh,struct drivers*drivers, int driver_count)
{
int csel = 16;
struct object *obj = ((struct object * (*)(const char *))drivers[DRIVER_objects_NUMBER].get_export_tables()->api_version_exports->symbols[0].procedure)("console_service");
if (0 != obj) {
print_module_addr = obj->owner;
print_fnc = (void(*)(void *,const char *)) obj->exports->api_version_exports[0].symbols[0].procedure;
set_interrupt(33, csel, keyboard_interrupt);
}
write_port(100, 0xae);
write_port(33, 0xFD);
__asm__ __volatile__ ("sti");
}
struct driver_export_table *driver_x86_init()
{
if (0 == init) {
int i;
int_info.size = sizeof(interrupts) - 1;
//int_info.size = 255;//sizeof(interrupts) - sizeof(interrupts[0]);
int_info.ptr = &interrupts;
int csel = 16;
for (i = 0; i < ARRAY_SIZE(interrupts); ++i) {
set_interrupt(i, csel, default_interrupt);
}
++init;
__asm__ __volatile__ ("lidt (int_info)":: :);
write_port(32, 17);
write_port(160, 17);
write_port(33, 32);
write_port(161, 40);
write_port(33, 4);
write_port(161, 2);
write_port(33, 1);
write_port(161, 1);
write_port(33, 0xFF);
write_port(161, 0xFF);
do_after_modules_loaded(interrupts_init);
}
return robjects;
}
Thanks!