diff --git a/devices/common/pci/bandit.cpp b/devices/common/pci/bandit.cpp index 828427b..d270636 100644 --- a/devices/common/pci/bandit.cpp +++ b/devices/common/pci/bandit.cpp @@ -194,7 +194,9 @@ void BanditHost::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int } } -inline 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) +inline 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; @@ -209,11 +211,12 @@ inline void BanditHost::cfg_setup(uint32_t offset, int size, int &bus_num, int & 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 + bus_num = 0; // use dummy value for bus number 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); + 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); diff --git a/devices/common/pci/bandit.h b/devices/common/pci/bandit.h index e7f2b3a..4a90308 100644 --- a/devices/common/pci/bandit.h +++ b/devices/common/pci/bandit.h @@ -78,7 +78,9 @@ protected: uint32_t config_addr; private: - inline void cfg_setup(uint32_t offset, int size, int &bus_num, int &dev_num, int &fun_num, uint8_t ®_offs, AccessDetails &details, PCIDevice *&device); + void cfg_setup(uint32_t offset, int size, int &bus_num, int &dev_num, + int &fun_num, uint8_t ®_offs, AccessDetails &details, + PCIDevice *&device); }; /* diff --git a/devices/common/pci/pcibridge.cpp b/devices/common/pci/pcibridge.cpp index 158eccf..75fb76a 100644 --- a/devices/common/pci/pcibridge.cpp +++ b/devices/common/pci/pcibridge.cpp @@ -1,6 +1,6 @@ /* DingusPPC - The Experimental PowerPC Macintosh emulator -Copyright (C) 2018-22 divingkatae and maximum +Copyright (C) 2018-23 divingkatae and maximum (theweirdo) spatium (Contact divingkatae#1017 or powermax#2286 on Discord for more info) @@ -47,19 +47,73 @@ PCIBridge::PCIBridge(std::string name) : PCIDevice(name) this->pci_wr_primary_bus = [this](uint8_t val) { this->primary_bus = val; }; this->pci_wr_secondary_bus = [this](uint8_t val) { this->secondary_bus = val; }; this->pci_wr_subordinate_bus = [this](uint8_t val) { this->subordinate_bus = val; }; - this->pci_wr_sec_latency_timer = [this](uint8_t val) { this->sec_latency_timer = (this->sec_latency_timer & ~this->sec_latency_timer_cfg) | (val & this->sec_latency_timer_cfg); }; - this->pci_wr_sec_status = [this](uint16_t val) {}; - this->pci_wr_memory_base = [this](uint16_t val) { this->memory_base = (val & this->memory_cfg ) | (this->memory_cfg & 15); this->memory_base_32 = ((this->memory_base & 0xfff0) << 16) ; }; - this->pci_wr_memory_limit = [this](uint16_t val) { this->memory_limit = (val & this->memory_cfg ) | (this->memory_cfg & 15); this->memory_limit_32 = ((this->memory_limit & 0xfff0) << 16) + 0x100000; }; - this->pci_wr_io_base = [this](uint8_t val) { this->io_base = (val & this->io_cfg ) | (this->io_cfg & 15); this->io_base_32 = ((uint32_t)this->io_base_upper16 << 16) | ((this->io_base & 0xf0) << 8) ; }; - this->pci_wr_io_limit = [this](uint8_t val) { this->io_limit = (val & this->io_cfg ) | (this->io_cfg & 15); this->io_limit_32 = (((uint32_t)this->io_limit_upper16 << 16) | ((this->io_limit & 0xf0) << 8)) + 0x1000 ; }; - this->pci_wr_pref_mem_base = [this](uint16_t val) { this->pref_mem_base = (val & this->pref_mem_cfg) | (this->pref_mem_cfg & 15); this->pref_mem_base_64 = ((uint64_t)this->pref_base_upper32 << 32) | ((this->pref_mem_base & 0xfff0) << 16) ; }; - this->pci_wr_pref_mem_limit = [this](uint16_t val) { this->pref_mem_limit = (val & this->pref_mem_cfg) | (this->pref_mem_cfg & 15); this->pref_mem_limit_64 = (((uint64_t)this->pref_limit_upper32 << 32) | ((this->pref_mem_limit & 0xfff0) << 16)) + 0x100000; }; - this->pci_wr_io_base_upper16 = [this](uint16_t val) { if ((this->io_base & 15) == 1) this->io_base_upper16 = val; { this->io_base_32 = ((uint32_t)this->io_base_upper16 << 16) | ((this->io_base & 0xf0) << 8) ; } }; - this->pci_wr_io_limit_upper16 = [this](uint16_t val) { if ((this->io_limit & 15) == 1) this->io_limit_upper16 = val; { this->io_limit_32 = (((uint32_t)this->io_limit_upper16 << 16) | ((this->io_limit & 0xf0) << 8)) + 0x1000 ; } }; - this->pci_wr_pref_base_upper32 = [this](uint32_t val) { if ((this->pref_mem_cfg & 15) == 1) this->pref_base_upper32 = val; { this->pref_mem_base_64 = ((uint64_t)this->pref_base_upper32 << 32) | ((this->pref_mem_base & 0xfff0) << 16) ; } }; - this->pci_wr_pref_limit_upper32 = [this](uint32_t val) { if ((this->pref_mem_cfg & 15) == 1) this->pref_limit_upper32 = val; { this->pref_mem_limit_64 = (((uint64_t)this->pref_limit_upper32 << 32) | ((this->pref_mem_limit & 0xfff0) << 16)) + 0x100000; } }; - this->pci_wr_bridge_control = [this](uint16_t val) { this->bridge_control = val; }; + + this->pci_wr_sec_latency_timer = [this](uint8_t val) { + this->sec_latency_timer = (this->sec_latency_timer & ~this->sec_latency_timer_cfg) | + (val & this->sec_latency_timer_cfg); + }; + + this->pci_wr_sec_status = [this](uint16_t val) {}; + + this->pci_wr_memory_base = [this](uint16_t val) { + this->memory_base = (val & this->memory_cfg) | (this->memory_cfg & 15); + this->memory_base_32 = ((this->memory_base & 0xfff0) << 16); + }; + + this->pci_wr_memory_limit = [this](uint16_t val) { + this->memory_limit = (val & this->memory_cfg) | (this->memory_cfg & 15); + this->memory_limit_32 = ((this->memory_limit & 0xfff0) << 16) + 0x100000; + }; + + this->pci_wr_io_base = [this](uint8_t val) { + this->io_base = (val & this->io_cfg) | (this->io_cfg & 15); + this->io_base_32 = ((uint32_t)this->io_base_upper16 << 16) | ((this->io_base & 0xf0) << 8); + }; + + this->pci_wr_io_limit = [this](uint8_t val) { + this->io_limit = (val & this->io_cfg) | (this->io_cfg & 15); + this->io_limit_32 = (((uint32_t)this->io_limit_upper16 << 16) | + ((this->io_limit & 0xf0) << 8)) + 0x1000; + }; + + this->pci_wr_pref_mem_base = [this](uint16_t val) { + this->pref_mem_base = (val & this->pref_mem_cfg) | (this->pref_mem_cfg & 15); + this->pref_mem_base_64 = ((uint64_t)this->pref_base_upper32 << 32) | + ((this->pref_mem_base & 0xfff0) << 16); + }; + this->pci_wr_pref_mem_limit = [this](uint16_t val) { + this->pref_mem_limit = (val & this->pref_mem_cfg) | (this->pref_mem_cfg & 15); + this->pref_mem_limit_64 = (((uint64_t)this->pref_limit_upper32 << 32) | + ((this->pref_mem_limit & 0xfff0) << 16)) + 0x100000; + }; + this->pci_wr_io_base_upper16 = [this](uint16_t val) { + if ((this->io_base & 15) == 1) + this->io_base_upper16 = val; + this->io_base_32 = ((uint32_t)this->io_base_upper16 << 16) | + ((this->io_base & 0xf0) << 8); + }; + this->pci_wr_io_limit_upper16 = [this](uint16_t val) { + if ((this->io_limit & 15) == 1) + this->io_limit_upper16 = val; + this->io_limit_32 = (((uint32_t)this->io_limit_upper16 << 16) | + ((this->io_limit & 0xf0) << 8)) + 0x1000; + }; + + this->pci_wr_pref_base_upper32 = [this](uint32_t val) { + if ((this->pref_mem_cfg & 15) == 1) + this->pref_base_upper32 = val; + this->pref_mem_base_64 = ((uint64_t)this->pref_base_upper32 << 32) | + ((this->pref_mem_base & 0xfff0) << 16); + }; + + this->pci_wr_pref_limit_upper32 = [this](uint32_t val) { + if ((this->pref_mem_cfg & 15) == 1) + this->pref_limit_upper32 = val; + this->pref_mem_limit_64 = (((uint64_t)this->pref_limit_upper32 << 32) | + ((this->pref_mem_limit & 0xfff0) << 16)) + 0x100000; + }; + + this->pci_wr_bridge_control = [this](uint16_t val) { this->bridge_control = val; }; }; bool PCIBridge::pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj) @@ -80,26 +134,30 @@ uint32_t PCIBridge::pci_cfg_read(uint32_t reg_offs, AccessDetails &details) } switch (reg_offs) { - case PCI_CFG_PRIMARY_BUS: - return (this->pci_rd_sec_latency_timer() << 24) | (this->pci_rd_subordinate_bus() << 16) | (this->pci_rd_secondary_bus() << 8) | (this->pci_rd_primary_bus()); - case PCI_CFG_IO_BASE: - return (this->pci_rd_sec_status() << 16) | (this->pci_rd_io_limit() << 8) | (this->pci_rd_io_base()); - case PCI_CFG_MEMORY_BASE: - return (this->pci_rd_memory_limit() << 16) | (this->pci_rd_memory_base()); - case PCI_CFG_PREF_MEM_BASE: - return (this->pci_rd_pref_mem_limit() << 16) | (this->pci_rd_pref_mem_base()); - case PCI_CFG_PREF_BASE_UPPER32: - return this->pci_rd_pref_base_upper32(); - case PCI_CFG_PREF_LIMIT_UPPER32: - return this->pci_rd_pref_limit_upper32(); - case PCI_CFG_IO_BASE_UPPER16: - return (this->pci_rd_io_limit_upper16() << 16) | (this->pci_rd_io_base_upper16()); - case PCI_CFG_CAP_PTR: - return cap_ptr; - case PCI_CFG_BRIDGE_ROM_ADDRESS: - return exp_rom_bar; - case PCI_CFG_INTERRUPT_LINE: - return (this->pci_rd_bridge_control() << 16) | (irq_pin << 8) | irq_line; + case PCI_CFG_PRIMARY_BUS: + return (this->pci_rd_sec_latency_timer() << 24) | + (this->pci_rd_subordinate_bus() << 16) | + (this->pci_rd_secondary_bus() << 8) | + (this->pci_rd_primary_bus()); + case PCI_CFG_IO_BASE: + return (this->pci_rd_sec_status() << 16) | + (this->pci_rd_io_limit() << 8) | (this->pci_rd_io_base()); + case PCI_CFG_MEMORY_BASE: + return (this->pci_rd_memory_limit() << 16) | (this->pci_rd_memory_base()); + case PCI_CFG_PREF_MEM_BASE: + return (this->pci_rd_pref_mem_limit() << 16) | (this->pci_rd_pref_mem_base()); + case PCI_CFG_PREF_BASE_UPPER32: + return this->pci_rd_pref_base_upper32(); + case PCI_CFG_PREF_LIMIT_UPPER32: + return this->pci_rd_pref_limit_upper32(); + case PCI_CFG_IO_BASE_UPPER16: + return (this->pci_rd_io_limit_upper16() << 16) | (this->pci_rd_io_base_upper16()); + case PCI_CFG_CAP_PTR: + return cap_ptr; + case PCI_CFG_BRIDGE_ROM_ADDRESS: + return exp_rom_bar; + case PCI_CFG_INTERRUPT_LINE: + return (this->pci_rd_bridge_control() << 16) | (irq_pin << 8) | irq_line; } LOG_READ_UNIMPLEMENTED_CONFIG_REGISTER(); return 0; @@ -112,44 +170,44 @@ void PCIBridge::pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails & } switch (reg_offs) { - case PCI_CFG_PRIMARY_BUS: - this->pci_wr_sec_latency_timer(value >> 24); - this->pci_wr_subordinate_bus(value >> 16); - this->pci_wr_secondary_bus(value >> 8); - this->pci_wr_primary_bus(value & 0xFFU); - break; - case PCI_CFG_IO_BASE: - this->pci_wr_sec_status(value >> 16); - this->pci_wr_io_limit(value >> 8); - this->pci_wr_io_base(value & 0xFFU); - break; - case PCI_CFG_MEMORY_BASE: - this->pci_wr_memory_limit(value >> 16); - this->pci_wr_memory_base(value & 0xFFFFU); - break; - case PCI_CFG_PREF_MEM_BASE: - this->pci_wr_pref_mem_limit(value >> 16); - this->pci_wr_pref_mem_base(value & 0xFFFFU); - break; - case PCI_CFG_PREF_BASE_UPPER32: - this->pci_wr_pref_base_upper32(value); - break; - case PCI_CFG_PREF_LIMIT_UPPER32: - this->pci_wr_pref_limit_upper32(value); - break; - case PCI_CFG_IO_BASE_UPPER16: - this->pci_wr_io_limit_upper16(value >> 16); - this->pci_wr_io_base_upper16(value & 0xFFFFU); - break; - case PCI_CFG_BRIDGE_ROM_ADDRESS: - this->pci_wr_exp_rom_bar(value); - break; - case PCI_CFG_INTERRUPT_LINE: - this->irq_line = value >> 24; - this->pci_wr_bridge_control(value >> 16); - break; - default: - LOG_WRITE_UNIMPLEMENTED_CONFIG_REGISTER(); + case PCI_CFG_PRIMARY_BUS: + this->pci_wr_sec_latency_timer(value >> 24); + this->pci_wr_subordinate_bus(value >> 16); + this->pci_wr_secondary_bus(value >> 8); + this->pci_wr_primary_bus(value & 0xFFU); + break; + case PCI_CFG_IO_BASE: + this->pci_wr_sec_status(value >> 16); + this->pci_wr_io_limit(value >> 8); + this->pci_wr_io_base(value & 0xFFU); + break; + case PCI_CFG_MEMORY_BASE: + this->pci_wr_memory_limit(value >> 16); + this->pci_wr_memory_base(value & 0xFFFFU); + break; + case PCI_CFG_PREF_MEM_BASE: + this->pci_wr_pref_mem_limit(value >> 16); + this->pci_wr_pref_mem_base(value & 0xFFFFU); + break; + case PCI_CFG_PREF_BASE_UPPER32: + this->pci_wr_pref_base_upper32(value); + break; + case PCI_CFG_PREF_LIMIT_UPPER32: + this->pci_wr_pref_limit_upper32(value); + break; + case PCI_CFG_IO_BASE_UPPER16: + this->pci_wr_io_limit_upper16(value >> 16); + this->pci_wr_io_base_upper16(value & 0xFFFFU); + break; + case PCI_CFG_BRIDGE_ROM_ADDRESS: + this->pci_wr_exp_rom_bar(value); + break; + case PCI_CFG_INTERRUPT_LINE: + this->irq_line = value >> 24; + this->pci_wr_bridge_control(value >> 16); + break; + default: + LOG_WRITE_UNIMPLEMENTED_CONFIG_REGISTER(); } } diff --git a/devices/common/pci/pcibridge.h b/devices/common/pci/pcibridge.h index e50cb4b..d03654a 100644 --- a/devices/common/pci/pcibridge.h +++ b/devices/common/pci/pcibridge.h @@ -1,6 +1,6 @@ /* DingusPPC - The Experimental PowerPC Macintosh emulator -Copyright (C) 2018-22 divingkatae and maximum +Copyright (C) 2018-23 divingkatae and maximum (theweirdo) spatium (Contact divingkatae#1017 or powermax#2286 on Discord for more info) @@ -121,10 +121,18 @@ protected: uint16_t io_limit_upper16 = 0; uint16_t bridge_control = 0; - uint8_t sec_latency_timer_cfg = 0; // 0 = not writable, 0xf8 = limits the granularity to eight PCI clocks - uint8_t io_cfg = 0xf0; // 0 = not writable, 0xf0 = supports 16 bit io range, 0xf1 = supports 32 bit io range - uint16_t memory_cfg = 0xfff0; // 0 = not writable, 0xfff0 = supports 32 bit memory range - uint16_t pref_mem_cfg = 0xfff0; // 0 = not writable, 0xfff0 = supports 32 bit prefetchable memory range, 0xfff1 = supports 64 bit prefetchable memory range + // 0 = not writable, 0xf8 = limits the granularity to eight PCI clocks + uint8_t sec_latency_timer_cfg = 0; + + // 0 = not writable, 0xf0 = supports 16 bit io range, 0xf1 = supports 32 bit I/O range + uint8_t io_cfg = 0xf0; + + // 0 = not writable, 0xfff0 = supports 32 bit memory range + uint16_t memory_cfg = 0xfff0; + + // 0 = not writable, 0xfff0 = supports 32 bit prefetchable memory range, + // 0xfff1 = supports 64 bit prefetchable memory range + uint16_t pref_mem_cfg = 0xfff0; uint32_t io_base_32 = 0; uint32_t io_limit_32 = 0; diff --git a/devices/common/pci/pcidevice.h b/devices/common/pci/pcidevice.h index 44ea5e9..138572e 100644 --- a/devices/common/pci/pcidevice.h +++ b/devices/common/pci/pcidevice.h @@ -191,7 +191,8 @@ inline uint32_t pci_cfg_log(uint32_t value, AccessDetails &details) { } } -#define SIZE_ARGS details.size == 4 ? 'l' : details.size == 2 ? 'w' : details.size == 1 ? 'b' : '0' + details.size +#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) { \ diff --git a/devices/common/pci/pcihost.h b/devices/common/pci/pcihost.h index 1ad9ce2..4f1f4d4 100644 --- a/devices/common/pci/pcihost.h +++ b/devices/common/pci/pcihost.h @@ -67,7 +67,8 @@ public: virtual bool pci_unregister_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj); virtual void attach_pci_device(const std::string& dev_name, int slot_id); - PCIDevice *attach_pci_device(const std::string& dev_name, int slot_id, const std::string& dev_suffix); + PCIDevice *attach_pci_device(const std::string& dev_name, int slot_id, + const std::string& dev_suffix); virtual bool pci_io_read_loop (uint32_t offset, int size, uint32_t &res); virtual bool pci_io_write_loop(uint32_t offset, int size, uint32_t value); diff --git a/devices/memctrl/mpc106.cpp b/devices/memctrl/mpc106.cpp index 00abf28..ffd5294 100644 --- a/devices/memctrl/mpc106.cpp +++ b/devices/memctrl/mpc106.cpp @@ -136,7 +136,9 @@ void MPC106::pci_write(uint32_t offset, uint32_t value, uint32_t size) { LOG_WRITE_NON_EXISTENT_PCI_DEVICE(); } -inline 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) +inline 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; diff --git a/devices/memctrl/mpc106.h b/devices/memctrl/mpc106.h index 077c30f..252ae3d 100644 --- a/devices/memctrl/mpc106.h +++ b/devices/memctrl/mpc106.h @@ -95,7 +95,9 @@ protected: void setup_ram(void); private: - inline void cfg_setup(uint32_t offset, int size, int &bus_num, int &dev_num, int &fun_num, uint8_t ®_offs, AccessDetails &details, PCIDevice *&device); + inline void cfg_setup(uint32_t offset, int size, int &bus_num, int &dev_num, + int &fun_num, uint8_t ®_offs, AccessDetails &details, + PCIDevice *&device); uint32_t config_addr;