PDP10, PDP11, VAX: Make DMC/DMR initialization more accurate.
These changes cure a number of issues in RSTS/E, which is more sensitive to details of emulation than most: 1. Additional KMC opcodes supported for ROMI 2. MCLR now initializes the CSRs per the spec 3. MCLR and ROMI are processed immediately at CSR write rather than being deferred, because these actions are implemented in the device hardware rather than in the microprogram.
This commit is contained in:
parent
f48d1f418d
commit
223f080724
1 changed files with 201 additions and 44 deletions
|
@ -247,12 +247,15 @@ extern int32 tmr_poll; /* instructions per tick
|
|||
#define DMC_SEL6_M_HDX 0x0400
|
||||
#define DMC_SEL6_V_LONGSTRT 11
|
||||
#define DMC_SEL6_M_LONGSTRT 0x0800
|
||||
|
||||
/* Bit flags used in DMR modem status after RDI */
|
||||
#define DMC_SEL6_V_LMODEM 11
|
||||
#define DMC_SEL6_M_LMODEM 0x0800
|
||||
|
||||
#define DSPDSR 0x22b3 /* KMC opcode to move line unit status to SEL2 */
|
||||
#define DROPDTR 0xa40b /* KMC opcode to drop DTR */
|
||||
#define UINST_CNF 0x2296 /* KMC opcode to get config switches */
|
||||
#define UINST_RROM 0x814d /* KMC opcode to read DMC ROM */
|
||||
#define UINST_CNF3 0x2293 /* KMC opcode ditto but to BSEL3 */
|
||||
#define UINST_RROM 0x8100 /* KMC opcode to read DMC ROM, address in low bits */
|
||||
|
||||
#define SEL2_TYPEO_BIT 0
|
||||
#define SEL2_RDO_BIT 7
|
||||
|
@ -291,6 +294,140 @@ typedef enum {
|
|||
OutputControl
|
||||
} TransferState;
|
||||
|
||||
/* 129 words taken from RSTS/E ECO checker listing; the rest is not
|
||||
used so we can leave it as zeroes. */
|
||||
static const uint16 hi_speed_ucode[256] = {
|
||||
063220,
|
||||
063223,
|
||||
063237,
|
||||
063232,
|
||||
061200,
|
||||
061202,
|
||||
03370,
|
||||
063130,
|
||||
076423,
|
||||
063060,
|
||||
0101414,
|
||||
0100407,
|
||||
03401,
|
||||
063231,
|
||||
010162,
|
||||
0626,
|
||||
062234,
|
||||
016403,
|
||||
016402,
|
||||
016406,
|
||||
016407,
|
||||
016401,
|
||||
010210,
|
||||
016455,
|
||||
016472,
|
||||
010067,
|
||||
016471,
|
||||
02471,
|
||||
043236,
|
||||
010022,
|
||||
016424,
|
||||
02424,
|
||||
043235,
|
||||
010240,
|
||||
016642,
|
||||
02642,
|
||||
0600,
|
||||
061221,
|
||||
0110642,
|
||||
020620,
|
||||
0173202,
|
||||
020640,
|
||||
0167203,
|
||||
010210,
|
||||
0140620,
|
||||
020620,
|
||||
0103060,
|
||||
0100463,
|
||||
0433,
|
||||
060342,
|
||||
0101047,
|
||||
0123620,
|
||||
0113246,
|
||||
023240,
|
||||
060520,
|
||||
0103451,
|
||||
010211,
|
||||
0140620,
|
||||
060601,
|
||||
0103100,
|
||||
0123400,
|
||||
01620,
|
||||
0117034,
|
||||
0100447,
|
||||
02611,
|
||||
0100447,
|
||||
0123400,
|
||||
0103505,
|
||||
0114434,
|
||||
060520,
|
||||
0103603,
|
||||
0120400,
|
||||
01620,
|
||||
0103047,
|
||||
02514,
|
||||
0100447,
|
||||
0123400,
|
||||
0102527,
|
||||
02654,
|
||||
0102124,
|
||||
01620,
|
||||
02722,
|
||||
0102524,
|
||||
02701,
|
||||
060601,
|
||||
0102130,
|
||||
0100447,
|
||||
0102140,
|
||||
02472,
|
||||
0500,
|
||||
061260,
|
||||
010177,
|
||||
016402,
|
||||
02400,
|
||||
042233,
|
||||
0114474,
|
||||
060721,
|
||||
0102130,
|
||||
02472,
|
||||
010017,
|
||||
0136500,
|
||||
0136520,
|
||||
0122560,
|
||||
0123000,
|
||||
0500,
|
||||
061260,
|
||||
02133,
|
||||
040620,
|
||||
0103164,
|
||||
010151,
|
||||
016406,
|
||||
02700,
|
||||
063161,
|
||||
0641,
|
||||
03374,
|
||||
0110727,
|
||||
03004,
|
||||
063070,
|
||||
010017,
|
||||
0731,
|
||||
0110463,
|
||||
010154,
|
||||
057310,
|
||||
057231,
|
||||
057235,
|
||||
043237,
|
||||
043232,
|
||||
063170,
|
||||
063161
|
||||
};
|
||||
|
||||
/* Queue elements
|
||||
* A queue is a double-linked list of element headers.
|
||||
* The head of the queue is an element without a body.
|
||||
|
@ -946,6 +1083,7 @@ void dmc_set_count (CTLR *controller, uint16 count);
|
|||
uint8 dmc_get_modem (CTLR *controller);
|
||||
void dmc_set_modem_dtr (CTLR *controller);
|
||||
void dmc_clr_modem_dtr (CTLR *controller);
|
||||
void dmc_process_immediate(CTLR *controller);
|
||||
void dmc_process_command (CTLR *controller);
|
||||
t_bool dmc_buffer_fill_receive_buffers (CTLR *controller);
|
||||
void dmc_start_transfer_buffer (CTLR *controller);
|
||||
|
@ -2201,8 +2339,12 @@ void dmc_set_rdyi(CTLR *controller)
|
|||
{
|
||||
if (dmc_is_dmc(controller)) {
|
||||
dmc_setreg(controller, 0, *controller->csrs->sel0 | DMC_SEL0_M_RDI, DBG_RGC);
|
||||
dmc_setreg(controller, 4, *controller->modem | 0x0800, DBG_RGC);
|
||||
dmc_setreg(controller, 6, *controller->modem & DMC_SEL4_M_DTR, DBG_RGC);
|
||||
if (controller->dev_type == DMR) {
|
||||
dmc_setreg(controller, 4, *controller->modem | 0x0800, DBG_RGC);
|
||||
dmc_setreg(controller, 6,
|
||||
(*controller->modem & DMC_SEL4_M_DTR) | DMC_SEL6_M_LMODEM,
|
||||
DBG_RGC);
|
||||
}
|
||||
}
|
||||
else
|
||||
dmc_setreg(controller, 2, *controller->csrs->sel2 | DMP_SEL2_M_RDI, DBG_RGC);
|
||||
|
@ -2301,7 +2443,8 @@ dmc_setreg(controller, 6, *controller->csrs->sel6 | DMC_SEL6_M_LOSTDATA, DBG_RGC
|
|||
|
||||
void dmc_clear_master_clear(CTLR *controller)
|
||||
{
|
||||
dmc_setreg(controller, 0, *controller->csrs->sel0 & ~DMC_SEL0_M_MCLEAR, DBG_RGC);
|
||||
dmc_setreg(controller, 0,
|
||||
*controller->csrs->sel0 & ~(DMC_SEL0_M_MCLEAR|DMC_SEL0_M_STEPUP|DMC_SEL0_M_ROMI|DMC_SEL0_M_ROMO|DMC_SEL0_M_LU_LOOP|DMC_SEL0_M_STEPLU), DBG_RGC);
|
||||
}
|
||||
|
||||
void dmc_set_run(CTLR *controller)
|
||||
|
@ -2339,7 +2482,6 @@ while ((control = controller->control_out)) {
|
|||
free (control);
|
||||
}
|
||||
controller->control_out = NULL;
|
||||
dmc_setreg(controller, 0, 0, DBG_RGC);
|
||||
if (controller->dev_type == DMR) {
|
||||
if (dmc_is_attached(controller->unit)) {
|
||||
/* Indicates microdiagnostics complete */
|
||||
|
@ -2354,19 +2496,10 @@ if (controller->dev_type == DMR) {
|
|||
dmc_setreg(controller, 2, 0x0200, DBG_RGC);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* preserve contents of BSEL3 if DMC-11 */
|
||||
dmc_setreg(controller, 2, *controller->csrs->sel2 & 0xFF00, DBG_RGC);
|
||||
}
|
||||
if (controller->dev_type == DMP)
|
||||
if (controller->dev_type == DMP) {
|
||||
dmc_setreg(controller, 4, 077, DBG_RGC);
|
||||
else
|
||||
dmc_setreg(controller, 4, 0, DBG_RGC);
|
||||
|
||||
if (controller->dev_type == DMP)
|
||||
dmc_setreg(controller, 6, 0305, DBG_RGC);
|
||||
else
|
||||
dmc_setreg(controller, 6, 0, DBG_RGC);
|
||||
}
|
||||
dmc_buffer_queue_init_all(controller);
|
||||
|
||||
controller->transfer_state = Idle;
|
||||
|
@ -3483,12 +3616,58 @@ while (buffer) {
|
|||
}
|
||||
}
|
||||
|
||||
void dmc_process_command(CTLR *controller)
|
||||
void dmc_check_romi(CTLR *controller)
|
||||
{
|
||||
if (dmc_is_dmc (controller) &&
|
||||
(*controller->csrs->sel0 & DMC_SEL0_M_ROMI) &&
|
||||
(*controller->csrs->sel0 & (DMC_SEL0_M_STEPUP | DMC_SEL0_M_RUN))) {
|
||||
/* DMC-11 or DMR-11, with ROMI and either STEP or RUN bits set. */
|
||||
switch (*controller->csrs->sel6) {
|
||||
case DSPDSR: /* 0x22b3 (read line status instruction), set the DSR and high speed bits in SEL2. */
|
||||
sim_debug(DBG_TRC, controller->device, "%s%d: dmc_check_romi(). report DSR\n", controller->device->name, controller->index);
|
||||
dmc_setreg (controller, 2, 0xa00, DBG_RGC);
|
||||
break;
|
||||
case DROPDTR: /* 0xa40b (drop DTR instruction) - VMS Driver uses this */
|
||||
sim_debug(DBG_TRC, controller->device, "%s%d: dmc_check_romi(). drop_DTR\n", controller->device->name, controller->index);
|
||||
dmc_clr_modem_dtr (controller);
|
||||
break;
|
||||
case UINST_CNF3: /* 0x2293 (config switches to BSEL3) RSTS uses this */
|
||||
sim_debug(DBG_TRC, controller->device, "%s%d: dmc_check_romi(). report config\n", controller->device->name, controller->index);
|
||||
dmc_setreg (controller, 2, 0x0600, DBG_RGC); /* 1 Mb, DMR */
|
||||
break;
|
||||
case UINST_CNF: /* 0x2296 (get configuration switches) - VMS Driver uses this */
|
||||
sim_debug(DBG_TRC, controller->device, "%s%d: dmc_check_romi(). report config\n", controller->device->name, controller->index);
|
||||
dmc_setreg (controller, 6, 0x0006, DBG_RGC); /* 1 Mb, DMR */
|
||||
break;
|
||||
default:
|
||||
if ((*controller->csrs->sel6 & 0xff00) == UINST_RROM) {
|
||||
/* Read ROM: VMS and RSTS do this */
|
||||
sim_debug(DBG_TRC, controller->device, "%s%d: dmc_check_romi(). read rom[0x%02x]\n", controller->device->name, controller->index, *controller->csrs->sel6 & 0xff);
|
||||
dmc_setreg (controller, 6,
|
||||
hi_speed_ucode[*controller->csrs->sel6 & 0xff],
|
||||
DBG_RGC);
|
||||
}
|
||||
else
|
||||
sim_debug(DBG_WRN, controller->device, "%s%d: dmc_check_romi(). Unknown Microcode instruction 0x%04x\n", controller->device->name, controller->index, *controller->csrs->sel6);
|
||||
break;
|
||||
}
|
||||
/* If it was a STEP we do this only once. */
|
||||
*controller->csrs->sel0 &= ~DMC_SEL0_M_STEPUP;
|
||||
controller->transfer_state = Idle;
|
||||
}
|
||||
}
|
||||
|
||||
void dmc_process_immediate(CTLR *controller)
|
||||
{
|
||||
if (dmc_is_master_clear_set(controller)) {
|
||||
dmc_process_master_clear(controller);
|
||||
return;
|
||||
}
|
||||
dmc_check_romi(controller); /* Do any needed immediate actions */
|
||||
}
|
||||
|
||||
void dmc_process_command(CTLR *controller)
|
||||
{
|
||||
if (controller->transfer_state == InputTransfer) {
|
||||
dmc_process_input_transfer_completion(controller);
|
||||
return;
|
||||
|
@ -3506,32 +3685,8 @@ if (dmc_is_rqi_set(controller)) {
|
|||
dmc_start_input_transfer(controller);
|
||||
return;
|
||||
}
|
||||
if (dmc_is_dmc (controller) &&
|
||||
(*controller->csrs->sel0 & DMC_SEL0_M_ROMI) &&
|
||||
(!dmc_is_run_set(controller)) &&
|
||||
(*controller->csrs->sel0 & DMC_SEL0_M_STEPUP)) {
|
||||
/* DMC-11 or DMR-11, with RUN off and step and ROMI bits set. */
|
||||
switch (*controller->csrs->sel6) {
|
||||
case DSPDSR: /* 0x22b3 (read line status instruction), set the DTR bit in SEL2. */
|
||||
dmc_setreg (controller, 2, 0x800, DBG_RGC);
|
||||
break;
|
||||
case DROPDTR: /* 0xa40b (drop DTR instruction) - VMS Driver uses this */
|
||||
dmc_clr_modem_dtr (controller);
|
||||
break;
|
||||
case UINST_CNF: /* 0x2296 (get configuration switches) - VMS Driver uses this */
|
||||
dmc_setreg (controller, 6, 0x0006, DBG_RGC);
|
||||
break;
|
||||
case UINST_RROM:/* 0x814d (read DMC ROM) - VMS Driver uses this */
|
||||
dmc_setreg (controller, 6, 0x0391, DBG_RGC); /* Not Low Speed uCode value (0x390) */
|
||||
break;
|
||||
default:
|
||||
sim_debug(DBG_WRN, controller->device, "%s%d: dmc_process_command(). Unknown Microcode instruction 0x%04x", controller->device->name, controller->index, *controller->csrs->sel6);
|
||||
break;
|
||||
}
|
||||
*controller->csrs->sel0 &= ~DMC_SEL0_M_STEPUP;
|
||||
controller->transfer_state = Idle;
|
||||
}
|
||||
else {
|
||||
if (!dmc_is_dmc (controller) ||
|
||||
(*controller->csrs->sel0 & DMC_SEL0_M_ROMI) == 0) {
|
||||
if (dmc_is_run_set(controller)) {
|
||||
dmc_start_control_output_transfer(controller);
|
||||
dmc_start_transfer_buffer(controller);
|
||||
|
@ -3591,6 +3746,8 @@ else {
|
|||
dmc_setreg(controller, PA, (oldValue & ~mask) | (data & mask), DBG_REG);
|
||||
}
|
||||
|
||||
if (dmc_getsel(reg) == 0) /* writes to SEL0 may need immediate action */
|
||||
dmc_process_immediate(controller); /* Do any needed immediate actions */
|
||||
if ((dmc_getsel(reg) == 0) || (dmc_getsel(reg) == 1)) {/* writes to SEL0 and SEL2 are actionable */
|
||||
if (0 == controller->dmc_wr_delay) { /* Not waiting? */
|
||||
controller->dmc_wr_delay = 10; /* Wait a bit before acting on the changed register */
|
||||
|
|
Loading…
Add table
Reference in a new issue