summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-06-08 16:06:30 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-06-08 16:06:30 +0200
commit00bea0a48f5e8c59260470bdc004734a87034d42 (patch)
treeb71fdffcf397eec9307958c15bfc4d256e4b72f9
parent9ab2b8ec18c34780492e7bcbf4c7b21c1997c734 (diff)
downloadabaos-00bea0a48f5e8c59260470bdc004734a87034d42.tar.gz
abaos-00bea0a48f5e8c59260470bdc004734a87034d42.tar.bz2
added driver manager
keyboard and mouse are now "derived" from driver_t reading and printing more PCI members
-rw-r--r--doc/LINKS.TODO3
-rw-r--r--src/.gdbinit2
-rw-r--r--src/Makefile12
-rw-r--r--src/README7
-rw-r--r--src/driver.c58
-rw-r--r--src/driver.h29
-rw-r--r--src/kernel.c40
-rw-r--r--src/keyboard.c30
-rw-r--r--src/keyboard.h11
-rw-r--r--src/mouse.c29
-rw-r--r--src/mouse.h11
-rw-r--r--src/pci.c10
-rw-r--r--src/pci.h17
-rw-r--r--src/stage1_functions.asm2
14 files changed, 235 insertions, 26 deletions
diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO
index 1711346..d58cc0d 100644
--- a/doc/LINKS.TODO
+++ b/doc/LINKS.TODO
@@ -67,3 +67,6 @@ http://www.sci.muni.cz/docs/pc/serport.txt
Boot:
https://www.cs.cmu.edu/~410-s07/p4/p4-boot.pdf
+
+C:
+http://www.drdobbs.com/extending-c-for-object-oriented-programm/184402731
diff --git a/src/.gdbinit b/src/.gdbinit
index 12d2269..da2e75c 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1,5 +1,5 @@
target remote localhost:1234
symbol-file kernel.sym
-break entry
+break kernel_main
c
wh 10
diff --git a/src/Makefile b/src/Makefile
index 934ec7b..615c3b6 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -13,10 +13,10 @@ all: image.bin kernel.sym
# + M * 512 (M is currently 7) = 3144 for kernel.bin
# + 1 * 512 = 512 for magic.bin
# (M + N + 1 is the number of sectors to be read in stage 2, as stage 1
-# loads only the first sector, so adapt NOF_LOAD_SECTORS to 36)
+# loads only the first sector, so adapt NOF_LOAD_SECTORS to 38)
image.bin: boot.bin kernel.bin magic.bin
cat boot.bin kernel.bin > image.tmp
- truncate -s 18432 image.tmp
+ truncate -s 19456 image.tmp
cat image.tmp magic.bin > image.bin
boot.bin: boot.asm boot_gdt.asm stage1_functions.asm stage2_functions.asm stage2_switch_mode.asm stage2_a20.asm
@@ -28,10 +28,11 @@ kernel.bin: kernel.elf
kernel.sym: kernel.elf
$(OBJCOPY) --only-keep-debug kernel.elf kernel.sym
-kernel.elf: kernel.o kernel_asm.o console.o vga.o serial.o port.o port_asm.o interrupts.o interrupts_asm.o pci.o keyboard.o mouse.o string.o stdlib.o stdio.o setjmp.o
+kernel.elf: kernel.o kernel_asm.o console.o vga.o serial.o port.o port_asm.o interrupts.o interrupts_asm.o driver.o pci.o keyboard.o mouse.o string.o stdlib.o stdio.o setjmp.o
$(LD) -o kernel.elf -N -n -Ttext 0x8400 --oformat elf32-i386 \
kernel.o kernel_asm.o console.o vga.o serial.o \
- port.o port_asm.o interrupts.o interrupts_asm.o pci.o \
+ port.o port_asm.o interrupts.o interrupts_asm.o \
+ driver.o pci.o \
keyboard.o mouse.o \
string.o stdlib.o stdio.o setjmp.o
@@ -65,6 +66,9 @@ interrupts.o: interrupts.c interrupts.h
interrupts_asm.o: interrupts.asm
$(NASM) interrupts.asm $(NASMFLAGS) -o interrupts_asm.o
+driver.o: driver.c driver.h
+ $(CC) $(CFLAGS) -c -o driver.o driver.c
+
pci.o: pci.c pci.h
$(CC) $(CFLAGS) -c -o pci.o pci.c
diff --git a/src/README b/src/README
index a6d5b9a..0d1719c 100644
--- a/src/README
+++ b/src/README
@@ -14,13 +14,14 @@ kernel utility routines
* port.c, port.asm - I/O ports
* interrupts.c, interrups.asm - interrupt handlers
* pci.c - PCI introspection and driver initialization
-
-kernel drivers
* console.c - the kernel console, can use VGA or serial port for now
* vga.c - VGA basic output routines for early kernel output
+* serial.c - serial output to COM1 (only sequential ASCII chars, no terminal)
+
+kernel drivers
+* driver.c - generic driver manager
* keyboard.c - PS/2 keyboard
* mouse.c - PS/2 mouse
-* serial.c - serial output to COM1 (only sequential ASCII chars, no terminal)
C library definitions
* stddef.h - definition of NULL, size_t
diff --git a/src/driver.c b/src/driver.c
new file mode 100644
index 0000000..145e143
--- /dev/null
+++ b/src/driver.c
@@ -0,0 +1,58 @@
+#include "driver.h"
+
+#include "kernel.h"
+#include "string.h"
+
+void driver_manager_init( driver_manager_t *manager )
+{
+ memset( manager, 0, sizeof( driver_manager_t ) );
+
+ manager->nof_drivers = 0;
+}
+
+void driver_manager_add_driver( driver_manager_t *manager, driver_t *driver )
+{
+ if( manager->nof_drivers >= MAX_NOF_DRIVERS - 1 ) {
+ kernel_panic( "Allocating more than %d drivers.. increase kernel constant", MAX_NOF_DRIVERS );
+ }
+
+ manager->driver[manager->nof_drivers] = driver;
+ manager->nof_drivers++;
+}
+
+void driver_manager_activate_all( driver_manager_t *manager )
+{
+ for( int i = 0; i < manager->nof_drivers; i++ ) {
+ driver_t *driver = (driver_t *)manager->driver[i];
+ driver_vtable_t *driver_vtable = driver->vtable;
+ driver_vtable->activate( driver );
+ }
+}
+
+void driver_manager_deactivate_all( driver_manager_t *manager )
+{
+ if( manager->nof_drivers == 0 ) {
+ return;
+ }
+
+ for( int i = manager->nof_drivers - 1; i >= 0; i-- ) {
+ driver_t *driver = (driver_t *)manager->driver[i];
+ driver_vtable_t *driver_vtable = driver->vtable;
+ driver_vtable->deactivate( driver );
+ }
+}
+
+void driver_manager_deinit_all( driver_manager_t *manager )
+{
+ if( manager->nof_drivers == 0 ) {
+ return;
+ }
+
+ for( int i = manager->nof_drivers - 1; i >= 0; i-- ) {
+ driver_t *driver = (driver_t *)manager->driver[i];
+ driver_vtable_t *driver_vtable = driver->vtable;
+ driver_vtable->deinit( driver );
+ }
+}
+
+
diff --git a/src/driver.h b/src/driver.h
new file mode 100644
index 0000000..1b6b4fc
--- /dev/null
+++ b/src/driver.h
@@ -0,0 +1,29 @@
+#ifndef DRIVER_H
+#define DRIVER_H
+
+#include "interrupts.h"
+
+typedef struct {
+ void (*activate)( void *obj );
+ void (*deactivate)( void *obj );
+ void (*deinit)( void *obj );
+} driver_vtable_t;
+
+typedef struct {
+ driver_vtable_t *vtable;
+} driver_t;
+
+#define MAX_NOF_DRIVERS 256
+
+typedef struct {
+ int nof_drivers;
+ driver_t *driver[MAX_NOF_DRIVERS];
+} driver_manager_t;
+
+void driver_manager_init( driver_manager_t *manager );
+void driver_manager_add_driver( driver_manager_t *manager, driver_t *driver );
+void driver_manager_activate_all( driver_manager_t *manager );
+void driver_manager_deactivate_all( driver_manager_t *manager );
+void driver_manager_deinit( driver_manager_t *manager );
+
+#endif // DRIVER_H
diff --git a/src/kernel.c b/src/kernel.c
index 9f4fae5..c5f03e5 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -9,6 +9,7 @@
#include "string.h"
#include "stdio.h"
#include "interrupts.h"
+#include "driver.h"
#include "keyboard.h"
#include "mouse.h"
#include "pci.h"
@@ -45,38 +46,54 @@ void kernel_main( void )
puts( "Started early kernel console" );
printf( "Kernel code and data is at 0x%X, kernel stack at 0x%X\n", 0x8400, 0x90000 );
+ // exit point in case of kernel panic, do this as soon as
+ // possible, as soon we have an early console we can croak on
+ if( setjmp( panic_jmp_buf ) > 0 ) {
+ goto TERMINATE;
+ }
+
puts( "Initializing interrupts" );
interrupt_t interrupt;
interrupts_init( &interrupt );
-
- puts( "Initializing PS/2 keyboard" );
+
+ puts( "Initializing drivers" );
+ driver_manager_t driver_manager;
+ driver_manager_init( &driver_manager );
+
+ // hard-wired drivers
+
keyboard_t keyboard;
keyboard_init( &keyboard, &handle_keyboard_event, (void *)&vga );
interrupt_handler_t keyboard_interrupt_handler;
interrupt_handler_init( &keyboard_interrupt_handler, IRQ_BASE + 0x01, &interrupt, keyboard_handle_interrupt, &keyboard );
interrupts_register_interrupt_handler( keyboard_interrupt_handler );
+ driver_manager_add_driver( &driver_manager, (driver_t *)&keyboard );
- puts( "Initializing PS/2 mouse" );
mouse_t mouse;
mouse_init( &mouse, &handle_mouse_event, (void *)&vga );
interrupt_handler_t mouse_interrupt_handler;
interrupt_handler_init( &mouse_interrupt_handler, IRQ_BASE + 0x0C, &interrupt, mouse_handle_interrupt, &mouse );
interrupts_register_interrupt_handler( mouse_interrupt_handler );
+ driver_manager_add_driver( &driver_manager, (driver_t *)&mouse );
// exit point in case of kernel panic, do this as soon as
// possible
if( setjmp( panic_jmp_buf ) > 0 ) {
goto TERMINATE;
}
-
- puts( "Enabling interrupt handing now.." );
- interrupts_enable( );
+ // dynamically detected and registered drivers
puts( "Detecting devices via PCI.." );
pci_controller_t pci_controller;
pci_controller_init( &pci_controller );
pci_controller_scan( &pci_controller );
+ puts( "Activating drivers" );
+ driver_manager_activate_all( &driver_manager );
+
+ puts( "Enabling interrupt handing now.." );
+ interrupts_enable( );
+
puts( "Running.." );
// endless loop doing nothing, later we have to get events
@@ -90,11 +107,14 @@ void kernel_main( void )
}
TERMINATE:
+ puts( "Deactivating drivers" );
+ driver_manager_deactivate_all( &driver_manager );
+
puts( "Deinitializing PS/2 mouse.." );
mouse_deinit( &mouse );
- puts( "Deinitializing PS/2 keyboard.." );
- keyboard_deinit( &keyboard );
+// puts( "Deinitializing PS/2 keyboard.." );
+// keyboard_deinit( &keyboard );
puts( "Terminating" );
}
@@ -126,11 +146,11 @@ static void handle_keyboard_event( keyboard_event_t *event, void *context )
pos = 0;
puts( "" );
if( strcmp( buf, "help" ) == 0 ) {
- puts( "quit - terminate os" );
+ puts( "halt - terminate os" );
puts( "mem - show memory usage" );
puts( "driver - show status of drivers" );
puts( "proc - show process status" );
- } else if( strcmp( buf, "quit" ) == 0 ) {
+ } else if( strcmp( buf, "halt" ) == 0 ) {
terminate = true;
} else if( strcmp( buf, "mem" ) == 0 ) {
// TODO: print memory usage
diff --git a/src/keyboard.c b/src/keyboard.c
index 2b2ac71..053b721 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -64,6 +64,14 @@ static void read_ack( keyboard_t *keyboard )
}
*/
+static keyboard_vtable_t keyboard_vtable = {
+ {
+ keyboard_activate,
+ keyboard_deactivate,
+ keyboard_deinit
+ }
+};
+
void keyboard_init( keyboard_t *keyboard, keyboard_event_handler_t handler, void *context )
{
memset( keyboard, 0, sizeof( keyboard_t ) );
@@ -74,7 +82,16 @@ void keyboard_init( keyboard_t *keyboard, keyboard_event_handler_t handler, void
keyboard->shift = false;
keyboard->handler = handler;
keyboard->context = context;
-
+
+ keyboard->base.vtable = &keyboard_vtable.base;
+}
+
+void keyboard_activate( void *obj )
+{
+ puts( "Activating driver for PS/2 keyboard.." );
+
+ keyboard_t *keyboard = obj;
+
// first switch off port 1
send_command( keyboard, COMMAND_DISABLE_PORT1 );
@@ -107,11 +124,20 @@ void keyboard_init( keyboard_t *keyboard, keyboard_event_handler_t handler, void
send_command( keyboard, COMMAND_ENABLE_PORT1 );
}
-void keyboard_deinit( keyboard_t *keyboard )
+void keyboard_deactivate( void *obj )
{
+ puts( "Deactivating driver for PS/2 keyboard.." );
+
+ keyboard_t *keyboard = obj;
+
send_command( keyboard, COMMAND_DISABLE_PORT1 );
}
+void keyboard_deinit( void *obj )
+{
+ // nothing to do
+}
+
typedef enum {
KEYCODE_UNKNOWN,
KEYCODE_ASCII_CHAR
diff --git a/src/keyboard.h b/src/keyboard.h
index 167a901..6e1b6ca 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -7,6 +7,8 @@
#include "interrupts.h"
#include "port.h"
+
+#include "driver.h"
typedef enum {
KEYBOARD_EVENT_TYPE_KEY_PRESSED,
@@ -43,6 +45,7 @@ typedef struct {
typedef void (*keyboard_event_handler_t)( keyboard_event_t *event, void *context );
typedef struct {
+ driver_t base;
interrupt_t *interrupts;
port8_t command_port;
port8_t data_port;
@@ -51,8 +54,14 @@ typedef struct {
void *context;
} keyboard_t;
+typedef struct {
+ driver_vtable_t base;
+} keyboard_vtable_t;
+
void keyboard_init( keyboard_t *keyboard, keyboard_event_handler_t handler, void *context );
-void keyboard_deinit( keyboard_t *keyboard );
+void keyboard_activate( void *obj );
+void keyboard_deactivate( void *obj );
+void keyboard_deinit( void *obj );
uint32_t keyboard_handle_interrupt( interrupt_handler_t *handler, uint32_t esp );
diff --git a/src/mouse.c b/src/mouse.c
index c7708ae..ea7a3ea 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -76,6 +76,14 @@ static void set_sample_rate( mouse_t *mouse, uint8_t samples )
read_ack( mouse );
}
+static mouse_vtable_t mouse_vtable = {
+ {
+ mouse_activate,
+ mouse_deactivate,
+ mouse_deinit
+ }
+};
+
void mouse_init( mouse_t *mouse, mouse_event_handler_t handler, void *context )
{
memset( mouse, 0, sizeof( mouse_t ) );
@@ -95,6 +103,15 @@ void mouse_init( mouse_t *mouse, mouse_event_handler_t handler, void *context )
port8_init( &mouse->command_port, 0x64 );
port8_init( &mouse->data_port, 0x60 );
+ mouse->base.vtable = &mouse_vtable.base;
+}
+
+void mouse_activate( void *obj )
+{
+ puts( "Activating driver for PS/2 mouse.." );
+
+ mouse_t *mouse = obj;
+
// enable port 2
send_command( mouse, COMMAND_ENABLE_PORT2 );
@@ -129,12 +146,20 @@ void mouse_init( mouse_t *mouse, mouse_event_handler_t handler, void *context )
read_ack( mouse );
}
-void mouse_deinit( mouse_t *mouse )
+void mouse_deactivate( void *obj )
{
- // disable mouse on second port
+ puts( "Dectivating driver for PS/2 mouse.." );
+
+ mouse_t *mouse = obj;
+
send_command( mouse, COMMAND_DISABLE_PORT2 );
}
+void mouse_deinit( void *obj )
+{
+ // nothing to do
+}
+
uint32_t mouse_handle_interrupt( interrupt_handler_t *handler, uint32_t esp )
{
mouse_t *mouse = (mouse_t *)handler->driver;
diff --git a/src/mouse.h b/src/mouse.h
index 561f0c7..3217736 100644
--- a/src/mouse.h
+++ b/src/mouse.h
@@ -6,6 +6,8 @@
#include "interrupts.h"
#include "port.h"
+#include "driver.h"
+
#define MAX_NOF_MOUSE_PACKETS 5
typedef enum {
@@ -32,6 +34,7 @@ typedef struct {
typedef void (*mouse_event_handler_t)( mouse_event_t *event, void *context );
typedef struct {
+ driver_t base;
interrupt_t *interrupts;
port8_t command_port;
port8_t data_port;
@@ -47,8 +50,14 @@ typedef struct {
void *context;
} mouse_t;
+typedef struct {
+ driver_vtable_t base;
+} mouse_vtable_t;
+
void mouse_init( mouse_t *mouse, mouse_event_handler_t handler, void *context );
-void mouse_deinit( mouse_t *mouse );
+void mouse_activate( void *obj );
+void mouse_deactivate( void *obj );
+void mouse_deinit( void *obj );
uint32_t mouse_handle_interrupt( interrupt_handler_t *handler, uint32_t esp );
diff --git a/src/pci.c b/src/pci.c
index 763454f..6035323 100644
--- a/src/pci.c
+++ b/src/pci.c
@@ -66,10 +66,11 @@ void pci_controller_scan( pci_controller_t *controller )
continue;
}
- printf( "%X:%X.%d: %X:%X (class %X:%X, rev: %d)\n",
+ printf( "%X:%X.%d: %X:%X (interface: %X, class %X:%X, rev: %d)\n",
bus, device, function,
device_descriptor.vendor_id,
device_descriptor.device_id,
+ device_descriptor.interface_id,
device_descriptor.class_id,
device_descriptor.subclass_id,
device_descriptor.revision_id );
@@ -86,5 +87,12 @@ void pci_device_descriptor_init( pci_device_descriptor_t *descriptor, pci_contro
descriptor->device_id = pci_controller_read( controller, bus, device, function, 0x02 );
descriptor->class_id = pci_controller_read( controller, bus, device, function, 0x0B );
descriptor->subclass_id = pci_controller_read( controller, bus, device, function, 0x0A );
+ descriptor->interface_id = pci_controller_read( controller, bus, device, function, 0x09 );
descriptor->revision_id = pci_controller_read( controller, bus, device, function, 0x08 );
}
+
+void pci_base_address_register_init( pci_base_address_register_t *base_address_register, pci_controller_t *controller, uint16_t bus, uint16_t device, uint16_t function, uint16_t bar )
+{
+ memset( base_address_register, 0, sizeof( pci_base_address_register_t ) );
+}
+
diff --git a/src/pci.h b/src/pci.h
index 6f82f12..6f22da6 100644
--- a/src/pci.h
+++ b/src/pci.h
@@ -1,6 +1,8 @@
#ifndef PCI_H
#define PCI_H
+#include <stdbool.h>
+
#include "port.h"
typedef struct {
@@ -8,6 +10,7 @@ typedef struct {
uint16_t device_id;
uint8_t class_id;
uint8_t subclass_id;
+ uint8_t interface_id;
uint8_t revision_id;
} pci_device_descriptor_t;
@@ -16,6 +19,18 @@ typedef struct {
port32_t data_port;
} pci_controller_t;
+typedef enum {
+ BASE_ADDRESS_REGISTER_TYPE_IO,
+ BASE_ADDRESS_REGISTER_TYPE_MEMORY_MAPPED
+} pci_base_address_register_type_t;
+
+typedef struct {
+ pci_base_address_register_type_t type;
+ bool prefechable;
+ uint8_t *addr;
+ uint32_t *size;
+} pci_base_address_register_t;
+
void pci_controller_init( pci_controller_t *controller );
uint16_t pci_controller_read( pci_controller_t *controller, uint16_t bus, uint16_t device, uint16_t function, uint32_t offset );
@@ -24,4 +39,6 @@ void pci_controller_scan( pci_controller_t *controller );
void pci_device_descriptor_init( pci_device_descriptor_t *descriptor, pci_controller_t *controller, uint16_t bus, uint16_t device, uint16_t function );
+void pci_base_address_register_init( pci_base_address_register_t *base_address_register, pci_controller_t *controller, uint16_t bus, uint16_t device, uint16_t function, uint16_t bar );
+
#endif // PCI_H
diff --git a/src/stage1_functions.asm b/src/stage1_functions.asm
index ddb1c76..30b9294 100644
--- a/src/stage1_functions.asm
+++ b/src/stage1_functions.asm
@@ -2,7 +2,7 @@
; 3 * 512 for bootloader stage2 and the kernel code
; (note: the first sector gets loaded by the BIOS, so
; subtract 1 here!)
-NOF_LOAD_SECTORS equ 36
+NOF_LOAD_SECTORS equ 38
; IN bx: begin of memory area to dump
; IN ax: number of words to dump