Some work on the i440BX chipset and related changes.

- Fixed PCI BAR initialization (now using memset()).
  - Fixed reset failure (set all PAM memory types to ROM).
  - Added stub for the AGP aperture (register BAR #0, handle APSIZE and read
    GART entry in read/write handlers).
  - Added some more PCI register defaults and write masks.
  - Fixed a warning in the ES1370 code.
  - Voodoo Banshee: set up PCI subsystem ID depending on bus and model.
  - Volatile BIOS write support must also be present in ISA BIOS memory.
This commit is contained in:
Volker Ruppert 2018-03-04 04:53:16 +00:00
parent 73bc76072e
commit 8952c144bd
8 changed files with 187 additions and 14 deletions

View File

@ -132,17 +132,27 @@ bx_banshee_c::bx_banshee_c() : bx_voodoo_base_c()
void bx_banshee_c::init_model(void)
{
static char model[40];
if (theVoodooVga == NULL) {
BX_PANIC(("Voodoo Banshee with VGA disabled not supported yet"));
}
Bit8u bus = SIM->is_agp_device(BX_PLUGIN_VOODOO);
bus = SIM->is_agp_device(BX_PLUGIN_VOODOO);
if (s.model == VOODOO_BANSHEE) {
DEV_register_pci_handlers2(this, &s.devfunc, BX_PLUGIN_VOODOO,
"Experimental 3dfx Voodoo Banshee", bus);
if (bus == 0) {
strcpy(model, "Experimental 3dfx Voodoo Banshee PCI");
} else {
strcpy(model, "Experimental 3dfx Voodoo Banshee AGP");
}
DEV_register_pci_handlers2(this, &s.devfunc, BX_PLUGIN_VOODOO, model, bus);
init_pci_conf(0x121a, 0x0003, 0x01, 0x030000, 0x00, BX_PCI_INTA);
} else if (s.model == VOODOO_3) {
DEV_register_pci_handlers2(this, &s.devfunc, BX_PLUGIN_VOODOO,
"Experimental 3dfx Voodoo 3", bus);
if (bus == 0) {
strcpy(model, "Experimental 3dfx Voodoo 3 PCI");
} else {
strcpy(model, "Experimental 3dfx Voodoo 3 AGP");
}
DEV_register_pci_handlers2(this, &s.devfunc, BX_PLUGIN_VOODOO, model, bus);
init_pci_conf(0x121a, 0x0005, 0x01, 0x030000, 0x00, BX_PCI_INTA);
} else {
BX_PANIC(("Unknown Voodoo Banshee compatible model"));
@ -177,15 +187,18 @@ void bx_banshee_c::reset(unsigned type)
{ 0x1a, 0x00 }, { 0x1b, 0x00 },
// address space 0x2c - 0x2f
{ 0x2c, 0x1a }, { 0x2d, 0x12 }, // subsystem ID
{ 0x2e, 0x04 }, { 0x2f, 0x00 },
{ 0x2e, 0x04 }, { 0x2f, 0x00 }, // for Banshee PCI and Voodoo 3 AGP
{ 0x3c, 0x00 }, // IRQ
};
for (i = 0; i < sizeof(reset_vals2) / sizeof(*reset_vals2); ++i) {
pci_conf[reset_vals2[i].addr] = reset_vals2[i].val;
}
if (s.model == VOODOO_3) {
pci_conf[0x2e] = 0x36; // Subsystem ID.for a PCI model
// Special subsystem IDs
if ((s.model == VOODOO_3) && (bus == 0)) {
pci_conf[0x2e] = 0x36; // Voodoo 3 PCI model
} else if ((s.model == VOODOO_BANSHEE) && (bus == 1)) {
pci_conf[0x2e] = 0x03; // Banshee AGP model
}
// TODO

View File

@ -168,6 +168,7 @@ private:
void blt_line(bx_bool pline);
bx_ddc_c ddc;
Bit8u bus;
};
class bx_voodoo_vga_c : public bx_vgacore_c {

View File

@ -113,7 +113,7 @@ typedef struct {
class BOCHSAPI bx_pci_device_c : public bx_devmodel_c {
public:
bx_pci_device_c(): pci_rom(NULL), pci_rom_size(0) {
for (int i = 0; i < 6; i++) pci_bar[i].type = BX_PCI_BAR_TYPE_NONE;
for (int i = 0; i < 6; i++) memset(&pci_bar[i], 0, sizeof(bx_pci_bar_t));
}
virtual ~bx_pci_device_c() {
if (pci_rom != NULL) delete [] pci_rom;

View File

@ -86,10 +86,18 @@ void bx_pci_bridge_c::init(void)
init_pci_conf(0x8086, 0x0122, 0x02, 0x060000, 0x00, 0);
} else if (BX_PCI_THIS chipset == BX_PCI_CHIPSET_I440BX) {
init_pci_conf(0x8086, 0x7190, 0x02, 0x060000, 0x00, 0);
BX_PCI_THIS pci_conf[0x10] = 0x08;
init_bar_mem(0, 0xf0000000, agp_ap_read_handler, agp_ap_write_handler);
BX_PCI_THIS pci_conf[0x06] = 0x10;
BX_PCI_THIS pci_conf[0x34] = 0xa0;
BX_PCI_THIS pci_conf[0xa0] = 0x02;
BX_PCI_THIS pci_conf[0xa2] = 0x10;
BX_PCI_THIS pci_conf[0xa4] = 0x03;
BX_PCI_THIS pci_conf[0xa5] = 0x02;
BX_PCI_THIS pci_conf[0xa7] = 0x1f;
BX_PCI_THIS pci_conf[0xf3] = 0xf8;
BX_PCI_THIS pci_conf[0xf8] = 0x20;
BX_PCI_THIS pci_conf[0xf9] = 0x0f;
BX_PCI_THIS vbridge = new bx_pci_vbridge_c();
BX_PCI_THIS vbridge->init();
} else { // i440FX
@ -204,9 +212,18 @@ bx_pci_bridge_c::reset(unsigned type)
BX_PCI_THIS pci_conf[0x06] = 0x80;
BX_PCI_THIS pci_conf[0x51] = 0x01;
BX_PCI_THIS pci_conf[0x58] = 0x10;
BX_PCI_THIS pci_conf[0xb4] = 0x00;
BX_PCI_THIS pci_conf[0xb9] = 0x00;
BX_PCI_THIS pci_conf[0xba] = 0x00;
BX_PCI_THIS pci_conf[0xbb] = 0x00;
BX_PCI_THIS gart_base = 0;
}
for (i=0x59; i<0x60; i++)
BX_PCI_THIS pci_conf[i] = 0x00;
for (i = 0; i <= BX_MEM_AREA_F0000; i++) {
DEV_mem_set_memory_type(i, 0, 0);
DEV_mem_set_memory_type(i, 1, 0);
}
BX_PCI_THIS pci_conf[0x72] = 0x02;
}
@ -234,6 +251,8 @@ void bx_pci_bridge_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io
unsigned area;
Bit8u drba_reg, old_dram_detect;
bx_bool drba_changed;
bx_bool attbase_changed = 0;
Bit32u apsize;
old_dram_detect = BX_PCI_THIS dram_detect;
if ((address >= 0x10) && (address < 0x34))
@ -274,6 +293,8 @@ void bx_pci_bridge_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io
case 0x50:
if (BX_PCI_THIS chipset == BX_PCI_CHIPSET_I430FX) {
BX_PCI_THIS pci_conf[address+i] = (value8 & 0xef);
} else if (BX_PCI_THIS chipset == BX_PCI_CHIPSET_I440BX) {
BX_PCI_THIS pci_conf[address+i] = (value8 & 0xec);
} else {
BX_PCI_THIS pci_conf[address+i] = (value8 & 0x70);
}
@ -281,6 +302,8 @@ void bx_pci_bridge_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io
case 0x51:
if (BX_PCI_THIS chipset != BX_PCI_CHIPSET_I430FX) {
BX_PCI_THIS pci_conf[address+i] = (value8 & 0x80) | 0x01;
} else if (BX_PCI_THIS chipset == BX_PCI_CHIPSET_I440BX) {
BX_PCI_THIS pci_conf[address+i] = (value8 & 0x8f);
}
break;
case 0x59:
@ -328,6 +351,51 @@ void bx_pci_bridge_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io
case 0x72:
smram_control(value8); // SMRAM control register
break;
case 0xb4:
if (BX_PCI_THIS chipset == BX_PCI_CHIPSET_I440BX) {
BX_PCI_THIS pci_conf[address+i] = value8 & 0x3f;
switch (BX_PCI_THIS pci_conf[0xb4]) {
case 0x00:
apsize = (1 << 28);
break;
case 0x20:
apsize = (1 << 27);
break;
case 0x30:
apsize = (1 << 26);
break;
case 0x38:
apsize = (1 << 25);
break;
case 0x3c:
apsize = (1 << 24);
break;
case 0x3e:
apsize = (1 << 23);
break;
case 0x3f:
apsize = (1 << 22);
break;
default:
BX_ERROR(("Invalid AGP aperture size mask"));
apsize = 0;
}
BX_INFO(("AGP aperture size set to %d MB", apsize >> 20));
pci_bar[0].size = apsize;
}
break;
case 0xb8:
break;
case 0xb9:
value8 &= 0xf0;
case 0xba:
case 0xbb:
if ((BX_PCI_THIS chipset == BX_PCI_CHIPSET_I440BX) &&
(value8 != oldval)) {
BX_PCI_THIS pci_conf[address+i] = value8;
attbase_changed |= 1;
}
break;
case 0xf0:
if (BX_PCI_THIS chipset == BX_PCI_CHIPSET_I440BX) {
BX_PCI_THIS pci_conf[address+i] = value8 & 0xc0;
@ -345,6 +413,75 @@ void bx_pci_bridge_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io
// TODO
BX_INFO(("normal memory access mode"));
}
if (attbase_changed) {
BX_PCI_THIS gart_base = ((BX_PCI_THIS pci_conf[0xbb] << 24) |
(BX_PCI_THIS pci_conf[0xba] << 16) |
(BX_PCI_THIS pci_conf[0xb9] << 8));
BX_INFO(("New GART base address = 0x%08x", BX_PCI_THIS gart_base));
}
}
bx_bool bx_pci_bridge_c::agp_ap_read_handler(bx_phy_address addr, unsigned len,
void *data, void *param)
{
bx_pci_bridge_c *class_ptr = (bx_pci_bridge_c*)param;
Bit32u value = class_ptr->agp_aperture_read(addr, len, 0);
switch (len) {
case 1:
value &= 0xFF;
*((Bit8u *) data) = (Bit8u) value;
break;
case 2:
value &= 0xFFFF;
*((Bit16u *) data) = (Bit16u) value;
break;
case 4:
*((Bit32u *) data) = value;
break;
}
return 1;
}
Bit32u bx_pci_bridge_c::agp_aperture_read(bx_phy_address addr, unsigned len,
bx_bool agp)
{
Bit32u gart_addr, gart_index, offset, page_addr, page_offset;
if (BX_PCI_THIS pci_conf[0x51] & 0x02) {
offset = (addr - pci_bar[0].addr);
gart_index = (Bit32u)(offset >> 12);
page_offset = (Bit32u)(offset & 0xfff);
gart_addr = BX_PCI_THIS gart_base + (gart_index << 2);
DEV_MEM_READ_PHYSICAL(gart_addr, 4, (Bit8u*)&page_addr);
BX_INFO(("AGP aperture read: page address = 0x%08x", page_addr));
// TODO
}
return 0;
}
bx_bool bx_pci_bridge_c::agp_ap_write_handler(bx_phy_address addr, unsigned len,
void *data, void *param)
{
bx_pci_bridge_c *class_ptr = (bx_pci_bridge_c*)param;
Bit32u value = *(Bit32u*)data;
class_ptr->agp_aperture_write(addr, value, len, 0);
return 1;
}
void bx_pci_bridge_c::agp_aperture_write(bx_phy_address addr, Bit32u value,
unsigned len, bx_bool agp)
{
Bit32u gart_addr, gart_index, offset, page_addr, page_offset;
if (BX_PCI_THIS pci_conf[0x51] & 0x02) {
offset = (addr - pci_bar[0].addr);
gart_index = (Bit32u)(offset >> 12);
page_offset = (Bit32u)(offset & 0xfff);
gart_addr = BX_PCI_THIS gart_base + (gart_index << 2);
DEV_MEM_READ_PHYSICAL(gart_addr, 4, (Bit8u*)&page_addr);
BX_INFO(("AGP aperture write: page address = 0x%08x", page_addr));
// TODO
}
}
void bx_pci_bridge_c::smram_control(Bit8u value8)

View File

@ -47,6 +47,12 @@ public:
virtual void register_state(void);
virtual void after_restore_state(void);
static bx_bool agp_ap_read_handler(bx_phy_address addr, unsigned len, void *data, void *param);
static bx_bool agp_ap_write_handler(bx_phy_address addr, unsigned len, void *data, void *param);
Bit32u agp_aperture_read(bx_phy_address addr, unsigned len, bx_bool agp);
void agp_aperture_write(bx_phy_address addr, Bit32u value, unsigned len, bx_bool agp);
virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len);
#if BX_DEBUGGER
virtual void debug_dump(int argc, char **argv);
@ -58,6 +64,7 @@ private:
unsigned chipset;
Bit8u DRBA[8];
Bit8u dram_detect;
Bit32u gart_base;
bx_pci_vbridge_c *vbridge;
};

