mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-12-23 06:29:38 +00:00
pcidevice: improve BAR configuration.
This commit is contained in:
parent
654ff0219c
commit
cc17035e67
@ -1,6 +1,6 @@
|
||||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-22 divingkatae and maximum
|
||||
Copyright (C) 2018-23 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
@ -123,6 +123,18 @@ void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &
|
||||
}
|
||||
}
|
||||
|
||||
void PCIDevice::setup_bars(std::vector<BarConfig> cfg_data)
|
||||
{
|
||||
for (auto cfg_entry : cfg_data) {
|
||||
if (cfg_entry.bar_num > 5) {
|
||||
ABORT_F("BAR number %d out of range", cfg_entry.bar_num);
|
||||
}
|
||||
this->bars_cfg[cfg_entry.bar_num] = cfg_entry.bar_cfg;
|
||||
}
|
||||
|
||||
this->finish_config_bars();
|
||||
}
|
||||
|
||||
int PCIDevice::attach_exp_rom_image(const std::string img_path)
|
||||
{
|
||||
std::ifstream img_file;
|
||||
@ -201,74 +213,73 @@ int PCIDevice::attach_exp_rom_image(const std::string img_path)
|
||||
return result;
|
||||
}
|
||||
|
||||
void PCIDevice::do_bar_sizing(int bar_num)
|
||||
{
|
||||
}
|
||||
|
||||
void PCIDevice::set_bar_value(int bar_num, uint32_t value)
|
||||
{
|
||||
uint32_t bar_cfg = this->bars_cfg[bar_num];
|
||||
switch (bars_typ[bar_num]) {
|
||||
case BAR_Unused:
|
||||
case PCIBarType::Unused:
|
||||
return;
|
||||
|
||||
case BAR_IO_16Bit:
|
||||
case BAR_IO_32Bit:
|
||||
case PCIBarType::Io_16_Bit:
|
||||
case PCIBarType::Io_32_Bit:
|
||||
this->bars[bar_num] = (value & bar_cfg & ~3) | (bar_cfg & 3);
|
||||
break;
|
||||
|
||||
case BAR_MEM_20Bit:
|
||||
case BAR_MEM_32Bit:
|
||||
case BAR_MEM_64Bit:
|
||||
case PCIBarType::Mem_20_Bit:
|
||||
case PCIBarType::Mem_32_Bit:
|
||||
case PCIBarType::Mem_64_Bit_Lo:
|
||||
this->bars[bar_num] = (value & bar_cfg & ~0xF) | (bar_cfg & 0xF);
|
||||
break;
|
||||
|
||||
case BAR_MEM_64BitHi:
|
||||
this->bars[bar_num] = (value & bar_cfg);
|
||||
case PCIBarType::Mem_64_Bit_Hi:
|
||||
this->bars[bar_num] = value & bar_cfg;
|
||||
break;
|
||||
}
|
||||
|
||||
if (value == 0xFFFFFFFFUL) {
|
||||
do_bar_sizing(bar_num);
|
||||
return;
|
||||
}
|
||||
|
||||
this->pci_notify_bar_change(bar_num);
|
||||
if (value != 0xFFFFFFFFUL) // don't notify the device during BAR sizing
|
||||
this->pci_notify_bar_change(bar_num);
|
||||
}
|
||||
|
||||
void PCIDevice::finish_config_bars()
|
||||
{
|
||||
for (int bar_num = 0; bar_num < 6; bar_num++) {
|
||||
uint32_t bar_cfg = this->bars_cfg[bar_num];
|
||||
|
||||
if (!bar_cfg) // skip unimplemented BARs
|
||||
continue;
|
||||
|
||||
if (bar_cfg & 1) {
|
||||
bars_typ[bar_num] = (bar_cfg & 0xffff0000) ? BAR_IO_32Bit : BAR_IO_16Bit;
|
||||
bars_typ[bar_num] = (bar_cfg & 0xffff0000) ? PCIBarType::Io_32_Bit :
|
||||
PCIBarType::Io_16_Bit;
|
||||
}
|
||||
else if (bar_cfg != 0) {
|
||||
else {
|
||||
int pci_space_type = (bar_cfg >> 1) & 3;
|
||||
switch (pci_space_type) {
|
||||
case 0:
|
||||
bars_typ[bar_num] = BAR_MEM_32Bit;
|
||||
break;
|
||||
case 1:
|
||||
bars_typ[bar_num] = BAR_MEM_20Bit;
|
||||
break;
|
||||
case 2:
|
||||
if (bar_num > 4) {
|
||||
ABORT_F("%s: BAR %d cannot be 64-bit", this->pci_name.c_str(), bar_num);
|
||||
}
|
||||
else if (this->bars_cfg[bar_num+1] == 0) {
|
||||
ABORT_F("%s: 64-bit BAR %d has zero for upper 32 bits", this->pci_name.c_str(), bar_num);
|
||||
}
|
||||
else {
|
||||
bars_typ[bar_num++] = BAR_MEM_64Bit;
|
||||
bars_typ[bar_num] = BAR_MEM_64BitHi;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
ABORT_F("%s: invalid or unsupported PCI space type %d for BAR %d", this->pci_name.c_str(), pci_space_type, bar_num);
|
||||
break;
|
||||
case 0:
|
||||
bars_typ[bar_num] = PCIBarType::Mem_32_Bit;
|
||||
break;
|
||||
case 1:
|
||||
bars_typ[bar_num] = PCIBarType::Mem_20_Bit;
|
||||
break;
|
||||
case 2:
|
||||
if (bar_num >= 5) {
|
||||
ABORT_F("%s: BAR %d cannot be 64-bit",
|
||||
this->pci_name.c_str(), bar_num);
|
||||
}
|
||||
else if (this->bars_cfg[bar_num+1] == 0) {
|
||||
ABORT_F("%s: 64-bit BAR %d has zero for upper 32 bits",
|
||||
this->pci_name.c_str(), bar_num);
|
||||
}
|
||||
else {
|
||||
bars_typ[bar_num] = PCIBarType::Mem_64_Bit_Hi;
|
||||
bars_typ[bar_num++] = PCIBarType::Mem_64_Bit_Lo;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ABORT_F("%s: invalid or unsupported PCI space type %d for BAR %d",
|
||||
this->pci_name.c_str(), pci_space_type, bar_num);
|
||||
} // switch pci_space_type
|
||||
} // if BAR_MEM
|
||||
}
|
||||
} // for bar_num
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-22 divingkatae and maximum
|
||||
Copyright (C) 2018-23 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
@ -29,6 +29,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/** PCI configuration space registers offsets */
|
||||
enum {
|
||||
@ -59,16 +60,21 @@ enum {
|
||||
};
|
||||
|
||||
/** PCI BAR types */
|
||||
enum PCIBarType {
|
||||
BAR_Unused,
|
||||
BAR_IO_16Bit,
|
||||
BAR_IO_32Bit,
|
||||
BAR_MEM_20Bit, // < 1M
|
||||
BAR_MEM_32Bit,
|
||||
BAR_MEM_64Bit,
|
||||
BAR_MEM_64BitHi,
|
||||
enum PCIBarType : uint32_t {
|
||||
Unused = 0,
|
||||
Io_16_Bit,
|
||||
Io_32_Bit,
|
||||
Mem_20_Bit, // legacy type for < 1MB memory
|
||||
Mem_32_Bit,
|
||||
Mem_64_Bit_Lo,
|
||||
Mem_64_Bit_Hi
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t bar_num;
|
||||
uint32_t bar_cfg;
|
||||
} BarConfig;
|
||||
|
||||
class PCIDevice : public MMIODevice {
|
||||
public:
|
||||
PCIDevice(std::string name);
|
||||
@ -116,8 +122,8 @@ public:
|
||||
virtual void write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size) { }
|
||||
|
||||
protected:
|
||||
void do_bar_sizing(int bar_num);
|
||||
void set_bar_value(int bar_num, uint32_t value);
|
||||
void setup_bars(std::vector<BarConfig> cfg_data);
|
||||
void finish_config_bars();
|
||||
void map_exp_rom_mem();
|
||||
|
||||
@ -143,7 +149,7 @@ protected:
|
||||
|
||||
uint32_t bars[6] = { 0 }; // base address registers
|
||||
uint32_t bars_cfg[6] = { 0 }; // configuration values for base address registers
|
||||
PCIBarType bars_typ[6] = { BAR_Unused }; // types for base address registers
|
||||
PCIBarType bars_typ[6] = { PCIBarType::Unused }; // types for base address registers
|
||||
|
||||
uint32_t exp_bar_cfg = 0; // expansion ROM configuration
|
||||
uint32_t exp_rom_bar = 0; // expansion ROM base address register
|
||||
|
@ -42,8 +42,8 @@ GrandCentral::GrandCentral() : PCIDevice("mac-io/grandcentral"), InterruptCtrl()
|
||||
this->device_id = 0x0002;
|
||||
this->class_rev = 0xFF000002;
|
||||
this->cache_ln_sz = 8;
|
||||
this->bars_cfg[0] = 0xFFFE0000UL; // declare 128Kb of memory-mapped I/O space
|
||||
this->finish_config_bars();
|
||||
|
||||
this->setup_bars({{0, 0xFFFE0000UL}}); // declare 128Kb of memory-mapped I/O space
|
||||
|
||||
this->pci_notify_bar_change = [this](int bar_num) {
|
||||
this->notify_bar_change(bar_num);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-22 divingkatae and maximum
|
||||
Copyright (C) 2018-23 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
@ -34,7 +34,6 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <cinttypes>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
/** Heathrow Mac I/O device emulation.
|
||||
@ -54,8 +53,8 @@ HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow"), InterruptCtrl()
|
||||
this->class_rev = 0xFF000001;
|
||||
this->cache_ln_sz = 8;
|
||||
this->lat_timer = 0x40;
|
||||
this->bars_cfg[0] = 0xFFF80000UL; // declare 512Kb of memory-mapped I/O space
|
||||
this->finish_config_bars();
|
||||
|
||||
this->setup_bars({{0, 0xFFF80000UL}}); // declare 512Kb of memory-mapped I/O space
|
||||
|
||||
this->pci_notify_bar_change = [this](int bar_num) {
|
||||
this->notify_bar_change(bar_num);
|
||||
|
@ -36,8 +36,8 @@ OHare::OHare() : PCIDevice("mac-io/ohare"), InterruptCtrl()
|
||||
this->device_id = 0x0007;
|
||||
this->class_rev = 0xFF000001;
|
||||
this->cache_ln_sz = 8;
|
||||
this->bars_cfg[0] = 0xFFF80000UL; // declare 512Kb of memory-mapped I/O space
|
||||
this->finish_config_bars();
|
||||
|
||||
this->setup_bars({{0, 0xFFF80000UL}}); // declare 512Kb of memory-mapped I/O space
|
||||
|
||||
this->pci_notify_bar_change = [this](int bar_num) {
|
||||
this->notify_bar_change(bar_num);
|
||||
|
@ -44,8 +44,8 @@ AtiMach64Gx::AtiMach64Gx()
|
||||
this->vendor_id = PCI_VENDOR_ATI;
|
||||
this->device_id = ATI_MACH64_GX_DEV_ID;
|
||||
this->class_rev = (0x030000 << 8) | 3;
|
||||
this->bars_cfg[0] = 0xFF000000UL; // declare main aperture (16MB)
|
||||
this->finish_config_bars();
|
||||
|
||||
this->setup_bars({{0, 0xFF000000UL}}); // declare main aperture (16MB)
|
||||
|
||||
this->pci_notify_bar_change = [this](int bar_num) {
|
||||
this->notify_bar_change(bar_num);
|
||||
|
@ -124,10 +124,12 @@ ATIRage::ATIRage(uint16_t dev_id)
|
||||
this->class_rev = (0x030000 << 8) | asic_id;
|
||||
this->min_gnt = 8;
|
||||
this->irq_pin = 1;
|
||||
this->bars_cfg[0] = 0xFF000000UL; // declare main aperture (16MB)
|
||||
this->bars_cfg[1] = 0xFFFFFF01UL; // declare I/O region (256 bytes)
|
||||
this->bars_cfg[2] = 0xFFFFF000UL; // declare register aperture (4KB)
|
||||
this->finish_config_bars();
|
||||
|
||||
this->setup_bars({
|
||||
{0, 0xFF000000UL}, // declare main aperture (16MB)
|
||||
{1, 0xFFFFFF01UL}, // declare I/O region (256 bytes)
|
||||
{2, 0xFFFFF000UL} // declare register aperture (4KB)
|
||||
});
|
||||
|
||||
this->pci_notify_bar_change = [this](int bar_num) {
|
||||
this->notify_bar_change(bar_num);
|
||||
|
@ -59,10 +59,12 @@ ControlVideo::ControlVideo()
|
||||
this->vendor_id = PCI_VENDOR_APPLE;
|
||||
this->device_id = 3;
|
||||
this->class_rev = 0;
|
||||
this->bars_cfg[0] = 0xFFFFFFFFUL; // I/O region (4 bytes but it's weird because bit 1 is set)
|
||||
this->bars_cfg[1] = 0xFFFFF000UL; // base address for the HW registers (4KB)
|
||||
this->bars_cfg[2] = 0xFC000000UL; // base address for the VRAM (64MB)
|
||||
this->finish_config_bars();
|
||||
|
||||
this->setup_bars({
|
||||
{0, 0xFFFFFFFFUL}, // I/O region (4 bytes but it's weird because bit 1 is set)
|
||||
{1, 0xFFFFF000UL}, // base address for the HW registers (4KB)
|
||||
{2, 0xFC000000UL} // base address for the VRAM (64MB)
|
||||
});
|
||||
|
||||
this->pci_notify_bar_change = [this](int bar_num) {
|
||||
this->notify_bar_change(bar_num);
|
||||
|
Loading…
Reference in New Issue
Block a user