mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-11 05:29:43 +00:00
Standardize PCIDevice slot_id for PCIHost.
PCIHost - PCIHosts (bandit and grackle) now use device number and function number for identifying attached PCIDevices. A macro DEV_FUN is added to calculate this new slot_id. Bandit no longer uses IDSEL. Grackle no longer uses only device number. machinecatalyst, machinegossamer, machinetnt - Use DEV_FUN to attach PCI devices by device number and function number.
This commit is contained in:
parent
fd2e6c5b09
commit
b472123746
@ -39,6 +39,7 @@ const int MultiplyDeBruijnBitPosition2[] =
|
||||
|
||||
/** finds the position of the bit that is set */
|
||||
#define WHAT_BIT_SET(val) (MultiplyDeBruijnBitPosition2[(uint32_t)(val * 0x077CB531U) >> 27])
|
||||
#define IDSEL_TO_DEV_FUN(idsel) DEV_FUN(WHAT_BIT_SET(idsel) + 11,0)
|
||||
|
||||
BanditPciDevice::BanditPciDevice(int bridge_num, std::string name, int dev_id, int rev)
|
||||
: PCIDevice(name)
|
||||
@ -159,18 +160,18 @@ uint32_t BanditHost::read(uint32_t rgn_start, uint32_t offset, int size)
|
||||
return 0xFFFFFFFFUL; // PCI spec §6.1
|
||||
}
|
||||
|
||||
if (this->dev_map.count(idsel)) {
|
||||
if (this->dev_map.count(IDSEL_TO_DEV_FUN(idsel))) {
|
||||
AccessDetails details;
|
||||
details.offset = offset & 3;
|
||||
details.size = size;
|
||||
details.flags = PCI_CONFIG_TYPE_0 | PCI_CONFIG_READ;
|
||||
|
||||
result = this->dev_map[idsel]->pci_cfg_read(REG_NUM(), details);
|
||||
result = this->dev_map[IDSEL_TO_DEV_FUN(idsel)]->pci_cfg_read(REG_NUM(), details);
|
||||
return pci_conv_rd_data(result, details);
|
||||
} else {
|
||||
LOG_F(
|
||||
ERROR, "%s err: read attempt from non-existing PCI device ??:%02x.%x @%02x",
|
||||
this->name.c_str(), WHAT_BIT_SET(idsel) + 11, FUN_NUM(), REG_NUM() + (offset & 3)
|
||||
this->name.c_str(), IDSEL_TO_DEV_FUN(idsel), FUN_NUM(), REG_NUM() + (offset & 3)
|
||||
);
|
||||
return 0xFFFFFFFFUL; // PCI spec §6.1
|
||||
}
|
||||
@ -215,23 +216,23 @@ void BanditHost::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->dev_map.count(idsel)) {
|
||||
if (this->dev_map.count(IDSEL_TO_DEV_FUN(idsel))) {
|
||||
AccessDetails details;
|
||||
details.offset = offset & 3;
|
||||
details.size = size;
|
||||
details.flags = PCI_CONFIG_TYPE_0 | PCI_CONFIG_WRITE;
|
||||
|
||||
if (size == 4 && !details.offset) { // aligned DWORD writes -> fast path
|
||||
this->dev_map[idsel]->pci_cfg_write(REG_NUM(), BYTESWAP_32(value), details);
|
||||
this->dev_map[IDSEL_TO_DEV_FUN(idsel)]->pci_cfg_write(REG_NUM(), BYTESWAP_32(value), details);
|
||||
} else { // otherwise perform necessary data transformations -> slow path
|
||||
uint32_t old_val = this->dev_map[idsel]->pci_cfg_read(REG_NUM(), details);
|
||||
uint32_t old_val = this->dev_map[IDSEL_TO_DEV_FUN(idsel)]->pci_cfg_read(REG_NUM(), details);
|
||||
uint32_t new_val = pci_conv_wr_data(old_val, value, details);
|
||||
this->dev_map[idsel]->pci_cfg_write(REG_NUM(), new_val, details);
|
||||
this->dev_map[IDSEL_TO_DEV_FUN(idsel)]->pci_cfg_write(REG_NUM(), new_val, details);
|
||||
}
|
||||
} else {
|
||||
LOG_F(
|
||||
ERROR, "%s err: write attempt to non-existing PCI device ??:%02x.%x @%02x",
|
||||
this->name.c_str(), WHAT_BIT_SET(idsel) + 11, FUN_NUM(), REG_NUM() + (offset & 3)
|
||||
this->name.c_str(), IDSEL_TO_DEV_FUN(idsel), FUN_NUM(), REG_NUM() + (offset & 3)
|
||||
);
|
||||
}
|
||||
break;
|
||||
@ -276,7 +277,7 @@ Bandit::Bandit(int bridge_num, std::string name, int dev_id, int rev)
|
||||
this->my_pci_device = unique_ptr<BanditPciDevice>(
|
||||
new BanditPciDevice(bridge_num, name, dev_id, rev)
|
||||
);
|
||||
this->pci_register_device(1, this->my_pci_device.get());
|
||||
this->pci_register_device(DEV_FUN(BANDIT_DEV,0), this->my_pci_device.get());
|
||||
}
|
||||
|
||||
Chaos::Chaos(std::string name) : BanditHost()
|
||||
|
@ -46,6 +46,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#define BANDIT_DEV (11) // Bandit's own device number
|
||||
#define BANDIT_CAR_TYPE (1 << 0) // Bandit config address type bit
|
||||
|
||||
/* Convenient macros for parsing CONFIG_ADDR fields. */
|
||||
|
@ -28,13 +28,13 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
bool PCIHost::pci_register_device(int dev_num, PCIDevice* dev_instance)
|
||||
bool PCIHost::pci_register_device(int dev_fun_num, PCIDevice* dev_instance)
|
||||
{
|
||||
// return false if dev_num already registered
|
||||
if (this->dev_map.count(dev_num))
|
||||
if (this->dev_map.count(dev_fun_num))
|
||||
return false;
|
||||
|
||||
this->dev_map[dev_num] = dev_instance;
|
||||
this->dev_map[dev_fun_num] = dev_instance;
|
||||
|
||||
dev_instance->set_host(this);
|
||||
|
||||
|
@ -48,6 +48,8 @@ typedef struct AccessDetails {
|
||||
uint8_t flags;
|
||||
} AccessDetails;
|
||||
|
||||
#define DEV_FUN(dev_num,fun_num) (((dev_num) << 3) | (fun_num))
|
||||
|
||||
class PCIDevice; // forward declaration to prevent errors
|
||||
|
||||
class PCIHost {
|
||||
@ -58,7 +60,7 @@ public:
|
||||
};
|
||||
~PCIHost() = default;
|
||||
|
||||
virtual bool pci_register_device(int dev_num, PCIDevice* dev_instance);
|
||||
virtual bool pci_register_device(int dev_fun_num, PCIDevice* dev_instance);
|
||||
|
||||
virtual bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj);
|
||||
virtual bool pci_unregister_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj);
|
||||
|
@ -48,7 +48,7 @@ MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle"), PCIHost()
|
||||
this->status = 0x80;
|
||||
|
||||
// assign PCI device number zero to myself
|
||||
this->pci_register_device(0, this);
|
||||
this->pci_register_device(DEV_FUN(0,0), this);
|
||||
|
||||
// add PCI/ISA I/O space, 64K for now
|
||||
add_mmio_region(0xFE000000, 0x10000, this);
|
||||
@ -62,7 +62,7 @@ int MPC106::device_postinit()
|
||||
std::string pci_dev_name;
|
||||
|
||||
static const std::map<std::string, int> pci_slots = {
|
||||
{"pci_A1", 0xD}, {"pci_B1", 0xE}, {"pci_C1", 0xF}
|
||||
{"pci_A1", DEV_FUN(0xD,0)}, {"pci_B1", DEV_FUN(0xE,0)}, {"pci_C1", DEV_FUN(0xF,0)}
|
||||
};
|
||||
|
||||
for (auto& slot : pci_slots) {
|
||||
@ -131,12 +131,12 @@ uint32_t MPC106::pci_read(uint32_t offset, uint32_t size) {
|
||||
return 0xFFFFFFFFUL; // PCI spec §6.1
|
||||
}
|
||||
|
||||
if (this->dev_map.count(dev_num)) {
|
||||
if (this->dev_map.count(DEV_FUN(dev_num,fun_num))) {
|
||||
AccessDetails details;
|
||||
details.offset = offset & 3;
|
||||
details.size = size;
|
||||
details.flags = PCI_CONFIG_TYPE_0 | PCI_CONFIG_READ;
|
||||
uint32_t result = this->dev_map[dev_num]->pci_cfg_read(reg_offs, details);
|
||||
uint32_t result = this->dev_map[DEV_FUN(dev_num,fun_num)]->pci_cfg_read(reg_offs, details);
|
||||
return pci_conv_rd_data(result, details);
|
||||
} else {
|
||||
LOG_F(ERROR, "%s: read attempt from non-existing PCI device ??:%02x.%x @%02x",
|
||||
@ -158,18 +158,18 @@ void MPC106::pci_write(uint32_t offset, uint32_t value, uint32_t size) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->dev_map.count(dev_num)) {
|
||||
if (this->dev_map.count(DEV_FUN(dev_num,fun_num))) {
|
||||
AccessDetails details;
|
||||
details.offset = offset & 3;
|
||||
details.size = size;
|
||||
details.flags = PCI_CONFIG_TYPE_0 | PCI_CONFIG_WRITE;
|
||||
|
||||
if (size == 4 && !details.offset) { // aligned DWORD writes -> fast path
|
||||
this->dev_map[dev_num]->pci_cfg_write(reg_offs, BYTESWAP_32(value), details);
|
||||
this->dev_map[DEV_FUN(dev_num,fun_num)]->pci_cfg_write(reg_offs, BYTESWAP_32(value), details);
|
||||
} else { // otherwise perform necessary data transformations -> slow path
|
||||
uint32_t old_val = this->dev_map[dev_num]->pci_cfg_read(reg_offs, details);
|
||||
uint32_t old_val = this->dev_map[DEV_FUN(dev_num,fun_num)]->pci_cfg_read(reg_offs, details);
|
||||
uint32_t new_val = pci_conv_wr_data(old_val, value, details);
|
||||
this->dev_map[dev_num]->pci_cfg_write(reg_offs, new_val, details);
|
||||
this->dev_map[DEV_FUN(dev_num,fun_num)]->pci_cfg_write(reg_offs, new_val, details);
|
||||
}
|
||||
} else {
|
||||
LOG_F(ERROR, "%s: write attempt to non-existing PCI device ??:%02x.%x @%02x",
|
||||
|
@ -44,7 +44,7 @@ int initialize_catalyst(std::string& id)
|
||||
|
||||
// add the GrandCentral I/O controller
|
||||
pci_host->pci_register_device(
|
||||
32, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("GrandCentral")));
|
||||
DEV_FUN(0x10,0), dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("GrandCentral")));
|
||||
|
||||
// get (raw) pointer to the memory controller
|
||||
platinum_obj = dynamic_cast<PlatinumCtrl*>(gMachineObj->get_comp_by_name("Platinum"));
|
||||
|
@ -53,7 +53,7 @@ int initialize_gazelle(std::string& id)
|
||||
|
||||
// register O'Hare I/O controller with the main PCI bus
|
||||
pci_host->pci_register_device(
|
||||
32, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("OHare")));
|
||||
DEV_FUN(0x10,0), dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("OHare")));
|
||||
|
||||
PsxCtrl* psx_obj = dynamic_cast<PsxCtrl*>(gMachineObj->get_comp_by_name("Psx"));
|
||||
|
||||
|
@ -124,9 +124,9 @@ int initialize_gossamer(std::string& id)
|
||||
|
||||
// add pci devices
|
||||
grackle_obj->pci_register_device(
|
||||
16, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("Heathrow")));
|
||||
DEV_FUN(0x10,0), dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("Heathrow")));
|
||||
grackle_obj->pci_register_device(
|
||||
18, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name(id == "pmg3twr" ? "AtiRagePro" : "AtiRageGT")));
|
||||
DEV_FUN(0x12,0), dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name(id == "pmg3twr" ? "AtiRagePro" : "AtiRageGT")));
|
||||
|
||||
// add Athens clock generator device and register it with the I2C host
|
||||
gMachineObj->add_device("Athens", std::unique_ptr<AthensClocks>(new AthensClocks(0x28)));
|
||||
|
@ -44,14 +44,14 @@ int initialize_tnt(std::string& id)
|
||||
|
||||
// connect GrandCentral I/O controller to the PCI1 bus
|
||||
pci_host->pci_register_device(
|
||||
32, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("GrandCentral")));
|
||||
DEV_FUN(0x10,0), dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("GrandCentral")));
|
||||
|
||||
// get video PCI controller object
|
||||
PCIHost *vci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("Chaos"));
|
||||
|
||||
// connect built-in video device to the VCI bus
|
||||
vci_host->pci_register_device(
|
||||
1, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("ControlVideo")));
|
||||
DEV_FUN(0x0B,0), dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("ControlVideo")));
|
||||
|
||||
// get (raw) pointer to the memory controller
|
||||
memctrl_obj = dynamic_cast<HammerheadCtrl*>(gMachineObj->get_comp_by_name("Hammerhead"));
|
||||
|
Loading…
x
Reference in New Issue
Block a user