summaryrefslogtreecommitdiff
path: root/src/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pci.c')
-rw-r--r--src/pci.c101
1 files changed, 95 insertions, 6 deletions
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;
+}