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