mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-11 05:29:43 +00:00
Add support for PCI I/O space.
This commit is contained in:
parent
cc5261cfa9
commit
a243c79d0f
@ -94,9 +94,9 @@ public:
|
||||
|
||||
bool supports_type(HWCompType type) { return type == HWCompType::MMIO_DEV; };
|
||||
|
||||
void set_host(PCIHost *host_instance) {this->host_instance = host_instance;};
|
||||
|
||||
/* PCI device methods */
|
||||
bool supports_io_space(void) { return false; };
|
||||
|
||||
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);
|
||||
|
||||
|
@ -40,10 +40,14 @@ MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge")
|
||||
{
|
||||
this->name = "Grackle";
|
||||
|
||||
/* add PCI/ISA I/O space, 64K for now */
|
||||
add_mmio_region(0xFE000000, 0x10000, this);
|
||||
|
||||
/* add memory mapped I/O region for MPC106 registers */
|
||||
add_mmio_region(0xFEC00000, 0x300000, this);
|
||||
|
||||
this->pci_0_bus.clear();
|
||||
this->io_space_devs.clear();
|
||||
}
|
||||
|
||||
MPC106::~MPC106()
|
||||
@ -63,9 +67,23 @@ bool MPC106::supports_type(HWCompType type)
|
||||
|
||||
uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size)
|
||||
{
|
||||
if (offset >= 0x200000) {
|
||||
if (this->config_addr & 0x80) // process only if bit E (enable) is set
|
||||
return pci_read(size);
|
||||
uint32_t result;
|
||||
|
||||
if (reg_start == 0xFE000000) {
|
||||
/* 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, "Attempt to read from unmapped PCI I/O space, offset=0x%X", offset);
|
||||
}
|
||||
else {
|
||||
if (offset >= 0x200000) {
|
||||
if (this->config_addr & 0x80) // process only if bit E (enable) is set
|
||||
return pci_read(size);
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: reading from CONFIG_ADDR is ignored for now */
|
||||
@ -75,11 +93,24 @@ uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size)
|
||||
|
||||
void MPC106::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
if (offset < 0x200000) {
|
||||
this->config_addr = value;
|
||||
} else {
|
||||
if (this->config_addr & 0x80) // process only if bit E (enable) is set
|
||||
return pci_write(value, size);
|
||||
if (reg_start == 0xFE000000) {
|
||||
/* 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, "Attempt to write to unmapped PCI I/O space, offset=0x%X", offset);
|
||||
}
|
||||
else {
|
||||
if (offset < 0x200000) {
|
||||
this->config_addr = value;
|
||||
}
|
||||
else {
|
||||
if (this->config_addr & 0x80) // process only if bit E (enable) is set
|
||||
return pci_write(value, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,6 +235,10 @@ bool MPC106::pci_register_device(int dev_num, PCIDevice *dev_instance)
|
||||
|
||||
dev_instance->set_host(this);
|
||||
|
||||
if (dev_instance->supports_io_space()) {
|
||||
this->io_space_devs.push_back(dev_instance);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -67,10 +67,8 @@ protected:
|
||||
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);
|
||||
|
||||
void set_host(PCIHost *host_instance) {}; // unimplemented for now
|
||||
bool supports_io_space(void) { return true; };
|
||||
|
||||
/* PCI host bridge API */
|
||||
//bool pci_register_device(int dev_num, PCIDevice *dev_instance);
|
||||
bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice *obj);
|
||||
|
||||
void setup_ram(void);
|
||||
@ -175,6 +173,7 @@ private:
|
||||
//uint32_t config_data;
|
||||
|
||||
std::unordered_map<int, PCIDevice*> pci_0_bus;
|
||||
std::vector<PCIDevice*> io_space_devs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -30,8 +30,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
/* convert little-endian DWORD to big-endian DWORD */
|
||||
#define LE2BE(x) (x >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | (x << 24)
|
||||
|
||||
/** PCI configuration space registers offsets */
|
||||
enum {
|
||||
CFG_REG_BAR0 = 0x10 // base address register 0
|
||||
CFG_REG_CMD = 0x04, // command/status register
|
||||
CFG_REG_BAR0 = 0x10, // base address register 0
|
||||
CFG_REG_BAR1 = 0x14, // base address register 1
|
||||
CFG_REG_BAR2 = 0x18, // base address register 2
|
||||
CFG_REG_BAR3 = 0x1C, // base address register 3
|
||||
CFG_REG_BAR4 = 0x20, // base address register 4
|
||||
CFG_REG_BAR5 = 0x24, // base address register 5
|
||||
CFG_EXP_BASE = 0x30, // expansion ROM base
|
||||
};
|
||||
|
||||
|
||||
@ -40,11 +48,20 @@ public:
|
||||
PCIDevice(std::string name) { this->pci_name = name; };
|
||||
virtual ~PCIDevice() = default;
|
||||
|
||||
virtual bool supports_io_space(void) = 0;
|
||||
|
||||
/* I/O space access methods */
|
||||
virtual bool pci_io_read(uint32_t offset, uint32_t size, uint32_t* res)
|
||||
{ return false; };
|
||||
|
||||
virtual bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size)
|
||||
{ return false; };
|
||||
|
||||
/* configuration space access methods */
|
||||
virtual uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size) = 0;
|
||||
virtual void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) = 0;
|
||||
|
||||
virtual void set_host(PCIHost *host_instance) = 0;
|
||||
virtual void set_host(PCIHost* host_instance) { this->host_instance = host_instance; };
|
||||
|
||||
protected:
|
||||
std::string pci_name; // human-readable device name
|
||||
|
Loading…
x
Reference in New Issue
Block a user