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:
joevt 2023-02-05 00:37:29 -08:00
parent fd2e6c5b09
commit b472123746
9 changed files with 31 additions and 27 deletions

View File

@ -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()

View File

@ -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. */

View File

@ -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);

View File

@ -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);

View File

@ -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",

View File

@ -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"));

View File

@ -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"));

View File

@ -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)));

View File

@ -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"));