1
0
mirror of https://github.com/simh/simh.git synced 2026-02-27 09:09:46 +00:00

PDP11, PDP10 & VAXen: Fix TS11, RH11/TM02-3, TU45 for proper BOT handling

A user observed that the TS11 would not run XXDP+, even though it ran
fine with the PDP11 operating systems, VMS, and XXDP V2.  I traced this
back to a conceptual error in the implementation of some magtapes,
specifically the TS11, RH11/TM02-3, and the PDP10 TU45.

The issues is that beginning of tape, and being positioned in front of
the first record, are not necessarily the same. Following BOT, tape
drives record a ID burst If high density and an inter-record gap before
the first record. When the first record is read backwards or backspaced
over, the tape ends up at position 0 but should not show BOT.  Most
simulated tape drives did this correctly, but a few used sim_tape_bot()
as a shortcut for BOT, and it's simply not correct.

BOT should be set at ATTACH, by a successful rewind, and by any reverse
operation when the tape is positioned in front of the first record.

BOT should be cleared by any successful movement operation, except
rewind.
This commit is contained in:
Bob Supnik
2023-11-07 09:06:27 -10:00
committed by Mark Pizzolato
parent 67ec597696
commit 4c63340ba9
3 changed files with 120 additions and 67 deletions

View File

