- added PCI ROM init code that copies to shadow RAM and use it for both VGA

and other boot ROMs
- define and use PCI constants (patch by Sebastian Herbszt)
This commit is contained in:
Volker Ruppert 2011-12-20 19:34:05 +00:00
parent e312454851
commit 46d5caa98d
2 changed files with 83 additions and 26 deletions

View File

@ -225,6 +225,10 @@
#define PCI_DEVICES_MAX 64
#define PCI_CLASS_STORAGE_IDE 0x0101
#define PCI_CLASS_DISPLAY_VGA 0x0300
#define PCI_CLASS_SYSTEM_PIC 0x0800
#define PCI_VENDOR_ID 0x00 /* 16 bits */
#define PCI_DEVICE_ID 0x02 /* 16 bits */
#define PCI_COMMAND 0x04 /* 16 bits */
@ -236,6 +240,11 @@
#define PCI_MIN_GNT 0x3e /* 8 bits */
#define PCI_MAX_LAT 0x3f /* 8 bits */
#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
#define PCI_ROM_ADDRESS_ENABLE 0x01
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_82441 0x1237
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000

View File

@ -599,6 +599,7 @@ typedef struct PCIDevice {
static uint32_t pci_bios_io_addr;
static uint32_t pci_bios_mem_addr;
static uint32_t pci_bios_rom_start;
/* host irqs corresponding to PCI irqs A-D */
static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
static PCIDevice i440_pcidev = {-1, -1};
@ -645,10 +646,10 @@ static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
uint32_t ofs, old_addr;
if ( region_num == PCI_ROM_SLOT ) {
ofs = 0x30;
addr |= 0x01;
ofs = PCI_ROM_ADDRESS;
addr |= PCI_ROM_ADDRESS_ENABLE;
}else{
ofs = 0x10 + region_num * 4;
ofs = PCI_BASE_ADDRESS_0 + region_num * 4;
}
old_addr = pci_config_readl(d, ofs);
@ -659,11 +660,11 @@ static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
/* enable memory mappings */
cmd = pci_config_readw(d, PCI_COMMAND);
if ( region_num == PCI_ROM_SLOT )
cmd |= 2;
cmd |= PCI_COMMAND_MEMORY;
else if (old_addr & PCI_ADDRESS_SPACE_IO)
cmd |= 1;
cmd |= PCI_COMMAND_IO;
else
cmd |= 2;
cmd |= PCI_COMMAND_MEMORY;
pci_config_writew(d, PCI_COMMAND, cmd);
}
@ -817,10 +818,55 @@ static void piix4_pm_enable(PCIDevice *d)
#endif
}
static void pci_bios_init_pcirom(PCIDevice *d, uint32_t paddr)
{
PCIDevice d1, *i440fx = &d1;
uint32_t tmpaddr, size;
uint8_t reg, v;
int copied, shift, tmpsize;
i440fx->bus = 0;
i440fx->devfn = 0;
if (paddr != 0) {
size = readb((void *)(paddr + 2));
if (size & 0x03) {
size &= 0xfc;
size += 0x04;
}
size <<= 9;
if ((pci_bios_rom_start + size) > 0xe0000)
return;
tmpaddr = pci_bios_rom_start;
copied = 0;
do {
tmpsize = 0x4000 - (tmpaddr & 0x3fff);
if ((size - copied) < tmpsize) {
tmpsize = size;
}
reg = 0x5a + (uint8_t)((tmpaddr >> 15) & 0x07);
if (tmpaddr & 0x4000) {
shift = 4;
} else {
shift = 0;
}
v = pci_config_readb(i440fx, reg);
v = (v & (~(0x03 << shift))) | (0x02 << shift);
pci_config_writeb(i440fx, reg, v);
memcpy((void *)tmpaddr, (void *)(paddr + copied), tmpsize);
v = (v & (~(0x03 << shift))) | (0x01 << shift);
pci_config_writeb(i440fx, reg, v);
tmpaddr += tmpsize;
copied += tmpsize;
} while (copied < size);
BX_INFO("PCI ROM copied to 0x%05x (size=0x%05x)\n", pci_bios_rom_start, size);
pci_bios_rom_start += size;
}
}
static void pci_bios_init_device(PCIDevice *d)
{
PCIDevice d1, *i440fx = &d1;
int class, v;
uint16_t class;
uint32_t *paddr;
int i, pin, pic_irq, vendor_id, device_id;
@ -832,7 +878,7 @@ static void pci_bios_init_device(PCIDevice *d)
BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x class=0x%04x\n",
d->bus, d->devfn, vendor_id, device_id, class);
switch(class) {
case 0x0101: /* Mass storage controller - IDE interface */
case PCI_CLASS_STORAGE_IDE:
if (vendor_id == PCI_VENDOR_ID_INTEL &&
(device_id == PCI_DEVICE_ID_INTEL_82371SB_1 ||
device_id == PCI_DEVICE_ID_INTEL_82371AB)) {
@ -848,7 +894,7 @@ static void pci_bios_init_device(PCIDevice *d)
pci_set_io_region_addr(d, 3, 0x374);
}
break;
case 0x0800: /* Generic system peripheral - PIC */
case PCI_CLASS_SYSTEM_PIC:
if (vendor_id == PCI_VENDOR_ID_IBM) {
/* IBM */
if (device_id == 0x0046 || device_id == 0xFFFF) {
@ -872,10 +918,10 @@ static void pci_bios_init_device(PCIDevice *d)
uint32_t val, size ;
if (i == PCI_ROM_SLOT) {
ofs = 0x30;
ofs = PCI_ROM_ADDRESS;
pci_config_writel(d, ofs, 0xfffffffe);
} else {
ofs = 0x10 + i * 4;
ofs = PCI_BASE_ADDRESS_0 + i * 4;
pci_config_writel(d, ofs, 0xffffffff);
}
val = pci_config_readl(d, ofs);
@ -887,21 +933,8 @@ static void pci_bios_init_device(PCIDevice *d)
paddr = &pci_bios_mem_addr;
*paddr = (*paddr + size - 1) & ~(size - 1);
pci_set_io_region_addr(d, i, *paddr);
if ((i == PCI_ROM_SLOT) && (class == 0x0300)) {
v = pci_config_readb(i440fx, 0x5a);
v = (v & 0xcc) | 0x22;
pci_config_writeb(i440fx, 0x5a, v);
memcpy((void *)0xc0000, (void *)*paddr, 0x8000);
v = (v & 0xcc) | 0x11;
pci_config_writeb(i440fx, 0x5a, v);
if (size > 0x8000) {
v = pci_config_readb(i440fx, 0x5b);
v = (v & 0xcc) | 0x22;
pci_config_writeb(i440fx, 0x5b, v);
memcpy((void *)0xc8000, (void *)(*paddr + 0x8000), size - 0x8000);
v = (v & 0xcc) | 0x11;
pci_config_writeb(i440fx, 0x5b, v);
}
if ((i == PCI_ROM_SLOT) && (class == PCI_CLASS_DISPLAY_VGA)) {
pci_bios_init_pcirom(d, *paddr);
}
*paddr += size;
}
@ -929,6 +962,18 @@ static void pci_bios_init_device(PCIDevice *d)
}
}
static void pci_bios_init_optrom(PCIDevice *d)
{
uint32_t paddr;
uint16_t class;
class = pci_config_readw(d, PCI_CLASS_DEVICE);
if (class != PCI_CLASS_DISPLAY_VGA) {
paddr = pci_config_readl(d, PCI_ROM_ADDRESS) & 0xfffffc00;
pci_bios_init_pcirom(d, paddr);
}
}
void pci_for_each_device(void (*init_func)(PCIDevice *d))
{
PCIDevice d1, *d = &d1;
@ -952,10 +997,13 @@ void pci_bios_init(void)
{
pci_bios_io_addr = 0xc000;
pci_bios_mem_addr = 0xc0000000;
pci_bios_rom_start = 0xc0000;
pci_for_each_device(pci_bios_init_bridges);
pci_for_each_device(pci_bios_init_device);
pci_for_each_device(pci_bios_init_optrom);
}
/****************************************************/