kvmbox/pci.c
2015-12-26 14:02:52 +13:00

287 lines
6.6 KiB
C

// Copyright (c) 2011 Scott Mansell <phiren@gmail.com>
// Licensed under the MIT license
// Refer to the included LICENCE file.
#include <stdint.h>
#include <stdio.h>
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;
}
}
}
}