View File

@ -377,6 +377,7 @@ void bx_piix3_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len)
break;
case 0x4e:
if ((value8 & 0x04) != (oldval & 0x04)) {
BX_DEBUG(("Set BIOS write support to %d", (value8 & 0x04) != 0));
DEV_mem_set_bios_write((value8 & 0x04) != 0);
}
BX_P2I_THIS pci_conf[address+i] = value8;

View File

@ -1085,14 +1085,12 @@ void bx_es1370_c::closemidioutput()
// pci configuration space write callback handler
void bx_es1370_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len)
{
Bit8u value8, oldval;
if ((address >= 0x14) && (address < 0x34))
return;
for (unsigned i=0; i<io_len; i++) {
value8 = (value >> (i*8)) & 0xFF;
oldval = BX_ES1370_THIS pci_conf[address+i];
Bit8u value8 = (value >> (i*8)) & 0xFF;
// Bit8u oldval = BX_ES1370_THIS pci_conf[address+i];
switch (address+i) {
case 0x04:
value8 &= 0x05;

View File

@ -2,7 +2,7 @@
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2017 The Bochs Project
// Copyright (C) 2001-2018 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@ -162,6 +162,22 @@ mem_write:
// Writes to ShadowRAM
BX_DEBUG(("Writing to ShadowRAM: address 0x" FMT_PHY_ADDRX ", data %02x", a20addr, *data_ptr));
*(BX_MEM_THIS get_vector(a20addr)) = *data_ptr;
} else if ((area >= BX_MEM_AREA_E0000) && BX_MEM_THIS bios_write_enabled) {
// volatile BIOS write support
#ifdef BX_LITTLE_ENDIAN
data_ptr = (Bit8u *) data;
#else // BX_BIG_ENDIAN
data_ptr = (Bit8u *) data + (len - 1);
#endif
for (unsigned i = 0; i < len; i++) {
BX_MEM_THIS rom[BIOS_MAP_LAST128K(a20addr)] = *data_ptr;
a20addr++;
#ifdef BX_LITTLE_ENDIAN
data_ptr++;
#else // BX_BIG_ENDIAN
data_ptr--;
#endif
}
} else {
// Writes to ROM, Inhibit
BX_DEBUG(("Write to ROM ignored: address 0x" FMT_PHY_ADDRX ", data %02x", a20addr, *data_ptr));