From 03b54c5ab504e8a9abafaf60c7b4fed4f8629ea6 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Wed, 7 Jun 2017 11:57:16 +0200 Subject: added 32-bit port functions started to add PCI functions (for now read/write only) added help menu in boot kernel input mode --- doc/LINKS.TODO | 9 +++++++++ src/Makefile | 7 +++++-- src/kernel.c | 18 ++++++++++++++++-- src/pci.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/pci.h | 16 ++++++++++++++++ src/port.asm | 24 ++++++++++++++++++++++++ src/port.c | 7 +++++++ src/port.h | 11 ++++++++++- 8 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 src/pci.c create mode 100644 src/pci.h diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO index b61fd98..66aa777 100644 --- a/doc/LINKS.TODO +++ b/doc/LINKS.TODO @@ -50,3 +50,12 @@ https://www.lowlevel.eu/wiki/Keyboard_Controller PIT: http://wiki.osdev.org/Programmable_Interval_Timer + +PCI: +http://wiki.osdev.org/PCI +https://www.lowlevel.eu/wiki/Peripheral_Component_Interconnect +http://www.ics.uci.edu/~harris/ics216/pci/PCI_22.pdf + +assembly: +NASM +FASM diff --git a/src/Makefile b/src/Makefile index 6e52754..9c793df 100644 --- a/src/Makefile +++ b/src/Makefile @@ -28,10 +28,10 @@ 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 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 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 \ + port.o port_asm.o interrupts.o interrupts_asm.o pci.o \ keyboard.o mouse.o \ string.o stdlib.o stdio.o setjmp.o @@ -65,6 +65,9 @@ interrupts.o: interrupts.c interrupts.h interrupts_asm.o: interrupts.asm $(NASM) interrupts.asm $(NASMFLAGS) -o interrupts_asm.o +pci.o: pci.c pci.h + $(CC) $(CFLAGS) -c -o pci.o pci.c + keyboard.o: keyboard.c keyboard.h $(CC) $(CFLAGS) -c -o keyboard.o keyboard.c diff --git a/src/kernel.c b/src/kernel.c index e8cfc88..c84d28c 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -11,6 +11,7 @@ #include "interrupts.h" #include "keyboard.h" #include "mouse.h" +#include "pci.h" #include "setjmp.h" #include "kernel.h" @@ -72,7 +73,11 @@ void entry( void ) puts( "Enabling interrupt handing now.." ); interrupts_enable( ); - + + puts( "Detecting devices via PCI.." ); + pci_controller_t pci_controller; + pci_controller_init( &pci_controller ); + puts( "Running.." ); // endless loop doing nothing, later we have to get events @@ -118,12 +123,21 @@ static void handle_keyboard_event( keyboard_event_t *event, void *context ) buf[pos] = '\0'; pos = 0; puts( "" ); - if( strcmp( buf, "quit" ) == 0 ) { + if( strcmp( buf, "help" ) == 0 ) { + puts( "quit - terminate os" ); + puts( "mem - show memory usage" ); + puts( "driver - show status of drivers" ); + puts( "proc - show process status" ); + } else if( strcmp( buf, "quit" ) == 0 ) { terminate = true; } else if( strcmp( buf, "mem" ) == 0 ) { // TODO: print memory usage } else if( strcmp( buf, "proc" ) == 0 ) { // TODO: print scheduler status + } else if( strcmp( buf, "driver" ) == 0 ) { + // TODO: print driver information + } else { + printf( "ERR: Unknown pre-boot command '%s'\n", buf ); } } else { printf( "%c", event->ascii_key ); diff --git a/src/pci.c b/src/pci.c new file mode 100644 index 0000000..fce20df --- /dev/null +++ b/src/pci.c @@ -0,0 +1,48 @@ +#include "pci.h" + +#include "string.h" + +void pci_controller_init( pci_controller_t *controller ) +{ + memset( controller, 0, sizeof( pci_controller_t ) ); + + port32_init( &controller->command_port, 0xCF8 ); + port32_init( &controller->data_port, 0xCFC ); +} + +static uint32_t compute_id( uint16_t bus, uint16_t device, uint16_t function, uint32_t offset ) +{ + uint32_t id; + + id = ( 0x01 << 31 ) + | ( ( bus & 0xFF ) << 16 ) + | ( ( device & 0x1F ) << 11 ) + | ( ( function & 0x07 ) << 8 ) + | ( offset & 0xFC ); + + return id; +} + +uint16_t pci_controller_read( pci_controller_t *controller, uint16_t bus, uint16_t device, uint16_t function, uint32_t offset ) +{ + uint32_t id = compute_id( bus, device, function, offset ); + + port32_write( &controller->command_port, id ); + + uint32_t data = port32_read( &controller->data_port ); + + // we get 256 byte data blocks aligned to 32-bit addresses + // for each offset + data = data >> ( ( 8 * ( offset % 4 ) ) & 0xFFFF ); + + return data; +} + +void pci_controller_write( pci_controller_t *controller, uint16_t bus, uint16_t device, uint16_t function, uint32_t offset, uint32_t data ) +{ + uint32_t id = compute_id( bus, device, function, offset ); + + port32_write( &controller->command_port, id ); + port32_write( &controller->data_port, data ); +} + diff --git a/src/pci.h b/src/pci.h new file mode 100644 index 0000000..2381fc3 --- /dev/null +++ b/src/pci.h @@ -0,0 +1,16 @@ +#ifndef PCI_H +#define PCI_H + +#include "port.h" + +typedef struct { + port32_t command_port; + port32_t data_port; +} pci_controller_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 ); +void pci_controller_write( pci_controller_t *controller, uint16_t bus, uint16_t device, uint16_t function, uint32_t offset, uint32_t data ); + +#endif // PCI_H diff --git a/src/port.asm b/src/port.asm index 4f2b646..555a4e8 100644 --- a/src/port.asm +++ b/src/port.asm @@ -23,3 +23,27 @@ port8_read: in al, dx leave ret + +global port32_write +global port32_read + +; void port32_write( port32_t *port, uint32_t data ); +port32_write: + push ebp + mov ebp, esp + mov ecx, [ebp+8] + mov edx, DWORD [ecx] + mov eax, DWORD [ebp+12] + out dx, eax + leave + ret + +; uint32_t port32_read( port32_t *port ) +port32_read: + push ebp + mov ebp, esp + mov ecx, DWORD [ebp+8] + mov edx, [ecx] + in eax, dx + leave + ret diff --git a/src/port.c b/src/port.c index 3eae387..46e7f37 100644 --- a/src/port.c +++ b/src/port.c @@ -8,3 +8,10 @@ void port8_init( port8_t *port, uint16_t number ) port->number = number; } + +void port32_init( port32_t *port, uint16_t number ) +{ + memset( port, 0, sizeof( port32_t ) ); + + port->number = number; +} diff --git a/src/port.h b/src/port.h index 32679ee..ec96d09 100644 --- a/src/port.h +++ b/src/port.h @@ -11,4 +11,13 @@ void port8_init( port8_t *port, uint16_t number ); void port8_write( port8_t *port, uint8_t data ); uint8_t port8_read( port8_t *port ); -#endif // +typedef struct { + uint16_t number; // port number, e.g. 0x3d4 VGA index register +} port32_t; + +void port32_init( port32_t *port, uint16_t number ); +void port32_write( port32_t *port, uint32_t data ); +uint32_t port32_read( port32_t *port ); + +#endif // PORT_H + -- cgit v1.2.3-54-g00ecf