#include "pci.h" #include "string.h" #include "stdio.h" #define NOF_BUSES 8 #define NOF_DEVICES_PER_BUS 32 #define NOF_FUNCTIONS_PER_DEVICE 8 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 ); } void pci_controller_scan_and_register( pci_controller_t *controller, driver_manager_t *driver_manager, interrupt_t *interrupt ) { for( int bus = 0; bus < NOF_BUSES; bus++ ) { for( int device = 0; device < NOF_DEVICES_PER_BUS; device++ ) { // TODO: detect single/multi function device from header for( int function = 0; function < NOF_FUNCTIONS_PER_DEVICE; function++ ) { pci_device_descriptor_t device_descriptor; pci_device_descriptor_init( &device_descriptor, controller, bus, device, function ); // no device if( device_descriptor.device_id == 0x0 || device_descriptor.device_id == 0xFFFF ) { continue; } 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 ); } } } } void pci_device_descriptor_init( pci_device_descriptor_t *descriptor, pci_controller_t *controller, uint16_t bus, uint16_t device, uint16_t function ) { 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 ); } 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 ) ); }