1
0
mirror of https://github.com/open-simh/simh.git synced 2026-04-26 12:17:25 +00:00

Notes For V3.3-1

1. New Features in 3.3-1

1.1 H316

TTY	- implemented paper-tape reader and punch
	- added ASCII file support

PTR,PTP	- added ASCII file support

1.2 HP2100

CPU	- added SET CPU 21MX-M, 21MX-E (from Dave Brian)
	- disabled TIMER/EXECUTE/DIAG instructions for 21MX-M (from Dave Bryan)
	- added post-processor to maintain T/M consistency (from Dave Bryan)

DS	- released 13037 disk controller

1.3 Interdata

MT	- added read-only file support

1.4 SDS

MT	- added read-only file support

1.5 PDP-11

TM,TS	- added read-only file support

2. Bugs Fixed in 3.3

2.1 H316

CPU	- fixed bug in divide

LPT	- fixed bug in DMA/DMC support

MT	- fixed bug in DMA/DMC support

DP	- fixed bug in skip on not seeking

TTY	- fixed bugs in SKS '104, '504

2.2 HP2100

CPU	- fixed DMA reset to clear alternate CTL flop (from Dave Bryan)
	- fixed bug in JPY (from Dave Bryan)
	- fixed bugs in CBS, SBS, TBS
	- separate A/B from M[0/1] for DMA (found by Dave Bryan)

LPS	- added restart when set online, etc. (from Dave Bryan)
	- fixed col count for non-printing chars (from Dave Bryan)

LPT	- added restart when set online, etc. (from Dave Bryan)

2.3 PDP-11

CPU	- fixed WAIT to work in all modes (from John Dundas)
This commit is contained in:
Bob Supnik
2005-01-09 13:55:00 -08:00
committed by Mark Pizzolato
parent b6393b36b4
commit 9b5c8c9711
42 changed files with 1698 additions and 584 deletions

View File

@@ -23,10 +23,19 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
CPU 2116A/2100A/21MXE central processing unit
CPU 2116A/2100A/21MX-M/21MX-E central processing unit
MP 12892B memory protect
DMA0,DMA1 12895A/12897B direct memory access/dual channel port controller
26-Dec-04 RMS DMA reset doesn't clear alternate CTL flop (from Dave Bryan)
DMA reset shouldn't clear control words (from Dave Bryan)
Alternate CTL flop not visible as register (from Dave Bryan)
Fixed CBS, SBS, TBS to perform virtual reads
Separated A/B from M[0/1] for DMA IO (from Dave Bryan)
Fixed bug in JPY (from Dave Bryan)
25-Dec-04 JDB Added SET CPU 21MX-M, 21MX-E (21MX defaults to MX-E)
TIMER/EXECUTE/DIAG instructions disabled for 21MX-M
T-register reflects changes in M-register when halted
25-Sep-04 JDB Moved MP into its own device; added MP option jumpers
Modified DMA to allow disabling
Modified SET CPU 2100/2116 to truncate memory > 32K
@@ -327,13 +336,14 @@
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = err_PC
#define UNIT_V_2100 (UNIT_V_UF + 0) /* 2100 */
#define UNIT_V_21MX (UNIT_V_UF + 1) /* 21MX */
#define UNIT_V_21MX (UNIT_V_UF + 1) /* 21MX-E or 21MX-M */
#define UNIT_V_EAU (UNIT_V_UF + 2) /* EAU */
#define UNIT_V_FP (UNIT_V_UF + 3) /* FP */
#define UNIT_V_DMS (UNIT_V_UF + 4) /* DMS */
#define UNIT_V_IOP (UNIT_V_UF + 5) /* 2100 IOP */
#define UNIT_V_IOPX (UNIT_V_UF + 6) /* 21MX IOP */
#define UNIT_V_MSIZE (UNIT_V_UF + 7) /* dummy mask */
#define UNIT_V_MXM (UNIT_V_UF + 8) /* 21MX is M-series */
#define UNIT_2116 (0)
#define UNIT_2100 (1 << UNIT_V_2100)
#define UNIT_21MX (1 << UNIT_V_21MX)
@@ -343,6 +353,7 @@
#define UNIT_IOP (1 << UNIT_V_IOP)
#define UNIT_IOPX (1 << UNIT_V_IOPX)
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
#define UNIT_MXM (1 << UNIT_V_MXM)
#define UNIT_V_MP_JSB (UNIT_V_UF + 0) /* MP jumper W5 out */
#define UNIT_V_MP_INT (UNIT_V_UF + 1) /* MP jumper W6 out */
@@ -365,6 +376,7 @@
uint16 *M = NULL; /* memory */
uint32 saved_AR = 0; /* A register */
uint32 saved_BR = 0; /* B register */
uint16 ABREG[2]; /* during execution */
uint32 PC = 0; /* P register */
uint32 SR = 0; /* S register */
uint32 MR = 0; /* M register */
@@ -433,11 +445,14 @@ uint16 ReadW (uint32 addr);
uint16 ReadWA (uint32 addr);
uint32 ReadF (uint32 addr);
uint16 ReadIO (uint32 addr, uint32 map);
uint16 ReadPW (uint32 addr);
uint16 ReadTAB (uint32 addr);
void WriteB (uint32 addr, uint32 dat);
void WriteBA (uint32 addr, uint32 dat);
void WriteW (uint32 addr, uint32 dat);
void WriteWA (uint32 addr, uint32 dat);
void WriteIO (uint32 addr, uint32 dat, uint32 map);
void WritePW (uint32 addr, uint32 dat);
t_stat iogrp (uint32 ir, uint32 iotrap);
uint32 dms (uint32 va, uint32 map, uint32 prot);
uint32 dms_io (uint32 va, uint32 map);
@@ -460,6 +475,7 @@ t_stat dma1_reset (DEVICE *dptr);
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc);
t_bool dev_conflict (void);
void hp_post_cmd (t_bool from_scp);
extern uint32 f_as (uint32 op, t_bool sub);
extern uint32 f_mul (uint32 op);
@@ -467,6 +483,7 @@ extern uint32 f_div (uint32 op);
extern uint32 f_fix (void);
extern uint32 f_flt (void);
extern int32 clk_delay (int32 flg);
extern void (*sim_vm_post) (t_bool from_scp);
/* CPU data structures
@@ -525,12 +542,16 @@ MTAB cpu_mod[] = {
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
UNIT_2100+UNIT_EAU, NULL, "2100", &cpu_set_opt,
NULL, (void *) UNIT_2100 },
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS, NULL, "21MX", &cpu_set_opt,
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS, NULL, "21MX-E", &cpu_set_opt,
NULL, (void *) UNIT_21MX },
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
UNIT_21MX+UNIT_MXM+UNIT_EAU+UNIT_FP+UNIT_DMS, NULL, "21MX-M", &cpu_set_opt,
NULL, (void *) UNIT_21MX },
{ UNIT_2116+UNIT_2100+UNIT_21MX, UNIT_2116, "2116", NULL, NULL },
{ UNIT_2116+UNIT_2100+UNIT_21MX, UNIT_2100, "2100", NULL, NULL },
{ UNIT_2116+UNIT_2100+UNIT_21MX, UNIT_21MX, "21MX", NULL, NULL },
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM, UNIT_21MX, "21MX-E", NULL, NULL },
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM, UNIT_21MX+UNIT_MXM, "21MX-M", NULL, NULL },
{ UNIT_EAU, UNIT_EAU, "EAU", "EAU", &cpu_set_opt,
NULL, (void *) UNIT_EAU },
{ UNIT_EAU, 0, "no EAU", "NOEAU", &cpu_set_opt,
@@ -616,6 +637,7 @@ REG dma0_reg[] = {
{ FLDATA (CTL, dev_ctl[DMA0/32], INT_V (DMA0)) },
{ FLDATA (FLG, dev_flg[DMA0/32], INT_V (DMA0)) },
{ FLDATA (FBF, dev_fbf[DMA0/32], INT_V (DMA0)) },
{ FLDATA (CTLALT, dev_ctl[DMALT0/32], INT_V (DMALT0)) },
{ ORDATA (CW1, dmac[0].cw1, 16) },
{ ORDATA (CW2, dmac[0].cw2, 16) },
{ ORDATA (CW3, dmac[0].cw3, 16) },
@@ -635,6 +657,7 @@ REG dma1_reg[] = {
{ FLDATA (CTL, dev_ctl[DMA1/32], INT_V (DMA1)) },
{ FLDATA (FLG, dev_flg[DMA1/32], INT_V (DMA1)) },
{ FLDATA (FBF, dev_fbf[DMA1/32], INT_V (DMA1)) },
{ FLDATA (CTLALT, dev_ctl[DMALT1/32], INT_V (DMALT1)) },
{ ORDATA (CW1, dmac[1].cw1, 16) },
{ ORDATA (CW2, dmac[1].cw2, 16) },
{ ORDATA (CW3, dmac[1].cw3, 16) },
@@ -735,7 +758,7 @@ static const uint32 e_inst[512] = {
X_MR,X_NO,X_MR,X_MR,X_NO,X_MR,X_MR,X_NO, /* S*X,C*X,L*X,STX,CX*,LDX,ADX,X*X */
X_MR,X_NO,X_MR,X_MR,X_NO,X_MR,X_MR,X_NO, /* S*Y,C*Y,L*Y,STY,CY*,LDY,ADY,X*Y */
X_NO,X_NO,X_MR,X_NO,X_NO,X_AZ,X_AZ,X_NO, /* ISX,DSX,JLY,LBT,SBT,MBT,CBT,SFB */
X_NO,X_NO,X_MR,X_AA,X_AA,X_AA,X_AZ,X_AZ }; /* ISY,DSY,JPY,SBS,CBS,TBS,CMW,MVW */
X_NO,X_NO,X_NO,X_AA,X_AA,X_AA,X_AZ,X_AZ }; /* ISY,DSY,JPY,SBS,CBS,TBS,CMW,MVW */
/* Interrupt defer table */
@@ -1095,16 +1118,31 @@ case 0214:case 0215:case 0216:case 0217:
intrq = calc_int (); /* recalc interrupts */
break; /* end if I/O */
/* Extended arithmetic */
/* Extended arithmetic
The 21MX-E adds three "special instructions" that do not exist in earlier
CPUs, including the 21MX-M. They are: TIMER (100060), EXECUTE (100120), and
DIAG (100000). On the 21MX-M, these instruction codes map to the
microroutines for MPY, ASL, and RRL, respectively.
Under simulation, these cause undefined instruction stops if the CPU is set
to 2100 or 2116. They do not cause stops on the 21MX-M, as TIMER in
particular is used by several HP programs to differentiate between M- and
E-series machines. */
case 0200: /* EAU group 0 */
if ((cpu_unit.flags & UNIT_EAU) == 0) { /* implemented? */
reason = stop_inst;
break; }
switch ((IR >> 4) & 017) { /* decode IR<7:4> */
case 000: /* diagnostic */
break;
case 001: /* ASL */
case 005: /* EXECUTE */
if (!(cpu_unit.flags & UNIT_21MX)) { /* must be 21MX */
reason = stop_inst; /* trap if not */
break; }
else if (!(cpu_unit.flags & UNIT_MXM)) { /* E-series? */
PC = (PC + 1) & VAMASK; /* not simulated */
break; }
case 001: /* ASL (+ EXECUTE on 21MX-M) */
sc = (IR & 017)? (IR & 017): 16; /* get sc */
O = 0; /* clear ovflo */
while (sc-- != 0) { /* bit by bit */
@@ -1118,17 +1156,27 @@ case 0200: /* EAU group 0 */
BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK;
AR = (AR << sc) & DMASK; /* BR'AR lsh left */
break;
case 003: /* TIMER */
BR = (BR + 1) & DMASK; /* increment B */
if (BR) PC = err_PC; /* if !=0, repeat */
break;
case 004: /* RRL */
case 000: /* DIAG */
if (!(cpu_unit.flags & UNIT_21MX)) { /* must be 21MX */
reason = stop_inst; /* trap if not */
break; }
else if (!(cpu_unit.flags & UNIT_MXM)) /* E-series? */
break; /* is NOP unless halted */
case 004: /* RRL (+ DIAG on 21MX-M) */
sc = (IR & 017)? (IR & 017): 16; /* get sc */
t = BR; /* BR'AR rot left */
BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK;
AR = ((AR << sc) | (t >> (16 - sc))) & DMASK;
break;
case 010: /* MPY */
case 003: /* TIMER */
if (!(cpu_unit.flags & UNIT_21MX)) { /* must be 21MX */
reason = stop_inst; /* trap if not */
break; }
else if (!(cpu_unit.flags & UNIT_MXM)) { /* E-series? */
BR = (BR + 1) & DMASK; /* increment B */
if (BR) PC = err_PC; /* if !=0, repeat */
break; }
case 010: /* MPY (+ TIMER on 21MX-M) */
if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */
sop1 = SEXT (AR); /* sext AR */
sop2 = SEXT (ReadW (MA)); /* sext mem */
@@ -1844,13 +1892,19 @@ case 0203:case 0213: /* MAC1 ext */
/* Bit, word instructions */
case 0773: /* SBS (E_AA) */
WriteW (M1, M[M1] | M [MA]); /* set bit */
v1 = ReadW (MA);
v2 = ReadW (M1);
WriteW (M1, v2 | v1); /* set bit */
break;
case 0774: /* CBS (E_AA) */
WriteW (M1, M[M1] & ~M[MA]); /* clear bit */
v1 = ReadW (MA);
v2 = ReadW (M1);
WriteW (M1, v2 & ~v1); /* clear bit */
break;
case 0775: /* TBS (E_AA) */
if ((M[MA] & M[M1]) != M[MA]) /* test bit */
v1 = ReadW (MA);
v2 = ReadW (M1);
if ((v2 & v1) != v1) /* test bits */
PC = (PC + 1) & VAMASK;
break;
case 0776: /* CMW (E_AZ) */
@@ -1900,13 +1954,13 @@ if (reason == STOP_INDINT) { /* indirect intr? */
/* Simulation halted */
if (iotrap && (reason == STOP_HALT)) MR = intaddr; /* HLT in trap cell? */
else MR = (PC - 1) & VAMASK; /* no, M = P - 1 */
TR = ReadIO (MR, dms_ump); /* last word fetched */
if ((reason == STOP_RSRV) || (reason == STOP_IODV) || /* instr error? */
(reason == STOP_IND)) PC = err_PC; /* back up PC */
saved_AR = AR & DMASK;
saved_BR = BR & DMASK;
if (iotrap && (reason == STOP_HALT)) MR = intaddr; /* HLT in trap cell? */
else MR = (PC - 1) & VAMASK; /* no, M = P - 1 */
TR = ReadTAB (MR); /* last word fetched */
if ((reason == STOP_RSRV) || (reason == STOP_IODV) || /* instr error? */
(reason == STOP_IND)) PC = err_PC; /* back up PC */
dms_upd_sr (); /* update dms_sr */
for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */
dibp = (DIB *) dptr->ctxt; /* get DIB */
@@ -2096,8 +2150,8 @@ int32 pa;
if (dms_enb) pa = dms (va >> 1, dms_ump, RD);
else pa = va >> 1;
if (va & 1) return (M[pa] & 0377);
else return ((M[pa] >> 8) & 0377);
if (va & 1) return (ReadPW (pa) & 0377);
else return ((ReadPW (pa) >> 8) & 0377);
}
uint8 ReadBA (uint32 va)
@@ -2106,8 +2160,8 @@ uint32 pa;
if (dms_enb) pa = dms (va >> 1, dms_ump ^ MAP_LNT, RD);
else pa = va >> 1;
if (va & 1) return (M[pa] & 0377);
else return ((M[pa] >> 8) & 0377);
if (va & 1) return (ReadPW (pa) & 0377);
else return ((ReadPW (pa) >> 8) & 0377);
}
uint16 ReadW (uint32 va)
@@ -2116,7 +2170,7 @@ uint32 pa;
if (dms_enb) pa = dms (va, dms_ump, RD);
else pa = va;
return M[pa];
return ReadPW (pa);
}
uint16 ReadWA (uint32 va)
@@ -2125,7 +2179,7 @@ uint32 pa;
if (dms_enb) pa = dms (va, dms_ump ^ MAP_LNT, RD);
else pa = va;
return M[pa];
return ReadPW (pa);
}
uint32 ReadF (uint32 va)
@@ -2144,6 +2198,19 @@ else pa = va;
return M[pa];
}
uint16 ReadPW (uint32 pa)
{
if (pa <= 1) return ABREG[pa];
return M[pa];
}
uint16 ReadTAB (uint32 addr)
{
if (addr == 0) return saved_AR;
else if (addr == 1) return saved_BR;
else return ReadIO (addr, dms_ump);
}
/* Memory protection test for writes
From Dave Bryan: The problem is that memory writes aren't being checked for
@@ -2157,20 +2224,22 @@ return M[pa];
void WriteB (uint32 va, uint32 dat)
{
uint32 pa;
uint32 pa, t;
if (dms_enb) pa = dms (va >> 1, dms_ump, WR);
else pa = va >> 1;
if (MP_TEST (va >> 1)) ABORT (ABORT_PRO);
if (MEM_ADDR_OK (pa)) {
if (va & 1) M[pa] = (M[pa] & 0177400) | (dat & 0377);
else M[pa] = (M[pa] & 0377) | ((dat & 0377) << 8); }
t = ReadPW (pa);
if (va & 1) t = (t & 0177400) | (dat & 0377);
else t = (t & 0377) | ((dat & 0377) << 8);
WritePW (pa, t); }
return;
}
void WriteBA (uint32 va, uint32 dat)
{
uint32 pa;
uint32 pa, t;
if (dms_enb) {
dms_viol (va >> 1, MVI_WPR); /* viol if prot */
@@ -2178,8 +2247,10 @@ if (dms_enb) {
else pa = va >> 1;
if (MP_TEST (va >> 1)) ABORT (ABORT_PRO);
if (MEM_ADDR_OK (pa)) {
if (va & 1) M[pa] = (M[pa] & 0177400) | (dat & 0377);
else M[pa] = (M[pa] & 0377) | ((dat & 0377) << 8); }
t = ReadPW (pa);
if (va & 1) t = (t & 0177400) | (dat & 0377);
else t = (t & 0377) | ((dat & 0377) << 8);
WritePW (pa, t); }
return;
}
@@ -2190,7 +2261,7 @@ uint32 pa;
if (dms_enb) pa = dms (va, dms_ump, WR);
else pa = va;
if (MP_TEST (va)) ABORT (ABORT_PRO);
if (MEM_ADDR_OK (pa)) M[pa] = dat;
if (MEM_ADDR_OK (pa)) WritePW (pa, dat);
return;
}
@@ -2203,7 +2274,7 @@ if (dms_enb) {
pa = dms (va, dms_ump ^ MAP_LNT, WR); }
else pa = va;
if (MP_TEST (va)) ABORT (ABORT_PRO);
if (MEM_ADDR_OK (pa)) M[pa] = dat;
if (MEM_ADDR_OK (pa)) WritePW (pa, dat);
return;
}
@@ -2213,7 +2284,14 @@ uint32 pa;
if (dms_enb) pa = dms_io (va, map);
else pa = va;
if (MEM_ADDR_OK (pa)) M[pa] = dat;
if (MEM_ADDR_OK (pa)) M[pa] = dat & DMASK;
return;
}
void WritePW (uint32 pa, uint32 dat)
{
if (pa <= 1) ABREG[pa] = dat & DMASK;
else M[pa] = dat & DMASK;
return;
}
@@ -2630,6 +2708,7 @@ if (M == NULL) M = calloc (PASIZE, sizeof (uint16));
if (M == NULL) return SCPE_MEM;
if (pcq_r) pcq_r->qptr = 0;
else return SCPE_IERR;
sim_vm_post = &hp_post_cmd; /* set cmd post proc */
return SCPE_OK;
}
@@ -2652,7 +2731,9 @@ clrCMD (DMA0);
clrCTL (DMA0);
setFLG (DMA0);
clrSRQ (DMA0);
dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0;
clrCTL (DMALT0);
if (sim_switches & SWMASK ('P')) /* power up? */
dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0;
return SCPE_OK;
}
@@ -2663,7 +2744,9 @@ clrCMD (DMA1);
clrCTL (DMA1);
setFLG (DMA1);
clrSRQ (DMA1);
dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0;
clrCTL (DMALT1);
if (sim_switches & SWMASK ('P')) /* power up? */
dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0;
return SCPE_OK;
}
@@ -2675,8 +2758,8 @@ int32 d;
addr = dms_cons (addr, sw);
if (addr >= MEMSIZE) return SCPE_NXM;
if (addr == 0) d = saved_AR;
else if (addr == 1) d = saved_BR;
if (!(sw & SIM_SW_REST) && (addr == 0)) d = saved_AR;
else if (!(sw & SIM_SW_REST) && (addr == 1)) d = saved_BR;
else d = M[addr];
if (vptr != NULL) *vptr = d & DMASK;
return SCPE_OK;
@@ -2688,8 +2771,8 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
{
addr = dms_cons (addr, sw);
if (addr >= MEMSIZE) return SCPE_NXM;
if (addr == 0) saved_AR = val & DMASK;
else if (addr == 1) saved_BR = val & DMASK;
if (!(sw & SIM_SW_REST) && (addr == 0)) saved_AR = val & DMASK;
else if (!(sw & SIM_SW_REST) && (addr == 1)) saved_BR = val & DMASK;
else M[addr] = val & DMASK;
return SCPE_OK;
}
@@ -2758,6 +2841,16 @@ else dcp->flags = dcp->flags & ~DEV_DIS;
return;
}
/* Command post-processor
Update T register to contents of memory addressed by M register. */
void hp_post_cmd (t_bool from_scp)
{
TR = ReadTAB (MR); /* sync T with M */
return;
}
/* Test for device conflict */
t_bool dev_conflict (void)

