diff --git a/devices/memctrl/mpc106.cpp b/devices/memctrl/mpc106.cpp index 5f7c7c0..aaf6439 100644 --- a/devices/memctrl/mpc106.cpp +++ b/devices/memctrl/mpc106.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) @@ -173,80 +173,120 @@ void MPC106::pci_write(uint32_t offset, uint32_t value, uint32_t size) { } uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, AccessDetails &details) { -#ifdef MPC106_DEBUG - LOG_F(9, "read from Grackle register %08X", reg_offs); -#endif - if (reg_offs < 64) { return PCIDevice::pci_cfg_read(reg_offs, details); } - uint32_t value = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[reg_offs]); - if ((reg_offs >= 0x80 && reg_offs <= 0xA0) || reg_offs == 0xF0) { - return value; + switch (reg_offs) { + case GrackleReg::CFG10: + return 0; + case GrackleReg::PMCR1: + return (this->odcr << 24) | (this->pmcr2 << 16) | this->pmcr1; + case GrackleReg::MBER: + return this->mem_bank_en; + case GrackleReg::PICR1: + return this->picr1; + case GrackleReg::PICR2: + return this->picr2; + case GrackleReg::MCCR1: + return this->mccr1; + default: + LOG_READ_UNIMPLEMENTED_CONFIG_REGISTER(); } - LOG_READ_UNIMPLEMENTED_CONFIG_REGISTER_WITH_VALUE(); - return value; + + return 0; // PCI Spec ยง6.1 } void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, AccessDetails &details) { -#ifdef MPC106_DEBUG - LOG_F(9, "write %08X to Grackle register %08X", value, reg_offs); -#endif - if (reg_offs < 64) { PCIDevice::pci_cfg_write(reg_offs, value, details); return; } - // FIXME: implement write-protection for read-only registers - - uint32_t *addr = (uint32_t *)&this->my_pci_cfg_hdr[reg_offs]; - WRITE_DWORD_LE_A(addr, value); - - if ((reg_offs >= 0x80 && reg_offs <= 0xA0) || reg_offs == 0xF0) { - if (this->my_pci_cfg_hdr[0xF2] & 8) { -#ifdef MPC106_DEBUG - LOG_F(9, "MPC106: MCCR1[MEMGO] was set!"); -#endif - setup_ram(); + switch (reg_offs) { + case GrackleReg::CFG10: + // Open Firmware writes 0 to subordinate bus # - we don't care + break; + case GrackleReg::PMCR1: + this->pmcr1 = value & 0xFFFFU; + this->pmcr2 = (value >> 16) & 0xFF; + this->odcr = value >> 24; + break; + case GrackleReg::MSAR1: + case GrackleReg::MSAR2: + this->mem_start[(reg_offs >> 2) & 1] = value; + break; + case GrackleReg::EMSAR1: + case GrackleReg::EMSAR2: + this->ext_mem_start[(reg_offs >> 2) & 1] = value; + break; + case GrackleReg::MEAR1: + case GrackleReg::MEAR2: + this->mem_end[(reg_offs >> 2) & 1] = value; + break; + case GrackleReg::EMEAR1: + case GrackleReg::EMEAR2: + this->ext_mem_end[(reg_offs >> 2) & 1] = value; + break; + case GrackleReg::MBER: + this->mem_bank_en = value & 0xFFU; + break; + case GrackleReg::PICR1: + this->picr1 = value; + break; + case GrackleReg::PICR2: + this->picr2 = value; + break; + case GrackleReg::MCCR1: + if ((value ^ this->mccr1) & MEMGO) { + if (value & MEMGO) + setup_ram(); } - return; + this->mccr1 = value; + break; + case GrackleReg::MCCR2: + this->mccr2 = value; + break; + case GrackleReg::MCCR3: + this->mccr3 = value; + break; + case GrackleReg::MCCR4: + this->mccr4 = value; + break; + default: + LOG_WRITE_UNIMPLEMENTED_CONFIG_REGISTER(); } - LOG_WRITE_UNIMPLEMENTED_CONFIG_REGISTER(); } void MPC106::setup_ram() { uint32_t mem_start, mem_end, ext_mem_start, ext_mem_end, bank_start, bank_end; uint32_t ram_size = 0; - uint8_t bank_en = this->my_pci_cfg_hdr[0xA0]; - for (int bank = 0; bank < 8; bank++) { - if (bank_en & (1 << bank)) { + if (this->mem_bank_en & (1 << bank)) { if (bank < 4) { - mem_start = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x80]); - ext_mem_start = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x88]); - mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x90]); - ext_mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x98]); + mem_start = this->mem_start[0]; + ext_mem_start = this->ext_mem_start[0]; + mem_end = this->mem_end[0]; + ext_mem_end = this->ext_mem_end[0]; } else { - mem_start = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x84]); - ext_mem_start = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x8C]); - mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x94]); - ext_mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x9C]); + mem_start = this->mem_start[1]; + ext_mem_start = this->ext_mem_start[1]; + mem_end = this->mem_end[1]; + ext_mem_end = this->ext_mem_end[1]; } bank_start = (((ext_mem_start >> bank * 8) & 3) << 30) | (((mem_start >> bank * 8) & 0xFF) << 20); bank_end = (((ext_mem_end >> bank * 8) & 3) << 30) | (((mem_end >> bank * 8) & 0xFF) << 20) | 0xFFFFFUL; if (bank && bank_start != ram_size) - LOG_F(WARNING, "MPC106: RAM not contiguous!"); + LOG_F(WARNING, "Grackle: RAM not contiguous!"); ram_size += bank_end - bank_start + 1; } } if (!this->add_ram_region(0, ram_size)) { - LOG_F(WARNING, "MPC106 RAM allocation 0x%X..0x%X failed (maybe already exists?)", + LOG_F(WARNING, "Grackle: RAM allocation 0x%X..0x%X failed (maybe already exists?)", 0, ram_size - 1); } } diff --git a/devices/memctrl/mpc106.h b/devices/memctrl/mpc106.h index c338d6c..640eb57 100644 --- a/devices/memctrl/mpc106.h +++ b/devices/memctrl/mpc106.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) @@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/** MPC106 (Grackle) emulation +/** MPC106 (Grackle) definitions. Grackle IC is a combined memory and PCI controller manufactured by Motorola. It's the central device in the Gossamer architecture. @@ -31,8 +31,8 @@ along with this program. If not, see . - our virtual device reports revision 4.0 as expected by machine firmware */ -#ifndef MPC106_H_ -#define MPC106_H_ +#ifndef MPC106_H +#define MPC106_H #include #include @@ -43,6 +43,32 @@ along with this program. If not, see . #include #include +/** Grackle configuration space registers. */ +enum GrackleReg : uint32_t { + CFG10 = 0x40, // bus # + subordinate bus # + disconnect counter + PMCR1 = 0x70, // power management config 1 + MSAR1 = 0x80, // memory starting address 1 + MSAR2 = 0x84, // memory starting address 2 + EMSAR1 = 0x88, // extended memory starting address 1 + EMSAR2 = 0x8C, // extended memory starting address 2 + MEAR1 = 0x90, // memory ending address 1 + MEAR2 = 0x94, // memory ending address 2 + EMEAR1 = 0x98, // extended memory ending address 1 + EMEAR2 = 0x9C, // extended memory ending address 2 + MBER = 0xA0, // memory bank enable + PICR1 = 0xA8, // processor interface configuration 1 + PICR2 = 0xAC, // processor interface configuration 2 + MCCR1 = 0xF0, // memory control configuration 1 + MCCR2 = 0xF4, // memory control configuration 2 + MCCR3 = 0xF8, // memory control configuration 3 + MCCR4 = 0xFC // memory control configuration 4 +}; + +/* MCCR1 bit definitions. */ +enum { + MEMGO = 1 << 19, +}; + class MPC106 : public MemCtrlBase, public PCIDevice, public PCIHost { public: MPC106(); @@ -74,92 +100,23 @@ protected: void setup_ram(void); private: - uint8_t my_pci_cfg_hdr[256] = { - 0x57, 0x10, // vendor ID: Motorola - 0x02, 0x00, // device ID: MPC106 - 0x06, 0x00, // PCI command - 0x80, 0x00, // PCI status - 0x40, // revision ID: 4.0 - 0x00, // standard programming - 0x00, // subclass code: host bridge - 0x06, // class code: bridge device - 0x08, // cache line size - 0x00, // latency timer - 0x00, // header type - 0x00, // BIST Control - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, // Interrupt line - 0x00, // Interrupt pin - 0x00, // MIN GNT - 0x00, // MAX LAT - 0x00, // Bus number - 0x00, // Subordinate bus number - 0x00, // Discount counter - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // Performance monitor command - 0x00, 0x00, // Performance monitor mode control - 0xFF, 0xFF, - - 0x00, 0x00, 0x00, 0x00, // Performance monitor counter 0 - 0x00, 0x00, 0x00, 0x00, // Performance monitor counter 1 - 0x00, 0x00, 0x00, 0x00, // Performance monitor counter 2 - 0x00, 0x00, 0x00, 0x00, // Performance monitor counter 3 - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, - - 0x00, 0x00, // Power mgt config 1 - 0x00, // Power mgt config 2 - 0xCD, // default value for ODCR - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, // Memory Starting Address - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Extended Memory Starting Address - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Memory Ending Address - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Extended Memory Ending Address - - 0x00, // Memory bank enable - 0xFF, 0xFF, - 0x00, // Memory page mode - 0xFF, 0xFF, 0xFF, 0xFF, - - 0x10, 0x00, 0x00, 0xFF, // PICR1 - 0x0C, 0x06, 0x0C, 0x00, // PICR2 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, // ECC single-bit error counter - 0x00, // ECC single-bit error trigger - 0x04, // Alternate OS visible paramaters 1 - 0x01, // Alternate OS visible paramaters 2 - - 0xFF, 0xFF, 0xFF, 0xFF, - - 0x01, // Error enabling 1 - 0x00, // Error detection 1 - 0xFF, - 0x00, // 60x bus error status - 0x00, // Error enabling 2 - 0x00, // Error detection 2 - 0xFF, - 0x00, // PCI bus error status - 0x00, 0x00, 0x00, 0x00, // 60x/PCI ERROR address - - 0xFF, 0xFF, 0xFF, 0xFF, - - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, - - 0x42, 0x00, 0xFF, 0x0F, // Emulation support config 1 - 0x00, 0x00, 0x00, 0x00, // Modified memory status (no clear) - 0x20, 0x00, 0x00, 0x00, // Emulation support config 2 - 0x00, 0x00, 0x00, 0x00, // Modified memory status (clear) - - 0x00, 0x00, 0x02, 0xFF, // Memory ctrl config 1 - 0x03, 0x00, 0x00, 0x00, // Memory ctrl config 2 - 0x00, 0x00, 0x00, 0x00, // Memory ctrl config 3 - 0x00, 0x00, 0x10, 0x00 // Memory ctrl config 4 - }; - uint32_t config_addr; + + uint16_t pmcr1 = 0; // power management config 1 + uint8_t pmcr2 = 0; // power management config 2 + uint8_t odcr = 0xCD; // output driver control + uint32_t picr1 = 0xFF100010; // ROM on CPU bus, address map B, CPU type = MPC601 + uint32_t picr2 = 0x000C060C; + uint32_t mccr1 = 0xFF820000; // 64bit ROM bus + uint32_t mccr2 = 3; + uint32_t mccr3 = 0; + uint32_t mccr4 = 0x00100000; + + uint32_t mem_start[2] = {}; + uint32_t ext_mem_start[2] = {}; + uint32_t mem_end[2] = {}; + uint32_t ext_mem_end[2] = {}; + uint8_t mem_bank_en = 0; }; -#endif +#endif // MPC106_H