From 57e6e90002ec75c238e06ebdbc915e558ebfb05a Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Thu, 7 Mar 2024 23:30:55 -0800 Subject: [PATCH] Add support for the CUDA_RESTART_SYSTEM command There are cases where when it's necessary (e.g. given uninitialized NVRAM, the Beige G3 with the 10.2 install CD inserted will update the boot device and restart to boot from it). Restart support was done by wrapping the ppc_exec function in a loop and checking for a restart power off reason. We also need to disconnect all event listeners, since they will be recreated when the machine is re-initialized. --- core/coresignal.h | 8 ++++++++ core/hostevents.h | 7 +++++++ cpu/ppc/ppcemu.h | 2 ++ debugger/debugger.cpp | 4 ++++ devices/common/viacuda.cpp | 7 ++++++- main.cpp | 38 ++++++++++++++++++++++++++------------ 6 files changed, 53 insertions(+), 13 deletions(-) diff --git a/core/coresignal.h b/core/coresignal.h index 5caae1a..198180f 100644 --- a/core/coresignal.h +++ b/core/coresignal.h @@ -58,6 +58,14 @@ public: } } + void disconnect(int id) { + _slots.erase(id); + } + + void disconnect_all() { + _slots.clear(); + } + private: mutable std::map> _slots; mutable unsigned int _current_id { 0 }; diff --git a/core/hostevents.h b/core/hostevents.h index 2092f33..4aeeff9 100644 --- a/core/hostevents.h +++ b/core/hostevents.h @@ -94,6 +94,13 @@ public: _post_signal.connect_method(inst, func); } + void disconnect_handlers() { + _window_signal.disconnect_all(); + _mouse_signal.disconnect_all(); + _keyboard_signal.disconnect_all(); + _post_signal.disconnect_all(); + } + private: static EventManager* event_manager; EventManager() {}; // private constructor to implement a singleton diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index 0895a7a..acb468e 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -322,6 +322,8 @@ enum Po_Cause : int { po_starting_up, po_shut_down, po_shutting_down, + po_restarting, + po_restart, po_disassemble_on, po_disassemble_off, po_enter_debugger, diff --git a/debugger/debugger.cpp b/debugger/debugger.cpp index e9cd6d6..0f392fe 100644 --- a/debugger/debugger.cpp +++ b/debugger/debugger.cpp @@ -458,6 +458,10 @@ void enter_debugger() { power_off_reason = po_shutting_down; break; } + if (power_off_reason == po_restart) { + power_off_reason = po_restarting; + break; + } power_on = true; if (power_off_reason == po_starting_up) { diff --git a/devices/common/viacuda.cpp b/devices/common/viacuda.cpp index 78eebc9..796705a 100644 --- a/devices/common/viacuda.cpp +++ b/devices/common/viacuda.cpp @@ -25,6 +25,7 @@ along with this program. If not, see . #include #include #include +#include #include #include #include @@ -654,10 +655,14 @@ void ViaCuda::pseudo_command(int cmd, int data_count) { LOG_F(INFO, "Cuda: send %d to PB0", (int)(this->in_buf[2])); response_header(CUDA_PKT_PSEUDO, 0); break; + case CUDA_RESTART_SYSTEM: + LOG_F(INFO, "Cuda: system restart"); + power_on = false; + power_off_reason = po_restart; + break; case CUDA_WARM_START: case CUDA_POWER_DOWN: case CUDA_MONO_STABLE_RESET: - case CUDA_RESTART_SYSTEM: /* really kludge temp code */ LOG_F(INFO, "Cuda: Restart/Shutdown signal sent with command 0x%x!", cmd); //exit(0); diff --git a/main.cpp b/main.cpp index 784af16..53ecd2e 100644 --- a/main.cpp +++ b/main.cpp @@ -61,6 +61,8 @@ static string appDescription = string( "\n" ); +void run_machine(std::string machine_str, std::string bootrom_path, uint32_t execution_mode); + int main(int argc, char** argv) { uint32_t execution_mode = interpreter; @@ -166,10 +168,6 @@ int main(int argc, char** argv) { // initialize global profiler object gProfilerObj.reset(new Profiler()); - if (MachineFactory::create_machine_for_id(machine_str, bootrom_path) < 0) { - goto bail; - } - // graceful handling of fatal errors loguru::set_fatal_handler([](const loguru::Message& message) { // Make sure the reason for the failure is visible (it may have been @@ -187,9 +185,29 @@ int main(int argc, char** argv) { // redirect SIGABRT to our own handler signal(SIGABRT, sigabrt_handler); + while (true) { + run_machine(machine_str, bootrom_path, execution_mode); + if (power_off_reason == po_restarting) { + LOG_F(INFO, "Restarting..."); + power_on = true; + continue; + } + break; + } + + cleanup(); + + return 0; +} + +void run_machine(std::string machine_str, std::string bootrom_path, uint32_t execution_mode) { + if (MachineFactory::create_machine_for_id(machine_str, bootrom_path) < 0) { + return; + } + // set up system wide event polling using // default Macintosh polling rate of 11 ms - TimerManager::get_instance()->add_cyclic_timer(MSECS_TO_NSECS(11), [] { + uint32_t event_timer = TimerManager::get_instance()->add_cyclic_timer(MSECS_TO_NSECS(11), [] { EventManager::get_instance()->poll_events(); }); @@ -204,15 +222,11 @@ int main(int argc, char** argv) { break; default: LOG_F(ERROR, "Invalid EXECUTION MODE"); - return 1; + return; } -bail: LOG_F(INFO, "Cleaning up..."); - + TimerManager::get_instance()->cancel_timer(event_timer); + EventManager::get_instance()->disconnect_handlers(); delete gMachineObj.release(); - - cleanup(); - - return 0; }