PCI configuration support.

This commit is contained in:
Scott Mansell 2011-10-11 01:57:48 +13:00
parent 2654f1c0e0
commit fe801a9cea
4 changed files with 322 additions and 4 deletions

View file

@ -2,8 +2,8 @@ CFLAGS = -g -O2 -Wall
all: kvmbox loader
kvmbox: kvmbox.o smbus.o
gcc $(CFLAGS) kvmbox.o smbus.o -o kvmbox
kvmbox: kvmbox.o smbus.o pci.o
gcc $(CFLAGS) kvmbox.o smbus.o pci.o -o kvmbox
loader: loader.asm
nasm loader.asm

View file

@ -92,8 +92,11 @@ void mmio_handler(struct kvm *kvm) {
void io_handler(struct kvm *kvm) {
unsigned char *p = (unsigned char *)(kvm->run) + kvm->run->io.data_offset;
assert(kvm->run->io.count == 1);
if(kvm->run->io.port >= 0xc000 && kvm->run->io.port <= 0xc008)
smbusIO(kvm->run->io.port, kvm->run->io.direction, kvm->run->io.size, p);
uint16_t port = kvm->run->io.port;
if(port >= 0xc000 && port <= 0xc008)
smbusIO(port, kvm->run->io.direction, kvm->run->io.size, p);
else if(port == 0xcf8 || port == 0xcfc)
pciConfigIO(port, kvm->run->io.direction, kvm->run->io.size, p);
else if(kvm->run->io.direction) {
printf("I/O port 0x%04x out ", kvm->run->io.port);
switch(kvm->run->io.size) {

View file

@ -12,3 +12,34 @@
0xffc00000 ISA Bridge?
0xfff00000-0xffffffff Flash
Ports
0000-001f : dma1
0020-003f : pic1
0040-0043 : timer0
0050-0053 : timer1
0060-006f : keyboard
0070-007f : rtc
0080-008f : dma page reg
00a0-00bf : pic2
00c0-00df : dma2
00f0-00ff : fpu
01f0-01f7 : ide0
03c0-03df : vesafb
03f6-03f6 : ide0
0cf8-0cff : PCI conf1
1000-100f : nVidia Corporation nForce PCI System Management
1080-10ff : nVidia Corporation Intel 537 [nForce MC97 Modem]
1400-14ff : nVidia Corporation Intel 537 [nForce MC97 Modem]
c000-c00f : nVidia Corporation nForce PCI System Management
c000-c00f : amd756-smbus
c200-c21f : nVidia Corporation nForce PCI System Management
d000-d0ff : nVidia Corporation nForce Audio
d000-d0ff : NVIDIA nForce Audio
d200-d27f : nVidia Corporation nForce Audio
d200-d23f : NVIDIA nForce Audio
e000-e007 : nVidia Corporation nForce Ethernet Controller
e000-e007 : forcedeth
ff60-ff6f : nVidia Corporation nForce IDE
ff60-ff67 : ide0

284
pci.c Normal file
View file

@ -0,0 +1,284 @@
#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() {
struct pci_config *config;
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;
}
return ((uint32_t *)config)[reg];
}
uint32_t readConfig(reg) {
struct pci_config *config = getConfig();
if (!config) {
printf("Unimplemented PCI device read %i:%i:%i[0x%02x]\n", bus, device, function, reg);
return 0;
}
return ((uint32_t *)config)[reg];
}
uint32_t writeConfig(reg, value) {
struct pci_config *config = getConfig();
if (!config) {
printf("Unimplemented PCI device write %i:%i:%i[0x%02x] = %08x\n", bus, device, function, reg, value);
return 0;
}
((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;
}
}
}
}