|
| 1 | +/* |
| 2 | +DingusPPC - The Experimental PowerPC Macintosh emulator |
| 3 | +Copyright (C) 2018-25 divingkatae and maximum |
| 4 | + (theweirdo) spatium |
| 5 | +
|
| 6 | +(Contact divingkatae#1017 or powermax#2286 on Discord for more info) |
| 7 | +
|
| 8 | +This program is free software: you can redistribute it and/or modify |
| 9 | +it under the terms of the GNU General Public License as published by |
| 10 | +the Free Software Foundation, either version 3 of the License, or |
| 11 | +(at your option) any later version. |
| 12 | +
|
| 13 | +This program is distributed in the hope that it will be useful, |
| 14 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | +GNU General Public License for more details. |
| 17 | +
|
| 18 | +You should have received a copy of the GNU General Public License |
| 19 | +along with this program. If not, see <https://www.gnu.org/licenses/>. |
| 20 | +*/ |
| 21 | + |
| 22 | +/** @file Construct the Bondi machine (iMac G3). */ |
| 23 | + |
| 24 | +#include <cpu/ppc/ppcemu.h> |
| 25 | +#include <devices/ioctrl/macio.h> |
| 26 | +#include <devices/memctrl/mpc106.h> |
| 27 | +#include <devices/memctrl/spdram.h> |
| 28 | +#include <machines/machinebase.h> |
| 29 | +#include <machines/machinefactory.h> |
| 30 | +#include <machines/machineproperties.h> |
| 31 | + |
| 32 | +static const std::vector<PciIrqMap> grackle_irq_map = { |
| 33 | + {nullptr , DEV_FUN(0x00,0), }, // Grackle |
| 34 | + {"pci_A1" , DEV_FUN(0x0D,0), IntSrc::PCI_A }, |
| 35 | + {"pci_B1" , DEV_FUN(0x0E,0), IntSrc::PCI_B }, |
| 36 | + {"pci_C1" , DEV_FUN(0x0F,0), IntSrc::PCI_C }, |
| 37 | + {nullptr , DEV_FUN(0x10,0), }, |
| 38 | + {"pci_GPU" , DEV_FUN(0x12,0), IntSrc::PCI_GPU }, // Heathrow |
| 39 | + {"pci_PERCH", DEV_FUN(0x14,0), IntSrc::PCI_PERCH}, |
| 40 | +}; |
| 41 | + |
| 42 | +static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs) { |
| 43 | + if (!capacity_megs) |
| 44 | + return; |
| 45 | + |
| 46 | + gMachineObj->add_device(name, std::unique_ptr<SpdSdram168>(new SpdSdram168(i2c_addr))); |
| 47 | + SpdSdram168* ram_dimm = dynamic_cast<SpdSdram168*>(gMachineObj->get_comp_by_name(name)); |
| 48 | + ram_dimm->set_capacity(capacity_megs); |
| 49 | + |
| 50 | + // register RAM DIMM with the I2C bus |
| 51 | + I2CBus* i2c_bus = dynamic_cast<I2CBus*>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST)); |
| 52 | + i2c_bus->register_device(i2c_addr, ram_dimm); |
| 53 | +} |
| 54 | + |
| 55 | +int initialize_bondi(std::string& id) { |
| 56 | + LOG_F(INFO, "Building machine Bondi..."); |
| 57 | + |
| 58 | + // get pointer to the memory controller/primary PCI bridge object |
| 59 | + MPC106* grackle_obj = dynamic_cast<MPC106*>(gMachineObj->get_comp_by_name("Grackle")); |
| 60 | + grackle_obj->set_irq_map(grackle_irq_map); |
| 61 | + |
| 62 | + HeathrowIC* heathrow = dynamic_cast<HeathrowIC*>(gMachineObj->get_comp_by_name("Heathrow")); |
| 63 | + heathrow->set_media_bay_id(0x30); |
| 64 | + |
| 65 | + grackle_obj->pci_register_device(DEV_FUN(0x10,0), heathrow); |
| 66 | + |
| 67 | + grackle_obj->pci_register_device( |
| 68 | + DEV_FUN(0x12,0), dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("AtiMach64Gx"))); |
| 69 | + |
| 70 | + // allocate ROM region |
| 71 | + if (!grackle_obj->add_rom_region(0xFFF00000, 0x100000)) { |
| 72 | + LOG_F(ERROR, "Could not allocate ROM region!"); |
| 73 | + return -1; |
| 74 | + } |
| 75 | + |
| 76 | + // configure RAM slots |
| 77 | + // First ram slot is enumerated twice for some reason, the second slot is never enumerated, so |
| 78 | + // put half the ram in each slot. |
| 79 | + setup_ram_slot("RAM_DIMM_1", 0x50, GET_INT_PROP("rambank1_size") / 2); |
| 80 | + setup_ram_slot("RAM_DIMM_2", 0x51, GET_INT_PROP("rambank1_size") / 2); |
| 81 | + |
| 82 | + // configure CPU clocks |
| 83 | + uint64_t bus_freq = 66820000ULL; |
| 84 | + uint64_t timebase_freq = bus_freq / 4; |
| 85 | + |
| 86 | + // initialize virtual CPU and request MPC750 CPU aka G3 |
| 87 | + ppc_cpu_init(grackle_obj, PPC_VER::MPC750, false, timebase_freq); |
| 88 | + |
| 89 | + // set CPU PLL ratio to 3.5 |
| 90 | + ppc_state.spr[SPR::HID1] = 0xE << 28; |
| 91 | + |
| 92 | + return 0; |
| 93 | +} |
| 94 | + |
| 95 | +static const PropMap bondi_settings = { |
| 96 | + {"rambank1_size", new IntProperty(128, std::vector<uint32_t>({32, 64, 128}))}, |
| 97 | + {"emmo", new BinProperty(0)}, |
| 98 | + {"hdd_config", new StrProperty("Ide0:0")}, |
| 99 | + {"cdr_config", new StrProperty("Ide1:0")}, |
| 100 | +}; |
| 101 | + |
| 102 | +static std::vector<std::string> bondi_devices = { |
| 103 | + "Grackle", "BurgundySnd", "Heathrow", "AtiMach64Gx", "AtaHardDisk", "AtapiCdrom"}; |
| 104 | + |
| 105 | +static const MachineDescription bondi_descriptor = { |
| 106 | + .name = "imacg3", |
| 107 | + .description = "iMac G3 Bondi Blue", |
| 108 | + .devices = bondi_devices, |
| 109 | + .settings = bondi_settings, |
| 110 | + .init_func = &initialize_bondi}; |
| 111 | + |
| 112 | +REGISTER_MACHINE(imacg3, bondi_descriptor); |
0 commit comments