Code: Select all
//PCI support, yes!
#include <arch/i686/pci.h>
#include <arch/i686/io.h>
#include <stdint.h>
#include <stdio.h>
//pci_read_confspc_word(): Returns 16-bit value from PCI Configuration Space of specified device at specified offset.
uint16_t pci_read_confspc_word(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset)
{
uint32_t addr;
uint32_t bus32 = bus;
uint32_t slot32 = slot;
uint32_t func32 = function;
addr = (uint32_t)((bus32 << 16) | (slot32 << 11) |
(func32 << 8) | (offset & 0xfc) | ((uint32_t)0x80000000)); //yes, this line is copied from osdev
outl(PCI_ADDRESS_PORT, addr);
return (uint16_t)((inl(PCI_DATA_PORT) >> ((offset & 2) * 8)) & 0xffff); //this too... I'm too lazy to write them
}
static struct {
uint8_t dev_class, dev_subclass; //added dev_ to prevent errors in C++
const char *name;
} pci_device_type_strings[] = {
{0x00, 0x00, "Unknown device"},
{0x00, 0x01, "VGA-compatible Device"},
{0x01, 0x00, "SCSI Bus Controller"},
{0x01, 0x01, "IDE Controller"},
{0x01, 0x02, "Floppy Disk Controller"},
{0x01, 0x03, "IPI Bus Controller"},
{0x01, 0x04, "RAID Controller"},
{0x01, 0x05, "ATA Controller"},
{0x01, 0x06, "SATA Controller"},
{0x01, 0x07, "Serial Attached SCSI Controller"},
{0x01, 0x80, "Other Mass Storage Controller"},
{0x02, 0x00, "Ethernet Controller"},
{0x02, 0x01, "Token Ring Controller"},
{0x02, 0x02, "FDDI Controller"},
{0x02, 0x03, "ATM Controller"},
{0x02, 0x04, "ISDN Controller"},
{0x02, 0x05, "WorldFip Controller"},
{0x02, 0x06, "PICMG 2.14 Multi Computing"},
{0x02, 0x80, "Other Network Controller"},
{0x03, 0x00, "VGA-compatible Controller"},
{0x03, 0x01, "XGA Controller"},
{0x03, 0x02, "3D Controller"},
{0x03, 0x80, "Other Display Controller"},
{0x04, 0x00, "Video Device"},
{0x04, 0x01, "Audio Device"},
{0x04, 0x02, "Computer Telephony Device"},
{0x04, 0x80, "Other Multimedia Device"},
{0x05, 0x00, "RAM Controller"},
{0x05, 0x01, "Flash Controller"},
{0x05, 0x80, "Other Memory Controller"},
{0x06, 0x00, "Host Bridge"},
{0x06, 0x01, "ISA Bridge"},
{0x06, 0x02, "EISA Bridge"},
{0x06, 0x03, "MCA Bridge"},
{0x06, 0x04, "PCI-to-PCI Bridge"},
{0x06, 0x05, "PCMCIA Bridge"},
{0x06, 0x06, "NuBus Bridge"},
{0x06, 0x07, "CardBus Bridge"},
{0x06, 0x08, "RACEWay Bridge"},
{0x06, 0x09, "PCI-to-PCI Bridge (Semi-Transparent)"},
{0x06, 0x0A, "InfiniBand-to-PCI Host Bridge"},
{0x06, 0x80, "Other Bridge Device"},
{0x07, 0x00, "Serial Controller"},
{0x07, 0x01, "Parallel Port"},
{0x07, 0x02, "Multiport Serial Controller"},
{0x07, 0x03, "Generic Modem"},
{0x07, 0x04, "IEEE 488.1/2 (GPIB) Controller"},
{0x07, 0x05, "Smart Card"},
{0x07, 0x80, "Other Communication Device"},
{0x08, 0x00, "Programmable Interrupt Controller"},
{0x08, 0x01, "DMA Controller"},
{0x08, 0x02, "System Timer"},
{0x08, 0x03, "Real-Time Clock"},
{0x08, 0x04, "Generic PCI Hot-Plug Controller"},
{0x08, 0x80, "Other System Peripheral"},
{0x09, 0x00, "Keyboard Controller"},
{0x09, 0x01, "Digitizer"},
{0x09, 0x02, "Mouse Controller"},
{0x09, 0x03, "Scanner Controller"},
{0x09, 0x04, "Gameport Controller"},
{0x09, 0x80, "Other Input Controller"},
{0x0A, 0x00, "Generic Docking Station"},
{0x0A, 0x80, "Other Docking Station"},
{0x0B, 0x00, "i386 CPU"},
{0x0B, 0x01, "i486 CPU"},
{0x0B, 0x02, "Pentium CPU"},
{0x0B, 0x10, "Alpha CPU"},
{0x0B, 0x20, "PowerPC CPU"},
{0x0B, 0x30, "MIPS CPU"},
{0x0B, 0x40, "Co-processor"},
{0x0C, 0x00, "FireWire Controller"},
{0x0C, 0x01, "ACCESS.bus Controller"},
{0x0C, 0x02, "SSA Controller"},
{0x0C, 0x03, "USB Controller"},
{0x0C, 0x04, "Fibre Channel"},
{0x0C, 0x05, "SMBus"},
{0x0C, 0x06, "InfiniBand"},
{0x0C, 0x07, "IPMI SMIC Interface"},
{0x0C, 0x08, "SERCOS Interface"},
{0x0C, 0x09, "CANbus Interface"},
{0x0D, 0x00, "iRDA Compatible Controller"},
{0x0D, 0x01, "Consumer IR Controller"},
{0x0D, 0x10, "RF Controller"},
{0x0D, 0x11, "Bluetooth Controller"},
{0x0D, 0x12, "Broadband Controller"},
{0x0D, 0x20, "802.11a (Wi-Fi) Ethernet Controller"},
{0x0D, 0x21, "802.11b (Wi-Fi) Ethernet Controller"},
{0x0D, 0x80, "Other Wireless Controller"},
{0x00, 0x00, NULL} //here array ends
};
uint8_t pci_get_class(uint8_t bus, uint8_t slot, uint8_t function)
{
return (uint8_t) (pci_read_confspc_word(bus, slot, function, 5) >> 8) /* shifting to leave only class id in the variable. */;
}
uint8_t pci_get_subclass(uint8_t bus, uint8_t slot, uint8_t function)
{
return (uint8_t) pci_read_confspc_word(bus, slot, function, 5);
}
uint8_t pci_get_hdr_type(uint8_t bus, uint8_t slot, uint8_t function)
{
return (uint8_t) pci_read_confspc_word(bus, slot, function, 7);
}
uint16_t pci_get_vendor(uint8_t bus, uint8_t slot, uint8_t function)
{
return pci_read_confspc_word(bus, slot, function, 0);
}
const char *pci_get_device_type(uint8_t dev_class, uint8_t dev_subclass)
{
for(int i=0; pci_device_type_strings[i].name != NULL; i++)
if(pci_device_type_strings[i].dev_class == dev_class && pci_device_type_strings[i].dev_subclass == dev_subclass)
return pci_device_type_strings[i].name;
return NULL;
}
void list_pci()
{
uint8_t clid;
uint8_t sclid;
uint16_t vendor;
for(unsigned bus = 0; bus < 256; bus++)
{
for(unsigned slot = 0; slot < 32; slot++)
{
unsigned func = 0;
clid = pci_get_class(bus, slot, func);
sclid = pci_get_subclass(bus, slot, func);
vendor = pci_get_vendor(bus, slot, func);
if(clid != 0xFF && vendor != 0xFFFF)
printf("Vendor: 0x%x, device: %s %d %d\n", vendor, pci_get_device_type(clid, sclid), sclid, clid);
if((pci_get_hdr_type(bus, slot, func) & 0x80) == 0)
for(func = 1; func < 8; func++)
{
clid = pci_get_class(bus, slot, func);
sclid = pci_get_subclass(bus, slot, func);
vendor = pci_get_vendor(bus, slot, func);
if(clid != 0xFF && vendor != 0xFFFF)
printf("Vendor: 0x%x, device: %s %d %d\n", vendor, pci_get_device_type(clid, sclid), sclid, clid);
}
}
}
}