@@ -1,6 +1,6 @@
/* pdp10_tu.c - PDP-10 RH11/TM03/TU45 magnetic tape simulator
Copyright (c) 1993-2022, Robert M Supnik
Copyright (c) 1993-2023, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -25,6 +25,7 @@
tu RH11/TM03/TU45 magtape
06-Nov-23 RMS Fixed BOT logic
26-Mar-22 RMS Added extra case points for new MTSE definitions
07-Sep-20 RMS Fixed || -> | in macro (Mark Pizzolato)
12-Jan-18 RMS Fixed missing () in logical test (Mark Pizzolato)
@@ -94,6 +95,10 @@
level sensitive.
- The DONE interrupt, once set, is not disabled if IE is cleared,
but the SC interrupt is.
BOT is not the same as POS == 0. BOT is set after rewinding or after
a reverse operation from before the first record. It is cleared by
any successful motion operation.
*/
#include "pdp10_defs.h"
@@ -183,7 +188,7 @@
*/
#define FS_SAT 0000001 /* slave attention */
#define FS_BOT 0000002 /* ^beginning of tape */
#define FS_BOT 0000002 /* +beginning of tape */
#define FS_TMK 0000004 /* end of file */
#define FS_ID 0000010 /* ID burst detected */
#define FS_SLOW 0000020 /* slowing down NI */
@@ -191,7 +196,7 @@
#define FS_SSC 0000100 /* slave stat change */
#define FS_RDY 0000200 /* ^formatter ready */
#define FS_FPR 0000400 /* formatter present */
#define FS_EOT 0002000 /* +end of tape */
#define FS_EOT 0002000 /* ^end of tape */
#define FS_WRL 0004000 /* ^write locked */
#define FS_MOL 0010000 /* ^medium online */
#define FS_PIP 0020000 /* +pos in progress */
@@ -675,7 +680,7 @@ switch (fnc) { /* case on function */
tufs = tufs & ~(FS_SAT | FS_SSC | FS_ID | FS_ERR);
if (!(uptr->TU_STATEFLAGS & TUS_ATTPENDING))
sim_cancel (uptr); /* stop motion, not on-line delay */
uptr->USTAT = 0;
uptr->USTAT &= FS_BOT; /* fall through */
/* fall through */
case FNC_NOP:
tucs1 = tucs1 & ~CS1_GO; /* no operation */
@@ -687,8 +692,10 @@ switch (fnc) { /* case on function */
break;
}
tutc = TC_RIP; /* density = 800 */
sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */
tu_unit[0].USTAT = 0;
if (tu_unit[0].flags & UNIT_ATT) { /* attached? */
sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */
tu_unit[0].USTAT = FS_BOT;
}
tucs1 = tucs1 & ~CS1_GO;
tufs = tufs & ~FS_TMK;
return;
@@ -733,7 +740,7 @@ switch (fnc) { /* case on function */
set_tuer (ER_UNS);
break;
}
if (sim_tape_bot (uptr) || ((tutc & TC_FCS) == 0)) {
if ((uptr->USTAT & FS_BOT) || ((tutc & TC_FCS) == 0)) {
set_tuer (ER_NXF);
break;
}
@@ -761,7 +768,7 @@ switch (fnc) { /* case on function */
case FNC_WCHKR: /* wchk = read */
case FNC_READR: /* read rev */
if (tufs & FS_BOT) { /* beginning of tape? */
if (uptr->USTAT & FS_BOT) { /* beginning of tape? */
set_tuer (ER_NXF);
break;
}
@@ -835,7 +842,9 @@ if (uptr->TU_STATEFLAGS & TUS_ATTPENDING) {
if (uptr->USTAT & FS_REW) { /* rewind or unload? */
sim_tape_rewind (uptr); /* rewind tape */
uptr->USTAT = 0; /* clear status */
if (uptr->flags & UNIT_ATT) /* attached? */
uptr->USTAT = FS_BOT; /* set BOT */
else uptr->USTAT = 0; /* clear status */
tufs = tufs | FS_ATA | FS_SSC;
update_tucs (CS1_SC, drv); /* update status */
return SCPE_OK;
@@ -1041,21 +1050,17 @@ if ((flag & ~tucs1) & CS1_DONE) /* DONE 0 to 1? */
tuiff = (tucs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */
if (GET_FMTR (tucs2) == 0) { /* formatter present? */
tufs = (tufs & ~FS_DYN) | FS_FPR;
if (tu_unit[drv].TU_STATEFLAGS & TUS_ATTPENDING) /* Delayed on-line timer running? */
act = 0; /* Not a tape motion op */
if (tu_unit[drv].TU_STATEFLAGS & TUS_ATTPENDING) /* delayed on-line timer running? */
act = 0; /* not a tape motion op */
else {
if (tu_unit[drv].flags & UNIT_ATT) {
tufs = tufs | FS_MOL | tu_unit[drv].USTAT;
tufs = tufs | FS_MOL | (tu_unit[drv].USTAT & 0177777);
if (tu_unit[drv].UDENS == TC_1600)
tufs = tufs | FS_PE;
if (sim_tape_wrp (&tu_unit[drv]))
tufs = tufs | FS_WRL;
if (!act) {
if (sim_tape_bot (&tu_unit[drv]))
tufs = tufs | FS_BOT;
if (sim_tape_eot (&tu_unit[drv]))
if (!act && sim_tape_eot (&tu_unit[drv]))
tufs = tufs | FS_EOT;
}
}
}
if (tuer)
@@ -1138,6 +1143,7 @@ switch (st) {
break;
case MTSE_BOT: /* reverse into BOT */
uptr->USTAT = FS_BOT; /* set BOT */
break;
case MTSE_WRP: /* write protect */
@@ -1178,7 +1184,9 @@ for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */
if (!sim_is_active(uptr) )
sim_activate_after(uptr, SPINUPDLY);
}
uptr->USTAT = 0;
if ((uptr->flags & UNIT_ATT) && sim_tape_bot (uptr))
uptr->USTAT = FS_BOT;
else uptr->USTAT = 0;
}
if (xbuf == NULL)
xbuf = (uint8 *) calloc (MT_MAXFR + 4, sizeof (uint8));
@@ -1197,7 +1205,7 @@ t_stat r;
r = sim_tape_attach (uptr, cptr);
if (r != SCPE_OK)
return r;
uptr->USTAT = 0; /* clear unit status */
uptr->USTAT = FS_BOT; /* set BOT */
uptr->UDENS = UD_UNK; /* unknown density */
/* Delay setting MOL since we may have just detached a previous file.
* In that case, the OS must see MOL clear, so that it will know that the
@@ -1243,7 +1251,7 @@ return sim_tape_detach (uptr);
}
/* Device bootstrap */
/* Note that the dec and ITS boot code is word for word identical,
/* Note that the DEC and ITS boot code is word for word identical,
* except for the IO instructions. The ITS instructions encode the
* UBA number. No attempt is made to allow UBA selection under ITS,
* though it should work with the DEC rom.

View File

@@ -1,6 +1,6 @@
/* pdp11_ts.c: TS11/TSV05 magnetic tape simulator
Copyright (c) 1993-2022, Robert M Supnik
Copyright (c) 1993-2023, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -25,6 +25,8 @@
ts TS11/TSV05 magtape
29-Oct-23 RMS Implemented distinction between BOT and POS==0
INIT command is a NOP
26-Mar-22 RMS Added extra case points for new MTSE definitions
27-Oct-14 RMS Fixed bug in read forward with byte swap
23-Oct-13 RMS Revised for new boot setup routine
@@ -87,6 +89,25 @@
- PDP-11 Unibus 22b systems - the TS11 behaves as an 18b Unibus
peripheral and must go through the I/O map
- VAX Q22 systems - the TS11 must go through the I/O map
The TS11 must distinguish between true beginning of tape (BOT) -
positioned at the tape marker - and positioned before the first
record (POS == 0). BOT is set under the following circumstances:
- Mount (ATTACH)
- Rewind
- Backward operation, !BOT && POS==0. This sets RIB (rewind into
BOT) and is an error
It is cleared by any successful forward operation.
Therefore, reverse operations (except rewind) have three states:
- !BOT, POS != 0. BOT unchanaged.
- !BOT, POS == 0. Set BOT and RIB; error.
- BOT. Set function reject.
Rewind always moves the tape to BOT, even if it is already at BOT.
*/
#if defined (VM_PDP10) /* PDP10 version */
@@ -275,11 +296,12 @@ int32 tsdbx = 0; /* data buf ext */
int32 tscmdp[CMD_PLNT] = { 0 }; /* command packet */
int32 tsmsgp[MSG_PLNT] = { 0 }; /* message packet */
int32 tswchp[WCH_PLNT] = { 0 }; /* wr char packet */
int32 ts_bot = 0; /* at BOT */
int32 ts_ownc = 0; /* tape owns cmd */
int32 ts_ownm = 0; /* tape owns msg */
int32 ts_qatn = 0; /* queued attn */
int32 ts_bcmd = 0; /* boot cmd */
int32 ts_time = 2000; /* record latency */
int32 ts_time = 10; /* record latency */
static uint16 cpy_buf[MAX_PLNT]; /* copy buffer */
t_stat ts_rd (int32 *data, int32 PA, int32 access);
@@ -293,6 +315,7 @@ int32 ts_updtssr (int32 t);
int32 ts_updxs0 (int32 t);
void ts_cmpendcmd (int32 s0, int32 s1);
void ts_endcmd (int32 ssf, int32 xs0f, int32 msg);
void ts_set_mot (int32 bot);
int32 ts_map_status (t_stat st);
t_stat ts_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
const char *ts_description (DEVICE *dptr);
@@ -335,6 +358,7 @@ REG ts_reg[] = {
{ GRDATAD (WOPT, wchopt, DEV_RDX, 16, 0, "write char packet options") },
{ GRDATAD (WXOPT, wchxopt, DEV_RDX, 16, 0, "write char packet extended options") },
{ FLDATAD (INT, IREQ (TS), INT_V_TS, "interrupt pending") },
{ FLDATAD (BOT, ts_bot, 0, "beginning of tape") },
{ FLDATAD (ATTN, ts_qatn, 0, "attention message pending") },
{ FLDATAD (BOOT, ts_bcmd, 0, "boot request pending") },
{ FLDATAD (OWNC, ts_ownc, 0, "if set, tape owns command buffer") },
@@ -401,6 +425,7 @@ switch ((PA >> 1) & 01) { /* decode PA<1> */
case 0: /* TSBA */
*data = tsba & DMASK; /* low 16b of ba */
break;
case 1: /* TSSR */
*data = tssr = ts_updtssr (tssr); /* update tssr */
break;
@@ -433,7 +458,7 @@ switch ((PA >> 1) & 01) { /* decode PA<1> */
CLR_INT (TS); /* clr int req */
t = Map_ReadW (tsba, CMD_PLNT << 1, cpy_buf); /* read cmd pkt */
tsba = tsba + ((CMD_PLNT << 1) - t); /* incr tsba */
if (t) { /* nxm? */
if (t != 0) { /* nxm? */
ts_endcmd (TSSR_NXM + TC5, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL);
return SCPE_OK;
}
@@ -478,11 +503,11 @@ switch (st) {
break;
case MTSE_TMK:
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
return (XTC (XS0_TMK | XS0_RLS, TC2));
case MTSE_RECE: /* record in error */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
case MTSE_INVRL: /* invalid rec lnt */
case MTSE_IOERR: /* IO error */
default: /* unknown error */
@@ -497,6 +522,7 @@ switch (st) {
case MTSE_BOT: /* reverse into BOT */
msgxs3 = msgxs3 | XS3_RIB; /* set status */
ts_bot = 1; /* set BOT */
return (XTC (XS0_BOT | XS0_RLS, TC2)); /* tape alert */
case MTSE_WRP: /* write protect */
@@ -518,7 +544,7 @@ do {
msgrfc = fc;
if ((st = sim_tape_sprecf (uptr, &tbc))) /* space rec fwd, err? */
return ts_map_status (st); /* map status */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
} while (fc != 0);
return 0;
}
@@ -536,7 +562,7 @@ do {
st = sim_tape_sprecf (uptr, &tbc); /* space rec fwd */
if (st == MTSE_TMK) { /* tape mark? */
msgrfc = (msgrfc - 1) & DMASK; /* decr count */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */
return (XTC ((msgrfc? XS0_RLS: 0) |
XS0_TMK | XS0_LET, TC2));
@@ -545,7 +571,7 @@ do {
else if (st != MTSE_OK)
return ts_map_status (st);
else tmkprv = FALSE; /* not a tmk */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
} while (msgrfc != 0);
return 0;
}
@@ -561,7 +587,7 @@ do {
msgrfc = fc;
if ((st = sim_tape_sprecr (uptr, &tbc))) /* space rec rev, err? */
return ts_map_status (st); /* map status */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
} while (fc != 0);
return 0;
}
@@ -577,7 +603,7 @@ do {
st = sim_tape_sprecr (uptr, &tbc); /* space rec rev */
if (st == MTSE_TMK) { /* tape mark? */
msgrfc = (msgrfc - 1) & DMASK; /* decr count */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */
return (XTC ((msgrfc? XS0_RLS: 0) |
XS0_TMK | XS0_LET, TC2));
@@ -586,7 +612,7 @@ do {
else if (st != MTSE_OK)
return ts_map_status (st);
else tmkprv = FALSE; /* not a tmk */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
} while (msgrfc != 0);
return 0;
}
@@ -605,7 +631,7 @@ if (fc == 0) /* byte count */
fc = 0200000;
tsba = (cmdadh << 16) | cmdadl; /* buf addr */
wbc = (tbc > fc)? fc: tbc; /* cap buf size */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
if (cmdhdr & CMD_SWP) { /* swapped? */
for (i = 0; i < wbc; i++) { /* copy buffer */
wa = tsba ^ 1; /* apply OPP */
@@ -620,7 +646,7 @@ if (cmdhdr & CMD_SWP) { /* swapped? */
else {
t = Map_WriteB (tsba, wbc, tsxb); /* store record */
tsba = tsba + (wbc - t); /* update tsba */
if (t) { /* nxm? */
if (t != 0) { /* nxm? */
tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */
return (XTC (XS0_RLS, TC4));
}
@@ -647,7 +673,7 @@ if (fc == 0) /* byte count */
fc = 0200000;
tsba = ((cmdadh << 16) | cmdadl) + fc; /* buf addr */
wbc = (tbc > fc)? fc: tbc; /* cap buf size */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
for (i = wbc; i > 0; i--) { /* copy buffer */
tsba = tsba - 1;
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
@@ -687,14 +713,14 @@ if (cmdhdr & CMD_SWP) { /* swapped? */
else {
t = Map_ReadB (tsba, fc, tsxb); /* fetch record */
tsba = tsba + (fc - t); /* update tsba */
if (t) { /* nxm? */
if (t != 0) { /* nxm? */
tssr = ts_updtssr (tssr | TSSR_NXM);
return TC5;
}
}
if ((st = sim_tape_wrrecf (uptr, tsxb, fc))) /* write rec, err? */
return ts_map_status (st); /* return status */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
msgrfc = 0;
if (sim_tape_eot (&ts_unit)) /* EOT on write? */
return XTC (XS0_EOT, TC2);
@@ -707,7 +733,7 @@ t_stat st;
if ((st = sim_tape_wrtmk (uptr))) /* write tmk, err? */
return ts_map_status (st); /* return status */
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_set_mot (0); /* tape has moved, !BOT */
if (sim_tape_eot (&ts_unit)) /* EOT on write? */
return XTC (XS0_EOT, TC2);
return XTC (XS0_TMK, TC0);
@@ -738,7 +764,7 @@ static const char *fnc_name[CMD_N_FNC] = {
"30", "31", "32", "33", "34", "35", "36", "37"
};
if (ts_bcmd) { /* boot? */
if (ts_bcmd != 0) { /* boot? */
ts_bcmd = 0; /* clear flag */
sim_tape_rewind (uptr); /* rewind */
if (uptr->flags & UNIT_ATT) { /* attached? */
@@ -750,6 +776,7 @@ if (ts_bcmd) { /* boot? */
else tssr = ts_updtssr (tssr | TSSR_SSR | TC3);
if (cmdhdr & CMD_IE)
SET_INT (TS);
ts_bot = 0; /* unatt or !BOT */
return SCPE_OK;
}
@@ -792,7 +819,7 @@ if ((fnc_flg[fnc] & FLG_WR) && /* write? */
}
if ((((fnc == FNC_READ) && (mod == 1)) || /* read rev */
((fnc == FNC_POS) && (mod & 1))) && /* space rev */
sim_tape_bot (uptr)) { /* BOT? */
(ts_bot != 0)) { /* BOT? */
ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL);
return SCPE_OK;
}
@@ -805,9 +832,6 @@ st0 = st1 = 0;
switch (fnc) { /* case on func */
case FNC_INIT: /* init */
if (!sim_tape_bot (uptr)) /* set if tape moves */
msgxs0 = msgxs0 | XS0_MOT;
sim_tape_rewind (uptr); /* rewind */
case FNC_WSSM: /* write mem */
case FNC_GSTA: /* get status */
ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); /* send end packet */
@@ -822,7 +846,7 @@ switch (fnc) { /* case on func */
bc = ((WCH_PLNT << 1) > cmdlnt)? cmdlnt: WCH_PLNT << 1;
t = Map_ReadW (tsba, bc, cpy_buf); /* fetch packet */
tsba = tsba + (bc - t); /* inc tsba */
if (t) { /* nxm? */
if (t != 0) { /* nxm? */
ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0);
return SCPE_OK;
}
@@ -844,11 +868,12 @@ switch (fnc) { /* case on func */
tssr = ts_updtssr (tssr | TSSR_SSR); /* set SSR */
if (wchopt & WCH_ERI)
SET_INT (TS);
ts_ownc = 0; ts_ownm = 1; /* keep msg */
ts_ownc = 0;
ts_ownm = 1; /* keep msg */
break;
case 01: /* rewind and unload */
if (!sim_tape_bot (uptr)) /* if tape moves */
if (ts_bot == 0) /* if tape moves */
msgxs0 = msgxs0 | XS0_MOT;
sim_tape_detach (uptr); /* unload */
ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND);
@@ -863,9 +888,8 @@ switch (fnc) { /* case on func */
return SCPE_OK;
case 04: /* rewind */
if (!sim_tape_bot (uptr)) /* if tape moves */
msgxs0 = msgxs0 | XS0_MOT;
sim_tape_rewind (uptr);
ts_set_mot (1); /* always moves, BOT */
ts_endcmd (TC0, XS0_BOT, MSG_ACK | MSG_CEND);
break;
}
@@ -960,9 +984,8 @@ switch (fnc) { /* case on func */
break;
case 04: /* rewind */
if (!sim_tape_bot (uptr)) /* if tape moves */
msgxs0 = msgxs0 | XS0_MOT;
sim_tape_rewind (uptr);
ts_set_mot (1); /* always moves, BOT */
break;
}
ts_cmpendcmd (st0, 0);
@@ -983,6 +1006,13 @@ else t = t | TSSR_OFL;
return (t & ~TSSR_MBZ);
}
void ts_set_mot (int32 bot)
{
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
ts_bot = bot; /* set BOT state */
return;
}
int32 ts_updxs0 (int32 t)
{
t = (t & ~(XS0_ONL | XS0_WLK | XS0_BOT | XS0_IE)) | XS0_PET;
@@ -990,7 +1020,7 @@ if (ts_unit.flags & UNIT_ATT) {
t = t | XS0_ONL;
if (sim_tape_wrp (&ts_unit))
t = t | XS0_WLK;
if (sim_tape_bot (&ts_unit))
if (ts_bot != 0)
t = (t | XS0_BOT) & ~XS0_EOT;
if (sim_tape_eot (&ts_unit))
t = (t | XS0_EOT) & ~XS0_BOT;
@@ -1056,6 +1086,9 @@ t_stat ts_reset (DEVICE *dptr)
int32 i;
sim_tape_rewind (&ts_unit);
if ((ts_unit.flags & UNIT_ATT) != 0)
ts_bot = 1;
else ts_bot = 0;
tsba = tsdbx = 0;
ts_ownc = ts_ownm = 0;
ts_bcmd = 0;
@@ -1085,6 +1118,7 @@ t_stat r;
r = sim_tape_attach_ex (uptr, cptr, DBG_TAP, 0); /* attach unit */
if (r != SCPE_OK) /* error? */
return r;
ts_bot = 1; /* at BOT */
tssr = tssr & ~TSSR_OFL; /* clr offline */
if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) /* attn msg? */
return r;
@@ -1108,6 +1142,7 @@ if (!(uptr->flags & UNIT_ATT)) /* attached? */
r = sim_tape_detach (uptr); /* detach unit */
if (r != SCPE_OK)
return r; /* error? */
ts_bot = 0;
tssr = tssr | TSSR_OFL; /* set offline */
if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) /* attn msg? */
return r;

View File

@@ -1,6 +1,6 @@
/* pdp11_tu.c - PDP-11 TM02/TU16 TM03/TU45/TU77 Massbus magnetic tape controller
Copyright (c) 1993-2017, Robert M Supnik
Copyright (c) 1993-2023, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -25,6 +25,7 @@
tu TM02/TM03 magtape
06-Nov-23 RMS Fixed BOT logic
28-Dec-17 RMS Read tape mark must set Massbus EXC
13-Mar-17 RMS Annotated fall through in switch
23-Oct-13 RMS Revised for new boot setup routine
@@ -53,6 +54,10 @@
If the byte count is odd, the record is padded with an extra byte
of junk. File marks are represented by a single record length of 0.
End of tape is two consecutive end of file marks.
BOT is not the same as POS == 0. BOT is set after rewinding or after
a reverse operation from before the first record. It is cleared by
any successful motion operation.
*/
#if defined (VM_PDP10)
@@ -117,11 +122,12 @@
/* TUFS - formatter status - offset 1
+ indicates kept in drive status
^ indicates calculated on the fly
Rewinding is a pseudo-status flag and never appears in TUFS
*/
#define FS_OF 1
#define FS_SAT 0000001 /* slave attention */
#define FS_BOT 0000002 /* ^beginning of tape */
#define FS_BOT 0000002 /* +beginning of tape */
#define FS_TMK 0000004 /* end of file */
#define FS_ID 0000010 /* ID burst detected */
#define FS_SLOW 0000020 /* slowing down NI */
@@ -129,7 +135,7 @@
#define FS_SSC 0000100 /* slave stat change */
#define FS_RDY 0000200 /* ^formatter ready */
#define FS_FPR 0000400 /* formatter present */
#define FS_EOT 0002000 /* +end of tape */
#define FS_EOT 0002000 /* ^end of tape */
#define FS_WRL 0004000 /* ^write locked */
#define FS_MOL 0010000 /* ^medium online */
#define FS_PIP 0020000 /* +pos in progress */
@@ -502,7 +508,7 @@ switch (fnc) { /* case on function */
tutc = tutc & ~TC_FCS; /* clear fc status */
tufs = tufs & ~(FS_SAT | FS_SSC | FS_ID | FS_ERR);
sim_cancel (uptr); /* reset drive */
uptr->USTAT = 0;
uptr->USTAT &= FS_BOT; /* fall through */
/* fall through */
case FNC_NOP:
tucs1 = tucs1 & ~CS1_GO; /* no operation */
@@ -510,8 +516,10 @@ switch (fnc) { /* case on function */
case FNC_RIP: /* read-in preset */
tutc = TC_RIP; /* set tutc */
sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */
tu_unit[0].USTAT = 0;
if (tu_unit[0].flags & UNIT_ATT) { /* unit 0 attached? */
sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */
tu_unit[0].USTAT = FS_BOT;
}
tucs1 = tucs1 & ~CS1_GO;
tufs = tufs & ~FS_TMK;
return SCPE_OK;
@@ -556,7 +564,7 @@ switch (fnc) { /* case on function */
tu_set_er (ER_UNS);
break;
}
if (sim_tape_bot (uptr) || ((tutc & TC_FCS) == 0)) {
if ((uptr->USTAT & FS_BOT) || ((tutc & TC_FCS) == 0)) {
tu_set_er (ER_NXF);
break;
}
@@ -565,7 +573,7 @@ switch (fnc) { /* case on function */
case FNC_WCHKR: /* wchk = read */
case FNC_READR: /* read rev */
if (tufs & FS_BOT) { /* beginning of tape? */
if (uptr->USTAT & FS_BOT) { /* beginning of tape? */
tu_set_er (ER_NXF);
break;
}
@@ -636,7 +644,9 @@ t_stat st, r = SCPE_OK;
drv = (int32) (uptr - tu_dev.units); /* get drive # */
if (uptr->USTAT & FS_REW) { /* rewind or unload? */
sim_tape_rewind (uptr); /* rewind tape */
uptr->USTAT = 0; /* clear status */
if (uptr->flags & UNIT_ATT) /* standard rewind? */
uptr->USTAT = FS_BOT; /* set BOT */
else uptr->USTAT = 0; /* clear status */
tu_update_fs (FS_ATA | FS_SSC, drv);
return SCPE_OK;
}
@@ -835,17 +845,13 @@ int32 act = sim_activate_time (&tu_unit[drv]);
tufs = (tufs & ~FS_DYN) | FS_FPR | flg;
if (tu_unit[drv].flags & UNIT_ATT) {
tufs = tufs | FS_MOL | tu_unit[drv].USTAT;
tufs = tufs | FS_MOL | (tu_unit[drv].USTAT & 0177777);
if (tu_unit[drv].UDENS == TC_1600)
tufs = tufs | FS_PE;
if (sim_tape_wrp (&tu_unit[drv]))
tufs = tufs | FS_WRL;
if (!act) {
if (sim_tape_bot (&tu_unit[drv]))
tufs = tufs | FS_BOT;
if (sim_tape_eot (&tu_unit[drv]))
if (!act && sim_tape_eot (&tu_unit[drv]))
tufs = tufs | FS_EOT;
}
}
if (tuer)
tufs = tufs | FS_ERR;
@@ -904,6 +910,7 @@ switch (st) {
break;
case MTSE_BOT: /* reverse into BOT */
tu_unit[drv].USTAT = FS_BOT; /* set BOT */
return SCPE_OK;
case MTSE_WRP: /* write protect */
@@ -938,7 +945,10 @@ for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */
uptr = tu_dev.units + u;
sim_tape_reset (uptr); /* clear pos flag */
sim_cancel (uptr); /* cancel activity */
uptr->USTAT = 0;
if ((uptr->flags & UNIT_ATT) && /* if attached */
sim_tape_bot (uptr)) /* and BOT */
uptr->USTAT = FS_BOT; /* set BOT */
else uptr->USTAT = 0;
}
if (xbuf == NULL)
xbuf = (uint8 *) calloc (MT_MAXFR + 4, sizeof (uint8));
@@ -961,7 +971,7 @@ t_stat r;
r = sim_tape_attach (uptr, cptr);
if (r != SCPE_OK)
return r;
uptr->USTAT = 0; /* clear unit status */
uptr->USTAT = FS_BOT; /* set BOT */
uptr->UDENS = UD_UNK; /* unknown density */
flg = FS_ATA | FS_SSC; /* set attention */
if (GET_DRV (tutc) == drv) /* sel drv? set SAT */