- added PCI ROM support to bx_pci_device_stub_c and use it in the pcivga device (based on a patch by

Sebastian Herbszt). TODO list:
  - modify LGPL'd VGABIOS to make it work with SeaBIOS
  - modify Bochs BIOS to set up the legacy address 0xc0000
  - implement PCI ROM support in the cirrus device
  - move load_ROM calls to the display adapter code to handle the ISA case
This commit is contained in:
Volker Ruppert 2011-06-26 17:42:07 +00:00
parent 5ef9f8acf8
commit deef94eb12
4 changed files with 121 additions and 2 deletions

View File

@ -1183,3 +1183,58 @@ void bx_pci_device_stub_c::register_pci_state(bx_list_c *list)
new bx_shadow_num_c(pci, name, &pci_conf[i], BASE_HEX);
}
}
void bx_pci_device_stub_c::load_pci_rom(const char *path)
{
struct stat stat_buf;
int fd, ret;
unsigned long size, max_size;
if (*path == '\0') {
BX_PANIC(("PCI ROM image undefined"));
return;
}
// read in PCI ROM image file
fd = open(path, O_RDONLY
#ifdef O_BINARY
| O_BINARY
#endif
);
if (fd < 0) {
BX_PANIC(("couldn't open PCI ROM image file '%s'.", path));
return;
}
ret = fstat(fd, &stat_buf);
if (ret) {
BX_PANIC(("couldn't stat PCI ROM image file '%s'.", path));
return;
}
max_size = 0x10000;
size = (unsigned long)stat_buf.st_size;
if (size > max_size) {
close(fd);
BX_PANIC(("PCI ROM image too large"));
return;
}
if ((size % 512) != 0) {
close(fd);
BX_PANIC(("PCI ROM image size must be multiple of 512 (size = %ld)", size));
return;
}
while ((size - 1) < max_size) {
max_size >>= 1;
}
pci_rom_size = (max_size << 1);
while (size > 0) {
ret = read(fd, (bx_ptr_t) pci_rom, size);
if (ret <= 0) {
BX_PANIC(("read failed on PCI ROM image: '%s'", path));
}
size -= ret;
}
close(fd);
BX_INFO(("loaded PCI ROM '%s' (size=%u)", path, (unsigned) stat_buf.st_size));
}

View File

@ -96,9 +96,14 @@ public:
void register_pci_state(bx_list_c *list);
void load_pci_rom(const char *path);
protected:
Bit8u pci_conf[256];
Bit32u pci_base_address[6];
Bit8u pci_rom[65536];
Bit32u pci_rom_address;
Bit32u pci_rom_size;
};
//////////////////////////////////////////////////////////////////////

View File

@ -102,6 +102,8 @@ void bx_pcivga_c::init(void)
WriteHostDWordToLittleEndian(&BX_PCIVGA_THIS pci_conf[0x10], 0x08);
BX_PCIVGA_THIS pci_base_address[0] = 0;
}
BX_PCIVGA_THIS pci_rom_address = 0;
BX_PCIVGA_THIS load_pci_rom(SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr());
}
void bx_pcivga_c::reset(unsigned type)
@ -132,6 +134,45 @@ void bx_pcivga_c::after_restore_state(void)
BX_INFO(("new base address: 0x%08x", BX_PCIVGA_THIS pci_base_address[0]));
}
}
if (DEV_pci_set_base_mem(this, mem_read_handler, mem_write_handler,
&BX_PCIVGA_THIS pci_rom_address,
&BX_PCIVGA_THIS pci_conf[0x30],
BX_PCIVGA_THIS pci_rom_size)) {
BX_INFO(("new ROM address: 0x%08x", BX_PCIVGA_THIS pci_rom_address));
}
}
bx_bool bx_pcivga_c::mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param)
{
Bit8u *data_ptr;
#ifdef BX_LITTLE_ENDIAN
data_ptr = (Bit8u *) data;
#else
data_ptr = (Bit8u *) data + (len - 1);
#endif
for (unsigned i = 0; i < len; i++) {
if (BX_PCIVGA_THIS pci_conf[0x30] & 0x01) {
*data_ptr = BX_PCIVGA_THIS pci_rom[addr - BX_PCIVGA_THIS pci_rom_address];
} else {
*data_ptr = 0xff;
}
addr++;
#ifdef BX_LITTLE_ENDIAN
data_ptr++;
#else
data_ptr--;
#endif
}
return 1;
}
bx_bool bx_pcivga_c::mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param)
{
BX_INFO(("write to ROM ignored (addr=0x%08x len=%d)", (Bit32u)addr, len));
return 1;
}
// pci configuration space read callback handler
@ -157,7 +198,7 @@ Bit32u bx_pcivga_c::pci_read_handler(Bit8u address, unsigned io_len)
// static pci configuration space write callback handler
void bx_pcivga_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len)
{
bx_bool baseaddr_change = 0;
bx_bool baseaddr_change = 0, romaddr_change = 0;
if (io_len == 1)
BX_DEBUG(("write PCI register 0x%02x value 0x%02x", address, value));
@ -166,9 +207,14 @@ void bx_pcivga_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len
else if (io_len == 4)
BX_DEBUG(("write PCI register 0x%02x value 0x%08x", address, value));
if ((address >= 0x14) && (address < 0x34))
if ((address >= 0x14) && (address < 0x30))
return;
if (address == 0x30) {
value = value & 0xfffffc01;
romaddr_change = 1;
}
for (unsigned i = 0; i < io_len; i++) {
unsigned write_addr = address + i;
Bit8u old_value = BX_PCIVGA_THIS pci_conf[write_addr];
@ -197,6 +243,14 @@ void bx_pcivga_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len
BX_INFO(("new base address: 0x%08x", BX_PCIVGA_THIS pci_base_address[0]));
}
}
if (romaddr_change) {
if (DEV_pci_set_base_mem(this, mem_read_handler, mem_write_handler,
&BX_PCIVGA_THIS pci_rom_address,
&BX_PCIVGA_THIS pci_conf[0x30],
BX_PCIVGA_THIS pci_rom_size)) {
BX_INFO(("new ROM address: 0x%08x", BX_PCIVGA_THIS pci_rom_address));
}
}
}
#endif // BX_SUPPORT_PCI

View File

@ -23,8 +23,10 @@
#if BX_USE_PCIVGA_SMF
# define BX_PCIVGA_THIS thePciVgaAdapter->
# define BX_PCIVGA_SMF static
#else
# define BX_PCIVGA_THIS this->
# define BX_PCIVGA_SMF
#endif
class bx_pcivga_c : public bx_devmodel_c, public bx_pci_device_stub_c {
@ -36,6 +38,9 @@ public:
virtual void register_state(void);
virtual void after_restore_state(void);
BX_PCIVGA_SMF bx_bool mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param);
BX_PCIVGA_SMF bx_bool mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param);
virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len);
virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len);