View File

@@ -23,6 +23,8 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
30-Dec-04 JDB Added IBL_DS_HEAD head number mask
19-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF stop codes
25-Apr-04 RMS Added additional IBL definitions
Added DMA EDT I/O pseudo-opcode
25-Apr-03 RMS Revised for extended file support
@@ -35,7 +37,7 @@
14-Apr-99 RMS Changed t_addr to unsigned
The author gratefully acknowledges the help of Jeff Moffat in answering
questions about the HP2100; and of Dave Bryan in adding featurs and
questions about the HP2100; and of Dave Bryan in adding features and
correcting errors throughout the simulator.
*/
@@ -50,6 +52,8 @@
#define STOP_IND 5 /* indirect loop */
#define STOP_INDINT 6 /* indirect intr */
#define STOP_NOCONN 7 /* no connection */
#define STOP_OFFLINE 8 /* device offline */
#define STOP_PWROFF 9 /* device powered off */
#define ABORT_PRO 1 /* protection abort */
@@ -69,9 +73,8 @@
#define SIGN32 020000000000 /* 32b sign */
#define SIGN 0100000 /* 16b sign */
#define DMASK 0177777 /* 16b data mask */
#define AR M[0] /* A = location 0 */
#define BR M[1] /* B = location 1 */
#define ABREG M /* register array */
#define AR ABREG[0] /* A = reg 0 */
#define BR ABREG[1] /* B = reg 1 */
#define SEXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)))
/* Memory reference instructions */
@@ -232,6 +235,7 @@ struct DMA { /* DMA channel */
#define IBL_V_DEV 6 /* dev in <11:6> */
#define IBL_OPT 0000070 /* options in <5:3> */
#define IBL_DP_REM 0000001 /* DP removable */
#define IBL_DS_HEAD 0000003 /* DS head number */
#define IBL_LNT 64 /* boot length */
#define IBL_MASK (IBL_LNT - 1) /* boot length mask */
#define IBL_DPC (IBL_LNT - 2) /* DMA ctrl word */

View File

@@ -1,6 +1,6 @@
SIMH/HP 21XX DIAGNOSTICS PERFORMANCE
====================================
Last update: 2004-11-02
Last update: 2004-12-29
The HP 24396 diagnostic suite has been run against the SIMH HP 21xx simulation.
@@ -28,7 +28,7 @@ The results of the diagnostic runs are summarized below:
101100 Memory Reference Instruction Group 1624 3.2-3 Passed
101001 Alter-Skip Instruction Group 1431 3.2-3 Passed
101002 Shift-Rotate Instruction Group 1431 3.2-3 Passed
102200 Core Memory (2100/16/15/14) 1624 - No simulation
102200 Core Memory (2100/16/15/14) 1624 3.3-0 Passed
102104 Semiconductor Memory (21MX) 1644 3.2-3 Passed
101004 EAU Instruction Group 1431 3.2-3 Passed
@@ -75,7 +75,7 @@ The results of the diagnostic runs are summarized below:
111104 12732 Flexible Disc Subsystem 1708 - No simulation
151302 7900/01 Cartridge Disc 1805 3.2-3 Partial
151403 7905/06/20/25 Disc 1805 - No simulation
151403 7905/06/20/25 Disc 1805 3.3-1 Partial
104117 92900 Terminal Subsystem 1814 - No simulation
112200 9-Track Magnetic Tape (7970, 13181/3) 2040 3.2-3 Partial
@@ -225,6 +225,24 @@ TEST RESULT: Passed.
----------------------------------------
DSN 102200 - Core Memory (2100/16/15/14)
----------------------------------------
TESTED DEVICE: CPU (hp2100_cpu.c)
CONFIGURATION: sim> set CPU 2100
sim> set CPU 32K
sim> deposit S 000000
sim> reset
sim> go 100
TEST REPORT: HALT instruction 102077
TEST RESULT: Passed.
---------------------------------
DSN 102104 - Semiconductor Memory
---------------------------------
@@ -953,17 +971,381 @@ TEST NOTES: Steps 4, 7, 8, and 9 test the defective and protected cylinder
-------------------------------
DSN 151403 - 7905/06/20/25 Disc
-------------------------------
-----------------------------------------------
DSN 151403 - 7905/06/20/25 Disc (multiple unit)
-----------------------------------------------
TESTED DEVICE: DS (hp2100_ds.c)
CONFIGURATION:
CONFIGURATION: sim> set DS0 7905
sim> set DS1 7906
sim> set DS2 7920
sim> set DS3 7925
sim> set DS4 7905
sim> set DS5 7906
sim> set DS6 7920
sim> set DS7 7925
sim> attach DS0 scratch.U0.7905.disc
sim> attach DS1 scratch.U1.7906.disc
sim> attach DS2 scratch.U2.7920.disc
sim> attach DS3 scratch.U3.7925.disc
sim> attach DS4 scratch.U4.7905.disc
sim> attach DS5 scratch.U5.7906.disc
sim> attach DS6 scratch.U6.7920.disc
sim> attach DS7 scratch.U7.7925.disc
sim> deposit S 000034
sim> reset
sim> go 100
TEST REPORT:
HALT instruction 102074
TEST RESULT: Not tested.
sim> deposit S 000004
sim> reset
sim> go
H0 79XX/13037 DISC MEMORY DIAGNOSTIC
H37 UNIT TABLE: 01 DRIVE(S); 0
H25 WISH TO CHANGE?
YES
H34 ENTER UNIT NUMBERS(0-7)SEPARATED BY COMMAS
0,1,2,3,4,5,6,7
H37 UNIT TABLE: 08 DRIVE(S); 0 1 2 3 4 5 6 7
H25 WISH TO CHANGE?
NO
ENTER:(U)NIT,(?) ERRS,(H)EAD,(O)UTPUT,(P)ATT,(S)OFT,(C)YL,(M)CPU,(E)XIT
H
H62 HEAD TABLE; UNIT 0 7905A , 02 HEAD(S) 0 1
H62 HEAD TABLE; UNIT 1 7906A , 02 HEAD(S) 0 1
H62 HEAD TABLE; UNIT 2 7920A , 05 HEAD(S) 0 1 2 3 4
H62 HEAD TABLE; UNIT 3 7925A , 09 HEAD(S) 0 1 2 3 4 5 6 7 8
H62 HEAD TABLE; UNIT 4 7905A , 02 HEAD(S) 0 1
H62 HEAD TABLE; UNIT 5 7906A , 02 HEAD(S) 0 1
H62 HEAD TABLE; UNIT 6 7920A , 05 HEAD(S) 0 1 2 3 4
H62 HEAD TABLE; UNIT 7 7925A , 09 HEAD(S) 0 1 2 3 4 5 6 7 8
H25 WISH TO CHANGE?
YES
H132 TYPE UNITS YOU WISH TO CHANGE SEPERATED BY COMMAS
0,1,4,5
H62 HEAD TABLE; UNIT 0 7905A , 02 HEAD(S) 0 1
H106 ENTER HEADS SEPARATED BY COMMAS
0,1,2
H62 HEAD TABLE; UNIT 0 7905A , 03 HEAD(S) 0 1 2
H25 WISH TO CHANGE?
NO
H62 HEAD TABLE; UNIT 1 7906A , 02 HEAD(S) 0 1
H106 ENTER HEADS SEPARATED BY COMMAS
0,1,2,3
H62 HEAD TABLE; UNIT 1 7906A , 04 HEAD(S) 0 1 2 3
H25 WISH TO CHANGE?
NO
H62 HEAD TABLE; UNIT 4 7905A , 02 HEAD(S) 0 1
H106 ENTER HEADS SEPARATED BY COMMAS
0,1,2
H62 HEAD TABLE; UNIT 4 7905A , 03 HEAD(S) 0 1 2
H25 WISH TO CHANGE?
NO
H62 HEAD TABLE; UNIT 5 7906A , 02 HEAD(S) 0 1
H106 ENTER HEADS SEPARATED BY COMMAS
0,1,2,3
H62 HEAD TABLE; UNIT 5 7906A , 04 HEAD(S) 0 1 2 3
H25 WISH TO CHANGE?
NO
ENTER:(U)NIT,(?) ERRS,(H)EAD,(O)UTPUT,(P)ATT,(S)OFT,(C)YL,(M)CPU,(E)XIT
E
TEST REPORT: H121 WARNING-FORMAT SWITCH OFF
H65 LONG PASS 0001,HEAD 012 ,UNIT 0,0000 ERRORS-0000 SOFT
H65 LONG PASS 0002,HEAD 0123 ,UNIT 1,0000 ERRORS-0000 SOFT
H65 LONG PASS 0003,HEAD 01234 ,UNIT 2,0000 ERRORS-0000 SOFT
H65 LONG PASS 0004,HEAD 012345678,UNIT 3,0000 ERRORS-0000 SOFT
H65 LONG PASS 0005,HEAD 012 ,UNIT 4,0000 ERRORS-0000 SOFT
H65 LONG PASS 0006,HEAD 0123 ,UNIT 5,0000 ERRORS-0000 SOFT
H65 LONG PASS 0007,HEAD 01234 ,UNIT 6,0000 ERRORS-0000 SOFT
H65 LONG PASS 0008,HEAD 012345678,UNIT 7,0000 ERRORS-0000 SOFT,MULTI-UNIT
[CTRL+E]
Simulation stopped
TEST RESULT: Passed.
TEST NOTES: Eight passes are required to test all head/unit combinations.
--------------------------------------------------
DSN 151403 - 7905/06/20/25 Disc (user interaction)
--------------------------------------------------
TESTED DEVICE: DS (hp2100_ds.c)
CONFIGURATION: sim> set DS0 7905
sim> attach DS0 scratch.U0.7905.disc
sim> deposit S 000034
sim> reset
sim> go 100
HALT instruction 102074
sim> deposit S 000120
sim> reset
sim> go
H0 79XX/13037 DISC MEMORY DIAGNOSTIC
H37 UNIT TABLE: 01 DRIVE(S); 0
H25 WISH TO CHANGE?
NO
TEST REPORT: H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN
HALT instruction 102002
sim> set DS0 FORMAT
sim> go
H46 READ IN STEP 04
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 0 1 0 00000 XXXX XXXX / 0 000010 0 0 0 1 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET"
START 0000/00/00-LAST 0000/00/01 WORD COUNT 00128,OLD CYL 0000,UNIT 00
HALT instruction 102001
sim> go
H22 VERIFY IN STEP 04
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 0 1 0 00000 XXXX XXXX / 0 000010 0 0 0 1 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET"
START 0000/00/00-LAST 0001/00/00 WORD COUNT 00048,OLD CYL 0000,UNIT 00
HALT instruction 102001
sim> go
H67 CLEAR FORMAT SWITCH ON UNIT 0,PUSH RUN
HALT instruction 102002
sim> set DS0 NOFORMAT
sim> go
H46 READ IN STEP 07
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 0 0 0 0 0 0
SHOULD BE 0 0 1 10001 XXXX XXXX / 0 000010 0 0 0 0 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "DEFECTIVE TRK "
START 0001/00/00-LAST 0001/00/01 WORD COUNT 00128,OLD CYL 0000,UNIT 00
HALT instruction 102001
sim> go
H45 WRITE IN STEP 08
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 0 0 0 0 0 0
SHOULD BE 0 1 0 10110 XXXX XXXX / 0 000010 0 0 0 0 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "WRT PROTEC TRK"
START 0000/00/00-LAST 0000/00/01 WORD COUNT 00128,OLD CYL 0001,UNIT 00
HALT instruction 102001
sim> go
H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN
HALT instruction 102002
sim> set DS0 FORMAT
sim> go
H45 WRITE IN STEP 10
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 0 1 0 00000 XXXX XXXX / 0 000010 0 0 0 1 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET"
START 0000/00/00-LAST 0000/00/08 WORD COUNT 01024,OLD CYL 0000,UNIT 00
HALT instruction 102001
sim> go
H70 UNLOAD UNIT 0,PUSH RUN
HALT instruction 102002
sim> detach DS0
sim> go
H107 READY UNIT 0
[CTRL+E]
Simulation stopped
sim> attach DS0 scratch.U0.7905.disc
sim> go
H142 PROTECT U/D,PUSH RUN
HALT instruction 102002
sim> set DS0 LOCKED
sim> go
H143 CLEAR U/D PROTECT,PUSH RUN
HALT instruction 102002
sim> set DS0 WRITEENABLED
sim> go
H110 PRESS PRESET(S),PRESS RUN
HALT instruction 102002
sim> reset
sim> go
H46 READ IN STEP 38
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 0 0 0 00111 0000 0000 / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "CYL CMP ERROR "
START 0000/00/01-LAST 0000/00/03 WORD COUNT 00138,OLD CYL 0000,UNIT 00
HALT instruction 102001
sim> go
H46 READ IN STEP 39
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 0 0 0 01001 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "HD/SEC CMP ERR"
START 0000/00/01-LAST 0000/00/03 WORD COUNT 00138,OLD CYL 0000,UNIT 00
HALT instruction 102001
sim> go
H46 READ IN STEP 40
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 0 0 0 01001 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "HD/SEC CMP ERR"
START 0000/00/01-LAST 0000/00/03 WORD COUNT 00138,OLD CYL 0000,UNIT 00
HALT instruction 102001
sim> go
H46 READ IN STEP 41
E47 DATA WORD 0065 IS 075126 SHOULD BE 030400
E47 DATA WORD 0066 IS 000762 SHOULD BE 030400
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 0 0 0 01111 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "POSS CORR DATA"
START 0000/00/00-LAST 0000/00/03 WORD COUNT 00128,OLD CYL 0000,UNIT 00
HALT instruction 102001
sim> go
H46 READ IN STEP 42
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 0 0 0 01000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "UNCOR DATA ERR"
START 0000/00/00-LAST 0000/00/03 WORD COUNT 00276,OLD CYL 0000,UNIT 00
HALT instruction 102001
sim> go
H22 VERIFY IN STEP 43
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 0 0 1 10001 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "DEFECTIVE TRK "
START 0016/00/00-LAST 0017/00/00 WORD COUNT 00048,OLD CYL 0128,UNIT 00
HALT instruction 102001
sim> go
H22 VERIFY IN STEP 43
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 1 0 0 10000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "SPR TRK ACCESS"
START 0128/01/00-LAST 0129/01/00 WORD COUNT 00048,OLD CYL 0016,UNIT 00
HALT instruction 102001
sim> go
H45 WRITE IN STEP 43
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 1 0 0 00000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET"
START 0016/00/33-LAST 0016/00/34 WORD COUNT 00128,OLD CYL 0128,UNIT 00
HALT instruction 102001
sim> go
H46 READ IN STEP 43
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 1 0 0 00000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "NORMAL COMPLET"
START 0016/00/33-LAST 0016/00/34 WORD COUNT 00128,OLD CYL 0016,UNIT 00
HALT instruction 102001
sim> go
H46 READ IN STEP 43
H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B
E64 STATUS IS 0 0 0 00111 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0
SHOULD BE 1 0 0 00000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0
H137 TERMINATION STATUS IS "CYL CMP ERROR " SHOULD BE "NORMAL COMPLET"
E13 0000 WORDS TRANSFERRED 0128 EXPECTED
START 0016/00/33-LAST 0016/00/33 WORD COUNT 00128,OLD CYL 0016,UNIT 00
HALT instruction 102001
sim> go
H65 SHORT PASS 0001,HEAD 01 ,UNIT 0,0015 ERRORS-0015 SOFT
[CTRL+E]
Simulation stopped
TEST RESULT: Partially passed.
TEST NOTES: Steps 4, 8, and 10 test the protected cylinder bit. Step 7
tests the defective cylinder bit. Steps 38, 39, and 40 test the
Write Full Sector command. Steps 41 and 42 test error
correction. Step 43 tests the spare cylinder bit and track
sparing. These features are not simulated.

View File

@@ -1,7 +1,7 @@
To: Users
From: Bob Supnik
Subj: HP2100 Simulator Usage
Date: 26-Oct-2004
Date: 22-Dec-2004
COPYRIGHT NOTICE
@@ -59,6 +59,7 @@ sim/hp2100/ hp2100_defs.h
hp2100_dp.c
hp2100_dq.c
hp2100_dr.c
hp2100_ds.c
hp2100_ipl.c
hp2100_lps.c
hp2100_lpt.c
@@ -77,7 +78,7 @@ name(s)
CPU 2116 CPU with 32KW memory
2100 CPU with 32KW memory, FP or IOP instructions
21MX CPU with 1024KW memory, FP, DMS, and/or IOP instructions
21MX-M/E CPU with 1024KW memory, FP, DMS, and/or IOP instructions
MP 12892B memory protect
DMA0, DMA1 12895A/12897B direct memory access/dual channel port controller
PTR 12597A duplex register interface with 2748 paper tape reader
@@ -93,6 +94,7 @@ DP 12557A disk controller with four 2871 drives
DQ 12565A disk controller with two 2883 drives
DR 12606B fixed head disk controller with 2770/2771 disk
12610B drum controller with 2773/2774/2775 drum
DS 13037 disk controller with eight 7905/7906/7920/7925 drives
MT 12559C magnetic tape controller with one 3030 drive
MS 13181A magnetic tape controller with four 7970B drives
13183A magnetic tape controller with four 7970E drives
@@ -120,7 +122,8 @@ Options that may be specified are:
SET CPU 2116 2116 CPU
SET CPU 2100 2100 CPU
SET CPU 21MX 21MX CPU
SET CPU 21MX-M 21MX M-series CPU
SET CPU 21MX-E 21MX E-series CPU
SET CPU EAU EAU instructions (2116 only)
SET CPU NOEAU no EAU instructions (2116 only)
SET CPU FP FP instructions (2100 only)
@@ -141,7 +144,9 @@ Options that may be specified are:
On the 2100, EAU is standard, and the FP and IOP options are mutually
exclusive. On the 21MX, EAU and FP are standard. The 21MX optionally
includes DMS (dynamic mapping system) and IOP instructions.
includes DMS (dynamic mapping system) and IOP instructions. The 21MX-E
supports the TIMER instruction; on the 21MX-M, this instruction decodes
as MPY.
Setting the CPU type to 2116, 2100, or 21MX establishes a consistent set
of common options. Additional SET CPU commands may follow to fine-tune
@@ -274,6 +279,7 @@ DMA1). Each DMA channel has the following visible state:
CTL 1 interrupt enabled
FLG 1 channel ready
FBF 1 channel ready buffer
CTLALT 1 command word 2/3 selector
CW1 16 command word 1
CW2 16 command word 2
CW3 16 command word 3
@@ -532,8 +538,18 @@ In printer mode, error handling is as follows:
not attached 1 report error and stop
0 out of paper
SET POWEROFF 1 report error and stop
0 powered off
SET OFFLINE 1 report error and stop
0 offline
OS I/O error x report error and stop
With STOP_IOE set to 0, output performed when the device is powered off
or offline will initiate but then hang, waiting for the device to be
returned online. When it is, the output operation will complete.
In diagnostic mode, there are no errors; data sent to the output
buffer is looped back to the status register with a fixed delay of 1.
@@ -573,8 +589,18 @@ Error handling is as follows:
not attached 1 report error and stop
0 out of paper
SET POWEROFF 1 report error and stop
0 powered off
SET OFFLINE 1 report error and stop
0 offline
OS I/O error x report error and stop
With STOP_IOE set to 0, output performed when the device is powered off
or offline will initiate but then hang, waiting for the device to be
returned online. When it is, the output operation will complete.
2.5.6 12539C Time Base Generator (CLK)
The time base generator (CLK) may be set for diagnostic mode:
@@ -754,8 +780,10 @@ Both IPLI and IPLO implement these registers:
TIME 24 polling interval for input
STOP_IOE 1 stop on I/O error
2.6 12557A Disk Controller (DPC, DPD) with Four 2781 Drives
13210A Disk Controller (DPC, DPD) with Four 7900 Drives
2.6 Disk Controllers
2.6.1 12557A Disk Controller (DPC, DPD) with Four 2781 Drives
13210A Disk Controller (DPC, DPD) with Four 7900 Drives
The 12557A/13210A disk controller can be configured as either a
12557A, supporting 2.5MB drives, or a 13210A, supporting 5MB drives,
@@ -773,9 +801,19 @@ a command channel. The data channel includes a 128-word (one sector)
buffer for reads and writes. The command channel includes the four
disk drives. Disk drives can be set DISABLED or ENABLED.
Individual drives may be protected against writing. These commands
simulate the Upper/Lower Disc Protect switches on the drives:
SET DPCn LOCKED set unit n write locked
SET DPCn WRITEENABLED set unit n write enabled
Separate protection for the upper and lower platters of the 7900 drive
is not supported. Also, the drive Protect/Override switch is not
supported; drive protection is permanently overridden.
The 12557A/13210A supports the BOOT command. BOOT DPC copies the IBL
for 7900 class disks into memory and starts it running. BOOT -R DPC
boots from the removable platter (head 2). The switch register (S) is
boots from the removable platter (head 0). The switch register (S) is
set automatically to the value expected by the IBL loader:
<15:14> = 01
@@ -827,21 +865,26 @@ The command channel implements these registers:
Error handling is as follows:
error processed as
error processed as
not attached disk not ready
not attached disk not ready (drive unloaded)
end of file assume rest of disk is zero
end of file assume rest of disk is zero
OS I/O error report error and stop
OS I/O error report error and stop
2.7 12565A Disk Controller (DQC, DQD) with Two 2883 Drives
2.6.2 12565A Disk Controller (DQC, DQD) with Two 2883 Drives
The 12565A disk controller has two separate devices, a data channel and
a command channel. The data channel includes a 128-word (one sector)
buffer for reads and writes. The command channel includes the two
disk drives. Disk drives can be set DISABLED or ENABLED.
Individual drives may be protected against writing:
SET DQCn LOCKED set unit n write locked
SET DQCn WRITEENABLED set unit n write enabled
The 12565A supports the BOOT command. BOOT DQC copies the IBL for 2883
class disks into memory and starts it running. The switch register (S)
is set automatically to the value expected by the IBL loader:
@@ -892,16 +935,16 @@ The command channel implements these registers:
Error handling is as follows:
error processed as
error processed as
not attached disk not ready
not attached disk not ready
end of file assume rest of disk is zero
end of file assume rest of disk is zero
OS I/O error report error and stop
OS I/O error report error and stop
2.8 12606B Fixed Head Disk Controller (DRC, DRD) with 2770/2771 Disk
12610B Drum Controller (DRC, DRD) with 2773/2774/2775 Drum
2.6.3 12606B Fixed Head Disk Controller (DRC, DRD) with 2770/2771 Disk
12610B Drum Controller (DRC, DRD) with 2773/2774/2775 Drum
The 12606B/12610B fixed head disk/drum controller has two separate devices,
a data channel and a command channel.
@@ -982,7 +1025,93 @@ Error handling is as follows:
12606B/12610B data files are buffered in memory; therefore, end of file
and OS I/O errors cannot occur.
2.9 12559C Magnetic Tape Controller (MTC, MTD) with One 3030 Drive
2.6.4 13037 Disk Controller (DS) with Eight 7905/7906/7920/7925 Drives
The 13037 disk controller supports 7905 (15MB), 7906 (20MB), 7920 (50MB),
or 7925 (120MB) disk drives, as well as autosizing, based on the size
of the disk image file:
SET DSn 7905 drive n is a 15MB drive
SET DSn 7906 drive n is a 20MB drive
SET DSn 7920 drive n is a 50MB drive
SET DSn 7925 drive n is a 120MB drive
SET DSn AUTOSIZE drive n type based on file size at attach
Drive types can be intermixed. The 7905 is selected by default. Drives
can be set DISABLED or ENABLED.
Individual drives may be protected against writing. These commands
simulate the Disc Protect/Read Only switches on the drives:
SET DSn LOCKED set unit n write locked
SET DSn WRITEENABLED set unit n write enabled
Separate protection for the upper and lower platters of the 7905 and
7906 drives is not supported. Protecting a 7905 or 7906 drive behaves
as though both of the Disc Protect switches were on.
The setting of the drive Format switch may be changed with:
SET DSn FORMAT set format enabled
SET DSn NOFORMAT set format disabled
The 13037 supports the BOOT command. BOOT DS copies the IBL loader for
the 13037 controller into memory and starts it running. The switch register
(S) is set automatically to the value expected by the IBL loader:
<15:14> = 11
<13:12> = 01
<11:6> = data channel device code
<5:3> = unchanged
<2> = 0
<1:0> = unchanged (head number)
The DS controller implements these registers:
name size comments
CMD 16 command register
FIFO[0:15] 16 data FIFO
SR1 16 status register 1
VCTR 16 verify counter
FMASK 8 file mask
CYL 16 cylinder address register
HS 16 head/sector address register
STATE 2 controller state
LASTA 3 last unit polled for attention flag
FIP 4 FIFO insertion pointer
FRP 4 FIFO removal pointer
FCNT 5 FIFO counter
CTL 1 interrupt enable
FLG 1 ready flag
FBF 1 ready flag buffer
SRQ 1 DMA service request
BUSY 1 visible busy status
CMDF 1 command follows flag
CMDP 1 command pending flag
EOC 1 end of cylinder flag
EOD 1 end of data flag
DBUF[0:127] 16 sector buffer
DPTR 8 sector buffer pointer
CTIME 24 command response time
DTIME 24 data transfer response time
STIME 24 seek time (per cylinder)
RTIME 24 rotation time
TIMEOUT 31 controller timeout
Error handling is as follows:
error processed as
not attached disk not ready
end of file assume rest of disk is zero
OS I/O error report error and stop
2.7 Magnetic Tape
2.7.1 12559C Magnetic Tape Controller (MTC, MTD) with One 3030 Drive
Magnetic tape options include the ability to make the unit write enabled
or write locked.
@@ -1037,8 +1166,8 @@ Error handling is as follows:
OS I/O error parity error; if STOP_IOE, stop
2.10 13181A Magnetic Tape Controller (MSC, MSD) with Four 7970B Drives
18183A Magnetic Tape Controller (MSC, MSD) with Four 7970E Drives
2.7.2 13181A Magnetic Tape Controller (MSC, MSD) with Four 7970B Drives
18183A Magnetic Tape Controller (MSC, MSD) with Four 7970E Drives
Magnetic tape options include the ability to make the unit write enabled
or write locked, and the ability to select the 13181A (800 bpi) controller
@@ -1126,7 +1255,7 @@ Error handling is as follows:
OS I/O error parity error; if STOP_IOE, stop
2.11 Symbolic Display and Input
2.8 Symbolic Display and Input
The HP2100 simulator implements symbolic display and input. Display is
controlled by command line switches:

View File

@@ -199,7 +199,6 @@
#define STA_UNLOADED (dp_ctype ? (STA_NRDY | STA_BSY) : STA_NRDY)
#define STA_MBZ13 (STA_ATN | STA_RWU | STA_SKI) /* zero in 13210 */
extern uint16 *M;
extern uint32 PC, SR;
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
extern int32 sim_switches;

View File

@@ -136,7 +136,6 @@
#define STA_ERR 0000001 /* any error */
#define STA_ANYERR (STA_NRDY | STA_EOC | STA_AER | STA_FLG | STA_DTE)
extern uint16 *M;
extern uint32 PC, SR;
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
extern int32 sim_switches;

View File

@@ -39,6 +39,11 @@
- Busy. The controller is processing a command. The controller does not
respond to new commands or to drive attention interrupts.
The controller busy state is loosely related to the testable (visible) busy
flop. If the visible busy flop is set, the controller is in the busy state;
but the controller can also be busy (processing an invalid opcode or invalid
unit) while visible busy is clear.
Omissions: the following features are not implemented:
- Drive hold. Since this is a single CPU implementation, the drives are
@@ -46,6 +51,9 @@
- Spare, defective, protected. The disk files carry only data.
- Formatting. The disk files carry only data.
- ECC. Data errors are always uncorrectable.
Reference:
- 13037 Disc Controller Technical Information Package (13037-90902, Aug-1980)
*/
#include "hp2100_defs.h"
@@ -60,10 +68,9 @@
#define DS_FHS 2
#define DS_FDATA 3
#define DS_FIFO_SIZE 16 /* fifo size */
#define DS_FIFO_EMPTY (ds_fifo_cnt == 0)
#define ds_ctrl ds_unit[DS_NUMDR] /* ctrl thread */
#define ds_timer ds_unit[DS_NUMDR + 1] /* timeout thread */
#define GET_DA(x,y,z,t) \
((((((x) * drv_tab[t].hd) + (y)) * drv_tab[t].sc) + (z)) * DS_NUMWD)
#define GET_CURSEC(x,d) ((int32) fmod (sim_gtime() / ((double) (x)), \
((double) (drv_tab[d].sc))))
@@ -112,9 +119,9 @@
#define DSC_RFULL 006 /* read full */
#define DSC_VFY 007 /* verify */
#define DSC_WRITE 010 /* write */
#define DSC_WFULL 011 /* write full - na */
#define DSC_WFULL 011 /* write full */
#define DSC_CLEAR 012 /* clear */
#define DSC_INIT 013 /* initialize - na */
#define DSC_INIT 013 /* initialize */
#define DSC_AREC 014 /* address record */
#define DSC_RSYN 015 /* request syndrome */
#define DSC_ROFF 016 /* read with offset */
@@ -124,7 +131,7 @@
#define DSC_RDA 024 /* request disk addr */
#define DSC_END 025 /* end */
#define DSC_WAKE 026 /* wakeup */
#define DSC_ATTN 035 /* pseudo: ATTN */
#define DSC_ATN 035 /* pseudo: ATN */
#define DSC_BADU 036 /* pseudo: bad unit */
#define DSC_BADF 037 /* pseudo: bad opcode */
#define DSC_NEXT 0040 /* state increment */
@@ -138,24 +145,30 @@
#define DSC_V_RTY 4 /* retry count */
#define DSC_M_RTY 017
#define DSC_V_DECR 3 /* seek decrement */
#define DSC_V_SPAR 2 /* enable sparing */
#define DSC_V_SPEN 2 /* enable sparing */
#define DSC_V_CYLM 1 /* cylinder mode */
#define DSC_V_AUTO 0 /* auto seek */
#define DSC_V_HOLD 7 /* hold flag */
#define DSC_V_UNIT 0 /* unit */
#define DSC_M_UNIT 017
#define DSC_V_SPAR 15 /* INIT spare */
#define DSC_V_PROT 14 /* INIT protected */
#define DSC_V_DFCT 13 /* INIT defective */
#define DSC_HOLD (1u << DSC_V_HOLD)
#define DSC_DECR (1u << DSC_V_DECR)
#define DSC_SPAR (1u << DSC_V_SPAR)
#define DSC_SPEN (1u << DSC_V_SPEN)
#define DSC_CYLM (1u << DSC_V_CYLM)
#define DSC_AUTO (1u << DSC_V_AUTO)
#define DSC_FMASK ((DSC_M_RTY << DSC_V_RTY)|DSC_DECR|\
DSC_SPAR|DSC_CYLM|DSC_AUTO)
DSC_SPEN|DSC_CYLM|DSC_AUTO)
#define DSC_GETOP(x) (((x) >> DSC_V_OP) & DSC_M_OP)
#define DSC_GETUNIT(x) (((x) >> DSC_V_UNIT) & DSC_M_UNIT)
#define DSC_GETCHD(x) (((x) >> DSC_V_CHD) & DSC_M_CHD)
#define DSC_GETCSC(x) (((x) >> DSC_V_CSC) & DSC_M_CSC)
#define DSC_SPAR (1u << DSC_V_SPAR)
#define DSC_PROT (1u << DSC_V_PROT)
#define DSC_DFCT (1u << DSC_V_DFCT)
/* Command flags */
@@ -199,15 +212,19 @@
#define DS1_S2ERR (023 << DS1_V_STAT) /* status 2 error */
#define DS1_TKPER (026 << DS1_V_STAT) /* protected trk - na */
#define DS1_UNAVL (027 << DS1_V_STAT) /* illegal unit */
#define DS1_ATTN (037 << DS1_V_STAT) /* attention */
#define DS1_ATN (037 << DS1_V_STAT) /* attention */
#define DS1_V_UNIT 0
#define DS1_SPAR (1u << DS1_V_SPAR)
#define DS1_PROT (1u << DS1_V_PROT)
#define DS1_DFCT (1u << DS1_V_DFCT)
/* Status 2, ^ = kept in unit status, * = dynamic */
#define DS2_ERR 0100000 /* *error */
#define DS2_V_ID 9 /* drive type */
#define DS2_ATN 0000200 /* ^attention */
#define DS2_RO 0000100 /* *read only */
#define DS2_FRM 0000040 /* format - na */
#define DS2_FRM 0000040 /* *format */
#define DS2_FLT 0000020 /* fault - na */
#define DS2_FS 0000010 /* ^first status */
#define DS2_SC 0000004 /* ^seek error */
@@ -234,34 +251,69 @@
In theory, each drive can be a different type. The size field in
each unit selects the drive capacity for each drive and thus the
drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE.
The 7905 and 7906 have fixed and removable platters. Consequently,
they are almost always accessed with cylinders limited to each
platter. The 7920 and 7925 have multiple-platter packs, and so are
almost always accessed with cylinders that span all surfaces.
Disk image files are arranged as a linear set of tracks. To improve
locality, tracks on the 7905 and 7906 images are grouped per-platter,
i.e., all tracks on heads 0 and 1, followed by all tracks on head 2
(and, for the 7906, head 3), whereas tracks on the 7920 and 7925 are
sequential by cylinder and head number.
This variable-access geometry is accomplished by defining a "heads
per cylinder" value for the fixed and removable sections of each
drive that indicates the number of heads that should be grouped for
locality. The removable values are set to 2 on the 7905 and 7906,
indicating that those drives typically use cylinders of two surfaces.
They are set to the number of surfaces per drive for the 7920 and
7925, as those typically use cylinders encompassing the entire
spindle.
*/
#define GET_DA(x,y,z,t) \
(((((y) < drv_tab[t].rh)? \
(x) * drv_tab[t].rh + (y): \
drv_tab[t].cyl * drv_tab[t].rh + \
((x) * drv_tab[t].fh + (y) - drv_tab[t].rh)) * \
drv_tab[t].sc + (z)) * DS_NUMWD)
#define D7905_DTYPE 0
#define D7905_SECT 48
#define D7905_SURF 3
#define D7905_RH 2
#define D7905_FH (D7905_SURF - D7905_RH)
#define D7905_CYL 411
#define D7905_ID 2
#define D7905_ID (2 << DS2_V_ID)
#define D7905_SIZE (D7905_SECT * D7905_SURF * D7905_CYL * DS_NUMWD)
#define D7906_DTYPE 1
#define D7906_SECT 48
#define D7906_SURF 4
#define D7906_RH 2
#define D7906_FH (D7906_SURF - D7906_RH)
#define D7906_CYL 411
#define D7906_ID 0
#define D7906_ID (0 << DS2_V_ID)
#define D7906_SIZE (D7906_SECT * D7906_SURF * D7906_CYL * DS_NUMWD)
#define D7920_DTYPE 2
#define D7920_SECT 48
#define D7920_SURF 5
#define D7920_RH D7920_SURF
#define D7920_FH (D7920_SURF - D7920_RH)
#define D7920_CYL 823
#define D7920_ID 1
#define D7920_ID (1 << DS2_V_ID)
#define D7920_SIZE (D7920_SECT * D7920_SURF * D7920_CYL * DS_NUMWD)
#define D7925_DTYPE 3
#define D7925_SECT 64
#define D7925_SURF 9
#define D7925_RH D7925_SURF
#define D7925_FH (D7925_SURF - D7925_RH)
#define D7925_CYL 823
#define D7925_ID 3
#define D7925_ID (3 << DS2_V_ID)
#define D7925_SIZE (D7925_SECT * D7925_SURF * D7925_CYL * DS_NUMWD)
struct drvtyp {
@@ -270,16 +322,17 @@ struct drvtyp {
uint32 cyl; /* cylinders */
uint32 size; /* #blocks */
uint32 id; /* device type */
uint32 rh; /* removable surfaces */
uint32 fh; /* fixed surfaces */
};
static struct drvtyp drv_tab[] = {
{ D7905_SECT, D7905_SURF, D7905_CYL, D7905_SIZE, D7905_ID },
{ D7906_SECT, D7906_SURF, D7906_CYL, D7906_SIZE, D7906_ID },
{ D7920_SECT, D7920_SURF, D7920_CYL, D7920_SIZE, D7920_ID },
{ D7925_SECT, D7925_SURF, D7925_CYL, D7925_SIZE, D7925_ID },
{ D7905_SECT, D7905_SURF, D7905_CYL, D7905_SIZE, D7905_ID, D7905_RH, D7905_FH },
{ D7906_SECT, D7906_SURF, D7906_CYL, D7906_SIZE, D7906_ID, D7906_RH, D7906_FH },
{ D7920_SECT, D7920_SURF, D7920_CYL, D7920_SIZE, D7920_ID, D7920_RH, D7920_FH },
{ D7925_SECT, D7925_SURF, D7925_CYL, D7925_SIZE, D7925_ID, D7925_RH, D7925_FH },
{ 0 } };
extern uint16 *M;
extern uint32 PC, SR;
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
extern int32 sim_switches;
@@ -291,7 +344,6 @@ uint32 ds_fifo_rp = 0; /* removal ptr */
uint32 ds_fifo_cnt = 0; /* count */
uint32 ds_cmd = 0; /* command word */
uint32 ds_sr1 = 0; /* status word 1 */
uint32 ds_u = 0; /* saved unit */
uint32 ds_busy = 0; /* busy flag */
uint32 ds_eoc = 0; /* end of cylinder */
uint32 ds_eod = 0; /* end of data */
@@ -302,12 +354,12 @@ uint32 ds_cyl = 0; /* disk address: cyl */
uint32 ds_hs = 0; /* disk address: hs */
uint32 ds_vctr = 0; /* verify counter */
uint32 ds_state = 0; /* controller state */
uint32 ds_lastatn = 0; /* last attn intr */
uint32 ds_lastatn = 0; /* last atn intr */
int32 ds_stime = 100; /* seek time */
int32 ds_rtime = 100; /* inter-sector time */
int32 ds_ctime = 3; /* command time */
int32 ds_dtime = 1; /* dch time */
int32 ds_tmo = 1000000; /* timeout */
int32 ds_tmo = 2749200; /* timeout = 1.74 sec */
uint32 ds_ptr = 0; /* buffer ptr */
uint16 dsxb[DS_NUMWDF]; /* sector buffer */
@@ -351,7 +403,6 @@ t_stat ds_svc_c (UNIT *uptr);
t_stat ds_svc_u (UNIT *uptr);
t_stat ds_svc_t (UNIT *uptr);
t_stat ds_reset (DEVICE *dptr);
t_stat ds_vlock (UNIT *uptr, int32 val);
t_stat ds_attach (UNIT *uptr, char *cptr);
t_stat ds_detach (UNIT *uptr);
t_stat ds_boot (int32 unitno, DEVICE *dptr);
@@ -359,7 +410,7 @@ t_stat ds_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
void ds_poll (void);
void ds_docmd (uint32 cmd);
void ds_doatn (void);
uint32 ds_updds2 (UNIT *uptr, uint32 clear);
uint32 ds_updds2 (UNIT *uptr);
void ds_cmd_done (t_bool sf, uint32 sr1);
void ds_wait_for_cpu (UNIT *uptr, uint32 newst);
void ds_set_idle (void);
@@ -376,7 +427,7 @@ t_stat ds_cont_wr (UNIT *uptr, uint32 off, uint32 bsize);
void ds_end_rw (UNIT *uptr, uint32 newst);
t_stat ds_set_uncorr (UNIT *uptr);
t_stat ds_reset_cmn (DEVICE *dptr);
void ds_sched_attn (UNIT *uptr);
void ds_sched_atn (UNIT *uptr);
uint32 ds_fifo_read (void);
void ds_fifo_write (uint32 dat);
void ds_fifo_reset (void);
@@ -416,7 +467,6 @@ REG ds_reg[] = {
{ BRDATA (FIFO, ds_fifo, 8, 16, DS_FIFO_SIZE) },
{ ORDATA (SR1, ds_sr1, 16) },
{ ORDATA (VCTR, ds_vctr, 16) },
{ ORDATA (UNIT, ds_u, 4) },
{ ORDATA (FMASK, ds_fmask, 8) },
{ ORDATA (CYL, ds_cyl, 16) },
{ ORDATA (HS, ds_hs, 16) },
@@ -440,9 +490,9 @@ REG ds_reg[] = {
{ DRDATA (CTIME, ds_ctime, 24), PV_LEFT + REG_NZ },
{ DRDATA (DTIME, ds_dtime, 24), PV_LEFT + REG_NZ },
{ DRDATA (STIME, ds_stime, 24), PV_LEFT + REG_NZ },
{ DRDATA (TTIME, ds_rtime, 24), PV_LEFT + REG_NZ },
{ DRDATA (RTIME, ds_rtime, 24), PV_LEFT + REG_NZ },
{ DRDATA (TIMEOUT, ds_tmo, 31), PV_LEFT + REG_NZ },
{ URDATA (UCYL, ds_unit[0].CYL, 10, 8, 0,
{ URDATA (UCYL, ds_unit[0].CYL, 10, 10, 0,
DS_NUMDR + 1, PV_LEFT | REG_HRO) },
{ URDATA (UFNC, ds_unit[0].FNC, 8, 8, 0,
DS_NUMDR + 1, REG_HRO) },
@@ -493,15 +543,14 @@ DEVICE ds_dev = {
DS_NUMDR + 2, 8, 27, 1, 8, 16,
NULL, NULL, &ds_reset,
&ds_boot, &ds_attach, &ds_detach,
&ds_dib, DEV_DISABLE | DEV_DIS };
&ds_dib, DEV_DISABLE };
/* IO instructions */
int32 dsio (int32 inst, int32 IR, int32 dat)
{
int32 dev;
uint32 dev = IR & I_DEVMASK;
dev = IR & I_DEVMASK; /* get device no */
switch (inst) { /* case on opcode */
case ioFLG: /* flag clear/set */
if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */
@@ -516,7 +565,8 @@ case ioOTX: /* output */
if (ds_cmdf) { /* expecting command? */
ds_cmd = dat; /* save command */
ds_cmdf = 0;
ds_cmdp = 1; } /* command present */
ds_cmdp = 1; /* command present */
}
else ds_fifo_write (dat); /* put in fifo */
break;
case ioMIX: /* merge */
@@ -530,9 +580,11 @@ case ioCTL: /* control clear/set */
clrCTL (dev); /* clear control */
ds_cmdf = 1; /* expecting command */
ds_cmdp = 0; /* none pending */
ds_fifo_reset (); } /* clear fifo */
ds_fifo_reset (); /* clear fifo */
}
else { /* STC */
setCTL (dev); } /* set ctl */
setCTL (dev); /* set ctl */
}
break;
case ioEDT: /* end of transfer */
ds_eod = 1; /* flag end transfer */
@@ -546,7 +598,7 @@ return dat;
/* Run the controller polling loop, based on ds_state:
IDLE commands and ATTN interrupts
IDLE commands and ATN interrupts
WAIT commands only
BUSY nothing
*/
@@ -556,7 +608,7 @@ void ds_poll (void)
int32 dev = ds_dib.devno;
if ((ds_state != DS_BUSY) && ds_cmdp) ds_docmd (ds_cmd);/* cmd pending? */
if ((ds_state == DS_IDLE) && CTL (dev)) ds_doatn (); /* idle? chk atn */
if ((ds_state == DS_IDLE) && CTL (dev)) ds_doatn (); /* idle? check ATN */
return;
}
@@ -571,29 +623,31 @@ return;
void ds_docmd (uint32 cmd)
{
uint32 op, f, dtyp;
uint32 op, f, dtyp, unum;
op = DSC_GETOP (cmd); /* operation */
f = ds_opflags[op]; /* flags */
if (op == DSC_COLD) ds_u = 0; /* boot force unit 0 */
else ds_u = DSC_GETUNIT (cmd); /* get unit */
if ((f & CMF_UIDLE) && (ds_u < DS_NUMDR) && /* idle required */
sim_is_active (&ds_unit[ds_u])) { /* but unit busy? */
if (op == DSC_COLD) unum = 0; /* boot force unit 0 */
else unum = DSC_GETUNIT (cmd); /* get unit */
if ((f & CMF_UIDLE) && (unum < DS_NUMDR) && /* idle required */
sim_is_active (&ds_unit[unum])) { /* but unit busy? */
ds_state = DS_WAIT; /* wait */
return; }
return;
}
ds_cmdp = 0; /* flush command */
ds_state = DS_BUSY; /* ctrl is busy */
if (f & CMF_CLRS) ds_sr1 = 0; /* clear status */
if (f & CMF_CLREC) ds_eoc = 0; /* clear end cyl */
if (f & CMF_UNDF) { /* illegal op? */
ds_sched_ctrl_op (DSC_BADF, 0, CLR_BUSY); /* sched, not busy */
return; }
ds_sched_ctrl_op (DSC_BADF, 0, CLR_BUSY); /* sched, clr busy */
return;
}
switch (op) {
/* Drive commands */
case DSC_COLD: /* cold load read */
ds_fmask = DSC_SPAR; /* sparing enabled */
ds_fmask = DSC_SPEN; /* sparing enabled */
ds_cyl = 0; /* cylinder 0 */
ds_hs = (DSC_GETCHD (ds_cmd) << DSHS_V_HD) | /* reformat hd/sec */
(DSC_GETCSC (ds_cmd) << DSHS_V_SC);
@@ -607,13 +661,19 @@ case DSC_VFY: /* verify */
case DSC_WRITE: /* write */
case DSC_WFULL: /* write full */
case DSC_INIT: /* init */
ds_sr1 = ds_u; /* init status */
if (ds_u >= DS_NUMDR) { /* invalid unit? */
ds_sched_ctrl_op (DSC_BADU, ds_u, CLR_BUSY);/* sched, not busy */
return; }
ds_unit[ds_u].FNC = op; /* save op */
ds_unit[ds_u].STA &= ~DS2_ATN; /* clear ATTN */
sim_activate (&ds_unit[ds_u], ds_ctime); /* schedule unit */
ds_sr1 = unum; /* init status */
if (unum >= DS_NUMDR) { /* invalid unit? */
ds_sched_ctrl_op (DSC_BADU, unum, CLR_BUSY);/* sched, not busy */
return;
}
if (op == DSC_INIT) ds_sr1 |= /* init? */
((cmd & DSC_SPAR)? DS1_SPAR: 0) | /* copy SPD to stat1 */
((cmd & DSC_PROT)? DS1_PROT: 0) |
((cmd & DSC_DFCT)? DS1_DFCT: 0);
ds_unit[unum].FNC = op; /* save op */
ds_unit[unum].STA &= ~DS2_ATN; /* clear ATN */
sim_cancel (&ds_unit[unum]); /* cancel current */
sim_activate (&ds_unit[unum], ds_ctime); /* schedule unit */
ds_busy = 1; /* set visible busy */
break;
@@ -621,12 +681,15 @@ case DSC_INIT: /* init */
case DSC_RSTA: /* read status */
dsxb[1] = ds_sr1; /* return SR1 */
if (ds_u >= DS_NUMDR) dsxb[0] = DS2_ERR|DS2_NR|ds_u; /* SR2 */
else dsxb[0] = ds_updds2 (&ds_unit[ds_u], DS2_FS);
if (unum < DS_NUMDR) { /* and SR2 */
dsxb[0] = ds_updds2 (&ds_unit[unum]);
ds_unit[unum].STA &= ~DS2_FS; /* clear 1st */
}
else dsxb[0] = DS2_ERR|DS2_NR;
ds_sched_ctrl_op (DSC_RSTA, 2, SET_BUSY); /* sched 2 wds, busy */
break;
case DSC_RSA: /* read sector address */
dtyp = GET_DTYPE (ds_unit[ds_u].flags); /* get unit type */
dtyp = GET_DTYPE (ds_unit[unum].flags); /* get unit type */
dsxb[0] = GET_CURSEC (ds_dtime * DS_NUMWD, dtyp); /* rot position */
ds_sched_ctrl_op (DSC_RSTA, 1, SET_BUSY); /* sched 1 wd, busy */
break;
@@ -653,7 +716,8 @@ case DSC_WTIO: /* write TIO */
case DSC_END: /* end */
ds_set_idle (); /* idle ctrl */
break; }
break;
}
return;
}
@@ -669,9 +733,11 @@ for (i = 0; i < DS_NUMDR; i++) { /* intr disabled? */
if (ds_unit[ds_lastatn].STA & DS2_ATN) { /* ATN set? */
ds_unit[ds_lastatn].STA &= ~DS2_ATN; /* clear ATN */
setFLG (dev); /* request interrupt */
ds_sr1 = DS1_ATTN | ds_lastatn; /* set up status 1 */
ds_state = DS_WAIT; /* block attn intrs */
return; } }
ds_sr1 = DS1_ATN | ds_lastatn; /* set up status 1 */
ds_state = DS_WAIT; /* block atn intrs */
return;
}
}
return;
}
@@ -691,28 +757,31 @@ case DSC_AREC: /* address record */
ds_wait_for_cpu (uptr, DSC_AREC|DSC_2ND); /* set flag, new state */
break;
case DSC_AREC | DSC_2ND: /* poll done */
if (!FLG (dev)) { /* OTA x,C? */
if (!DS_FIFO_EMPTY) { /* OTA ds? */
ds_cyl = ds_fifo_read (); /* save cylinder */
ds_wait_for_cpu (uptr, DSC_AREC|DSC_3RD); }/* set flag, new state */
ds_wait_for_cpu (uptr, DSC_AREC|DSC_3RD); /* set flag, new state */
}
else sim_activate (uptr, ds_ctime); /* no, continue poll */
break;
case DSC_AREC | DSC_3RD: /* poll done */
if (!FLG (dev)) { /* OTA x,C? */
if (!DS_FIFO_EMPTY) { /* OTA ds? */
ds_hs = ds_fifo_read (); /* save head/sector */
ds_cmd_done (0, DS1_OK); } /* op done, no flag */
ds_cmd_done (0, DS1_OK); /* op done, no flag */
}
else sim_activate (uptr, ds_ctime); /* no, continue poll */
break;
case DSC_RSTA: /* rd stat (all forms) */
if (!FLG (dev)) { /* buffer clear? */
if (DS_FIFO_EMPTY) { /* fifo empty? */
uptr->CYL--;
ds_fifo_write (dsxb[uptr->CYL]); /* store next status */
ds_wait_for_cpu (uptr, DSC_RSTA |
(uptr->CYL? 0: DSC_2ND)); } /* set flag, new state */
(uptr->CYL? 0: DSC_2ND)); /* set flag, new state */
}
else sim_activate (uptr, ds_ctime); /* no, continue poll */
break;
case DSC_RSTA | DSC_2ND: /* poll done */
if (!FLG (dev)) ds_cmd_done (0, DS1_OK); /* op done? no flag */
if (DS_FIFO_EMPTY) ds_cmd_done (0, DS1_OK); /* op done? no flag */
else sim_activate (uptr, ds_ctime); /* no, continue poll */
break;
@@ -758,7 +827,7 @@ t_stat ds_svc_t (UNIT *uptr)
{
int32 i;
for (i = 0; i < DS_NUMDR; i++) /* cancel all ops */
for (i = 0; i < (DS_NUMDR + 1); i++) /* cancel all ops */
sim_cancel (&ds_unit[i]);
ds_set_idle (); /* idle the controller */
ds_fmask = 0; /* clear file mask */
@@ -783,7 +852,8 @@ switch (op) { /* case on function */
case DSC_RECAL: /* recalibrate */
if (uptr->flags & UNIT_ATT) { /* attached? */
ds_start_seek (uptr, 0, DSC_RECAL|DSC_2ND); /* set up seek */
ds_set_idle (); } /* ctrl is idle */
ds_set_idle (); /* ctrl is idle */
}
else ds_cmd_done (1, DS1_S2ERR); /* not ready error */
break;
case DSC_RECAL | DSC_2ND: /* recal complete */
@@ -794,18 +864,21 @@ case DSC_SEEK: /* seek */
ds_wait_for_cpu (uptr, DSC_SEEK|DSC_2ND); /* set flag, new state */
break;
case DSC_SEEK | DSC_2ND: /* waiting for word 1 */
if (!FLG (dev)) { /* OTA x,C? */
if (!DS_FIFO_EMPTY) { /* OTA ds? */
ds_cyl = ds_fifo_read (); /* save cylinder */
ds_wait_for_cpu (uptr, DSC_SEEK|DSC_3RD); }/* set flag, new state */
ds_wait_for_cpu (uptr, DSC_SEEK|DSC_3RD); /* set flag, new state */
}
else sim_activate (uptr, ds_ctime); /* no, continue poll */
break;
case DSC_SEEK | DSC_3RD: /* waiting for word 2 */
if (!FLG (dev)) { /* OTA x,C? */
if (!DS_FIFO_EMPTY) { /* OTA ds? */
ds_hs = ds_fifo_read (); /* save head/sector */
if (uptr->flags & UNIT_ATT) { /* attached? */
ds_start_seek (uptr, ds_cyl, DSC_SEEK|DSC_4TH); /* set up seek */
ds_set_idle (); } /* ctrl is idle */
else ds_cmd_done (1, DS1_S2ERR); } /* else not ready error */
ds_set_idle (); /* ctrl is idle */
}
else ds_cmd_done (1, DS1_S2ERR); /* else not ready error */
}
else sim_activate (uptr, ds_ctime); /* continue poll */
break;
case DSC_SEEK | DSC_4TH: /* seek complete */
@@ -818,7 +891,11 @@ case DSC_ROFF: /* read with offset */
ds_wait_for_cpu (uptr, DSC_ROFF|DSC_2ND); /* set flag, new state */
break;
case DSC_ROFF | DSC_2ND: /* poll done */
if (!FLG (dev)) uptr->FNC = DSC_READ; /* OTA x,C? new state */
if (!DS_FIFO_EMPTY) { /* OTA ds? new state */
ds_fifo_read (); /* drain fifo */
uptr->FNC = DSC_READ;
setFLG (dev); /* handshake */
}
sim_activate (uptr, ds_ctime); /* schedule unit */
break;
@@ -829,8 +906,7 @@ case DSC_COLD: /* cold load read */
break;
case DSC_READ: /* read */
if (r = ds_start_rd (uptr, 0, 1)) /* new sector; error? */
return r;
if (r = ds_start_rd (uptr, 0, 1)) return r; /* new sector; error? */
break;
case DSC_READ | DSC_2ND: /* word transfer */
ds_cont_rd (uptr, DS_NUMWD); /* xfr wd, check end */
@@ -840,8 +916,7 @@ case DSC_READ | DSC_3RD: /* end of sector */
break;
case DSC_RNOVFY: /* read, no verify */
if (r = ds_start_rd (uptr, 0, 0)) /* new sector; error? */
return r;
if (r = ds_start_rd (uptr, 0, 0)) return r; /* new sector; error? */
break;
case DSC_RNOVFY | DSC_2ND: /* word transfer */
ds_cont_rd (uptr, DS_NUMWD); /* xfr wd, check end */
@@ -868,10 +943,11 @@ case DSC_VFY: /* verify */
ds_wait_for_cpu (uptr, DSC_VFY|DSC_2ND); /* set flag, new state */
break;
case DSC_VFY | DSC_2ND: /* poll done */
if (!FLG (dev)) { /* OTA x,C? */
if (!DS_FIFO_EMPTY) { /* OTA ds? */
ds_vctr = ds_fifo_read (); /* save count */
uptr->FNC = DSC_VFY | DSC_3RD; /* next state */
sim_activate (uptr, ds_rtime); } /* delay for transfer */
sim_activate (uptr, ds_rtime); /* delay for transfer */
}
else sim_activate (uptr, ds_ctime); /* no, continue poll */
break;
case DSC_VFY | DSC_3RD: /* start sector */
@@ -978,9 +1054,9 @@ sim_activate (&ds_timer, ds_tmo);
return;
}
/* Return drive status (status word 2), clear specified flags */
/* Return drive status (status word 2) */
uint32 ds_updds2 (UNIT *uptr, uint32 clear)
uint32 ds_updds2 (UNIT *uptr)
{
uint32 sta;
uint32 dtyp = GET_DTYPE (uptr->flags);
@@ -988,10 +1064,10 @@ uint32 dtyp = GET_DTYPE (uptr->flags);
sta = drv_tab[dtyp].id | /* form status */
uptr->STA | /* static bits */
((uptr->flags & UNIT_WPR)? DS2_RO: 0) | /* dynamic bits */
((uptr->flags & UNIT_ATT)? 0: DS2_NR) |
((uptr->flags & UNIT_FMT)? DS2_FRM: 0) |
((uptr->flags & UNIT_ATT)? 0: DS2_NR | DS2_BS) |
(sim_is_active (uptr)? DS2_BS: 0);
if (sta & DS2_ALLERR) sta = sta | DS2_ERR; /* set error */
uptr->STA = uptr->STA & ~clear; /* clear static */
return sta;
}
@@ -1022,16 +1098,23 @@ return;
void ds_start_seek (UNIT *uptr, uint32 cyl, uint32 newst)
{
int32 t;
uint32 hd, sc;
uint32 dtyp = GET_DTYPE (uptr->flags);
uptr->FNC = newst; /* set new state */
if (cyl >= drv_tab[dtyp].cyl) { /* out of bounds? */
uptr->CYL = t = drv_tab[dtyp].cyl; /* put off edge */
uptr->STA = uptr->STA | DS2_SC; } /* set seek check */
else { /* seek in range */
t = abs (uptr->CYL - cyl); /* delta cylinders */
t = 0; /* don't change cyl */
uptr->STA = uptr->STA | DS2_SC; /* set seek check */
}
else { t = abs (uptr->CYL - cyl); /* delta cylinders */
uptr->CYL = cyl; /* put on cylinder */
uptr->STA = uptr->STA & ~DS2_SC; } /* clear seek check */
hd = DSHS_GETHD (ds_hs); /* invalid head or sec? */
sc = DSHS_GETSC (ds_hs);
if ((hd >= drv_tab[dtyp].hd) ||
(sc >= drv_tab[dtyp].sc))
uptr->STA = uptr->STA | DS2_SC; /* set seek check */
else uptr->STA = uptr->STA & ~DS2_SC; /* clear seek check */
}
sim_activate (uptr, ds_stime * (t + 1)); /* schedule */
return;
}
@@ -1048,29 +1131,36 @@ t_bool ds_start_rw (UNIT *uptr, int32 tm, t_bool vfy)
uint32 da, hd, sc;
uint32 dtyp = GET_DTYPE (uptr->flags);
ds_eod = 0; /* clear eod */
ds_eod = 0; /* init eod */
ds_ptr = 0; /* init buffer ptr */
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
ds_cmd_done (1, DS1_S2ERR);
return TRUE; }
return TRUE;
}
if (ds_eoc) { /* at end of cylinder? */
ds_next_cyl (uptr); /* auto seek to next */
return TRUE; } /* or error */
if (vfy && ((uint32) uptr->CYL != ds_cyl)) { /* on proper cylinder? */
ds_cmd_done (1, DS1_CYLCE); /* no, error */
return TRUE; }
return TRUE; /* or error */
}
if (vfy && ((uint32) uptr->CYL != ds_cyl)) { /* on wrong cylinder? */
if (ds_cyl >= drv_tab[dtyp].cyl) /* seeking to bad? */
ds_cmd_done (1, DS1_CYLCE); /* lose */
else ds_start_seek (uptr, ds_cyl, uptr->FNC); /* seek right cyl */
return TRUE;
}
hd = DSHS_GETHD (ds_hs);
sc = DSHS_GETSC (ds_hs);
if ((uint32) uptr->CYL >= drv_tab[dtyp].cyl) { /* valid cylinder? */
uptr->STA = uptr->STA | DS2_SC; /* set seek check */
ds_cmd_done (1, DS1_S2ERR); /* error */
return TRUE; }
return TRUE;
}
if ((hd >= drv_tab[dtyp].hd) || /* valid head, sector? */
(sc >= drv_tab[dtyp].sc)) {
ds_cmd_done (1, DS1_HSCE); /* no, error */
return TRUE; }
return TRUE;
}
da = GET_DA (uptr->CYL, hd, sc, dtyp); /* position in file */
sim_fseek (uptr->fileref, da * sizeof (uint16), SEEK_SET); /* set file pos */
ds_ptr = 0; /* init buffer ptr */
uptr->FNC += DSC_NEXT; /* next state */
sim_activate (uptr, tm); /* activate unit */
return FALSE;
@@ -1080,7 +1170,8 @@ return FALSE;
- Do common start for read and write
- If error, return, command has been terminated, nothing scheduled
- If no error, state has been advanced and unit scheduled
- If implicit seek, return, seek scheduled
- If no error or seek, state has been advanced and unit scheduled
- Read sector
- If read error, terminate command and return, nothing scheduled
- If no error, advance head/sector, next state scheduled */
@@ -1089,8 +1180,7 @@ t_stat ds_start_rd (UNIT *uptr, uint32 off, t_bool vfy)
{
uint32 t;
if (ds_start_rw (uptr, ds_rtime, vfy)) /* new sector; error? */
return SCPE_OK; /* nothing scheduled */
if (ds_start_rw (uptr, ds_rtime, vfy)) return SCPE_OK; /* new sec; err or seek? */
t = sim_fread (dsxb + off, sizeof (uint16), DS_NUMWD, uptr->fileref);
for (t = t + off ; t < DS_NUMWDF; t++) dsxb[t] = 0; /* fill sector */
if (ferror (uptr->fileref)) /* error? */
@@ -1103,20 +1193,22 @@ return SCPE_OK;
- Do common start for read and write
- If error, return, command has been terminated, nothing scheduled
- If no error, state has been advanced and unit scheduled
- If implicit seek, return, seek scheduled
- If no error or seek, state has been advanced and unit scheduled
- Clear buffer
- Set service request */
void ds_start_wr (UNIT *uptr, t_bool vfy)
{
uint32 i, dev;
uint32 i;
uint32 dev = ds_dib.devno;
dev = ds_dib.devno;
if ((uptr->flags & UNIT_WPR) || /* write protected? */
(!vfy && ((uptr->flags & UNIT_FMT) == 0))) { /* format, not enbl? */
ds_cmd_done (1, DS1_S2ERR); /* error */
return; }
if (ds_start_rw (uptr, ds_rtime, vfy)) return; /* new sector; error? */
return;
}
if (ds_start_rw (uptr, ds_rtime, vfy)) return; /* new sec; err or seek? */
for (i = 0; i < DS_NUMWDF; i++) dsxb[i] = 0; /* clear buffer */
setSRQ (dev); /* request word */
return;
@@ -1134,7 +1226,8 @@ ds_hs = ds_hs & ~DSHS_SC; /* yes, wrap sector */
if (ds_fmask & DSC_CYLM) { /* cylinder mode? */
ds_hs = ds_hs + (1 << DSHS_V_HD); /* increment head */
if (DSHS_GETHD (ds_hs) < drv_tab[dtyp].hd) return; /* end of cyl? */
ds_hs = ds_hs & ~DSHS_HD; } /* 0 head */
ds_hs = ds_hs & ~DSHS_HD; /* 0 head */
}
ds_eoc = 1; /* flag end cylinder */
return;
}
@@ -1146,13 +1239,12 @@ return;
void ds_next_cyl (UNIT *uptr)
{
uint32 dtyp = GET_DTYPE (uptr->flags);
if (ds_fmask & DSC_AUTO) { /* auto seek allowed? */
if (ds_fmask & DSC_DECR) ds_cyl = (ds_cyl - 1) & DMASK;
else ds_cyl = (ds_cyl + 1) & DMASK;
ds_eoc = 0; /* clear end cylinder */
ds_start_seek (uptr, ds_cyl, uptr->FNC); } /* seek, same state */
ds_start_seek (uptr, ds_cyl, uptr->FNC); /* seek, same state */
}
else ds_cmd_done (1, DS1_EOCYL); /* no, end of cyl err */
return;
}
@@ -1167,10 +1259,15 @@ void ds_cont_rd (UNIT *uptr, uint32 bsize)
uint32 dev = ds_dib.devno;
if (ds_eod) ds_cmd_done (1, DS1_OK); /* DMA end? done */
else if (SRQ (dev)) { /* overrun? */
ds_cmd_done (1, DS1_OVRUN); /* set done */
return;
}
else { ds_fifo_write (dsxb[ds_ptr++]); /* next word */
setSRQ (dev); /* request service */
if (ds_ptr >= bsize) uptr->FNC += DSC_NEXT; /* sec done? next state */
sim_activate (uptr, ds_dtime); } /* schedule */
sim_activate (uptr, ds_dtime); /* schedule */
}
return;
}
@@ -1183,18 +1280,26 @@ return;
t_stat ds_cont_wr (UNIT *uptr, uint32 off, uint32 bsize)
{
uint32 i, dat;
uint32 dev = ds_dib.devno;
dsxb[ds_ptr++] = ds_fifo_read (); /* next word */
if (SRQ (dev)) { /* overrun? */
ds_cmd_done (1, DS1_OVRUN); /* set done */
return SCPE_OK;
}
dsxb[ds_ptr++] = dat = ds_fifo_read (); /* next word */
if (ds_eod || (ds_ptr >= bsize)) { /* xfr or sector done? */
for (i = ds_ptr; i < bsize; i++) dsxb[i] = dat; /* fill sector */
sim_fwrite (dsxb + off, sizeof (uint16), DS_NUMWD, uptr->fileref);
if (ferror (uptr->fileref)) /* error on write? */
return ds_set_uncorr (uptr); /* uncorrectable */
ds_next_sec (uptr); /* increment hd, sc */
if (ds_eod) { /* end data? */
ds_cmd_done (1, DS1_OK); /* set done */
return SCPE_OK; }
else uptr->FNC += DSC_NEXT; } /* no, next state */
return SCPE_OK;
}
else uptr->FNC += DSC_NEXT; /* no, next state */
}
else { setSRQ (dev); } /* request next word */
sim_activate (uptr, ds_dtime); /* schedule */
return SCPE_OK;
@@ -1278,7 +1383,8 @@ for (i = 0; i < DS_NUMDR; i++) { /* loop thru drives */
sim_cancel (&ds_unit[i]); /* cancel activity */
ds_unit[i].FNC = 0; /* clear function */
ds_unit[i].CYL = 0;
ds_unit[i].STA = 0; }
ds_unit[i].STA = 0;
}
sim_cancel (&ds_ctrl);
sim_cancel (&ds_timer);
return SCPE_OK;
@@ -1305,14 +1411,16 @@ uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size;
r = attach_unit (uptr, cptr); /* attach unit */
if (r != SCPE_OK) return r; /* error? */
uptr->STA = DS2_ATN | DS2_FS; /* update drive status */
ds_sched_attn (uptr); /* schedule attention */
ds_sched_atn (uptr); /* schedule attention */
if (((uptr->flags & UNIT_AUTO) == 0) || /* static size? */
((p = sim_fsize (uptr->fileref)) == 0)) return SCPE_OK; /* new file? */
for (i = 0; drv_tab[i].sc != 0; i++) { /* find best fit */
if (p <= (drv_tab[i].size * sizeof (uint16))) {
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE);
uptr->capac = drv_tab[i].size;
return SCPE_OK; } }
if (p <= (drv_tab[i].size * sizeof (uint16))) {
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE);
uptr->capac = drv_tab[i].size;
return SCPE_OK;
}
}
return SCPE_OK;
}
@@ -1321,20 +1429,21 @@ return SCPE_OK;
t_stat ds_detach (UNIT *uptr)
{
uptr->STA = DS2_ATN; /* update drive status */
ds_sched_attn (uptr); /* schedule attention */
ds_sched_atn (uptr); /* schedule attention */
return detach_unit (uptr);
}
/* Schedule attention interrupt if CTL set, not restore, and controller idle */
void ds_sched_attn (UNIT *uptr)
void ds_sched_atn (UNIT *uptr)
{
int32 i;
if (!ds_dib.ctl || (sim_switches & SIM_SW_REST)) return;
for (i = 0; i < (DS_NUMDR + 1); i++) { /* check units, ctrl */
if (sim_is_active (ds_dev.units + i)) return; }
uptr->FNC = DSC_ATTN; /* pseudo operation */
if (sim_is_active (ds_dev.units + i)) return;
}
uptr->FNC = DSC_ATN; /* pseudo operation */
sim_activate (uptr, 1); /* do immediately */
return;
}
@@ -1424,6 +1533,6 @@ int32 dev;
if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */
dev = ds_dib.devno; /* get data chan dev */
if (ibl_copy (ds_rom, dev)) return SCPE_IERR; /* copy boot to memory */
SR = (SR & IBL_OPT) | IBL_DS | IBL_MAN | (dev << IBL_V_DEV); /* set SR */
SR = (SR & (IBL_OPT | IBL_DS_HEAD)) | IBL_DS | IBL_MAN | (dev << IBL_V_DEV);
return SCPE_OK;
}

