2020-08-23 01:32:47 +00:00
# include <kernel/chroma.h>
2020-08-22 23:50:10 +00:00
/************************
* * * Team Kitty , 2020 * * *
* * * Chroma * * *
* * * * * * * * * * * * * * * * * * * * * * */
/* This file contains functions for accessing the PCI bus,
* and devices contained wherein .
*
* It allows you to query the bus , as well as communicate with individual devices .
*
*/
2021-03-19 02:18:39 +00:00
pci_device_t * * pci_root_devices = NULL ;
2020-08-22 23:50:10 +00:00
pci_entry_t * pci_map = NULL ;
2020-08-23 01:32:47 +00:00
//static uint32_t PCIReadConfig(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset);
2021-03-19 02:18:39 +00:00
//static const char* PCIGetDeviceName_Subclass(uint8_t DeviceClass, uint8_t Subclass, uint8_t ProgrammableInterface);
2020-08-23 01:32:47 +00:00
2021-03-19 02:18:39 +00:00
//static const char* PCIGetClassName(uint8_t DeviceClass);
2020-08-22 23:50:10 +00:00
void PCIEnumerate ( ) {
uint8_t bus = 0 , device = 0 , function = 0 ;
2020-08-23 01:32:47 +00:00
uint32_t registerData ;
2020-08-22 23:50:10 +00:00
2021-03-19 02:18:39 +00:00
uint16_t DeviceID , VendorID ;
2020-08-22 23:50:10 +00:00
2021-03-19 02:18:39 +00:00
uint8_t ClassCode , subclass_code ;
2020-08-22 23:50:10 +00:00
2020-11-09 18:41:34 +00:00
SerialPrintf ( " [ PCI] Started PCI Enumeration. " ) ;
SerialPrintf ( " \n [ PCI] PCI Scan result: \n [ PCI] " ) ;
2020-08-23 01:32:47 +00:00
do {
2020-08-22 23:50:10 +00:00
for ( device = 0 ; device < = 31 ; device + + ) {
for ( function = 0 ; function < = 7 ; function + + ) {
2020-08-23 01:32:47 +00:00
registerData = PCIReadConfig ( bus , device , 0 , 0xC ) ; // Read BIST/Header/Latency/Cache Line register
uint8_t header = ( uint8_t ) ( ( registerData & 0x00FF0000 ) > > 24 ) ; // Header is lower byte of upper word, so mask it off and shift it down
uint8_t multifunction_bit = header & 0x80 ; // The multifunction bit is the highest bit of the header
2020-08-22 23:50:10 +00:00
2020-08-23 01:32:47 +00:00
registerData = PCIReadConfig ( bus , device , function , 0 ) ; // Read the Vendor/Device ID register
2021-03-19 02:18:39 +00:00
VendorID = ( uint16_t ) ( registerData & 0x0000FFFF ) ; // Vendor ID is bottom word
DeviceID = ( uint16_t ) ( registerData > > 16 ) ; // Device ID is top word
2020-08-22 23:50:10 +00:00
2020-08-23 01:32:47 +00:00
registerData = PCIReadConfig ( bus , device , function , 8 ) ; // Read the Device Info register
2021-03-19 02:18:39 +00:00
ClassCode = ( uint16_t ) ( registerData > > 24 ) ; // Device class is top byte, so shift them down
2020-08-31 20:51:41 +00:00
subclass_code = ( uint16_t ) ( ( registerData > > 16 ) & 0x00FF ) ; // Device subclass is same as header - lower byte of higher word. Shift down and mask just like before.
uint8_t device_progif = ( uint16_t ) ( ( registerData & 0x0000FF00 ) > > 8 ) ; // Device Programming Interface is higher byte of lower word, so mask and shift
uint8_t device_revision = ( uint16_t ) ( registerData & 0x000000FF ) ; // Device revision is lower byte of whole double word. Just mask it.
2020-08-22 23:50:10 +00:00
/* 0xFFFF is not a valid Vendor ID. This serves as a sanity check.
* If this check is true , then nothing is logged and we continue for the next loop .
*/
2021-03-19 02:18:39 +00:00
if ( VendorID ! = 0xFFFF ) {
SerialPrintf ( " [ PCI] \n [ PCI] \t %x:%x: \n [ PCI] \t \t Vendor: %x \n [ PCI] \t \t Device: %x " , bus , device , VendorID , DeviceID ) ;
SerialPrintf ( " \n [ PCI] \t \t Class: %s \n [ PCI] \t \t Device Type: %s \n [ PCI] \t \t Revision: %d \n " , PCIGetClassName ( ClassCode ) , PCIGetDeviceName_Subclass ( ClassCode , subclass_code , device_progif ) , device_revision ) ;
2020-08-22 23:50:10 +00:00
}
/* If the PCI Device header tells us that this is not a multifunction device,
* and we ' ve already scanned function 0 , then there is nothing else to see .
* Therefore , stop this loop and move onto device + +
*/
if ( multifunction_bit = = 0 )
break ;
}
}
2020-08-23 01:32:47 +00:00
} while ( + + bus ) ;
2020-08-22 23:50:10 +00:00
}
uint32_t PCIReadConfig ( uint8_t bus , uint8_t slot , uint8_t function , uint8_t offset ) {
uint32_t address ;
uint32_t busLong = ( uint32_t ) bus ;
uint32_t slotLong = ( uint32_t ) slot ;
uint32_t functionLong = ( uint32_t ) function ;
/* ---------------------------------------------------------------
* | 31 | 30 . . . 24 | 23 . . . 16 | 15 . . . 11 | 10 . . . 8 | 7 . . . 0 |
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* | EN | RESERVED | BUS NUM | DEVICE NO | FUNC NO | REG OFF |
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* NOTE : REG OFF * must * have 0 last two bits ( ie . & 0xFC )
*/
address = ( uint32_t ) ( ( busLong < < 16 ) | ( slotLong < < 11 ) |
( functionLong < < 8 ) | ( offset & 0xFC ) | ( ( uint32_t ) 0x80000000 ) ) ;
WritePort ( 0xCF8 , address , 4 ) ;
return ReadPort ( 0xCFC , 4 ) ;
}
2021-03-19 02:18:39 +00:00
const char * PCIGetDeviceName_Subclass ( uint8_t DeviceClass , uint8_t Subclass , uint8_t ProgrammableInterface ) {
switch ( DeviceClass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Non-VGA-Compatible device " ;
case 0x01 : return " VGA-Compatible device " ;
default : return " Unknown Unclassified " ;
}
}
case 0x01 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " SCSI Bus Controller " ;
case 0x01 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " ISA Compatibility Mode-only IDE Controller " ;
case 0x05 : return " PCI Native Mode-only IDE Controller " ;
case 0x0A : return " ISA Compatibility Mode IDE Controller (supports PCI Native Mode) " ;
case 0x0F : return " PCI Native Mode IDE Controller (supports ISA Compatibility Mode) " ;
case 0x80 : return " ISA Compatibilty Mode-only IDE Controller (supports Bus Mastering) " ;
case 0x85 : return " PCI Native Mode-only IDE Controller (supports Bus Mastering) " ;
case 0x8A : return " ISA Compatibility Mode IDE Controller (supports PCI Native Mode & Bus Mastering) " ;
case 0x8F : return " PCI Native Mode IDE Controller (supports ISA Compatibiliy Mode & Bus Mastering) " ;
default : return " IDE Controller " ;
}
}
case 0x02 : return " Floppy Disk Controller " ;
case 0x03 : return " IPI Bus Controller " ;
case 0x04 : return " RAID Controller " ;
case 0x05 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x20 : return " Single-DMA ATA Controller " ;
case 0x30 : return " Chained-DMA ATA Controller " ;
default : return " ATA Controller " ;
}
}
case 0x06 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Vendor-Specific Interface SATA Controller " ;
case 0x01 : return " AHCI 1.0 SATA Controller " ;
case 0x02 : return " Serial Storage Bus SATA Controller " ;
default : return " Serial ATA Controller " ;
}
}
case 0x07 : return " Serial Attached SCSI (SAS) " ;
case 0x08 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x01 : return " NVMHCI Memory Controller " ;
case 0x02 : return " NVMe Memory Controller " ;
default : return " Non-Volatile Memory Controller " ;
}
}
case 0x80 : return " Other " ;
2020-08-23 01:32:47 +00:00
default : return " Unknown Mass Storage Controller " ;
2020-08-22 23:50:10 +00:00
}
}
case 0x02 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Ethernet Controller " ;
case 0x01 : return " Token Ring Controller " ;
case 0x02 : return " FDDI Controller " ;
case 0x03 : return " ATM Controller " ;
case 0x04 : return " ISDN Controller " ;
case 0x05 : return " WorldFip Controller " ;
case 0x06 : return " PICMG 2.14 Multi Computing " ;
case 0x07 : return " Infiniband Controller " ;
case 0x08 : return " Fabric Controller " ;
case 0x80 : return " Other " ;
2020-08-23 01:32:47 +00:00
default : return " Unknown Network Controller " ;
2020-08-22 23:50:10 +00:00
}
}
case 0x03 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " VGA Controller " ;
case 0x01 : return " 8514 VGA Controller " ;
default : return " VGA Compatible Controller " ;
}
}
case 0x01 : return " XGA Controller " ;
case 0x02 : return " 3D Controller (Not VGA-Compatible) " ;
case 0x80 : return " Other " ;
2020-08-23 01:32:47 +00:00
default : return " Unknown Display Controller " ;
2020-08-22 23:50:10 +00:00
}
}
case 0x04 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Multimedia Video Controller " ;
case 0x01 : return " Multimedia Audio Controller " ;
case 0x02 : return " Computer Telephony Device " ;
case 0x03 : return " Audio Device " ;
case 0x80 : return " Other " ;
default : return " Unknown Multimedia Controller " ;
}
}
case 0x05 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " RAM Controller " ;
case 0x01 : return " Flash Controller " ;
case 0x80 : return " Other " ;
default : return " Unknown Memory Controller " ;
}
}
case 0x06 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Host Bridge " ;
case 0x01 : return " ISA Bridge " ;
case 0x02 : return " EISA Bridge " ;
case 0x03 : return " MCA Bridge " ;
case 0x04 :
case 0x09 :
return " PCI-to-PCI Bridge " ;
case 0x05 : return " PCMCIA Bridge " ;
case 0x06 : return " NuBus Bridge " ;
case 0x07 : return " CardBus Bridge " ;
case 0x08 : return " RACEway Bridge " ;
case 0x0A : return " InfiniBand-to-PCI Host Bridge " ;
case 0x80 : return " Other " ;
default : return " Unknown Bridge Device " ;
}
}
case 0x07 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Serial Controller <8250> " ;
case 0x01 : return " Serial controller <16450> " ;
case 0x02 : return " Serial controller <16550> " ;
case 0x03 : return " Serial controller <16650> " ;
case 0x04 : return " Serial controller <16750> " ;
case 0x05 : return " Serial controller <16850> " ;
case 0x06 : return " Serial controller <16950> " ;
default : return " Serial Controller " ;
}
}
case 0x01 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Standard Parallel Port " ;
case 0x01 : return " Bi-Directional Parallel Port " ;
case 0x02 : return " ECP 1.X Compliant Parallel Port " ;
case 0x03 : return " IEEE 1284 Parallel Controller " ;
case 0x04 : return " IEE 1284 Parallel Target " ;
default : return " Parallel Controller " ;
}
}
case 0x02 : return " Multiport Serial Controller " ;
case 0x03 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Generic Modem " ;
case 0x01 : return " Hayes 16450 Compatible Modem " ;
case 0x02 : return " Hayes 16550 Compatible Modem " ;
case 0x03 : return " Hayes 16650 Compatible Modem " ;
case 0x04 : return " Hayes 16750 Compatible Modem " ;
default : return " Modem " ;
}
}
case 0x04 : return " IEEE 488.1/2 (GPIB) Controller " ;
case 0x05 : return " Smart Card " ;
case 0x80 : return " Other " ;
default : return " Unknown Simple Comms Controller " ;
}
}
case 0x08 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Generic 8259-Compatible PIC " ;
case 0x01 : return " ISA-Compatible PIC " ;
case 0x02 : return " EISA-Compatible PIC " ;
case 0x03 : return " I/O APIC Interrupt Controller " ;
case 0x04 : return " I/O(x) APIC Interrupt Controller " ;
2020-08-23 01:32:47 +00:00
default : return " PIC " ;
2020-08-22 23:50:10 +00:00
}
}
case 0x01 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Generic 8237-Compatible DMA Controller " ;
case 0x01 : return " ISA-Compatible DMA Controller " ;
case 0x02 : return " EISA-Compatible DMA Controller " ;
2020-08-23 01:32:47 +00:00
default : return " DMA Controller " ;
2020-08-22 23:50:10 +00:00
}
}
case 0x02 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Generic 8254-Compatible Timer " ;
case 0x01 : return " ISA-Compatible Timer " ;
case 0x02 : return " EISA-Compatible Timer " ;
case 0x03 : return " HPET Timer " ;
2020-08-23 01:32:47 +00:00
default : return " Timer " ;
2020-08-22 23:50:10 +00:00
}
}
case 0x03 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Generic RTC Controller " ;
case 0x01 : return " ISA-Compatible RTC Controller " ;
2020-08-23 01:32:47 +00:00
default : return " RTC Controller " ;
2020-08-22 23:50:10 +00:00
}
}
case 0x04 : return " PCI Hot-Plug Controller " ;
case 0x05 : return " SD Host Controller " ;
case 0x06 : return " IOMMU " ;
case 0x80 : return " Other " ;
default : return " Unknown Base System Peripheral " ;
}
}
case 0x09 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Keyboard Controller " ;
case 0x01 : return " Digitiser Pen " ;
case 0x02 : return " Mouse Controller " ;
case 0x03 : return " Scanner Controller " ;
case 0x04 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Generic Gameport Controller " ;
case 0x10 : return " Extended Gameport Controller " ;
default : return " Gameport Controller " ;
}
}
case 0x80 : return " Other " ;
default : return " Unknown Input Device Controller " ;
}
}
case 0x0A : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Generic Docking Station " ;
case 0x80 : return " Other " ;
default : return " Unknown Docking Station " ;
}
}
case 0x0B : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " 386 Processor " ;
case 0x01 : return " 486 Processor " ;
case 0x02 : return " Pentium Processor " ;
case 0x03 : return " Pentium Pro Processor " ;
case 0x10 : return " Alpha Processor " ;
case 0x20 : return " PowerPC Processor " ;
case 0x30 : return " MIPS Processor " ;
case 0x40 : return " Co-Processor " ;
case 0x80 : return " Other " ;
default : return " Unknown Processor " ;
}
}
case 0x0C : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Generic Firewire Controller " ;
case 0x10 : return " OHCI Firewire Controller " ;
default : return " FireWire (IEEE 1394) Controller " ;
}
}
case 0x01 : return " ACCESS Bus " ;
case 0x02 : return " SSA " ;
case 0x03 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " UHCI USB Controller " ;
case 0x10 : return " OHCI USB Controller " ;
case 0x20 : return " EHCI USB (2.0) Controller " ;
case 0x30 : return " XHCI USB (3.0) Controller " ;
case 0x80 : return " Unspecified USB Controller " ;
case 0xFE : return " USB Device (NOT a Controller) " ;
default : return " USB Controller " ;
}
}
case 0x04 : return " Fibre Channel " ;
case 0x05 : return " SMBus " ;
case 0x06 : return " InfiniBand " ;
case 0x07 : {
2021-03-19 02:18:39 +00:00
switch ( ProgrammableInterface ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " SMIC IPMI Interface " ;
case 0x01 : return " Keyboard Controller-Style IPMI Interface " ;
case 0x02 : return " Block Transfer IPMI Interface " ;
default : return " IPMI Interface " ;
}
}
case 0x08 : return " SERCOS Interface (IEC 61491) " ;
case 0x09 : return " CANbus " ;
case 0x80 : return " Other " ;
default : return " Unknown Serial Bus Controller " ;
}
}
case 0x0D : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " IRDA Compatible Controller " ;
case 0x01 : return " Consumer IR Controller " ;
case 0x10 : return " RF Controller " ;
case 0x11 : return " Bluetooth Controller " ;
case 0x12 : return " Broadband Controller " ;
case 0x20 : return " Ethernet Controller (802.1a) " ;
case 0x21 : return " Ethernet Controller (802.1b) " ;
case 0x80 : return " Other " ;
default : return " Unknown Wireless Controller " ;
}
}
case 0x0E : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " I20 " ;
default : return " Unknown Intelligent Controller " ;
}
}
case 0x0F : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x01 : return " Satellite TV Controller " ;
case 0x02 : return " Satellite Audio Controller " ;
case 0x03 : return " Satellite Voice Controller " ;
case 0x04 : return " Satellite Data Controller " ;
default : return " Unknown Satelllite Comms Controller " ;
}
}
case 0x10 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Network & Computing Codec " ;
case 0x10 : return " Entertainment Codec " ;
case 0x80 : return " Other Codec " ;
default : return " Unknown Encryption Controller " ;
}
}
case 0x11 : {
2021-03-19 02:18:39 +00:00
switch ( Subclass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " DPIO Modules " ;
case 0x01 : return " Performance Counters " ;
case 0x10 : return " Communication Synchronizer " ;
case 0x20 : return " Signal Processing Management " ;
case 0x80 : return " Other " ;
default : return " Unknown Signal Processing Controller " ;
}
}
case 0x12 : return " Processing Accelerator " ;
case 0x13 : return " Non-Essential Instrumentation " ;
case 0x14 :
case 0x41 : return " Reserved " ;
case 0x40 : return " Co-Processor " ;
case 0xFF : return " Unassigned Class " ;
}
2020-08-23 01:32:47 +00:00
return " Invalid Device! " ;
2020-08-22 23:50:10 +00:00
}
2021-03-19 02:18:39 +00:00
const char * PCIGetClassName ( uint8_t DeviceClass ) {
2020-08-22 23:50:10 +00:00
2021-03-19 02:18:39 +00:00
switch ( DeviceClass ) {
2020-08-22 23:50:10 +00:00
case 0x00 : return " Unclassified " ;
case 0x01 : return " Mass Storage Controller " ;
case 0x02 : return " Network Controller " ;
case 0x03 : return " Display Controller " ;
case 0x04 : return " Multimedia Controller " ;
case 0x05 : return " Memory Controller " ;
case 0x06 : return " Bridge Device " ;
case 0x07 : return " Simple Communication Controller " ;
case 0x08 : return " Base System Peripheral " ;
case 0x09 : return " Input Device Controller " ;
case 0x0A : return " Docking Station " ;
case 0x0B : return " Processor " ;
case 0x0C : return " Serial Bus Controller " ;
case 0x0D : return " Wireless Controller " ;
case 0x0E : return " Intelligent Controller " ;
case 0x0F : return " Satellite Communication Controller " ;
case 0x10 : return " Encryption Controller " ;
case 0x11 : return " Signal Processing Controller " ;
case 0x12 : return " Processing Accelerator " ;
case 0x13 : return " Non-Essential Instrumentation " ;
case 0x14 : return " Reserved " ;
case 0x40 : return " Co-Processor " ;
case 0x41 : return " Reserved " ;
case 0xFF : return " Unassigned Class " ;
2020-08-23 01:32:47 +00:00
default : return " Unknown Category " ;
2020-08-22 23:50:10 +00:00
}
2020-08-23 01:32:47 +00:00
return " Invalid device! " ;
2020-08-22 23:50:10 +00:00
}