Created
May 12, 2012 00:53
-
-
Save mafice/2663420 to your computer and use it in GitHub Desktop.
PCI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #define PCI_IOPORT_CONFIG_ADDRESS 0x0cf8 | |
| #define PCI_IOPORT_CONFIG_DATA 0x0cfc | |
| #define PCI_BUS_MAX 255 | |
| #define PCI_DEVICE_MAX 31 | |
| #define PCI_FUNC_MAX 7 | |
| #define PCI_CONFIGREG_VENDOR_AND_DEVICE_ID 0x00 | |
| #define PCI_CONFIGREG_INTERRUPT 0x3c | |
| typedef unsigned char u8; | |
| typedef unsigned short u16; | |
| typedef unsigned long u32; | |
| typedef struct PCIDevice_st{ | |
| u16 vendorID; | |
| u16 deviceID; | |
| u8 interruptLine; | |
| } PCIDevice_st; | |
| static void pci_findDevices (PCIDevice_st devices[], unsigned int devicesMax); | |
| static u32 pci_readConfigRegister (u8 regAddr, u8 bus, u8 device, u8 func); | |
| void pci_test (void){ | |
| PCIDevice_st devices[100]; | |
| pci_findDevices(devices, 100); | |
| for(int i=0; i < 255 && devices[i].vendorID != 0xffff; i++){ | |
| if(devices[i].interruptLine == 0xff) | |
| print("PCI: device found (vendor: 0x%x) (device: 0x%x) (interrupt: none)\n", devices[i].vendorID, devices[i].deviceID); | |
| else | |
| print("PCI: device found (vendor: 0x%x) (device: 0x%x) (interrupt: %d)\n", devices[i].vendorID, devices[i].deviceID, devices[i].interruptLine); | |
| } | |
| return; | |
| } | |
| static void pci_findDevices (PCIDevice_st devices[], unsigned int devicesMax){ | |
| u32 reg; | |
| unsigned int i=0; | |
| for(unsigned int j=0; j <= PCI_BUS_MAX; j++){ | |
| for(unsigned int k=0; k <= PCI_DEVICE_MAX; k++){ | |
| for(unsigned int l=0; l <= PCI_FUNC_MAX; l++){ | |
| // get Vendor ID and device ID | |
| reg = pci_readConfigRegister(PCI_CONFIGREG_VENDOR_AND_DEVICE_ID, j, k, l); | |
| // if vendor ID is 0xffff, the device (or function) is not exist | |
| if((reg>>16) == 0xffff){ | |
| continue; | |
| } | |
| devices[i].vendorID = reg >> 16; | |
| devices[i].deviceID = reg & 0xffff; | |
| // get interrupt line | |
| reg = pci_readConfigRegister(PCI_CONFIGREG_INTERRUPT, j, k, l); | |
| // Notes: if the interrupt line is 0xff or the interrupt pin is 0, there is no connection | |
| devices[i].interruptLine = (((reg>>8) == 0x00)? 0xff : (reg & 0xff)); | |
| i++; | |
| // in order to prevent stack overflow | |
| if(i+1 >= devicesMax){ | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| devices[i].vendorID = 0xffff; | |
| devices[i].deviceID = 0xffff; | |
| devices[i].interruptLine = 0xff; | |
| return; | |
| } | |
| static u32 pci_readConfigRegister (u8 regAddr, u8 bus, u8 device, u8 func){ | |
| u32 ret; | |
| // tell PCI what I want to read | |
| asm_out32(PCI_IOPORT_CONFIG_ADDRESS, | |
| ((0 << 0) & 0x00000000) | // bit 0-1: must be 0 | |
| ((regAddr << 0) & 0x000000fc) | // bit 2-7: register number | |
| ((func << 8) & 0x00000700) | // bit 8-10: function number | |
| ((device << 11) & 0x0000f800) | // bit 11-15: device number | |
| ((bus << 16) & 0x00ff0000) | // bit 16-23: bus number | |
| ((0 << 24) & 0x7f000000) | // bit 24-30: reserved | |
| ((1 << 31) & 0x80000000) // bit 31: enable bit | |
| ); | |
| // read CONFIG_DATA | |
| ret = asm_in32(PCI_IOPORT_CONFIG_DATA); | |
| // clear enable bit | |
| asm_out32(PCI_IOPORT_CONFIG_ADDRESS, 0x00000000); | |
| return ret; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment