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:
parent
73bc76072e
commit
8952c144bd
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user