mpc106: refactor PCI read and write methods.

This commit is contained in:
Maxim Poliakovski 2023-02-02 01:59:07 +01:00
parent 99e92a5679
commit 36dee46e9b
2 changed files with 52 additions and 49 deletions

View File

@ -26,12 +26,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <devices/deviceregistry.h>
#include <devices/memctrl/memctrlbase.h>
#include <devices/memctrl/mpc106.h>
#include <loguru.hpp>
#include <memaccess.h>
#include <cinttypes>
#include <cstring>
#include <iostream>
#include <loguru.hpp>
#include <string>
#include <vector>
@ -48,6 +47,9 @@ MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle"), PCIHost()
this->command = 6;
this->status = 0x80;
// assign PCI device number zero to myself
this->pci_register_device(0, this);
// add PCI/ISA I/O space, 64K for now
add_mmio_region(0xFE000000, 0x10000, this);
@ -72,32 +74,6 @@ 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 &reg_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;
@ -143,33 +119,61 @@ void MPC106::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int size
}
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);
int bus_num = (this->config_addr >> 8) & 0xFF;
int dev_num = (this->config_addr >> 19) & 0x1F;
int fun_num = (this->config_addr >> 16) & 0x07;
int reg_offs = (this->config_addr >> 24) & 0xFC;
if (bus_num) {
LOG_F(ERROR, "%s: read attempt from non-local PCI bus, %02x:%02x.%x @%02x",
this->name.c_str(), bus_num, dev_num, fun_num, offset & 0xFCU);
return 0xFFFFFFFFUL; // PCI spec §6.1
}
LOG_READ_NON_EXISTENT_PCI_DEVICE();
if (this->dev_map.count(dev_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);
return pci_cfg_rev_read(result, details);
} else {
LOG_F(ERROR, "%s: read attempt from non-existing PCI device ??:%02x.%x @%02x",
this->name.c_str(), dev_num, fun_num, offset);
}
return 0xFFFFFFFFUL; // PCI spec §6.1
}
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, value, details);
device->pci_cfg_write(reg_offs, value, details);
int bus_num = (this->config_addr >> 8) & 0xFF;
int dev_num = (this->config_addr >> 19) & 0x1F;
int fun_num = (this->config_addr >> 16) & 0x07;
int reg_offs = (this->config_addr >> 24) & 0xFC;
if (bus_num) {
LOG_F(ERROR, "%s: write attempt to non-local PCI bus, %02x:%02x.%x @%02x",
this->name.c_str(), bus_num, dev_num, fun_num, offset & 0xFCU);
return;
}
LOG_WRITE_NON_EXISTENT_PCI_DEVICE();
if (this->dev_map.count(dev_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);
} 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 new_val = pci_cfg_rev_write(old_val, value, details);
this->dev_map[dev_num]->pci_cfg_write(reg_offs, new_val, details);
}
} else {
LOG_F(ERROR, "%s: write attempt to non-existing PCI device ??:%02x.%x @%02x",
this->name.c_str(), dev_num, fun_num, offset);
}
}
uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, AccessDetails &details) {

View File

@ -87,7 +87,6 @@ protected:
/* PCI access */
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 &reg_offs, AccessDetails &details, PCIDevice *&device);
/* my own PCI configuration registers access */
uint32_t pci_cfg_read(uint32_t reg_offs, AccessDetails &details);