View File

@@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
26-Dec-04 RMS Separated A/B from M[0/1] for DMA IO (from Dave Bryan)
15-Jul-03 RMS Fixed signed/unsigned warning
21-Oct-02 RMS Recoded for compatibility with 21MX microcode algorithms
@@ -102,7 +103,7 @@ struct ufp { /* unpacked fp */
#define FR_NEG(v) ((~(v) + 1) & DMASK32)
extern uint16 *M;
extern uint16 ABREG[2];
uint32 UnpackFP (struct ufp *fop, uint32 opnd);
void NegFP (struct ufp *fop);
void NormFP (struct ufp *fop);

View File

@@ -26,6 +26,8 @@
lps 12653A 2767 line printer
(based on 12566B microcircuit interface)
19-Nov-04 JDB Added restart when set online, etc.
Fixed col count for non-printing chars
01-Oct-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON
Fixed status returns for error conditions
Fixed handling of non-printing characters
@@ -164,6 +166,9 @@ DEVICE lps_dev;
int32 lpsio (int32 inst, int32 IR, int32 dat);
t_stat lps_svc (UNIT *uptr);
t_stat lps_reset (DEVICE *dptr);
t_stat lps_restart (UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat lps_poweroff (UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat lps_poweron (UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat lps_attach (UNIT *uptr, char *cptr);
t_stat lps_set_timing (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, void *desc);
@@ -204,10 +209,10 @@ REG lps_reg[] = {
MTAB lps_mod[] = {
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
{ UNIT_DIAG, 0, "printer mode", "PRINTER", NULL },
{ UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", NULL },
{ UNIT_POWEROFF, 0, "power on", "POWERON", NULL },
{ UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", lps_poweroff },
{ UNIT_POWEROFF, 0, "power on", "POWERON", lps_poweron },
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL },
{ UNIT_OFFLINE, 0, "online", "ONLINE", NULL },
{ UNIT_OFFLINE, 0, "online", "ONLINE", lps_restart },
{ MTAB_XTD | MTAB_VDV, 0, NULL, "REALTIME",
&lps_set_timing, NULL, NULL },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME",
@@ -250,27 +255,13 @@ case ioOTX: /* output */
case ioLIX: /* load */
dat = 0; /* default sta = 0 */
case ioMIX: /* merge */
if ((lps_unit.flags & UNIT_DIAG) == 0) { /* real lpt? */
if (lps_power == LPS_ON) { /* power on? */
if (lps_unit.flags & UNIT_POWEROFF) { /* power just turned off? */
lps_power = LPS_OFF; /* change state */
lps_sta = LPS_PWROFF;
if (DEBUG_PRS (lps_dev))
fputs (">>LPS LIx: Power state is OFF\n", sim_deb); }
else if (((lps_unit.flags & UNIT_ATT) == 0) ||
(lps_unit.flags & UNIT_OFFLINE) ||
sim_is_active (&lps_unit)) lps_sta = LPS_BUSY;
else lps_sta = 0; }
else if (lps_power == LPS_TURNING_ON) /* printer warming up? */
lps_sta = LPS_PWROFF;
else if (!(lps_unit.flags & UNIT_POWEROFF)) { /* power just turned on? */
lps_power = LPS_TURNING_ON; /* change state */
lps_unit.flags |= UNIT_OFFLINE; /* set offline */
sim_activate (&lps_unit, lps_rtime); /* schedule printer ready */
lps_sta = LPS_PWROFF;
if (DEBUG_PRS (lps_dev)) fprintf (sim_deb,
">>LPS LIx: Power state is TURNING ON, scheduled time = %d\n",
lps_rtime ); } }
if ((lps_unit.flags & UNIT_DIAG) == 0) /* real lpt? */
if (lps_power == LPS_ON) /* power on? */
if (((lps_unit.flags & UNIT_ATT) == 0) || /* paper out? */
(lps_unit.flags & UNIT_OFFLINE) || /* offline? */
sim_is_active (&lps_unit)) lps_sta = LPS_BUSY;
else lps_sta = 0;
else lps_sta = LPS_PWROFF;
dat = dat | lps_sta; /* diag, rtn status */
if (DEBUG_PRS (lps_dev))
fprintf (sim_deb, ">>LPS LIx: Status %06o returned\n", dat);
@@ -291,13 +282,10 @@ case ioCTL: /* control clear/set */
if ((lps_unit.buf != '\f') &&
(lps_unit.buf != '\n') &&
(lps_unit.buf != '\r')) { /* normal char */
if ((lps_unit.buf < ' ') || (lps_unit.buf > '_'))
sched = lps_ctime; /* non-printing char */
else { /* printing char */
lps_ccnt = lps_ccnt + 1; /* incr char counter */
if (lps_ccnt % LPS_ZONECNT == 0)/* end of zone? */
sched = lps_ptime; /* print zone */
else sched = lps_ctime; } } /* xfer char */
lps_ccnt = lps_ccnt + 1; /* incr char counter */
if (lps_ccnt % LPS_ZONECNT == 0) /* end of zone? */
sched = lps_ptime; /* print zone */
else sched = lps_ctime; } /* xfer char */
else { /* print cmd */
if (lps_ccnt % LPS_ZONECNT == 0) /* last zone printed? */
sched = lps_ctime; /* yes, so just char time */
@@ -328,22 +316,29 @@ int32 c = uptr->buf & 0177;
if (lps_power == LPS_TURNING_ON) { /* printer warmed up? */
lps_power = LPS_ON; /* change state */
lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */
if (DEBUG_PRS (lps_dev))
fputs (">>LPS svc: Power state is ON\n", sim_deb);
return SCPE_OK; } /* done */
dev = lps_dib.devno; /* get dev no */
clrCMD (dev); /* clear cmd */
setFSR (dev); /* set flag, fbf */
if (uptr->flags & UNIT_DIAG) { /* diagnostic? */
lps_sta = uptr->buf; /* loop back */
clrCMD (dev); /* clear cmd */
setFSR (dev); /* set flag, fbf */
return SCPE_OK; } /* done */
if ((uptr->flags & UNIT_ATT) == 0) /* real lpt, att? */
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (lps_stopioe, SCPE_UNATT);
else if (uptr->flags & UNIT_OFFLINE) /* offline? */
return IORETURN (lps_stopioe, STOP_OFFLINE);
else if (uptr->flags & UNIT_POWEROFF) /* powered off? */
return IORETURN (lps_stopioe, STOP_PWROFF);
clrCMD (dev); /* clear cmd */
setFSR (dev); /* set flag, fbf */
if (((c < ' ') || (c > '_')) && /* non-printing char? */
(c != '\f') && (c != '\n') && (c != '\r')) {
c = ' '; /* replace with blank */
if (DEBUG_PRS (lps_dev))
fprintf (sim_deb, ">>LPS svc: Character %06o erased\n", c); }
fprintf (sim_deb, ">>LPS svc: Character %06o erased\n", c);
c = ' '; } /* replace with blank */
if (lps_ccnt > LPS_PAGECNT) { /* 81st character? */
fputc ('\r', uptr->fileref); /* return to line start */
uptr->pos = uptr->pos + 1; /* update pos */
@@ -379,11 +374,60 @@ lps_set_timing (NULL, lps_timing, NULL, NULL); /* init timing set */
return SCPE_OK;
}
/* Restart I/O routine
If I/O is started via STC, and the printer is powered off, offline,
or out of paper, the CTL and CMD flip-flops will set, a service event
will be scheduled, and the service routine will be entered. If
STOP_IOE is not set, the I/O operation will "hang" at that point
until the printer is powered on, set online, or paper is supplied
(attached).
If a pending operation is "hung" when this routine is called, it is
restarted, which clears CTL and sets FBF and FLG, completing the
original I/O request.
*/
t_stat lps_restart (UNIT *uptr, int32 value, char *cptr, void *desc)
{
if (lps_dib.cmd && lps_dib.ctl && !sim_is_active (uptr))
sim_activate (uptr, 0); /* reschedule I/O */
return SCPE_OK;
}
/* Printer power off */
t_stat lps_poweroff (UNIT *uptr, int32 value, char *cptr, void *desc)
{
lps_power = LPS_OFF; /* change state */
if (DEBUG_PRS (lps_dev)) fputs (">>LPS set: Power state is OFF\n", sim_deb);
return SCPE_OK;
}
/* Printer power on */
t_stat lps_poweron (UNIT *uptr, int32 value, char *cptr, void *desc)
{
if (lps_unit.flags & UNIT_DIAG) { /* diag mode? */
lps_power = LPS_ON; /* no delay */
if (DEBUG_PRS (lps_dev))
fputs (">>LPS set: Power state is ON\n", sim_deb); }
else {
lps_power = LPS_TURNING_ON; /* change state */
lps_unit.flags |= UNIT_OFFLINE; /* set offline */
sim_activate (&lps_unit, lps_rtime); /* schedule ready */
if (DEBUG_PRS (lps_dev)) fprintf (sim_deb,
">>LPS set: Power state is TURNING ON, scheduled time = %d\n",
lps_rtime ); }
return SCPE_OK;
}
/* Attach routine */
t_stat lps_attach (UNIT *uptr, char *cptr)
{
lps_ccnt = lps_lcnt = 0; /* top of form */
lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */
return attach_unit (uptr, cptr);
}

View File

@@ -25,6 +25,7 @@
lpt 12845B 2607 line printer
19-Nov-04 JDB Added restart when set online, etc.
29-Sep-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON
Fixed status returns for error conditions
Fixed TOF handling so form remains on line 0
@@ -97,6 +98,7 @@ DEVICE lpt_dev;
int32 lptio (int32 inst, int32 IR, int32 dat);
t_stat lpt_svc (UNIT *uptr);
t_stat lpt_reset (DEVICE *dptr);
t_stat lpt_restart (UNIT *uptr, int32 value, char *cptr, void *desc);
t_stat lpt_attach (UNIT *uptr, char *cptr);
/* LPT data structures
@@ -128,9 +130,9 @@ REG lpt_reg[] = {
MTAB lpt_mod[] = {
{ UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", NULL },
{ UNIT_POWEROFF, 0, "power on", "POWERON", NULL },
{ UNIT_POWEROFF, 0, "power on", "POWERON", lpt_restart },
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL },
{ UNIT_OFFLINE, 0, "online", "ONLINE", NULL },
{ UNIT_OFFLINE, 0, "online", "ONLINE", lpt_restart },
{ MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO",
&hp_setdev, &hp_showdev, &lpt_dev },
{ 0 } };
@@ -196,9 +198,13 @@ t_stat lpt_svc (UNIT *uptr)
int32 i, skip, chan, dev;
dev = lpt_dib.devno; /* get dev no */
clrCMD (dev); /* clear cmd */
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (lpt_stopioe, SCPE_UNATT);
else if (uptr->flags & UNIT_OFFLINE) /* offline? */
return IORETURN (lpt_stopioe, STOP_OFFLINE);
else if (uptr->flags & UNIT_POWEROFF) /* powered off? */
return IORETURN (lpt_stopioe, STOP_PWROFF);
clrCMD (dev); /* clear cmd */
setFSR (dev); /* set flag, fbf */
if (uptr->buf & LPT_CTL) { /* control word? */
if (uptr->buf & LPT_CHAN) {
@@ -237,10 +243,32 @@ sim_cancel (&lpt_unit); /* deactivate unit */
return SCPE_OK;
}
/* Restart I/O routine
If I/O is started via STC, and the printer is powered off, offline,
or out of paper, the CTL and CMD flip-flops will set, a service event
will be scheduled, and the service routine will be entered. If
STOP_IOE is not set, the I/O operation will "hang" at that point
until the printer is powered on, set online, or paper is supplied
(attached).
If a pending operation is "hung" when this routine is called, it is
restarted, which clears CTL and sets FBF and FLG, completing the
original I/O request.
*/
t_stat lpt_restart (UNIT *uptr, int32 value, char *cptr, void *desc)
{
if (lpt_dib.cmd && lpt_dib.ctl && !sim_is_active (uptr))
sim_activate (uptr, 0); /* reschedule I/O */
return SCPE_OK;
}
/* Attach routine */
t_stat lpt_attach (UNIT *uptr, char *cptr)
{
lpt_lcnt = 0; /* top of form */
lpt_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */
return attach_unit (uptr, cptr);
}

View File

@@ -133,7 +133,6 @@
#define STA_LOCAL 0000001 /* local (d) */
#define STA_DYN (STA_PE|STA_SEL|STA_TBSY|STA_WLK|STA_LOCAL)
extern uint16 *M;
extern uint32 PC, SR;
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
extern int32 sim_switches;
@@ -854,12 +853,13 @@ const uint16 ms_rom[IBL_LNT] = {
t_stat msc_boot (int32 unitno, DEVICE *dptr)
{
int32 dev;
extern uint32 saved_AR;
if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */
dev = msd_dib.devno; /* get data chan dev */
if (ibl_copy (ms_rom, dev)) return SCPE_IERR; /* copy boot to memory */
SR = (SR & IBL_OPT) | IBL_MS | (dev << IBL_V_DEV); /* set SR */
if ((sim_switches & SWMASK ('S')) && AR) SR = SR | 1; /* skip? */
if ((sim_switches & SWMASK ('S')) && saved_AR) SR = SR | 1; /* skip? */
return SCPE_OK;
}

View File

@@ -115,7 +115,6 @@
#define CLK_V_ERROR 4 /* clock overrun */
#define CLK_ERROR (1 << CLK_V_ERROR)
extern uint16 *M;
extern uint32 PC, SR;
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
extern UNIT cpu_unit;

View File

@@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
19-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF messages
25-Sep-04 JDB Added memory protect device
Fixed display of CCA/CCB/CCE instructions
01-Jun-04 RMS Added latent 13037 support
@@ -108,7 +109,9 @@ const char *sim_stop_messages[] = {
"Breakpoint",
"Indirect address loop",
"Indirect address interrupt (should not happen!)",
"No connection on interprocessor link" };
"No connection on interprocessor link",
"Device/unit offline",
"Device/unit powered off" };
/* Binary loader