3b2: Soft-power shutdown via TIMER command
This change enables the simulator to be shut down cleanly via a soft-power shutdown command. This is implemented in the real 3B2/400 through the sanity timer, which, if it reaches zero, sets a bus timeout flag in the CSR and issues an interrupt at IPL 15. The operating system (System V UNIX) treats this as a shutdown request and enters runlevel 0. To use this change in a SIMH startup script, for example to implement a 3B2 simulator as a service, one could add these commands: # [... simulator setup ...] BOOT SET TIMER SHUTDOWN CONTINUE EXIT On catching a SIGTERM, SIGINT, or SIGHUP, the simulator would return to SCP control, set the soft power shutdown flag, and then continue simulator execution. After the system is cleanly shut down, the simulator would then exit back to the operating system.
This commit is contained in:
parent
ad9cb1d42d
commit
7455d28126
3 changed files with 32 additions and 2 deletions
|
@ -3455,7 +3455,7 @@ static void cpu_calc_ints()
|
||||||
cpu_int_ipl = cpu_int_vec = CPU_ID_IF_IPL;
|
cpu_int_ipl = cpu_int_vec = CPU_ID_IF_IPL;
|
||||||
} else if ((csr_data & CSRUART) || (csr_data & CSRDMA)) {
|
} else if ((csr_data & CSRUART) || (csr_data & CSRDMA)) {
|
||||||
cpu_int_ipl = cpu_int_vec = CPU_IU_DMA_IPL;
|
cpu_int_ipl = cpu_int_vec = CPU_IU_DMA_IPL;
|
||||||
} else if (csr_data & CSRCLK) {
|
} else if ((csr_data & CSRCLK) || (csr_data & CSRTIMO)) {
|
||||||
cpu_int_ipl = cpu_int_vec = CPU_TMR_IPL;
|
cpu_int_ipl = cpu_int_vec = CPU_TMR_IPL;
|
||||||
} else {
|
} else {
|
||||||
cpu_int_ipl = cpu_int_vec = 0;
|
cpu_int_ipl = cpu_int_vec = 0;
|
||||||
|
|
|
@ -433,8 +433,14 @@ REG timer_reg[] = {
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MTAB timer_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR|MTAB_NC, 0, NULL, "SHUTDOWN",
|
||||||
|
&timer_set_shutdown, NULL, NULL, "Soft Power Shutdown" },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
DEVICE timer_dev = {
|
DEVICE timer_dev = {
|
||||||
"TIMER", timer_unit, timer_reg, NULL,
|
"TIMER", timer_unit, timer_reg, timer_mod,
|
||||||
1, 16, 8, 4, 16, 32,
|
1, 16, 8, 4, 16, 32,
|
||||||
NULL, NULL, &timer_reset,
|
NULL, NULL, &timer_reset,
|
||||||
NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL,
|
||||||
|
@ -468,6 +474,23 @@ t_stat timer_reset(DEVICE *dptr) {
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_stat timer_set_shutdown(UNIT *uptr, int32 val, CONST char* cptr, void* desc)
|
||||||
|
{
|
||||||
|
struct timer_ctr *sanity = timer_unit[0].tmr;
|
||||||
|
|
||||||
|
sim_debug(EXECUTE_MSG, &timer_dev,
|
||||||
|
"[%08x] Setting sanity timer to 0 for shutdown.\n", R[NUM_PC]);
|
||||||
|
|
||||||
|
sanity->val = 0;
|
||||||
|
csr_data &= ~CSRCLK;
|
||||||
|
csr_data |= CSRTIMO;
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity Timer
|
||||||
|
*/
|
||||||
t_stat timer0_svc(UNIT *uptr)
|
t_stat timer0_svc(UNIT *uptr)
|
||||||
{
|
{
|
||||||
struct timer_ctr *ctr;
|
struct timer_ctr *ctr;
|
||||||
|
@ -486,6 +509,9 @@ t_stat timer0_svc(UNIT *uptr)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interval Timer
|
||||||
|
*/
|
||||||
t_stat timer1_svc(UNIT *uptr)
|
t_stat timer1_svc(UNIT *uptr)
|
||||||
{
|
{
|
||||||
struct timer_ctr *ctr;
|
struct timer_ctr *ctr;
|
||||||
|
@ -505,6 +531,9 @@ t_stat timer1_svc(UNIT *uptr)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bus Timeout Timer
|
||||||
|
*/
|
||||||
t_stat timer2_svc(UNIT *uptr)
|
t_stat timer2_svc(UNIT *uptr)
|
||||||
{
|
{
|
||||||
struct timer_ctr *ctr;
|
struct timer_ctr *ctr;
|
||||||
|
|
|
@ -69,6 +69,7 @@ void timer_write(uint32 pa, uint32 val, size_t size);
|
||||||
t_stat timer0_svc(UNIT *uptr);
|
t_stat timer0_svc(UNIT *uptr);
|
||||||
t_stat timer1_svc(UNIT *uptr);
|
t_stat timer1_svc(UNIT *uptr);
|
||||||
t_stat timer2_svc(UNIT *uptr);
|
t_stat timer2_svc(UNIT *uptr);
|
||||||
|
t_stat timer_set_shutdown(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
|
||||||
/* CSR */
|
/* CSR */
|
||||||
t_stat csr_svc(UNIT *uptr);
|
t_stat csr_svc(UNIT *uptr);
|
||||||
|
|
Loading…
Add table
Reference in a new issue