diff --git a/devices/common/pci/bandit.cpp b/devices/common/pci/bandit.cpp
index 4358c5e..64c2b60 100644
--- a/devices/common/pci/bandit.cpp
+++ b/devices/common/pci/bandit.cpp
@@ -41,9 +41,11 @@ const int MultiplyDeBruijnBitPosition2[] =
#define WHAT_BIT_SET(val) (MultiplyDeBruijnBitPosition2[(uint32_t)(val * 0x077CB531U) >> 27])
Bandit::Bandit(int bridge_num, std::string name, int dev_id, int rev)
- : PCIHost(), PCIDevice(name)
+ : BanditHost()
{
- supports_types(HWCompType::PCI_HOST | HWCompType::PCI_DEV);
+ this->name = name;
+
+ supports_types(HWCompType::PCI_HOST);
this->base_addr = 0xF0000000 + ((bridge_num & 3) << 25);
@@ -58,6 +60,15 @@ Bandit::Bandit(int bridge_num, std::string name, int dev_id, int rev)
// base_addr + 0x1000000 --> pass-through memory space (not included below)
mem_ctrl->add_mmio_region(base_addr, 0x01000000, this);
+ std::string banditpcitname = "Bandit1PCI";
+ attach_pci_device(banditpcitname, 1);
+}
+
+BanditPCI::BanditPCI(int bridge_num, std::string name)
+ : PCIDevice(name)
+{
+ supports_types(HWCompType::PCI_DEV);
+
// prepare the PCI config header
this->vendor_id = PCI_VENDOR_APPLE;
this->device_id = 0x0001;
@@ -80,195 +91,149 @@ Bandit::Bandit(int bridge_num, std::string name, int dev_id, int rev)
this->rd_hold_off_cnt = 8;
}
-uint32_t Bandit::pci_cfg_read(uint32_t reg_offs, uint32_t size)
+uint32_t BanditPCI::pci_cfg_read(uint32_t reg_offs, AccessDetails &details)
{
if (reg_offs < 64) {
- return PCIDevice::pci_cfg_read(reg_offs, size);
+ return PCIDevice::pci_cfg_read(reg_offs, details);
}
switch (reg_offs) {
case BANDIT_ADDR_MASK:
- return BYTESWAP_32(this->addr_mask);
+ return this->addr_mask;
case BANDIT_MODE_SELECT:
- return BYTESWAP_32(this->mode_ctrl);
+ return this->mode_ctrl;
case BANDIT_ARBUS_RD_HOLD_OFF:
- return BYTESWAP_32(this->rd_hold_off_cnt);
- default:
- LOG_F(WARNING, "%s: reading from unimplemented config register at 0x%X",
- this->pci_name.c_str(), reg_offs);
+ return this->rd_hold_off_cnt;
}
-
+ LOG_READ_UNIMPLEMENTED_CONFIG_REGISTER();
return 0;
}
-void Bandit::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
+void BanditPCI::pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &details)
{
if (reg_offs < 64) {
- PCIDevice::pci_cfg_write(reg_offs, value, size);
+ PCIDevice::pci_cfg_write(reg_offs, value, details);
return;
}
- if (size == 4) {
- value = BYTESWAP_32(value);
- } else {
- LOG_F(WARNING, "%s: non-DWORD writes to the control registers not supported",
- this->pci_name.c_str());
- }
-
switch (reg_offs) {
case BANDIT_ADDR_MASK:
this->addr_mask = value;
this->verbose_address_space();
- break;
+ return;
case BANDIT_MODE_SELECT:
this->mode_ctrl = value;
- break;
+ return;
case BANDIT_ARBUS_RD_HOLD_OFF:
- this->rd_hold_off_cnt = value & 0x1F;
- break;
- default:
- LOG_F(WARNING, "%s: writing to unimplemented config register at 0x%X",
- this->pci_name.c_str(), reg_offs);
+ this->rd_hold_off_cnt = value & 0x1F;
+ return;
+ }
+ LOG_WRITE_UNIMPLEMENTED_CONFIG_REGISTER();
+}
+
+void BanditHost::cfg_setup(uint32_t offset, int size, int &bus_num, int &dev_num, int &fun_num, uint8_t ®_offs, AccessDetails &details, PCIDevice *&device)
+{
+ device = NULL;
+ details.size = size;
+ details.offset = offset & 3;
+ fun_num = (this->config_addr >> 8) & 7;
+ reg_offs = this->config_addr & 0xFCU;
+ if (this->config_addr & BANDIT_CAR_TYPE) { // type 1 configuration command
+ details.flags = PCI_CONFIG_TYPE_1;
+ bus_num = (this->config_addr >> 16) & 255;
+ dev_num = (this->config_addr >> 11) & 31;
+ device = pci_find_device(bus_num, dev_num, fun_num);
+ return;
+ }
+ details.flags = PCI_CONFIG_TYPE_0;
+ bus_num = 0; // bus number is meaningless for type 0 configuration command; a type 1 configuration command cannot reach devices attached directly to the host
+ uint32_t idsel = this->config_addr & 0xFFFFF800U;
+ if (!SINGLE_BIT_SET(idsel)) {
+ for (dev_num = -1, idsel = this->config_addr; idsel; idsel >>= 1, dev_num++) {}
+ LOG_F(ERROR, "%s: config_addr 0x%08x does not contain valid IDSEL", this->name.c_str(), (uint32_t)this->config_addr);
+ return;
+ }
+ dev_num = WHAT_BIT_SET(idsel);
+ if (this->dev_map.count(idsel >> 11)) {
+ device = this->dev_map[idsel >> 11];
}
}
-uint32_t Bandit::read(uint32_t rgn_start, uint32_t offset, int size)
+uint32_t BanditHost::read(uint32_t rgn_start, uint32_t offset, int size)
{
- int bus_num, dev_num, fun_num;
- uint8_t reg_offs;
- uint32_t result, idsel;
+ switch (offset >> 22) {
- if (offset & BANDIT_CONFIG_SPACE) {
- if (offset & 0x00400000) {
- fun_num = (this->config_addr >> 8) & 7;
- reg_offs = this->config_addr & 0xFCU;
-
- // access to the CONFIG_DATA pseudo-register causes a Config Cycle
- if (this->config_addr & BANDIT_CAR_TYPE) {
- bus_num = (this->config_addr >> 16) & 255;
- dev_num = (this->config_addr >> 11) & 31;
- LOG_F(
- WARNING, "%s: read config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c",
- this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
- );
- return 0xFFFFFFFFUL; // PCI spec §6.1
+ case 3: // 0xC00000 // CONFIG_DATA
+ int bus_num, dev_num, fun_num;
+ uint8_t reg_offs;
+ AccessDetails details;
+ PCIDevice *device;
+ cfg_setup(offset, size, bus_num, dev_num, fun_num, reg_offs, details, device);
+ details.flags |= PCI_CONFIG_READ;
+ if (device) {
+ return pci_cfg_rev_read(device->pci_cfg_read(reg_offs, details), details);
}
+ LOG_READ_NON_EXISTENT_PCI_DEVICE();
+ return 0xFFFFFFFFUL; // PCI spec §6.1
- idsel = (this->config_addr >> 11) & 0x1FFFFFU;
+ case 2: // 0x800000 // CONFIG_ADDR
+ return this->config_addr;
- if (!SINGLE_BIT_SET(idsel)) {
- LOG_F(
- ERROR, "%s: read invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c",
- this->name.c_str(), idsel, this->config_addr,
- fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
- );
- return 0xFFFFFFFFUL; // PCI spec §6.1
- }
-
- if (idsel == BANDIT_ID_SEL) { // access to myself
- result = this->pci_cfg_read(reg_offs, size);
- } else {
- if (this->dev_map.count(idsel)) {
- result = this->dev_map[idsel]->pci_cfg_read(reg_offs, size);
- } else {
- dev_num = WHAT_BIT_SET(idsel) + 11;
- LOG_F(
- ERROR, "%s err: read attempt from non-existing PCI device ??:%02x.%x @%02x.%c",
- this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
- );
- return 0xFFFFFFFFUL; // PCI spec §6.1
+ default: // 0x000000 // I/O space
+ {
+ uint32_t result;
+ // broadcast I/O request to devices that support I/O space
+ // until a device returns true that means "request accepted"
+ for (auto& dev : this->io_space_devs) {
+ if (dev->pci_io_read(offset, size, &result)) {
+ return result;
}
}
- } else {
- result = this->config_addr;
+ LOG_F(ERROR, "%s: attempt to read from unmapped PCI I/O space, offset=0x%X",
+ this->name.c_str(), offset);
+ return 0;
}
- } else { // I/O space access
- // broadcast I/O request to devices that support I/O space
- // until a device returns true that means "request accepted"
- for (auto& dev : this->io_space_devs) {
- if (dev->pci_io_read(offset, size, &result)) {
- return result;
- }
- }
- LOG_F(ERROR, "%s: attempt to read from unmapped PCI I/O space, offset=0x%X",
- this->name.c_str(), offset);
}
- return result;
}
-void Bandit::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size)
+void BanditHost::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size)
{
- int bus_num, dev_num, fun_num;
- uint8_t reg_offs;
- uint32_t idsel;
+ switch (offset >> 22) {
- if (offset & BANDIT_CONFIG_SPACE) {
- if (offset & 0x00400000) {
- fun_num = (this->config_addr >> 8) & 7;
- reg_offs = this->config_addr & 0xFCU;
-
- // access to the CONFIG_DATA pseudo-register causes a Config Cycle
- if (this->config_addr & BANDIT_CAR_TYPE) {
- bus_num = (this->config_addr >> 16) & 255;
- dev_num = (this->config_addr >> 11) & 31;
- LOG_F(
- WARNING, "%s: write config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c = %0*x",
- this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
- size * 2, BYTESWAP_SIZED(value, size)
- );
+ case 3: // 0xC00000 // CONFIG_DATA
+ int bus_num, dev_num, fun_num;
+ uint8_t reg_offs;
+ AccessDetails details;
+ PCIDevice *device;
+ cfg_setup(offset, size, bus_num, dev_num, fun_num, reg_offs, details, device);
+ details.flags |= PCI_CONFIG_WRITE;
+ if (device) {
+ uint32_t oldvalue = details.size == 4 ? 0 : device->pci_cfg_read(reg_offs, details);
+ value = pci_cfg_rev_write(oldvalue, details, value);
+ device->pci_cfg_write(reg_offs, value, details);
return;
}
+ LOG_WRITE_NON_EXISTENT_PCI_DEVICE();
+ break;
- idsel = (this->config_addr >> 11) & 0x1FFFFFU;
-
- if (!SINGLE_BIT_SET(idsel)) {
- LOG_F(
- ERROR, "%s: write invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c = %0*x",
- this->name.c_str(), idsel, this->config_addr,
- fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
- size * 2, BYTESWAP_SIZED(value, size)
- );
- return;
- }
-
- if (idsel == BANDIT_ID_SEL) { // access to myself
- this->pci_cfg_write(reg_offs, value, size);
- return;
- }
-
- if (this->dev_map.count(idsel)) {
- this->dev_map[idsel]->pci_cfg_write(reg_offs, value, size);
- } else {
- dev_num = WHAT_BIT_SET(idsel) + 11;
- LOG_F(
- ERROR, "%s err: write attempt to non-existing PCI device ??:%02x.%x @%02x.%c = %0*x",
- this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
- size * 2, BYTESWAP_SIZED(value, size)
- );
- }
- } else {
+ case 2: // 0x800000 // CONFIG_ADDR
this->config_addr = BYTESWAP_32(value);
- }
- } else { // I/O space access
- // broadcast I/O request to devices that support I/O space
- // until a device returns true that means "request accepted"
- for (auto& dev : this->io_space_devs) {
- if (dev->pci_io_write(offset, value, size)) {
- return;
+ break;
+
+ default: // 0x000000 // I/O space
+ // broadcast I/O request to devices that support I/O space
+ // until a device returns true that means "request accepted"
+ for (auto& dev : this->io_space_devs) {
+ if (dev->pci_io_write(offset, value, size)) {
+ return;
+ }
}
- }
- LOG_F(ERROR, "%s: attempt to write to unmapped PCI I/O space, offset=0x%X",
- this->name.c_str(), offset);
+ LOG_F(ERROR, "%s: attempt to write to unmapped PCI I/O space, offset=0x%X",
+ this->name.c_str(), offset);
}
}
-void Bandit::verbose_address_space()
+void BanditPCI::verbose_address_space()
{
uint32_t mask;
int bit_pos;
@@ -296,7 +261,7 @@ void Bandit::verbose_address_space()
}
}
-Chaos::Chaos(std::string name) : PCIHost()
+Chaos::Chaos(std::string name) : BanditHost()
{
this->name = name;
@@ -312,118 +277,6 @@ Chaos::Chaos(std::string name) : PCIHost()
mem_ctrl->add_mmio_region(0xF0000000UL, 0x01000000, this);
}
-uint32_t Chaos::read(uint32_t rgn_start, uint32_t offset, int size)
-{
- int bus_num, dev_num, fun_num;
- uint8_t reg_offs;
- uint32_t result, idsel;
-
- if (offset & BANDIT_CONFIG_SPACE) {
- if (offset & 0x00400000) {
- fun_num = (this->config_addr >> 8) & 7;
- reg_offs = this->config_addr & 0xFCU;
-
- // access to the CONFIG_DATA pseudo-register causes a Config Cycle
- if (this->config_addr & BANDIT_CAR_TYPE) {
- bus_num = (this->config_addr >> 16) & 255;
- dev_num = (this->config_addr >> 11) & 31;
- LOG_F(
- WARNING, "%s: read config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c",
- this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
- );
- return 0xFFFFFFFFUL; // PCI spec §6.1
- }
-
- idsel = (this->config_addr >> 11) & 0x1FFFFFU;
-
- if (!SINGLE_BIT_SET(idsel)) {
- LOG_F(
- ERROR, "%s: read invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c",
- this->name.c_str(), idsel, this->config_addr,
- fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
- );
- return 0xFFFFFFFFUL; // PCI spec §6.1
- }
-
- if (this->dev_map.count(idsel)) {
- result = this->dev_map[idsel]->pci_cfg_read(reg_offs, size);
- } else {
- dev_num = WHAT_BIT_SET(idsel) + 11;
- LOG_F(
- ERROR, "%s err: read attempt from non-existing VCI device ??:%02x.%x @%02x.%c",
- this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
- );
- return 0xFFFFFFFFUL; // PCI spec §6.1
- }
- } else {
- result = this->config_addr;
- }
- } else { // I/O space access
- LOG_F(ERROR, "%s: I/O space not supported", this->name.c_str());
- return 0;
- }
- return result;
-}
-
-void Chaos::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size)
-{
- int bus_num, dev_num, fun_num;
- uint8_t reg_offs;
- uint32_t idsel;
-
- if (offset & BANDIT_CONFIG_SPACE) {
- if (offset & 0x00400000) {
- fun_num = (this->config_addr >> 8) & 7;
- reg_offs = this->config_addr & 0xFCU;
-
- // access to the CONFIG_DATA pseudo-register causes a Config Cycle
- if (this->config_addr & BANDIT_CAR_TYPE) {
- bus_num = (this->config_addr >> 16) & 255;
- dev_num = (this->config_addr >> 11) & 31;
- LOG_F(
- WARNING, "%s: write config cycle type 1 not supported yet %02x:%02x.%x @%02x.%c = %0*x",
- this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
- size * 2, BYTESWAP_SIZED(value, size)
- );
- return;
- }
-
- idsel = (this->config_addr >> 11) & 0x1FFFFFU;
-
- if (!SINGLE_BIT_SET(idsel)) {
- LOG_F(
- ERROR, "%s: write invalid IDSEL=0x%X config:0x%X ??:??.%x? @%02x?.%c = %0*x",
- this->name.c_str(), idsel, this->config_addr,
- fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
- size * 2, BYTESWAP_SIZED(value, size)
- );
- return;
- }
-
- if (this->dev_map.count(idsel)) {
- this->dev_map[idsel]->pci_cfg_write(reg_offs, value, size);
- } else {
- dev_num = WHAT_BIT_SET(idsel) + 11;
- LOG_F(
- ERROR, "%s err: write attempt to non-existing VCI device ??:%02x.%x @%02x.%c = %0*x",
- this->name.c_str(), dev_num, fun_num, reg_offs + (offset & 3),
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
- size * 2, BYTESWAP_SIZED(value, size)
- );
- }
- } else {
- this->config_addr = BYTESWAP_32(value);
- }
- } else { // I/O space access
- LOG_F(ERROR, "%s: I/O space not supported", this->name.c_str());
- }
-}
-
static const DeviceDescription Bandit1_Descriptor = {
Bandit::create_first, {}, {}
};
@@ -436,6 +289,11 @@ static const DeviceDescription Chaos_Descriptor = {
Chaos::create, {}, {}
};
-REGISTER_DEVICE(Bandit1, Bandit1_Descriptor);
-REGISTER_DEVICE(PsxPci1, PsxPci1_Descriptor);
-REGISTER_DEVICE(Chaos, Chaos_Descriptor);
+static const DeviceDescription Bandit1PCI_Descriptor = {
+ BanditPCI::create_first, {}, {}
+};
+
+REGISTER_DEVICE(Bandit1 , Bandit1_Descriptor);
+REGISTER_DEVICE(Bandit1PCI, Bandit1PCI_Descriptor);
+REGISTER_DEVICE(PsxPci1 , PsxPci1_Descriptor);
+REGISTER_DEVICE(Chaos , Chaos_Descriptor);
diff --git a/devices/common/pci/bandit.h b/devices/common/pci/bandit.h
index edb991c7..4880014 100644
--- a/devices/common/pci/bandit.h
+++ b/devices/common/pci/bandit.h
@@ -38,7 +38,7 @@ along with this program. If not, see .
#include
#include
-#define BANDIT_ID_SEL (1 << 0) // Bandit's own IDSEL
+#define BANDIT_DEV (11) // Bandit's own device number
#define BANDIT_CAR_TYPE (1 << 0) // Bandit config address type bit
#define BANDIT_CONFIG_SPACE 0x00800000 // Bandit Config Space bit
@@ -52,7 +52,19 @@ enum {
/** checks if one bit is set at time, return 0 if not */
#define SINGLE_BIT_SET(val) ((val) && !((val) & ((val)-1)))
-class Bandit : public PCIHost, public PCIDevice {
+class BanditHost : public PCIHost, public MMIODevice {
+public:
+ void cfg_setup(uint32_t offset, int size, int &bus_num, int &dev_num, int &fun_num, uint8_t ®_offs, AccessDetails &details, PCIDevice *&device);
+
+ // MMIODevice methods
+ uint32_t read(uint32_t rgn_start, uint32_t offset, int size);
+ void write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size);
+
+protected:
+ uint32_t config_addr;
+};
+
+class Bandit : public BanditHost {
public:
Bandit(int bridge_num, std::string name, int dev_id=1, int rev=3);
~Bandit() = default;
@@ -65,19 +77,27 @@ public:
return std::unique_ptr(new Bandit(1, "PSX-PCI1", 8, 0));
};
- uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
- void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
+private:
+ uint32_t base_addr;
+};
- // MMIODevice methods
- uint32_t read(uint32_t rgn_start, uint32_t offset, int size);
- void write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size);
+class BanditPCI : public PCIDevice {
+public:
+ BanditPCI(int bridge_num, std::string name);
+ ~BanditPCI() = default;
+
+ static std::unique_ptr create_first() {
+ return std::unique_ptr(new BanditPCI(1, "BanditPCI"));
+ };
+ // PCIDevice methods
+ uint32_t pci_cfg_read(uint32_t reg_offs, AccessDetails &details);
+ void pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &details);
+
protected:
void verbose_address_space();
private:
- uint32_t base_addr;
- uint32_t config_addr;
uint32_t addr_mask;
uint32_t mode_ctrl; // controls various chip modes/features
uint32_t rd_hold_off_cnt;
@@ -88,7 +108,7 @@ private:
frequency as the CPU bus (40-50 MHz) and provides an interface
between video input/output devices and the CPU bus.
*/
-class Chaos : public PCIHost, public MMIODevice {
+class Chaos : public BanditHost {
public:
Chaos(std::string name);
~Chaos() = default;
@@ -96,13 +116,6 @@ public:
static std::unique_ptr create() {
return std::unique_ptr(new Chaos("VCI0"));
};
-
- // MMIODevice methods
- uint32_t read(uint32_t rgn_start, uint32_t offset, int size);
- void write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size);
-
-private:
- uint32_t config_addr;
};
#endif // BANDIT_PCI_H
diff --git a/devices/common/pci/pcidevice.cpp b/devices/common/pci/pcidevice.cpp
index bb03f66..615487c 100644
--- a/devices/common/pci/pcidevice.cpp
+++ b/devices/common/pci/pcidevice.cpp
@@ -50,81 +50,49 @@ PCIDevice::PCIDevice(std::string name)
this->pci_notify_bar_change = [](int bar_num) {};
};
-uint32_t PCIDevice::pci_cfg_read(uint32_t reg_offs, uint32_t size)
+uint32_t PCIDevice::pci_cfg_read(uint32_t reg_offs, AccessDetails &details)
{
- uint32_t result;
-
switch (reg_offs) {
case PCI_CFG_DEV_ID:
- result = (this->device_id << 16) | (this->vendor_id);
- break;
+ return (this->device_id << 16) | (this->vendor_id);
case PCI_CFG_STAT_CMD:
- result = (this->pci_rd_stat() << 16) | (this->pci_rd_cmd());
- break;
+ return (this->pci_rd_stat() << 16) | (this->pci_rd_cmd());
case PCI_CFG_CLASS_REV:
- result = this->class_rev;
- break;
+ return this->class_rev;
case PCI_CFG_DWORD_3:
- result = (pci_rd_bist() << 24) | (this->hdr_type << 16) |
- (pci_rd_lat_timer() << 8) | pci_rd_cache_lnsz();
- break;
+ return (pci_rd_bist() << 24) | (this->hdr_type << 16) |
+ (pci_rd_lat_timer() << 8) | pci_rd_cache_lnsz();
case PCI_CFG_BAR0:
case PCI_CFG_BAR1:
case PCI_CFG_BAR2:
case PCI_CFG_BAR3:
case PCI_CFG_BAR4:
case PCI_CFG_BAR5:
- result = this->bars[(reg_offs - 0x10) >> 2];
- break;
+ return this->bars[(reg_offs - 0x10) >> 2];
case PCI_CFG_SUBSYS_ID:
- result = (this->subsys_id << 16) | (this->subsys_vndr);
- break;
+ return (this->subsys_id << 16) | (this->subsys_vndr);
case PCI_CFG_ROM_BAR:
- result = this->exp_rom_bar;
- break;
+ return this->exp_rom_bar;
case PCI_CFG_DWORD_15:
- result = (max_lat << 24) | (min_gnt << 16) | (irq_pin << 8) | irq_line;
- break;
+ return (max_lat << 24) | (min_gnt << 16) | (irq_pin << 8) | irq_line;
case PCI_CFG_CAP_PTR:
- result = cap_ptr;
- break;
- default:
- LOG_F(
- WARNING, "%s: attempt to read from reserved/unimplemented register @%02x.%c",
- this->pci_name.c_str(), reg_offs,
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
- );
- return 0;
- }
-
- if (size == 4) {
- return BYTESWAP_32(result);
- } else {
- return read_mem_rev(((uint8_t *)&result) + (reg_offs & 3), size);
+ return cap_ptr;
}
+ LOG_READ_UNIMPLEMENTED_CONFIG_REGISTER();
+ return 0;
}
-void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
+void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &details)
{
- uint32_t data;
-
- if (size == 4) {
- data = BYTESWAP_32(value);
- } else {
- // get current register content as DWORD and update it partially
- data = BYTESWAP_32(this->pci_cfg_read(reg_offs, 4));
- write_mem_rev(((uint8_t *)&data) + (reg_offs & 3), value, size);
- }
-
switch (reg_offs) {
case PCI_CFG_STAT_CMD:
- this->pci_wr_stat(data >> 16);
- this->pci_wr_cmd(data & 0xFFFFU);
+ this->pci_wr_stat(value >> 16);
+ this->pci_wr_cmd(value & 0xFFFFU);
break;
case PCI_CFG_DWORD_3:
- this->pci_wr_bist(data >> 24);
- this->pci_wr_lat_timer((data >> 8) & 0xFF);
- this->pci_wr_cache_lnsz(data & 0xFF);
+ this->pci_wr_bist(value >> 24);
+ this->pci_wr_lat_timer((value >> 8) & 0xFF);
+ this->pci_wr_cache_lnsz(value & 0xFF);
break;
case PCI_CFG_BAR0:
case PCI_CFG_BAR1:
@@ -132,17 +100,17 @@ void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
case PCI_CFG_BAR3:
case PCI_CFG_BAR4:
case PCI_CFG_BAR5:
- if (data == 0xFFFFFFFFUL) {
+ if (value == 0xFFFFFFFFUL) {
this->do_bar_sizing((reg_offs - 0x10) >> 2);
} else {
- this->set_bar_value((reg_offs - 0x10) >> 2, data);
+ this->set_bar_value((reg_offs - 0x10) >> 2, value);
}
break;
case PCI_CFG_ROM_BAR:
- if ((data & this->exp_bar_cfg) == this->exp_bar_cfg) {
- this->exp_rom_bar = (data & (this->exp_bar_cfg | 1));
+ if ((value & this->exp_bar_cfg) == this->exp_bar_cfg) {
+ this->exp_rom_bar = (value & (this->exp_bar_cfg | 1));
} else {
- this->exp_rom_bar = (data & (this->exp_bar_cfg | 1));
+ this->exp_rom_bar = (value & (this->exp_bar_cfg | 1));
if (this->exp_rom_bar & 1) {
this->map_exp_rom_mem();
} else {
@@ -152,15 +120,10 @@ void PCIDevice::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
}
break;
case PCI_CFG_DWORD_15:
- this->irq_line = data >> 24;
+ this->irq_line = value >> 24;
break;
default:
- LOG_F(
- WARNING, "%s: attempt to write to reserved/unimplemented register @%02x.%c = %0*x",
- this->pci_name.c_str(), reg_offs,
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
- size * 2, BYTESWAP_SIZED(value, size)
- );
+ LOG_WRITE_UNIMPLEMENTED_CONFIG_REGISTER();
}
}
diff --git a/devices/common/pci/pcidevice.h b/devices/common/pci/pcidevice.h
index b1503a8..5ed7418 100644
--- a/devices/common/pci/pcidevice.h
+++ b/devices/common/pci/pcidevice.h
@@ -78,8 +78,8 @@ public:
};
// configuration space access methods
- virtual uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
- virtual void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
+ virtual uint32_t pci_cfg_read(uint32_t reg_offs, AccessDetails &details);
+ virtual void pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &details);
// plugin interface for using in the derived classes
std::function pci_rd_stat;
@@ -101,6 +101,10 @@ public:
this->host_instance = host_instance;
};
+ // MMIODevice methods
+ virtual uint32_t read(uint32_t rgn_start, uint32_t offset, int size) { return 0; }
+ 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);
@@ -137,4 +141,124 @@ protected:
std::unique_ptr exp_rom_data;
};
+/* value is dword from PCI config. MSB..LSB of value is stored in PCI config as 0:LSB..3:MSB.
+ result is part of value at byte offset from LSB with size bytes (with wrap around) and flipped as required for pci_cfg_read result. */
+inline uint32_t pci_cfg_rev_read(uint32_t value, AccessDetails &details) {
+ switch (details.size << 2 | details.offset) {
+ case 0x04: return value & 0xff; // 0
+ case 0x05: return (value >> 8) & 0xff; // 1
+ case 0x06: return (value >> 16) & 0xff; // 2
+ case 0x07: return (value >> 24) & 0xff; // 3
+
+ case 0x08: return ((value & 0xff) << 8) | ((value >> 8) & 0xff); // 0 1
+ case 0x09: return ( value & 0xff00) | ((value >> 16) & 0xff); // 1 2
+ case 0x0a: return ((value >> 8) & 0xff00) | ((value >> 24) & 0xff); // 2 3
+ case 0x0b: return ((value >> 16) & 0xff00) | ( value & 0xff); // 3 0
+
+ case 0x10: return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value >> 8) & 0xff00) | ((value >> 24) & 0xff); // 0 1 2 3
+ case 0x11: return ((value & 0xff00) << 16) | ( value & 0xff0000) | ((value >> 16) & 0xff00) | ( value & 0xff); // 1 2 3 0
+ case 0x12: return ((value & 0xff0000) << 8) | ((value >> 8) & 0xff0000) | ((value & 0xff) << 8) | ((value >> 8) & 0xff); // 2 3 0 1
+ case 0x13: return ( value & 0xff000000) | ((value & 0xff) << 16) | ( value & 0xff00) | ((value >> 16) & 0xff); // 3 0 1 2
+
+ default: return 0xffffffff;
+ }
+}
+
+/* value is dword from PCI config. MSB..LSB of value (3.2.1.0) is stored in PCI config as 0:LSB..3:MSB.
+ newvalue is flipped bytes (d0.d1.d2.d3, as passed to pci_cfg_write) to be merged into value.
+ result is part of value at byte offset from LSB with size bytes (with wrap around) modified by newvalue. */
+inline uint32_t pci_cfg_rev_write(uint32_t value, AccessDetails &details, uint32_t newvalue) {
+ switch (details.size << 2 | details.offset) {
+ case 0x04: return (value & 0xffffff00) | (newvalue & 0xff); // 3 2 1 d0
+ case 0x05: return (value & 0xffff00ff) | ((newvalue & 0xff) << 8); // 3 2 d0 0
+ case 0x06: return (value & 0xff00ffff) | ((newvalue & 0xff) << 16); // 3 d0 1 0
+ case 0x07: return (value & 0x00ffffff) | ((newvalue & 0xff) << 24); // d0 2 1 0
+
+ case 0x08: return (value & 0xffff0000) | ((newvalue >> 8) & 0xff) | ((newvalue & 0xff) << 8); // 3 2 d1 d0
+ case 0x09: return (value & 0xff0000ff) | (newvalue & 0xff00) | ((newvalue & 0xff) << 16); // 3 d1 d0 0
+ case 0x0a: return (value & 0x0000ffff) | ((newvalue & 0xff00) << 8) | ((newvalue & 0xff) << 24); // d1 d0 1 0
+ case 0x0b: return (value & 0x00ffff00) | ((newvalue & 0xff00) << 16) | (newvalue & 0xff); // d0 2 1 d1
+
+ case 0x10: return ((newvalue & 0xff) << 24) | ((newvalue & 0xff00) << 8) | ((newvalue >> 8) & 0xff00) | ((newvalue >> 24) & 0xff); // d3 d2 d1 d0
+ case 0x11: return ((newvalue & 0xff00) << 16) | ( newvalue & 0xff0000) | ((newvalue >> 16) & 0xff00) | ( newvalue & 0xff); // d2 d1 d0 d3
+ case 0x12: return ((newvalue & 0xff0000) << 8) | ((newvalue >> 8) & 0xff0000) | ((newvalue & 0xff) << 8) | ((newvalue >> 8) & 0xff); // d1 d0 d3 d2
+ case 0x13: return ( newvalue & 0xff000000) | ((newvalue & 0xff) << 16) | ( newvalue & 0xff00) | ((newvalue >> 16) & 0xff); // d0 d3 d2 d1
+
+ default: return 0xffffffff;
+ }
+}
+
+inline uint32_t pci_cfg_log(uint32_t value, AccessDetails &details) {
+ switch (details.size << 2 | details.offset) {
+ case 0x04: return (uint8_t) value;
+ case 0x05: return (uint8_t)(value >> 8);
+ case 0x06: return (uint8_t)(value >> 16);
+ case 0x07: return (uint8_t)(value >> 24);
+
+ case 0x08: return (uint16_t) value;
+ case 0x09: return (uint16_t) (value >> 8);
+ case 0x0a: return (uint16_t) (value >> 16);
+ case 0x0b: return (uint16_t)((value >> 24) | (value << 8));
+
+ case 0x10: return value;
+ case 0x11: return (value >> 8) | (value << 24);
+ case 0x12: return (value >> 16) | (value << 16);
+ case 0x13: return (value >> 24) | (value << 8);
+
+ default: return 0xffffffff;
+ }
+}
+
+#define SIZE_ARGS details.size == 4 ? 'l' : details.size == 2 ? 'w' : details.size == 1 ? 'b' : '0' + details.size
+
+#define LOG_READ_UNIMPLEMENTED_CONFIG_REGISTER() \
+ do { if ((details.flags & PCI_CONFIG_DIRECTION) == PCI_CONFIG_READ) { \
+ VLOG_F( \
+ (~-details.size & details.offset) ? loguru::Verbosity_ERROR : loguru::Verbosity_WARNING, \
+ "%s: read unimplemented config register @%02x.%c", \
+ this->name.c_str(), reg_offs + details.offset, \
+ SIZE_ARGS \
+ ); \
+ } } while(0)
+
+#define LOG_NAMED_CONFIG_REGISTER(reg_verb, reg_name) \
+ VLOG_F( \
+ (~-details.size & details.offset) ? loguru::Verbosity_ERROR : loguru::Verbosity_WARNING, \
+ "%s: %s %s register @%02x.%c = %0*x", \
+ this->name.c_str(), reg_verb, reg_name, reg_offs + details.offset, \
+ SIZE_ARGS, \
+ details.size * 2, pci_cfg_log(value, details) \
+ )
+
+#define LOG_READ_NAMED_CONFIG_REGISTER(reg_name) \
+ do { if ((details.flags & PCI_CONFIG_DIRECTION) == PCI_CONFIG_READ) { \
+ LOG_NAMED_CONFIG_REGISTER("read ", reg_name); \
+ } } while(0)
+
+#define LOG_WRITE_NAMED_CONFIG_REGISTER(reg_name) \
+ LOG_NAMED_CONFIG_REGISTER("write", reg_name)
+
+#define LOG_READ_UNIMPLEMENTED_CONFIG_REGISTER_WITH_VALUE() \
+ LOG_READ_NAMED_CONFIG_REGISTER("unimplemented config")
+
+#define LOG_WRITE_UNIMPLEMENTED_CONFIG_REGISTER() \
+ LOG_WRITE_NAMED_CONFIG_REGISTER("unimplemented config")
+
+#define LOG_READ_NON_EXISTENT_PCI_DEVICE() \
+ LOG_F( \
+ ERROR, \
+ "%s err: read attempt from non-existent PCI device %02x:%02x.%x @%02x.%c", \
+ this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + details.offset, \
+ SIZE_ARGS \
+ )
+
+#define LOG_WRITE_NON_EXISTENT_PCI_DEVICE() \
+ LOG_F( \
+ ERROR, \
+ "%s err: write attempt to non-existent PCI device %02x:%02x.%x @%02x.%c = %0*x", \
+ this->name.c_str(), bus_num, dev_num, fun_num, reg_offs + details.offset, \
+ SIZE_ARGS, \
+ details.size * 2, BYTESWAP_SIZED(value, details.size) \
+ )
+
#endif /* PCI_DEVICE_H */
diff --git a/devices/common/pci/pcihost.cpp b/devices/common/pci/pcihost.cpp
index 761a57a..47d997c 100644
--- a/devices/common/pci/pcihost.cpp
+++ b/devices/common/pci/pcihost.cpp
@@ -83,3 +83,8 @@ void PCIHost::attach_pci_device(std::string& dev_name, int slot_id)
this->pci_register_device(
slot_id, dynamic_cast(gMachineObj->get_comp_by_name(dev_name)));
}
+
+PCIDevice *PCIHost::pci_find_device(uint8_t bus_num, uint8_t dev_num, uint8_t fun_num)
+{
+ return NULL;
+}
diff --git a/devices/common/pci/pcihost.h b/devices/common/pci/pcihost.h
index 5a0499a..93e144e 100644
--- a/devices/common/pci/pcihost.h
+++ b/devices/common/pci/pcihost.h
@@ -29,6 +29,23 @@ along with this program. If not, see .
#include
#include
+enum {
+ PCI_CONFIG_DIRECTION = 1,
+ PCI_CONFIG_READ = 0,
+ PCI_CONFIG_WRITE = 1,
+
+ PCI_CONFIG_TYPE = 4,
+ PCI_CONFIG_TYPE_0 = 0,
+ PCI_CONFIG_TYPE_1 = 4,
+};
+
+/** PCI config space access details */
+typedef struct AccessDetails {
+ uint8_t size;
+ uint8_t offset;
+ uint8_t flags;
+} AccessDetails;
+
class PCIDevice; // forward declaration to prevent errors
class PCIHost {
@@ -46,6 +63,8 @@ public:
virtual void attach_pci_device(std::string& dev_name, int slot_id);
+ virtual PCIDevice *pci_find_device(uint8_t bus_num, uint8_t dev_num, uint8_t fun_num);
+
protected:
std::unordered_map dev_map;
std::vector io_space_devs;
diff --git a/devices/memctrl/mpc106.cpp b/devices/memctrl/mpc106.cpp
index 1b40ac7..19b772f 100644
--- a/devices/memctrl/mpc106.cpp
+++ b/devices/memctrl/mpc106.cpp
@@ -72,6 +72,32 @@ int MPC106::device_postinit()
return 0;
}
+void MPC106::cfg_setup(uint32_t offset, int size, int &bus_num, int &dev_num, int &fun_num, uint8_t ®_offs, AccessDetails &details, PCIDevice *&device)
+{
+ device = NULL;
+ details.size = size;
+ details.offset = offset & 3;
+
+ bus_num = (this->config_addr >> 8) & 0xFF;
+ dev_num = (this->config_addr >> 19) & 0x1F;
+ fun_num = (this->config_addr >> 16) & 0x07;
+ reg_offs = (this->config_addr >> 24) & 0xFC;
+
+ if (bus_num) {
+ details.flags = PCI_CONFIG_TYPE_1;
+ device = pci_find_device(bus_num, dev_num, fun_num);
+ }
+ else {
+ details.flags = PCI_CONFIG_TYPE_0;
+ if (dev_num == 0 && fun_num == 0) {
+ device = this; // dev_num 0 is assigned to myself
+ }
+ else if (this->dev_map.count(dev_num)) {
+ device = this->dev_map[dev_num];
+ }
+ }
+}
+
uint32_t MPC106::read(uint32_t rgn_start, uint32_t offset, int size) {
uint32_t result;
@@ -87,7 +113,7 @@ uint32_t MPC106::read(uint32_t rgn_start, uint32_t offset, int size) {
} else {
if (offset >= 0x200000) {
if (this->config_addr & 0x80) // process only if bit E (enable) is set
- return pci_read(size);
+ return pci_read(offset, size);
}
}
@@ -111,116 +137,83 @@ void MPC106::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size
this->config_addr = value;
} else {
if (this->config_addr & 0x80) // process only if bit E (enable) is set
- return pci_write(value, size);
+ return pci_write(offset, value, size);
}
}
}
-uint32_t MPC106::pci_read(uint32_t size) {
- int bus_num, dev_num, fun_num, reg_offs;
-
- bus_num = (this->config_addr >> 8) & 0xFF;
- dev_num = (this->config_addr >> 19) & 0x1F;
- fun_num = (this->config_addr >> 16) & 0x07;
- reg_offs = (this->config_addr >> 24) & 0xFC;
-
- if (bus_num) {
- LOG_F(
- ERROR,
- "%s err: read attempt from non-local PCI bus, config_addr = %x %02x:%02x.%x @%02x.%c",
- this->name.c_str(), this->config_addr, bus_num, dev_num, fun_num, reg_offs,
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
- );
- return 0xFFFFFFFFUL; // PCI spec §6.1
+uint32_t MPC106::pci_read(uint32_t offset, uint32_t size) {
+ int bus_num, dev_num, fun_num;
+ uint8_t reg_offs;
+ AccessDetails details;
+ PCIDevice *device;
+ cfg_setup(offset, size, bus_num, dev_num, fun_num, reg_offs, details, device);
+ details.flags |= PCI_CONFIG_READ;
+ if (device) {
+ return pci_cfg_rev_read(device->pci_cfg_read(reg_offs, details), details);
}
-
- if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself
- return this->pci_cfg_read(reg_offs, size);
- } else {
- if (this->dev_map.count(dev_num)) {
- return this->dev_map[dev_num]->pci_cfg_read(reg_offs, size);
- } else {
- LOG_F(
- ERROR,
- "%s err: read attempt from non-existing PCI device %02x:%02x.%x @%02x.%c",
- this->name.c_str(), bus_num, dev_num, fun_num, reg_offs,
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size
- );
- return 0xFFFFFFFFUL; // PCI spec §6.1
- }
- }
-
- return 0;
+ LOG_READ_NON_EXISTENT_PCI_DEVICE();
+ return 0xFFFFFFFFUL; // PCI spec §6.1
}
-void MPC106::pci_write(uint32_t value, uint32_t size) {
- int bus_num, dev_num, fun_num, reg_offs;
-
- bus_num = (this->config_addr >> 8) & 0xFF;
- dev_num = (this->config_addr >> 19) & 0x1F;
- fun_num = (this->config_addr >> 16) & 0x07;
- reg_offs = (this->config_addr >> 24) & 0xFC;
-
- if (bus_num) {
- LOG_F(
- ERROR,
- "%s err: write attempt to non-local PCI bus, config_addr = %x %02x:%02x.%x @%02x.%c = %0*x",
- this->name.c_str(), this->config_addr, bus_num, dev_num, fun_num, reg_offs,
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
- size * 2, BYTESWAP_SIZED(value, size)
- );
+void MPC106::pci_write(uint32_t offset, uint32_t value, uint32_t size) {
+ int bus_num, dev_num, fun_num;
+ uint8_t reg_offs;
+ AccessDetails details;
+ PCIDevice *device;
+ cfg_setup(offset, size, bus_num, dev_num, fun_num, reg_offs, details, device);
+ details.flags |= PCI_CONFIG_WRITE;
+ if (device) {
+ uint32_t oldvalue = details.size == 4 ? 0 : device->pci_cfg_read(reg_offs, details);
+ value = pci_cfg_rev_write(oldvalue, details, value);
+ device->pci_cfg_write(reg_offs, value, details);
return;
}
-
- if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself
- this->pci_cfg_write(reg_offs, value, size);
- } else {
- if (this->dev_map.count(dev_num)) {
- this->dev_map[dev_num]->pci_cfg_write(reg_offs, value, size);
- } else {
- LOG_F(
- ERROR,
- "%s err: write attempt to non-existing PCI device %02x:%02x.%x @%02x.%c = %0*x",
- this->name.c_str(), bus_num, dev_num, fun_num, reg_offs,
- size == 4 ? 'l' : size == 2 ? 'w' : size == 1 ? 'b' : '0' + size,
- size * 2, BYTESWAP_SIZED(value, size)
- );
- }
- }
+ LOG_WRITE_NON_EXISTENT_PCI_DEVICE();
}
-uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, uint32_t size) {
+uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, AccessDetails &details) {
#ifdef MPC106_DEBUG
LOG_F(9, "read from Grackle register %08X", reg_offs);
#endif
if (reg_offs < 64) {
- return PCIDevice::pci_cfg_read(reg_offs, size);
+ return PCIDevice::pci_cfg_read(reg_offs, details);
}
- return read_mem(&this->my_pci_cfg_hdr[reg_offs], size);
+ uint32_t value = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[reg_offs]);
+ if ((reg_offs >= 0x80 && reg_offs <= 0xA0) || reg_offs == 0xF0) {
+ return value;
+ }
+ LOG_READ_UNIMPLEMENTED_CONFIG_REGISTER_WITH_VALUE();
+ return value;
}
-void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) {
+void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &details) {
#ifdef MPC106_DEBUG
LOG_F(9, "write %08X to Grackle register %08X", value, reg_offs);
#endif
if (reg_offs < 64) {
- PCIDevice::pci_cfg_write(reg_offs, value, size);
+ PCIDevice::pci_cfg_write(reg_offs, value, details);
return;
}
// FIXME: implement write-protection for read-only registers
- write_mem(&this->my_pci_cfg_hdr[reg_offs], value, size);
+ uint32_t *addr = (uint32_t *)&this->my_pci_cfg_hdr[reg_offs];
+ WRITE_DWORD_LE_A(addr, value);
- if (this->my_pci_cfg_hdr[0xF2] & 8) {
+ if ((reg_offs >= 0x80 && reg_offs <= 0xA0) || reg_offs == 0xF0) {
+ if (this->my_pci_cfg_hdr[0xF2] & 8) {
#ifdef MPC106_DEBUG
- LOG_F(9, "MPC106: MCCR1[MEMGO] was set!");
+ LOG_F(9, "MPC106: MCCR1[MEMGO] was set!");
#endif
- setup_ram();
+ setup_ram();
+ }
+ return;
}
+ LOG_WRITE_UNIMPLEMENTED_CONFIG_REGISTER();
}
void MPC106::setup_ram() {
diff --git a/devices/memctrl/mpc106.h b/devices/memctrl/mpc106.h
index 5d62df2..c338d6c 100644
--- a/devices/memctrl/mpc106.h
+++ b/devices/memctrl/mpc106.h
@@ -59,12 +59,13 @@ public:
protected:
/* PCI access */
- uint32_t pci_read(uint32_t size);
- void pci_write(uint32_t value, uint32_t size);
+ uint32_t pci_read(uint32_t offset, uint32_t size);
+ void pci_write(uint32_t offset, uint32_t value, uint32_t size);
+ void cfg_setup(uint32_t offset, int size, int &bus_num, int &dev_num, int &fun_num, uint8_t ®_offs, AccessDetails &details, PCIDevice *&device);
/* my own PCI configuration registers access */
- uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
- void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
+ uint32_t pci_cfg_read(uint32_t reg_offs, AccessDetails &details);
+ void pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &details);
bool supports_io_space(void) {
return true;
diff --git a/devices/video/atirage.cpp b/devices/video/atirage.cpp
index 7b8d640..c88bd64 100644
--- a/devices/video/atirage.cpp
+++ b/devices/video/atirage.cpp
@@ -161,34 +161,35 @@ void ATIRage::notify_bar_change(int bar_num)
}
}
-uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
+uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, AccessDetails &details)
{
if (reg_offs < 64) {
- return PCIDevice::pci_cfg_read(reg_offs, size);
+ return PCIDevice::pci_cfg_read(reg_offs, details);
}
switch (reg_offs) {
case 0x40:
return this->user_cfg;
default:
- LOG_F(WARNING, "ATIRage: reading from unimplemented config register at 0x%X", reg_offs);
+ LOG_READ_UNIMPLEMENTED_CONFIG_REGISTER();
}
return 0;
}
-void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
+void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &details)
{
if (reg_offs < 64) {
- PCIDevice::pci_cfg_write(reg_offs, value, size);
- } else {
- switch (reg_offs) {
- case 0x40:
- this->user_cfg = value;
- break;
- default:
- LOG_F(WARNING, "ATIRage: writing to unimplemented config register at 0x%X", reg_offs);
- }
+ PCIDevice::pci_cfg_write(reg_offs, value, details);
+ return;
+ }
+
+ switch (reg_offs) {
+ case 0x40:
+ this->user_cfg = value;
+ break;
+ default:
+ LOG_WRITE_UNIMPLEMENTED_CONFIG_REGISTER();
}
}
diff --git a/devices/video/atirage.h b/devices/video/atirage.h
index 30c3eb6..62dac2e 100644
--- a/devices/video/atirage.h
+++ b/devices/video/atirage.h
@@ -64,8 +64,8 @@ public:
return true;
};
- uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
- void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
+ uint32_t pci_cfg_read(uint32_t reg_offs, AccessDetails &details);
+ void pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &details);
/* I/O space access methods */
bool pci_io_read(uint32_t offset, uint32_t size, uint32_t* res);