mirror of
https://github.com/phire/kvmbox.git
synced 2024-05-13 02:35:11 -04:00
PCI configuration support.
This commit is contained in:
parent
2654f1c0e0
commit
fe801a9cea
4
Makefile
4
Makefile
|
@ -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
|
||||
|
|
7
kvmbox.c
7
kvmbox.c
|
@ -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) {
|
||||
|
|
|
@ -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
284
pci.c
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue