mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-11 20:29:46 +00:00
mpc106: refactor PCI read and write methods.
This commit is contained in:
parent
99e92a5679
commit
36dee46e9b
@ -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 ®_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) {
|
||||
|
@ -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 ®_offs, AccessDetails &details, PCIDevice *&device);
|
||||
|
||||
/* my own PCI configuration registers access */
|
||||
uint32_t pci_cfg_read(uint32_t reg_offs, AccessDetails &details);
|
||||
|
Loading…
x
Reference in New Issue
Block a user