Merge pull request #62 from mihaip/upstream-cuda-restart

Add support for the CUDA_RESTART_SYSTEM command
This commit is contained in:
Maxim Poliakovski 2024-03-08 15:25:02 +01:00 committed by GitHub
commit 3c7ce3de8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 102 additions and 23 deletions

View File

@ -58,6 +58,14 @@ public:
} }
} }
void disconnect(int id) {
_slots.erase(id);
}
void disconnect_all() {
_slots.clear();
}
private: private:
mutable std::map<int, std::function<void(Args...)>> _slots; mutable std::map<int, std::function<void(Args...)>> _slots;
mutable unsigned int _current_id { 0 }; mutable unsigned int _current_id { 0 };

View File

@ -94,6 +94,13 @@ public:
_post_signal.connect_method(inst, func); _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: private:
static EventManager* event_manager; static EventManager* event_manager;
EventManager() {}; // private constructor to implement a singleton EventManager() {}; // private constructor to implement a singleton

View File

@ -322,6 +322,8 @@ enum Po_Cause : int {
po_starting_up, po_starting_up,
po_shut_down, po_shut_down,
po_shutting_down, po_shutting_down,
po_restarting,
po_restart,
po_disassemble_on, po_disassemble_on,
po_disassemble_off, po_disassemble_off,
po_enter_debugger, po_enter_debugger,

View File

@ -77,11 +77,11 @@ uint64_t num_entry_replacements = 0; // number of entry replacements
#endif // TLB_PROFILING #endif // TLB_PROFILING
/** remember recently used physical memory regions for quicker translation. */ /** remember recently used physical memory regions for quicker translation. */
AddressMapEntry last_read_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr}; AddressMapEntry last_read_area;
AddressMapEntry last_write_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr}; AddressMapEntry last_write_area;
AddressMapEntry last_exec_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr}; AddressMapEntry last_exec_area;
AddressMapEntry last_ptab_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr}; AddressMapEntry last_ptab_area;
AddressMapEntry last_dma_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr}; AddressMapEntry last_dma_area;
/** 601-style block address translation. */ /** 601-style block address translation. */
static BATResult mpc601_block_address_translation(uint32_t la) static BATResult mpc601_block_address_translation(uint32_t la)
@ -2020,6 +2020,12 @@ static void invalidate_tlb_entries(std::array<TLBEntry, N> &tlb) {
void ppc_mmu_init() void ppc_mmu_init()
{ {
last_read_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr};
last_write_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr};
last_exec_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr};
last_ptab_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr};
last_dma_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr};
mmu_exception_handler = ppc_exception_handler; mmu_exception_handler = ppc_exception_handler;
if (is_601) { if (is_601) {

View File

@ -458,6 +458,10 @@ void enter_debugger() {
power_off_reason = po_shutting_down; power_off_reason = po_shutting_down;
break; break;
} }
if (power_off_reason == po_restart) {
power_off_reason = po_restarting;
break;
}
power_on = true; power_on = true;
if (power_off_reason == po_starting_up) { if (power_off_reason == po_starting_up) {

View File

@ -25,6 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <core/hostevents.h> #include <core/hostevents.h>
#include <core/timermanager.h> #include <core/timermanager.h>
#include <devices/common/adb/adbbus.h> #include <devices/common/adb/adbbus.h>
#include <cpu/ppc/ppcemu.h>
#include <devices/common/hwinterrupt.h> #include <devices/common/hwinterrupt.h>
#include <devices/common/viacuda.h> #include <devices/common/viacuda.h>
#include <devices/deviceregistry.h> #include <devices/deviceregistry.h>
@ -88,6 +89,26 @@ ViaCuda::ViaCuda() {
this->int_ctrl = nullptr; this->int_ctrl = nullptr;
} }
ViaCuda::~ViaCuda()
{
if (this->sr_timer_on) {
TimerManager::get_instance()->cancel_timer(this->sr_timer_id);
this->sr_timer_on = false;
}
if (this->t1_active) {
TimerManager::get_instance()->cancel_timer(this->t1_timer_id);
this->t1_active = false;
}
if (this->t2_active) {
TimerManager::get_instance()->cancel_timer(this->t2_timer_id);
this->t2_active = false;
}
if (this->treq_timer_id) {
TimerManager::get_instance()->cancel_timer(this->treq_timer_id);
this->treq_timer_id = 0;
}
}
int ViaCuda::device_postinit() int ViaCuda::device_postinit()
{ {
this->int_ctrl = dynamic_cast<InterruptCtrl*>( this->int_ctrl = dynamic_cast<InterruptCtrl*>(
@ -342,11 +363,12 @@ void ViaCuda::write(uint8_t new_state) {
process_packet(); process_packet();
// start response transaction // start response transaction
TimerManager::get_instance()->add_oneshot_timer( this->treq_timer_id = TimerManager::get_instance()->add_oneshot_timer(
USECS_TO_NSECS(13), // delay TREQ assertion for New World USECS_TO_NSECS(13), // delay TREQ assertion for New World
[this]() { [this]() {
this->via_regs[VIA_B] &= ~CUDA_TREQ; // assert TREQ this->via_regs[VIA_B] &= ~CUDA_TREQ; // assert TREQ
this->treq = 0; this->treq = 0;
this->treq_timer_id = 0;
}); });
} }
@ -633,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])); LOG_F(INFO, "Cuda: send %d to PB0", (int)(this->in_buf[2]));
response_header(CUDA_PKT_PSEUDO, 0); response_header(CUDA_PKT_PSEUDO, 0);
break; 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_WARM_START:
case CUDA_POWER_DOWN: case CUDA_POWER_DOWN:
case CUDA_MONO_STABLE_RESET: case CUDA_MONO_STABLE_RESET:
case CUDA_RESTART_SYSTEM:
/* really kludge temp code */ /* really kludge temp code */
LOG_F(INFO, "Cuda: Restart/Shutdown signal sent with command 0x%x!", cmd); LOG_F(INFO, "Cuda: Restart/Shutdown signal sent with command 0x%x!", cmd);
//exit(0); //exit(0);

View File

@ -155,7 +155,7 @@ enum {
class ViaCuda : public HWComponent, public I2CBus { class ViaCuda : public HWComponent, public I2CBus {
public: public:
ViaCuda(); ViaCuda();
~ViaCuda() = default; ~ViaCuda();
static std::unique_ptr<HWComponent> create() { static std::unique_ptr<HWComponent> create() {
return std::unique_ptr<ViaCuda>(new ViaCuda()); return std::unique_ptr<ViaCuda>(new ViaCuda());
@ -206,6 +206,7 @@ private:
uint8_t old_tip; uint8_t old_tip;
uint8_t old_byteack; uint8_t old_byteack;
uint8_t treq; uint8_t treq;
uint32_t treq_timer_id = 0;
uint8_t in_buf[CUDA_IN_BUF_SIZE]; uint8_t in_buf[CUDA_IN_BUF_SIZE];
int32_t in_count; int32_t in_count;
uint8_t out_buf[16]; uint8_t out_buf[16];

View File

@ -90,6 +90,14 @@ AMIC::AMIC() : MMIODevice()
this->swim3->set_dma_channel(this->floppy_dma.get()); this->swim3->set_dma_channel(this->floppy_dma.get());
} }
AMIC::~AMIC()
{
if (this->pseudo_vbl_tid) {
TimerManager::get_instance()->cancel_timer(this->pseudo_vbl_tid);
this->pseudo_vbl_tid = 0;
}
}
int AMIC::device_postinit() int AMIC::device_postinit()
{ {
MemCtrlBase *mem_ctrl = dynamic_cast<MemCtrlBase *> MemCtrlBase *mem_ctrl = dynamic_cast<MemCtrlBase *>

View File

@ -275,7 +275,7 @@ enum AMICReg : uint32_t {
class AMIC : public MMIODevice, public InterruptCtrl { class AMIC : public MMIODevice, public InterruptCtrl {
public: public:
AMIC(); AMIC();
~AMIC() = default; ~AMIC();
static std::unique_ptr<HWComponent> create() { static std::unique_ptr<HWComponent> create() {
return std::unique_ptr<AMIC>(new AMIC()); return std::unique_ptr<AMIC>(new AMIC());
@ -336,7 +336,7 @@ private:
uint8_t via2_slot_ifr = 0x7F; // reverse logic uint8_t via2_slot_ifr = 0x7F; // reverse logic
uint8_t via2_slot_irq = 0; // normal logic uint8_t via2_slot_irq = 0; // normal logic
uint32_t pseudo_vbl_tid; // ID for the pseudo-VBL timer uint32_t pseudo_vbl_tid = 0; // ID for the pseudo-VBL timer
// AMIC subdevice instances // AMIC subdevice instances
Sc53C94* scsi; Sc53C94* scsi;

View File

@ -19,7 +19,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
/** @file Video Conroller base class implementation. */ /** @file Video Controller base class implementation. */
#include <core/timermanager.h> #include <core/timermanager.h>
#include <devices/common/hwinterrupt.h> #include <devices/common/hwinterrupt.h>
@ -37,6 +37,7 @@ VideoCtrlBase::VideoCtrlBase(int width, int height)
VideoCtrlBase::~VideoCtrlBase() VideoCtrlBase::~VideoCtrlBase()
{ {
this->stop_refresh_task();
} }
void VideoCtrlBase::handle_events(const WindowEvent& wnd_event) { void VideoCtrlBase::handle_events(const WindowEvent& wnd_event) {
@ -110,9 +111,11 @@ void VideoCtrlBase::start_refresh_task() {
void VideoCtrlBase::stop_refresh_task() { void VideoCtrlBase::stop_refresh_task() {
if (this->refresh_task_id) { if (this->refresh_task_id) {
TimerManager::get_instance()->cancel_timer(this->refresh_task_id); TimerManager::get_instance()->cancel_timer(this->refresh_task_id);
this->refresh_task_id = 0;
} }
if (this->vbl_end_task_id) { if (this->vbl_end_task_id) {
TimerManager::get_instance()->cancel_timer(this->vbl_end_task_id); TimerManager::get_instance()->cancel_timer(this->vbl_end_task_id);
this->vbl_end_task_id = 0;
} }
} }

View File

@ -61,6 +61,8 @@ static string appDescription = string(
"\n" "\n"
); );
void run_machine(std::string machine_str, std::string bootrom_path, uint32_t execution_mode);
int main(int argc, char** argv) { int main(int argc, char** argv) {
uint32_t execution_mode = interpreter; uint32_t execution_mode = interpreter;
@ -166,10 +168,6 @@ int main(int argc, char** argv) {
// initialize global profiler object // initialize global profiler object
gProfilerObj.reset(new Profiler()); gProfilerObj.reset(new Profiler());
if (MachineFactory::create_machine_for_id(machine_str, bootrom_path) < 0) {
goto bail;
}
// graceful handling of fatal errors // graceful handling of fatal errors
loguru::set_fatal_handler([](const loguru::Message& message) { loguru::set_fatal_handler([](const loguru::Message& message) {
// Make sure the reason for the failure is visible (it may have been // 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 // redirect SIGABRT to our own handler
signal(SIGABRT, sigabrt_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 // set up system wide event polling using
// default Macintosh polling rate of 11 ms // 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(); EventManager::get_instance()->poll_events();
}); });
@ -204,15 +222,11 @@ int main(int argc, char** argv) {
break; break;
default: default:
LOG_F(ERROR, "Invalid EXECUTION MODE"); LOG_F(ERROR, "Invalid EXECUTION MODE");
return 1; return;
} }
bail:
LOG_F(INFO, "Cleaning up..."); LOG_F(INFO, "Cleaning up...");
TimerManager::get_instance()->cancel_timer(event_timer);
EventManager::get_instance()->disconnect_handlers();
delete gMachineObj.release(); delete gMachineObj.release();
cleanup();
return 0;
} }