diff options
Diffstat (limited to 'src/pci.c')
-rw-r--r-- | src/pci.c | 101 |
1 files changed, 95 insertions, 6 deletions
@@ -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; +} |