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:
committed by
Mark Pizzolato
parent
b6393b36b4
commit
9b5c8c9711
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user