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