1+ /*
2+ DingusPPC - The Experimental PowerPC Macintosh emulator
3+ Copyright (C) 2018-23 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 Yosemite machine (Power Macintosh G3 Blue & White). */
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 void setup_ram_slot (std::string name, int i2c_addr, int capacity_megs) {
33+ if (!capacity_megs)
34+ return ;
35+
36+ gMachineObj ->add_device (name, std::unique_ptr<SpdSdram168>(new SpdSdram168 (i2c_addr)));
37+ SpdSdram168* ram_dimm = dynamic_cast <SpdSdram168*>(gMachineObj ->get_comp_by_name (name));
38+ ram_dimm->set_capacity (capacity_megs);
39+
40+ // register RAM DIMM with the I2C bus
41+ I2CBus* i2c_bus = dynamic_cast <I2CBus*>(gMachineObj ->get_comp_by_type (HWCompType::I2C_HOST));
42+ i2c_bus->register_device (i2c_addr, ram_dimm);
43+ }
44+
45+ int initialize_bondi (std::string& id) {
46+ LOG_F (INFO, " Building machine Bondi..." );
47+
48+ // get pointer to the memory controller/primary PCI bridge object
49+ MPC106* grackle_obj = dynamic_cast <MPC106*>(gMachineObj ->get_comp_by_name (" Grackle" ));
50+
51+ dynamic_cast <HeathrowIC*>(gMachineObj ->get_comp_by_name (" Heathrow" ))->set_media_bay_id (0x30 );
52+
53+ grackle_obj->pci_register_device (
54+ DEV_FUN (0x10 , 0 ), dynamic_cast <PCIDevice*>(gMachineObj ->get_comp_by_name (" Heathrow" )));
55+
56+ grackle_obj->pci_register_device (
57+ DEV_FUN (0x12 , 0 ), dynamic_cast <PCIDevice*>(gMachineObj ->get_comp_by_name (" AtiMach64Gx" )));
58+
59+ // allocate ROM region
60+ if (!grackle_obj->add_rom_region (0xFFF00000 , 0x100000 )) {
61+ LOG_F (ERROR, " Could not allocate ROM region!" );
62+ return -1 ;
63+ }
64+
65+ // configure RAM slots
66+ // First ram slot is enumerated twice for some reason, the second slot is never enumerated, so
67+ // put half the ram in each slot.
68+ setup_ram_slot (" RAM_DIMM_1" , 0x50 , GET_INT_PROP (" rambank1_size" ) / 2 );
69+ setup_ram_slot (" RAM_DIMM_2" , 0x51 , GET_INT_PROP (" rambank1_size" ) / 2 );
70+
71+ // configure CPU clocks
72+ uint64_t bus_freq = 66820000ULL ;
73+ uint64_t timebase_freq = bus_freq / 4 ;
74+
75+ // initialize virtual CPU and request MPC750 CPU aka G3
76+ ppc_cpu_init (grackle_obj, PPC_VER::MPC750, timebase_freq);
77+
78+ // set CPU PLL ratio to 3.5
79+ ppc_state.spr [SPR::HID1] = 0xE << 28 ;
80+
81+ return 0 ;
82+ }
83+
84+ static const PropMap bondi_settings = {
85+ {" rambank1_size" , new IntProperty (128 , vector<uint32_t >({32 , 64 , 128 }))},
86+ {" emmo" , new BinProperty (0 )},
87+ {" hdd_config" , new StrProperty (" Ide0:0" )},
88+ {" cdr_config" , new StrProperty (" Ide1:0" )},
89+ };
90+
91+ static vector<string> bondi_devices = {
92+ " Grackle" , " BurgundySnd" , " Heathrow" , " AtiMach64Gx" , " AtaHardDisk" , " AtapiCdrom" };
93+
94+ static const MachineDescription bondi_descriptor = {
95+ .name = " imacg3" ,
96+ .description = " iMac G3 Bondi Blue" ,
97+ .devices = bondi_devices,
98+ .settings = bondi_settings,
99+ .init_func = &initialize_bondi};
100+
101+ REGISTER_MACHINE (imacg3, bondi_descriptor);
0 commit comments