HP2100: Latest changes from Dave Bryan.
hp2100_ipl.c: - Exposed "ipl_edtdelay" via a REG_HIDDEN register to allow user tuning of the EDT delay that works around a race condition in the HP 2000/Access Time-Shared BASIC system. - Corrected typos in comments and strings. - Merged SIMH 3.x and 4.x socket calls via conditionals, so that the module may be compiled for either version. hp2100_mux.c: - Corrected a typo in the RTS macro definition. hp2100_sys.c: - Added a cast to int for the parameter to "isspace" to avoid a compiler warning. hp2100_bugfixes.txt - Added a description of the IPL hidden register fix.
This commit is contained in:
parent
4baecec0b1
commit
1d6c14be3d
4 changed files with 117 additions and 17 deletions
|
@ -1,6 +1,6 @@
|
||||||
HP 2100 SIMULATOR BUG FIX WRITEUPS
|
HP 2100 SIMULATOR BUG FIX WRITEUPS
|
||||||
==================================
|
==================================
|
||||||
Last update: 2015-01-03
|
Last update: 2015-09-14
|
||||||
|
|
||||||
|
|
||||||
1. PROBLEM: Booting from magnetic tape reports "HALT instruction, P: 77756
|
1. PROBLEM: Booting from magnetic tape reports "HALT instruction, P: 77756
|
||||||
|
@ -6789,3 +6789,27 @@
|
||||||
modifying the S register directly.
|
modifying the S register directly.
|
||||||
|
|
||||||
STATUS: Fixed in version 4.0-0.
|
STATUS: Fixed in version 4.0-0.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
267. ENHANCEMENT: Add a register to the IPLI device to configure the DMA delay.
|
||||||
|
|
||||||
|
VERSION: 3.9-0
|
||||||
|
|
||||||
|
OBSERVATION: Occasionally, the 2000 Access terminal multiplexer does not
|
||||||
|
initialize properly; the problem is more prevalent on multiprocessor
|
||||||
|
systems.
|
||||||
|
|
||||||
|
There is a race condition between the system processor (SP) and the I/O
|
||||||
|
processor (IOP) during initialization. The problem occurs if the IOP DMA
|
||||||
|
completion interrupt routine finishes before the SP DMA completion
|
||||||
|
interrupt routine. As a workaround, the simulator suspends the IOP process
|
||||||
|
for one millisecond before signaling a DMA completion (EDT) interrupt.
|
||||||
|
Depending on system loading, this time may be insufficient.
|
||||||
|
|
||||||
|
RESOLUTION: Modify "ipli_reg" (hp2100_ipl.c) to add a hidden register,
|
||||||
|
EDTDELAY, that allows the user to configure the completion delay. The
|
||||||
|
register value is expressed in milliseconds and defaults to one
|
||||||
|
millisecond.
|
||||||
|
|
||||||
|
STATUS: Fixed in version 4.0-0.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* hp2100_ipl.c: HP 2000 interprocessor link simulator
|
/* hp2100_ipl.c: HP 2000 interprocessor link simulator
|
||||||
|
|
||||||
Copyright (c) 2002-2014, Robert M Supnik
|
Copyright (c) 2002-2015, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
IPLI, IPLO 12875A interprocessor link
|
IPLI, IPLO 12875A interprocessor link
|
||||||
|
|
||||||
|
14-Sep-15 JDB Exposed "ipl_edtdelay" via a REG_HIDDEN to allow user tuning
|
||||||
|
Corrected typos in comments and strings
|
||||||
|
05-Jun-15 JDB Merged 3.x and 4.x versions using conditionals
|
||||||
|
11-Feb-15 MP Revised ipl_detach and ipl_dscln for new sim_close_sock API
|
||||||
30-Dec-14 JDB Added S-register parameters to ibl_copy
|
30-Dec-14 JDB Added S-register parameters to ibl_copy
|
||||||
12-Dec-12 MP Revised ipl_attach for new socket API
|
12-Dec-12 MP Revised ipl_attach for new socket API
|
||||||
25-Oct-12 JDB Removed DEV_NET to allow restoration of listening ports
|
25-Oct-12 JDB Removed DEV_NET to allow restoration of listening ports
|
||||||
|
@ -72,6 +76,13 @@
|
||||||
#include "hp2100_cpu.h"
|
#include "hp2100_cpu.h"
|
||||||
#include "sim_sock.h"
|
#include "sim_sock.h"
|
||||||
#include "sim_tmxr.h"
|
#include "sim_tmxr.h"
|
||||||
|
#include "sim_rev.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if (SIM_MAJOR >= 4)
|
||||||
|
#define sim_close_sock(socket,master) sim_close_sock (socket)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef enum { ipli, iplo } CARD_INDEX; /* card index number */
|
typedef enum { ipli, iplo } CARD_INDEX; /* card index number */
|
||||||
|
|
||||||
|
@ -172,6 +183,7 @@ REG ipli_reg [] = {
|
||||||
{ ORDATA (HOLD, ipl [ipli].hold, 8) },
|
{ ORDATA (HOLD, ipl [ipli].hold, 8) },
|
||||||
{ DRDATA (TIME, ipl_ptime, 24), PV_LEFT },
|
{ DRDATA (TIME, ipl_ptime, 24), PV_LEFT },
|
||||||
{ FLDATA (STOP_IOE, ipl_stopioe, 0) },
|
{ FLDATA (STOP_IOE, ipl_stopioe, 0) },
|
||||||
|
{ DRDATA (EDTDELAY, ipl_edtdelay, 32), REG_HIDDEN | PV_LEFT },
|
||||||
{ ORDATA (SC, ipli_dib.select_code, 6), REG_HRO },
|
{ ORDATA (SC, ipli_dib.select_code, 6), REG_HRO },
|
||||||
{ ORDATA (DEVNO, ipli_dib.select_code, 6), REG_HRO },
|
{ ORDATA (DEVNO, ipli_dib.select_code, 6), REG_HRO },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
|
@ -256,7 +268,7 @@ DEVICE iplo_dev = {
|
||||||
The STC/CLC normally would cause a second "request device table" command
|
The STC/CLC normally would cause a second "request device table" command
|
||||||
to be recognized by the IOP, except that the IOP DMA setup routine
|
to be recognized by the IOP, except that the IOP DMA setup routine
|
||||||
"DMAXF" (in D61.asm) has specified an end-of-block CLC that holds off the
|
"DMAXF" (in D61.asm) has specified an end-of-block CLC that holds off the
|
||||||
IPL interrupt, and the completion interrupt routine "DMACP" ends with a
|
IPL interrupt, and the completion interrupt routine "DMCMP" ends with a
|
||||||
STC,C that clears the IPL flag.
|
STC,C that clears the IPL flag.
|
||||||
|
|
||||||
In hardware, the two CPUs are essentially interlocked by the DMA
|
In hardware, the two CPUs are essentially interlocked by the DMA
|
||||||
|
@ -266,7 +278,7 @@ DEVICE iplo_dev = {
|
||||||
that guarantee does not hold. If the STC/CLC occurs after the STC,C,
|
that guarantee does not hold. If the STC/CLC occurs after the STC,C,
|
||||||
then the IOP starts a second device table DMA transfer, which the SP is
|
then the IOP starts a second device table DMA transfer, which the SP is
|
||||||
not expecting. The IOP never processes the subsequent "start
|
not expecting. The IOP never processes the subsequent "start
|
||||||
timesharing" command, and the muxtiplexer is non-reponsive.
|
timesharing" command, and the multiplexer is non-responsive.
|
||||||
|
|
||||||
We employ a workaround that decreases the incidence of the problem: DMA
|
We employ a workaround that decreases the incidence of the problem: DMA
|
||||||
output completion interrupts are delayed to allow the other SIMH instance
|
output completion interrupts are delayed to allow the other SIMH instance
|
||||||
|
@ -276,7 +288,9 @@ DEVICE iplo_dev = {
|
||||||
a data response to the SP. This improves the race condition by delaying
|
a data response to the SP. This improves the race condition by delaying
|
||||||
the IOP until the SP has a chance to receive the last word, recognize its
|
the IOP until the SP has a chance to receive the last word, recognize its
|
||||||
own DMA input completion, drop out of the SFS loop, and execute the
|
own DMA input completion, drop out of the SFS loop, and execute the
|
||||||
STC/CLC.
|
STC/CLC. The delay, "ipl_edtdelay", is initialized to one millisecond
|
||||||
|
but is exposed via a hidden IPLI register, "EDTDELAY", that allows the
|
||||||
|
user to lengthen the delay if necessary.
|
||||||
|
|
||||||
The condition is only improved, and not solved, because "sleep"ing the
|
The condition is only improved, and not solved, because "sleep"ing the
|
||||||
IOP doesn't guarantee that the SP will actually execute. It's possible
|
IOP doesn't guarantee that the SP will actually execute. It's possible
|
||||||
|
@ -574,10 +588,14 @@ return SCPE_OK;
|
||||||
t_stat ipl_attach (UNIT *uptr, char *cptr)
|
t_stat ipl_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
SOCKET newsock;
|
SOCKET newsock;
|
||||||
uint32 i, t;
|
|
||||||
char host [CBUFSIZE], port [CBUFSIZE], hostport [2 * CBUFSIZE + 3];
|
|
||||||
char *tptr = NULL;
|
char *tptr = NULL;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
|
#if (SIM_MAJOR >= 4)
|
||||||
|
|
||||||
|
uint32 i, t;
|
||||||
|
char host [CBUFSIZE], port [CBUFSIZE], hostport [2 * CBUFSIZE + 3];
|
||||||
|
|
||||||
t_bool is_active;
|
t_bool is_active;
|
||||||
|
|
||||||
is_active = (uptr->flags & UNIT_ACTV) == UNIT_ACTV; /* is the connection active? */
|
is_active = (uptr->flags & UNIT_ACTV) == UNIT_ACTV; /* is the connection active? */
|
||||||
|
@ -636,6 +654,60 @@ if (tptr == NULL) { /* no memory? */
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
}
|
}
|
||||||
strcpy (tptr, hostport); /* copy ipaddr:port */
|
strcpy (tptr, hostport); /* copy ipaddr:port */
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
uint32 i, t, ipa, ipp, oldf;
|
||||||
|
|
||||||
|
r = get_ipaddr (cptr, &ipa, &ipp);
|
||||||
|
if ((r != SCPE_OK) || (ipp == 0))
|
||||||
|
return SCPE_ARG;
|
||||||
|
oldf = uptr->flags;
|
||||||
|
if (oldf & UNIT_ATT)
|
||||||
|
ipl_detach (uptr);
|
||||||
|
if ((sim_switches & SWMASK ('C')) ||
|
||||||
|
((sim_switches & SIM_SW_REST) && (oldf & UNIT_ACTV))) {
|
||||||
|
if (ipa == 0)
|
||||||
|
ipa = 0x7F000001;
|
||||||
|
newsock = sim_connect_sock (ipa, ipp);
|
||||||
|
if (newsock == INVALID_SOCKET)
|
||||||
|
return SCPE_IOERR;
|
||||||
|
printf ("Connecting to IP address %d.%d.%d.%d, port %d\n",
|
||||||
|
(ipa >> 24) & 0xff, (ipa >> 16) & 0xff,
|
||||||
|
(ipa >> 8) & 0xff, ipa & 0xff, ipp);
|
||||||
|
if (sim_log)
|
||||||
|
fprintf (sim_log,
|
||||||
|
"Connecting to IP address %d.%d.%d.%d, port %d\n",
|
||||||
|
(ipa >> 24) & 0xff, (ipa >> 16) & 0xff,
|
||||||
|
(ipa >> 8) & 0xff, ipa & 0xff, ipp);
|
||||||
|
uptr->flags = uptr->flags | UNIT_ACTV;
|
||||||
|
uptr->LSOCKET = 0;
|
||||||
|
uptr->DSOCKET = newsock;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (ipa != 0)
|
||||||
|
return SCPE_ARG;
|
||||||
|
newsock = sim_master_sock (ipp);
|
||||||
|
if (newsock == INVALID_SOCKET)
|
||||||
|
return SCPE_IOERR;
|
||||||
|
printf ("Listening on port %d\n", ipp);
|
||||||
|
if (sim_log)
|
||||||
|
fprintf (sim_log, "Listening on port %d\n", ipp);
|
||||||
|
uptr->flags = uptr->flags & ~UNIT_ACTV;
|
||||||
|
uptr->LSOCKET = newsock;
|
||||||
|
uptr->DSOCKET = 0;
|
||||||
|
}
|
||||||
|
uptr->IBUF = uptr->OBUF = 0;
|
||||||
|
uptr->flags = (uptr->flags | UNIT_ATT) & ~(UNIT_ESTB | UNIT_HOLD);
|
||||||
|
tptr = (char *) malloc (strlen (cptr) + 1); /* get string buf */
|
||||||
|
if (tptr == NULL) { /* no memory? */
|
||||||
|
ipl_detach (uptr); /* close sockets */
|
||||||
|
return SCPE_MEM;
|
||||||
|
}
|
||||||
|
strcpy (tptr, cptr); /* copy ipaddr:port */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
uptr->filename = tptr; /* save */
|
uptr->filename = tptr; /* save */
|
||||||
sim_activate (uptr, POLL_FIRST); /* activate first poll "immediately" */
|
sim_activate (uptr, POLL_FIRST); /* activate first poll "immediately" */
|
||||||
if (sim_switches & SWMASK ('W')) { /* wait? */
|
if (sim_switches & SWMASK ('W')) { /* wait? */
|
||||||
|
@ -644,7 +716,7 @@ if (sim_switches & SWMASK ('W')) { /* wait? */
|
||||||
if (t) /* established? */
|
if (t) /* established? */
|
||||||
break;
|
break;
|
||||||
if ((i % 10) == 0) /* status every 10 sec */
|
if ((i % 10) == 0) /* status every 10 sec */
|
||||||
printf ("Waiting for connnection\n");
|
printf ("Waiting for connection\n");
|
||||||
sim_os_sleep (1); /* sleep 1 sec */
|
sim_os_sleep (1); /* sleep 1 sec */
|
||||||
}
|
}
|
||||||
if (t) /* if connected (set by "ipl_check_conn" above) */
|
if (t) /* if connected (set by "ipl_check_conn" above) */
|
||||||
|
@ -661,12 +733,12 @@ if (!(uptr->flags & UNIT_ATT)) /* attached? */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
||||||
if (uptr->flags & UNIT_ACTV)
|
if (uptr->flags & UNIT_ACTV)
|
||||||
sim_close_sock (uptr->DSOCKET);
|
sim_close_sock (uptr->DSOCKET, 1);
|
||||||
|
|
||||||
else {
|
else {
|
||||||
if (uptr->flags & UNIT_ESTB) /* if established, */
|
if (uptr->flags & UNIT_ESTB) /* if established, */
|
||||||
sim_close_sock (uptr->DSOCKET); /* close data socket */
|
sim_close_sock (uptr->DSOCKET, 0); /* close data socket */
|
||||||
sim_close_sock (uptr->LSOCKET); /* closen listen socket */
|
sim_close_sock (uptr->LSOCKET, 1); /* closen listen socket */
|
||||||
}
|
}
|
||||||
|
|
||||||
free (uptr->filename); /* free string */
|
free (uptr->filename); /* free string */
|
||||||
|
@ -688,7 +760,7 @@ if (((uptr->flags & UNIT_ATT) == 0) ||
|
||||||
(uptr->flags & UNIT_ACTV) ||
|
(uptr->flags & UNIT_ACTV) ||
|
||||||
((uptr->flags & UNIT_ESTB) == 0))
|
((uptr->flags & UNIT_ESTB) == 0))
|
||||||
return SCPE_NOFNC;
|
return SCPE_NOFNC;
|
||||||
sim_close_sock (uptr->DSOCKET);
|
sim_close_sock (uptr->DSOCKET, 0);
|
||||||
uptr->DSOCKET = 0;
|
uptr->DSOCKET = 0;
|
||||||
uptr->flags = uptr->flags & ~UNIT_ESTB;
|
uptr->flags = uptr->flags & ~UNIT_ESTB;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -790,7 +862,7 @@ const int32 devi = ipli_dib.select_code;
|
||||||
const int32 devp = ptr_dib.select_code;
|
const int32 devp = ptr_dib.select_code;
|
||||||
|
|
||||||
if (ibl_copy (ipl_rom, devi, IBL_S_CLR, /* copy the boot ROM to memory and configure */
|
if (ibl_copy (ipl_rom, devi, IBL_S_CLR, /* copy the boot ROM to memory and configure */
|
||||||
IBL_SET_SC (devi) | devp)) /* the S register accordingly */
|
IBL_SET_SC (devi) | devp)) /* the S register accordingly */
|
||||||
return SCPE_IERR; /* return an internal error if the copy failed */
|
return SCPE_IERR; /* return an internal error if the copy failed */
|
||||||
|
|
||||||
WritePW (PC + MAX_BASE, (~PC + 1) & DMASK); /* fix ups */
|
WritePW (PC + MAX_BASE, (~PC + 1) & DMASK); /* fix ups */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* hp2100_mux.c: HP 2100 12920A terminal multiplexor simulator
|
/* hp2100_mux.c: HP 2100 12920A terminal multiplexor simulator
|
||||||
|
|
||||||
Copyright (c) 2002-2014, Robert M Supnik
|
Copyright (c) 2002-2015, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
MUX,MUXL,MUXM 12920A terminal multiplexor
|
MUX,MUXL,MUXM 12920A terminal multiplexor
|
||||||
|
|
||||||
|
29-Jun-15 JDB Corrected typo in RTS macro definition
|
||||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||||
10-Jan-13 MP Added DEV_MUX and additional DEVICE field values
|
10-Jan-13 MP Added DEV_MUX and additional DEVICE field values
|
||||||
10-Feb-12 JDB Deprecated DEVNO in favor of SC
|
10-Feb-12 JDB Deprecated DEVNO in favor of SC
|
||||||
|
@ -221,7 +222,7 @@
|
||||||
#define OTC_SS2 0000002 /* SSn flops */
|
#define OTC_SS2 0000002 /* SSn flops */
|
||||||
#define OTC_SS1 0000001
|
#define OTC_SS1 0000001
|
||||||
#define OTC_RW (OTC_ES2|OTC_ES1|OTC_SS2|OTC_SS1)
|
#define OTC_RW (OTC_ES2|OTC_ES1|OTC_SS2|OTC_SS1)
|
||||||
#define RTS OCT_C2 /* C2 = rts */
|
#define RTS OTC_C2 /* C2 = rts */
|
||||||
#define DTR OTC_C1 /* C1 = dtr */
|
#define DTR OTC_C1 /* C1 = dtr */
|
||||||
|
|
||||||
/* LIA, control */
|
/* LIA, control */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* hp2100_sys.c: HP 2100 simulator interface
|
/* hp2100_sys.c: HP 2100 simulator interface
|
||||||
|
|
||||||
Copyright (c) 1993-2014, Robert M. Supnik
|
Copyright (c) 1993-2015, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
18-Jun-15 JDB Added cast to int for isspace parameter
|
||||||
24-Dec-14 JDB Added casts to t_addr and t_value for 64-bit compatibility
|
24-Dec-14 JDB Added casts to t_addr and t_value for 64-bit compatibility
|
||||||
Made local routines static
|
Made local routines static
|
||||||
05-Feb-13 JDB Added hp_fprint_stopped to handle HLT instruction message
|
05-Feb-13 JDB Added hp_fprint_stopped to handle HLT instruction message
|
||||||
|
@ -430,10 +431,12 @@ static const int32 vtab[] = {
|
||||||
|
|
||||||
#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
|
#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
|
||||||
|
|
||||||
|
#if (SIM_MAJOR >= 4)
|
||||||
/* Use scp.c provided fprintf function */
|
/* Use scp.c provided fprintf function */
|
||||||
#define fprintf Fprintf
|
#define fprintf Fprintf
|
||||||
#define fputs(_s,f) Fprintf(f,"%s",_s)
|
#define fputs(_s,f) Fprintf(f,"%s",_s)
|
||||||
#define fputc(_c,f) Fprintf(f,"%c",_c)
|
#define fputc(_c,f) Fprintf(f,"%c",_c)
|
||||||
|
#endif
|
||||||
|
|
||||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||||
UNIT *uptr, int32 sw)
|
UNIT *uptr, int32 sw)
|
||||||
|
@ -615,7 +618,7 @@ t_stat r, ret;
|
||||||
char *cptr, gbuf[CBUFSIZE];
|
char *cptr, gbuf[CBUFSIZE];
|
||||||
|
|
||||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||||
while (isspace (*iptr)) iptr++; /* absorb spaces */
|
while (isspace ((int) *iptr)) iptr++; /* absorb spaces */
|
||||||
if ((sw & SWMASK ('A')) || ((*iptr == '\'') && iptr++)) { /* ASCII char? */
|
if ((sw & SWMASK ('A')) || ((*iptr == '\'') && iptr++)) { /* ASCII char? */
|
||||||
if (iptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
if (iptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||||
val[0] = (t_value) iptr[0] & 0177;
|
val[0] = (t_value) iptr[0] & 0177;
|
||||||
|
|
Loading…
Add table
Reference in a new issue