From 00bea0a48f5e8c59260470bdc004734a87034d42 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 8 Jun 2017 16:06:30 +0200 Subject: added driver manager keyboard and mouse are now "derived" from driver_t reading and printing more PCI members --- doc/LINKS.TODO | 3 +++ src/.gdbinit | 2 +- src/Makefile | 12 ++++++---- src/README | 7 +++--- src/driver.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ src/driver.h | 29 ++++++++++++++++++++++++ src/kernel.c | 40 ++++++++++++++++++++++++--------- src/keyboard.c | 30 +++++++++++++++++++++++-- src/keyboard.h | 11 ++++++++- src/mouse.c | 29 ++++++++++++++++++++++-- src/mouse.h | 11 ++++++++- src/pci.c | 10 ++++++++- src/pci.h | 17 ++++++++++++++ src/stage1_functions.asm | 2 +- 14 files changed, 235 insertions(+), 26 deletions(-) create mode 100644 src/driver.c create mode 100644 src/driver.h 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 + #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 -- cgit v1.2.3-54-g00ecf