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 */
|
/** finds the position of the bit that is set */
|
||||||
#define WHAT_BIT_SET(val) (MultiplyDeBruijnBitPosition2[(uint32_t)(val * 0x077CB531U) >> 27])
|
#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)
|
BanditPciDevice::BanditPciDevice(int bridge_num, std::string name, int dev_id, int rev)
|
||||||
: PCIDevice(name)
|
: 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
|
return 0xFFFFFFFFUL; // PCI spec §6.1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->dev_map.count(idsel)) {
|
if (this->dev_map.count(IDSEL_TO_DEV_FUN(idsel))) {
|
||||||
AccessDetails details;
|
AccessDetails details;
|
||||||
details.offset = offset & 3;
|
details.offset = offset & 3;
|
||||||
details.size = size;
|
details.size = size;
|
||||||
details.flags = PCI_CONFIG_TYPE_0 | PCI_CONFIG_READ;
|
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);
|
return pci_conv_rd_data(result, details);
|
||||||
} else {
|
} else {
|
||||||
LOG_F(
|
LOG_F(
|
||||||
ERROR, "%s err: read attempt from non-existing PCI device ??:%02x.%x @%02x",
|
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
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->dev_map.count(idsel)) {
|
if (this->dev_map.count(IDSEL_TO_DEV_FUN(idsel))) {
|
||||||
AccessDetails details;
|
AccessDetails details;
|
||||||
details.offset = offset & 3;
|
details.offset = offset & 3;
|
||||||
details.size = size;
|
details.size = size;
|
||||||
details.flags = PCI_CONFIG_TYPE_0 | PCI_CONFIG_WRITE;
|
details.flags = PCI_CONFIG_TYPE_0 | PCI_CONFIG_WRITE;
|
||||||
|
|
||||||
if (size == 4 && !details.offset) { // aligned DWORD writes -> fast path
|
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
|
} 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);
|
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 {
|
} else {
|
||||||
LOG_F(
|
LOG_F(
|
||||||
ERROR, "%s err: write attempt to non-existing PCI device ??:%02x.%x @%02x",
|
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;
|
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>(
|
this->my_pci_device = unique_ptr<BanditPciDevice>(
|
||||||
new BanditPciDevice(bridge_num, name, dev_id, rev)
|
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()
|
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 <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#define BANDIT_DEV (11) // Bandit's own device number
|
||||||
#define BANDIT_CAR_TYPE (1 << 0) // Bandit config address type bit
|
#define BANDIT_CAR_TYPE (1 << 0) // Bandit config address type bit
|
||||||
|
|
||||||
/* Convenient macros for parsing CONFIG_ADDR fields. */
|
/* 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>
|
#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
|
// return false if dev_num already registered
|
||||||
if (this->dev_map.count(dev_num))
|
if (this->dev_map.count(dev_fun_num))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this->dev_map[dev_num] = dev_instance;
|
this->dev_map[dev_fun_num] = dev_instance;
|
||||||
|
|
||||||
dev_instance->set_host(this);
|
dev_instance->set_host(this);
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@ typedef struct AccessDetails {
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
} AccessDetails;
|
} AccessDetails;
|
||||||
|
|
||||||
|
#define DEV_FUN(dev_num,fun_num) (((dev_num) << 3) | (fun_num))
|
||||||
|
|
||||||
class PCIDevice; // forward declaration to prevent errors
|
class PCIDevice; // forward declaration to prevent errors
|
||||||
|
|
||||||
class PCIHost {
|
class PCIHost {
|
||||||
|
@ -58,7 +60,7 @@ public:
|
||||||
};
|
};
|
||||||
~PCIHost() = default;
|
~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_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);
|
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;
|
this->status = 0x80;
|
||||||
|
|
||||||
// assign PCI device number zero to myself
|
// 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 PCI/ISA I/O space, 64K for now
|
||||||
add_mmio_region(0xFE000000, 0x10000, this);
|
add_mmio_region(0xFE000000, 0x10000, this);
|
||||||
|
@ -62,7 +62,7 @@ int MPC106::device_postinit()
|
||||||
std::string pci_dev_name;
|
std::string pci_dev_name;
|
||||||
|
|
||||||
static const std::map<std::string, int> pci_slots = {
|
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) {
|
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
|
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;
|
AccessDetails details;
|
||||||
details.offset = offset & 3;
|
details.offset = offset & 3;
|
||||||
details.size = size;
|
details.size = size;
|
||||||
details.flags = PCI_CONFIG_TYPE_0 | PCI_CONFIG_READ;
|
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);
|
return pci_conv_rd_data(result, details);
|
||||||
} else {
|
} else {
|
||||||
LOG_F(ERROR, "%s: read attempt from non-existing PCI device ??:%02x.%x @%02x",
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->dev_map.count(dev_num)) {
|
if (this->dev_map.count(DEV_FUN(dev_num,fun_num))) {
|
||||||
AccessDetails details;
|
AccessDetails details;
|
||||||
details.offset = offset & 3;
|
details.offset = offset & 3;
|
||||||
details.size = size;
|
details.size = size;
|
||||||
details.flags = PCI_CONFIG_TYPE_0 | PCI_CONFIG_WRITE;
|
details.flags = PCI_CONFIG_TYPE_0 | PCI_CONFIG_WRITE;
|
||||||
|
|
||||||
if (size == 4 && !details.offset) { // aligned DWORD writes -> fast path
|
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
|
} 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);
|
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 {
|
} else {
|
||||||
LOG_F(ERROR, "%s: write attempt to non-existing PCI device ??:%02x.%x @%02x",
|
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
|
// add the GrandCentral I/O controller
|
||||||
pci_host->pci_register_device(
|
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
|
// get (raw) pointer to the memory controller
|
||||||
platinum_obj = dynamic_cast<PlatinumCtrl*>(gMachineObj->get_comp_by_name("Platinum"));
|
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
|
// register O'Hare I/O controller with the main PCI bus
|
||||||
pci_host->pci_register_device(
|
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"));
|
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
|
// add pci devices
|
||||||
grackle_obj->pci_register_device(
|
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(
|
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
|
// add Athens clock generator device and register it with the I2C host
|
||||||
gMachineObj->add_device("Athens", std::unique_ptr<AthensClocks>(new AthensClocks(0x28)));
|
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
|
// connect GrandCentral I/O controller to the PCI1 bus
|
||||||
pci_host->pci_register_device(
|
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
|
// get video PCI controller object
|
||||||
PCIHost *vci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("Chaos"));
|
PCIHost *vci_host = dynamic_cast<PCIHost*>(gMachineObj->get_comp_by_name("Chaos"));
|
||||||
|
|
||||||
// connect built-in video device to the VCI bus
|
// connect built-in video device to the VCI bus
|
||||||
vci_host->pci_register_device(
|
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
|
// get (raw) pointer to the memory controller
|
||||||
memctrl_obj = dynamic_cast<HammerheadCtrl*>(gMachineObj->get_comp_by_name("Hammerhead"));
|
memctrl_obj = dynamic_cast<HammerheadCtrl*>(gMachineObj->get_comp_by_name("Hammerhead"));
|
||||||
|
|
Loading…
Reference in New Issue