From daa69726b2f3c9d4256a8a3591364419039f772e Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 10 Jun 2017 18:25:07 +0200 Subject: preparations for driver loading with PCI (BARs for I/O) --- src/Makefile | 4 +- src/pci.c | 101 +++++++++++++++++++++++++++++++++++++++--- src/pci.h | 5 ++- src/stage2_real_functions.asm | 2 +- 4 files changed, 102 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 1609299..c7925bf 100644 --- a/src/Makefile +++ b/src/Makefile @@ -14,13 +14,13 @@ all: image.bin kernel.sym # + 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, and stage 1 loads 3 sectors of stage 2, -# adapt NOF_LOAD_SECTORS to 36) +# adapt NOF_LOAD_SECTORS to 37) # then we make sure the image has the size of a 1.44 MB floppy # (emulators like qemu do some guess work for CHS resolution based # on the size of the image) image.bin: boot.bin kernel.bin magic.bin cat boot.bin kernel.bin > image.tmp - truncate -s 19968 image.tmp + truncate -s 20480 image.tmp cat image.tmp magic.bin > image.bin truncate -s 1474560 image.bin diff --git a/src/pci.c b/src/pci.c index 58d651a..6b124b2 100644 --- a/src/pci.c +++ b/src/pci.c @@ -6,6 +6,16 @@ #define NOF_BUSES 8 #define NOF_DEVICES_PER_BUS 32 #define NOF_FUNCTIONS_PER_DEVICE 8 +#define NOF_BARS 6 + +#define PCI_VENDOR_ID 0x00 +#define PCI_DEVICE_ID 0x02 +#define PCI_REVISION 0x08 +#define PCI_INTERFACE 0x09 +#define PCI_SUBCLASS 0x0A +#define PCI_CLASS 0x0B +#define PCI_HEADER_TYPE 0x0E +#define PCI_BAR_BASE 0x10 void pci_controller_init( pci_controller_t *controller ) { @@ -74,6 +84,25 @@ void pci_controller_scan_and_register( pci_controller_t *controller, driver_mana device_descriptor.class_id, device_descriptor.subclass_id, device_descriptor.revision_id ); + + uint8_t header_type = pci_controller_read( controller, bus, device, function, PCI_HEADER_TYPE ) & 0x7F; + int max_nof_bars = NOF_BARS; + if( header_type & 0x01 ) { + max_nof_bars = 2; + } + + for( int bar_number = 0; bar_number < max_nof_bars; bar_number++ ) { + pci_base_address_register_t bar; + pci_base_address_register_init( &bar, controller, bus, device, function, bar_number ); + if( bar.type == BASE_ADDRESS_REGISTER_TYPE_IO && bar.addr ) { + device_descriptor.port_base = (uint32_t)bar.addr; + } + + driver_t *driver = pci_device_get_driver( &device_descriptor, interrupt ); + if( driver ) { + driver_manager_add_driver( driver_manager, driver ); + } + } } } } @@ -83,16 +112,76 @@ void pci_device_descriptor_init( pci_device_descriptor_t *descriptor, pci_contro { memset( descriptor, 0, sizeof( pci_device_descriptor_t ) ); - descriptor->vendor_id = pci_controller_read( controller, bus, device, function, 0x00 ); - 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 ); + descriptor->vendor_id = pci_controller_read( controller, bus, device, function, PCI_VENDOR_ID ); + descriptor->device_id = pci_controller_read( controller, bus, device, function, PCI_DEVICE_ID ); + descriptor->class_id = pci_controller_read( controller, bus, device, function, PCI_CLASS ); + descriptor->subclass_id = pci_controller_read( controller, bus, device, function, PCI_SUBCLASS ); + descriptor->interface_id = pci_controller_read( controller, bus, device, function, PCI_INTERFACE ); + descriptor->revision_id = pci_controller_read( controller, bus, device, function, PCI_REVISION ); } 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 ) ); + + uint32_t val = pci_controller_read( controller, bus, device, function, PCI_BAR_BASE + sizeof( uint32_t ) * bar ); + + // bit 0 indicates whether we are I/O or memory mapped + base_address_register->type = ( val & 0x01 ) ? BASE_ADDRESS_REGISTER_TYPE_IO : BASE_ADDRESS_REGISTER_TYPE_MEMORY_MAPPED; + + switch( base_address_register->type ) { + case BASE_ADDRESS_REGISTER_TYPE_IO: + base_address_register->addr = (uint8_t *)( val & 0xFFFC ); + base_address_register->prefetchable = false; + break; + + case BASE_ADDRESS_REGISTER_TYPE_MEMORY_MAPPED: + switch( val << 1 & 0x03 ) { + case 0x00: + // 32-bit mode + break; + + case 0x01: + // 20-bit mode + break; + + case 0x02: + // 64-bit mode + break; + } + break; + } } +driver_t *pci_device_get_driver( pci_device_descriptor_t *descriptor, interrupt_t *interrupt ) +{ + // find a specific device + switch( descriptor->vendor_id ) { + case 0x10ec: // Realtek Semiconductor + switch( descriptor->device_id ) { + case 0x8029: // RTL-8029 + break; + } + break; + + case 0x8086: // Intel + break; + + default: + break; + } + + // find a generic driver + switch( descriptor->class_id ) { + case 0x03: // graphics + switch( descriptor->subclass_id ) { + case 0x00: // VGA + break; + } + break; + + default: // no driver found + break; + } + return NULL; +} diff --git a/src/pci.h b/src/pci.h index 9d4fc67..ddbc990 100644 --- a/src/pci.h +++ b/src/pci.h @@ -14,6 +14,7 @@ typedef struct { uint8_t subclass_id; uint8_t interface_id; uint8_t revision_id; + uint32_t port_base; } pci_device_descriptor_t; typedef struct { @@ -28,7 +29,7 @@ typedef enum { typedef struct { pci_base_address_register_type_t type; - bool prefechable; + bool prefetchable; uint8_t *addr; uint32_t *size; } pci_base_address_register_t; @@ -43,4 +44,6 @@ void pci_device_descriptor_init( pci_device_descriptor_t *descriptor, pci_contro 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 ); +driver_t *pci_device_get_driver( pci_device_descriptor_t *descriptor, interrupt_t *interrupt ); + #endif // PCI_H diff --git a/src/stage2_real_functions.asm b/src/stage2_real_functions.asm index 1728b1a..d49bfce 100644 --- a/src/stage2_real_functions.asm +++ b/src/stage2_real_functions.asm @@ -2,7 +2,7 @@ ; (note: the first sector gets loaded by the BIOS, the ; next 3 sectors are read by the simple stage 1 loader, ; so subtract 3 here!) -NOF_LOAD_SECTORS equ 36 +NOF_LOAD_SECTORS equ 37 ; data sections used for reading the kernel from disk SECTORS_PER_CYLINDER: -- cgit v1.2.3-54-g00ecf