Nucleus
Barry System headers (remove libc dependency) 18495cf (3 years, 2 months ago)
/*
* This file controls the PCI interface. It contains utility functions for
* accessing PCI configuration space. It scans all devices connected to the
* system and tries to initialise them.
*/
#include <stdint.h>
#include <nucleus/io.h>
#include <nucleus/pci.h>
/* PCI Configuration Ports */
enum PCIConfigPort {
CONFIG_ADDRESS = 0xCF8,
CONFIG_DATA = 0xCFC,
};
/* Make a PCI Address */
static inline uint32_t
make_pci_address(int bus, int dev, int func, int off)
{
return (1 << 31) | (bus << 16) | (dev << 11) | (func << 8) |
(off & 0xFC);
}
/* Read PCI config byte */
uint8_t
pci_read_byte(int bus, int dev, int func, int off)
{
outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
return inb(CONFIG_DATA + (off & 3));
}
/* Read PCI config word */
uint16_t
pci_read_word(int bus, int dev, int func, int off)
{
outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
return inw(CONFIG_DATA + (off & 2));
}
/* Read PCI config dword */
uint32_t
pci_read_dword(int bus, int dev, int func, int off)
{
outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
return inl(CONFIG_DATA);
}
/* Write PCI config byte */
void
pci_write_byte(int bus, int dev, int func, int off, uint8_t value)
{
outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
outb(CONFIG_DATA + (off & 3), value);
}
/* Write PCI config word */
void
pci_write_word(int bus, int dev, int func, int off, uint16_t value)
{
outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
outw(CONFIG_DATA + (off & 2), value);
}
/* Write PCI config dword */
void
pci_write_dword(int bus, int dev, int func, int off, uint32_t value)
{
outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
outl(CONFIG_DATA, value);
}
/* Scan for PCI devices */
void
init_pci(void)
{
uint16_t bus, dev, func;
/* This is one massive iteration */
for (bus = 0; bus < 256; bus++)
for (dev = 0; dev < 32; dev++)
for (func = 0; func < 8; func++)
if (pci_read_word(bus, dev, func, 0) != 0xFFFF)
init_pci_device(bus, dev, func);
}