#include #include int bus; int device; int function; int reg; struct pci_config { uint16_t DeviceID; uint16_t VenderID; uint16_t Status; uint16_t Command; uint8_t ClassCode; uint8_t Subclass; uint8_t ProgIF; uint8_t RevID; uint8_t BIST; uint8_t HeaderType; uint8_t LatTimer; uint8_t CacheLine; uint32_t bar1; uint32_t bar2; uint32_t bar3; uint32_t bar4; uint32_t bar5; uint32_t bar6; uint32_t CardbusCIS; uint16_t SubID; uint16_t SubVID; uint32_t ExpansionROM; uint8_t _reserved[3]; uint8_t CapPointer; uint32_t __reserved; uint8_t MaxLat; uint8_t MinGnt; uint8_t InterruptPin; uint8_t InterruptLine; uint8_t extra[0xc0]; } __attribute__((packed)); struct pci_config ideController = { .DeviceID = 0x10de, .VenderID = 0x01bc, .Status = 0x00b0, .ClassCode = 0x1, .Subclass = 0x1, .ProgIF = 0x8a, .RevID = 0xd4, .bar5 = 0x00000001, .CapPointer = 0x44, .MaxLat = 1, .MinGnt = 0, .extra = {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xff, 0x20, }, }; struct pci_config forcedeth = { .DeviceID = 0x10de, .VenderID = 0x01c3, .Status = 0x00b0, .ClassCode = 0x02, .Subclass = 0x00, .ProgIF = 0x00, .RevID = 0xd2, .bar2 = 1, .CapPointer = 0x44, .MaxLat = 0x14, .MinGnt = 1, .InterruptPin = 1, .InterruptLine = 0, .extra = {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xfe, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, }, }; struct pci_config usb1 = { .DeviceID = 0x10de, .VenderID = 0x01c2, .Status = 0x00b0, .ClassCode = 0x0c, .Subclass = 0x03, .ProgIF = 0x10, .RevID = 0xd4, .CapPointer = 0x44, .MaxLat = 1, .MinGnt = 1, .InterruptPin = 1, .InterruptLine = 0, .extra = {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, }, }; struct pci_config usb2 = { .DeviceID = 0x10de, .VenderID = 0x01c2, .Status = 0x00b0, .ClassCode = 0x0c, .Subclass = 0x03, .ProgIF = 0x10, .RevID = 0xd4, .CapPointer = 0x44, .MaxLat = 1, .MinGnt = 1, .InterruptPin = 1, .InterruptLine = 0, .extra = {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, }, }; struct pci_config audio = { .DeviceID = 0x10de, .VenderID = 0x01b1, .Status = 0x00b0, .ClassCode = 0x04, .Subclass = 0x01, .ProgIF = 0x00, .RevID = 0xd2, .bar1 = 1, .bar2 = 1, .CapPointer = 0x44, .MaxLat = 5, .MinGnt = 2, .InterruptPin = 1, .InterruptLine = 0, .extra = {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, }, }; struct pci_config audio2 = { .DeviceID = 0x10de, .VenderID = 0x01b0, .Status = 0x00b0, .ClassCode = 0x04, .Subclass = 0x01, .ProgIF = 0x00, .RevID = 0xd2, .CapPointer = 0x44, .MaxLat = 0xc, .MinGnt = 1, .InterruptPin = 1, .InterruptLine = 0, .extra = {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x05, 0x00, 0x00, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, 0x01, 0x00, 0x02, 0x06, }, }; struct pci_config vga = { .DeviceID = 0x10de, .VenderID = 0x02a0, .Status = 0x00b0, .ClassCode = 0x03, .Subclass = 0x00, .ProgIF = 0x00, .RevID = 0xa1, .CapPointer = 0x60, .MaxLat = 1, .MinGnt = 5, .InterruptPin = 1, .InterruptLine = 0, .extra = {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x1f, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xce, 0xd6, 0x23, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x44, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0xd0, 0x16, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, }; struct pci_config *getConfig() { switch(bus << 16 | device << 11 | function << 8) { case 9 << 11: return &ideController; case 4 << 11: return &forcedeth; case 2 << 11: return &usb1; case 3 << 11: return &usb2; case 6 << 11: return &audio; case 5 << 11: return &audio2; case 1 << 16: return &vga; default: return 0; } } uint32_t readConfig(reg) { struct pci_config *config = getConfig(); if (!config) { debugf("Unimplemented PCI device read %i:%i:%i[0x%02x]\n", bus, device, function, reg); return 0; } return ((uint32_t *)config)[reg]; } void writeConfig(reg, value) { struct pci_config *config = getConfig(); if (!config) { debugf("Unimplemented PCI device write %i:%i:%i[0x%02x] = %08x\n", bus, device, function, reg, value); return; } ((uint32_t *)config)[reg] = value; } void pciConfigIO(uint16_t port, uint8_t direction, uint8_t size, uint8_t *p) { if(port == 0xcf8) { uint32_t addr = *(uint32_t *)p; bus = (addr >> 16) & 0xff; device = (addr >> 11) & 0x1f; function = (addr >> 8) & 0x7; reg = (addr >> 2) & 0x3f; } if(port == 0xcfc) { if(direction) { switch(size) { case 1: writeConfig(reg, *p); break; case 2: writeConfig(reg, *(uint16_t *)p); break; case 4: writeConfig(reg, *(uint32_t *)p); break; } } else { switch(size) { case 1: *p = readConfig(reg); break; case 2: *(uint16_t *)p = readConfig(reg); break; case 4: *(uint32_t *)p = readConfig(reg); break; } } } }