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:
mutable std::map<int, std::function<void(Args...)>> _slots;
mutable unsigned int _current_id { 0 };

View File

@ -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

View File

@ -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,

View File

@ -77,11 +77,11 @@ uint64_t num_entry_replacements = 0; // number of entry replacements
#endif // TLB_PROFILING
/** remember recently used physical memory regions for quicker translation. */
AddressMapEntry last_read_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr};
AddressMapEntry last_write_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr};
AddressMapEntry last_exec_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr};
AddressMapEntry last_ptab_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr};
AddressMapEntry last_dma_area = {0xFFFFFFFF, 0xFFFFFFFF, 0, 0, nullptr, nullptr};
AddressMapEntry last_read_area;
AddressMapEntry last_write_area;
AddressMapEntry last_exec_area;
AddressMapEntry last_ptab_area;
AddressMapEntry last_dma_area;
/** 601-style block address translation. */
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()
{
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;
if (is_601) {

View File

@ -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) {

View File

@ -25,6 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <core/hostevents.h>
#include <core/timermanager.h>
#include <devices/common/adb/adbbus.h>
#include <cpu/ppc/ppcemu.h>
#include <devices/common/hwinterrupt.h>
#include <devices/common/viacuda.h>
#include <devices/deviceregistry.h>
@ -88,6 +89,26 @@ ViaCuda::ViaCuda() {
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()
{
this->int_ctrl = dynamic_cast<InterruptCtrl*>(
@ -342,11 +363,12 @@ void ViaCuda::write(uint8_t new_state) {
process_packet();
// 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
[this]() {
this->via_regs[VIA_B] &= ~CUDA_TREQ; // assert TREQ
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]));
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);

View File

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

View File

@ -90,6 +90,14 @@ AMIC::AMIC() : MMIODevice()
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()
{
MemCtrlBase *mem_ctrl = dynamic_cast<MemCtrlBase *>

View File

@ -275,7 +275,7 @@ enum AMICReg : uint32_t {
class AMIC : public MMIODevice, public InterruptCtrl {
public:
AMIC();
~AMIC() = default;
~AMIC();
static std::unique_ptr<HWComponent> create() {
return std::unique_ptr<AMIC>(new AMIC());
@ -336,7 +336,7 @@ private:
uint8_t via2_slot_ifr = 0x7F; // reverse 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
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/>.
*/
/** @file Video Conroller base class implementation. */
/** @file Video Controller base class implementation. */
#include <core/timermanager.h>
#include <devices/common/hwinterrupt.h>
@ -37,6 +37,7 @@ VideoCtrlBase::VideoCtrlBase(int width, int height)
VideoCtrlBase::~VideoCtrlBase()
{
this->stop_refresh_task();
}
void VideoCtrlBase::handle_events(const WindowEvent& wnd_event) {
@ -110,9 +111,11 @@ void VideoCtrlBase::start_refresh_task() {
void VideoCtrlBase::stop_refresh_task() {
if (this->refresh_task_id) {
TimerManager::get_instance()->cancel_timer(this->refresh_task_id);
this->refresh_task_id = 0;
}
if (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"
);
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;
}