diff --git a/devices/common/pci/bandit.cpp b/devices/common/pci/bandit.cpp index e408583..2dad3a5 100644 --- a/devices/common/pci/bandit.cpp +++ b/devices/common/pci/bandit.cpp @@ -147,7 +147,10 @@ uint32_t BanditHost::read(uint32_t rgn_start, uint32_t offset, int size) cfg_setup(offset, size, bus_num, dev_num, fun_num, reg_offs, details, device); details.flags |= PCI_CONFIG_READ; if (device) { - return pci_conv_rd_data(device->pci_cfg_read(reg_offs, details), details); + uint32_t value = device->pci_cfg_read(reg_offs, details); + // bytes 4 to 7 are random on bandit but + // we choose to repeat bytes 0 to 3 like grackle + return pci_conv_rd_data(value, value, details); } LOG_READ_NON_EXISTENT_PCI_DEVICE(); return 0xFFFFFFFFUL; // PCI spec §6.1 diff --git a/devices/common/pci/pcihost.h b/devices/common/pci/pcihost.h index db8c533..a535be8 100644 --- a/devices/common/pci/pcihost.h +++ b/devices/common/pci/pcihost.h @@ -93,11 +93,11 @@ protected: // Helpers for data conversion in the PCI Configuration space. /** - Perform size dependent endian swapping for value that is dword from PCI config. + Perform size dependent endian swapping for value that is dword from PCI config or any other dword little endian register. - Unaligned data is handled properly by wrapping around if needed. + Unaligned data is handled properly by using bytes from the next dword. */ -inline uint32_t pci_conv_rd_data(uint32_t value, AccessDetails &details) { +inline uint32_t pci_conv_rd_data(uint32_t value, uint32_t value2, AccessDetails &details) { switch (details.size << 2 | details.offset) { // Bytes case 0x04: @@ -117,17 +117,20 @@ inline uint32_t pci_conv_rd_data(uint32_t value, AccessDetails &details) { case 0x0A: return BYTESWAP_16((value >> 16) & 0xFFFFU); // 2 3 case 0x0B: - return ((value >> 16) & 0xFF00) | (value & 0xFF); // 3 0 + return ((value >> 16) & 0xFF00) | (value2 & 0xFF); // 3 4 // Dwords case 0x10: - return BYTESWAP_32(value); // 0 1 2 3 + return BYTESWAP_32(value); // 0 1 2 3 case 0x11: - return ROTL_32(BYTESWAP_32(value), 8); // 1 2 3 0 + value = (uint32_t)((((uint64_t)value2 << 32) | value) >> 8); + return BYTESWAP_32(value); // 1 2 3 4 case 0x12: - return ROTL_32(BYTESWAP_32(value), 16); // 2 3 0 1 + value = (uint32_t)((((uint64_t)value2 << 32) | value) >> 16); + return BYTESWAP_32(value); // 2 3 4 5 case 0x13: - return ROTR_32(BYTESWAP_32(value), 8); // 3 0 1 2 + value = (uint32_t)((((uint64_t)value2 << 32) | value) >> 24); + return BYTESWAP_32(value); // 3 4 5 6 default: return 0xFFFFFFFFUL; } diff --git a/devices/memctrl/mpc106.cpp b/devices/memctrl/mpc106.cpp index 77184d4..b8b0759 100644 --- a/devices/memctrl/mpc106.cpp +++ b/devices/memctrl/mpc106.cpp @@ -86,7 +86,9 @@ uint32_t MPC106::read(uint32_t rgn_start, uint32_t offset, int size) { cfg_setup(offset, size, bus_num, dev_num, fun_num, reg_offs, details, device); details.flags |= PCI_CONFIG_READ; if (device) { - return pci_conv_rd_data(device->pci_cfg_read(reg_offs, details), details); + uint32_t value = device->pci_cfg_read(reg_offs, details); + // bytes 0 to 3 repeat + return pci_conv_rd_data(value, value, details); } LOG_READ_NON_EXISTENT_PCI_DEVICE(); return 0xFFFFFFFFUL; // PCI spec §6.1