int32 ts_skipf (UNIT *uptr, int32 fc) { t_stat st; t_mtrlnt tbc; t_bool tmkprv = FALSE; msgrfc = fc; if (sim_tape_bot (uptr) && (wchopt & WCH_ENB)) tmkprv = TRUE; 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 */ if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */ return (XTC ((msgrfc? XS0_RLS: 0) | XS0_TMK | XS0_LET, TC2)); tmkprv = TRUE; /* flag tmk */ } else if (st != MTSE_OK) return ts_map_status (st); else tmkprv = FALSE; /* not a tmk */ msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ } while (msgrfc != 0); return 0; }
t_stat mt_reset (DEVICE *dptr) { hp_enbdis_pair (dptr, /* make pair cons */ (dptr == &mtd_dev) ? &mtc_dev : &mtd_dev); if (dptr == &mtc_dev) /* command channel reset? */ mtcio (mtc_dib.devno, ioPOPIO, 0); /* send POPIO signal to command channel */ else /* data channel reset */ mtdio (mtd_dib.devno, ioPOPIO, 0); /* send POPIO signal to data channel */ mtc_fnc = 0; mtc_1st = mtc_dtf = 0; sim_cancel (&mtc_unit); /* cancel activity */ sim_tape_reset (&mtc_unit); if (mtc_unit.flags & UNIT_ATT) mtc_sta = (sim_tape_bot (&mtc_unit)? STA_BOT: 0) | (sim_tape_wrp (&mtc_unit)? STA_WLK: 0); else mtc_sta = STA_LOCAL | STA_BUSY; return SCPE_OK; }
t_stat ts_svc (UNIT *uptr) { int32 i, t, bc, fnc, mod, st0, st1; static const int32 fnc_mod[CMD_N_FNC] = { /* max mod+1 0 ill */ 0, 4, 0, 0, 1, 2, 1, 0, /* 00 - 07 */ 5, 3, 5, 1, 0, 0, 0, 1, /* 10 - 17 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */ 0, 0, 0, 0, 0, 0, 0, 0 /* 30 - 37 */ }; static const int32 fnc_flg[CMD_N_FNC] = { 0, FLG_MO+FLG_AD, 0, 0, 0, FLG_MO+FLG_WR+FLG_AD, FLG_AD, 0, FLG_MO, FLG_MO+FLG_WR, FLG_MO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */ 0, 0, 0, 0, 0, 0, 0, 0 /* 30 - 37 */ }; static const char *fnc_name[CMD_N_FNC] = { "0", "READ", "2", "3", "WCHR", "WRITE", "WSSM", "7", "POS", "FMT", "CTL", "INIT", "14", "15", "16", "GSTA", "20", "21", "22", "23", "24", "25", "26", "27", "30", "31", "32", "33", "34", "35", "36", "37" }; if (ts_bcmd) { /* boot? */ ts_bcmd = 0; /* clear flag */ sim_tape_rewind (uptr); /* rewind */ if (uptr->flags & UNIT_ATT) { /* attached? */ cmdlnt = cmdadh = cmdadl = 0; /* defang rd */ ts_spacef (uptr, 1, FALSE); /* space fwd */ ts_readf (uptr, 512); /* read blk */ tssr = ts_updtssr (tssr | TSSR_SSR); } else tssr = ts_updtssr (tssr | TSSR_SSR | TC3); if (cmdhdr & CMD_IE) SET_INT (TS); return SCPE_OK; } if (!(cmdhdr & CMD_ACK)) { /* no acknowledge? */ tssr = ts_updtssr (tssr | TSSR_SSR); /* set rdy, int */ if (cmdhdr & CMD_IE) SET_INT (TS); ts_ownc = ts_ownm = 0; /* CPU owns all */ return SCPE_OK; } fnc = GET_FNC (cmdhdr); /* get fnc+mode */ mod = GET_MOD (cmdhdr); if (DEBUG_PRS (ts_dev)) { fprintf (sim_deb, ">>TS: cmd=%s, mod=%o, buf=%o, lnt=%d, pos=", fnc_name[fnc], mod, cmdadl, cmdlnt); fprint_val (sim_deb, ts_unit.pos, 10, T_ADDR_W, PV_LEFT); fprintf (sim_deb, "\n"); } if ((fnc != FNC_WCHR) && (tssr & TSSR_NBA)) { /* ~wr chr & nba? */ ts_endcmd (TC3, 0, 0); /* error */ return SCPE_OK; } if (ts_qatn && (wchopt & WCH_EAI)) { /* attn pending? */ ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn msg */ SET_INT (TS); /* set interrupt */ ts_qatn = 0; /* not pending */ return SCPE_OK; } if (cmdhdr & CMD_CVC) /* cvc? clr vck */ msgxs0 = msgxs0 & ~XS0_VCK; if ((cmdhdr & CMD_MBZ) || (mod >= fnc_mod[fnc])) { /* test mbz */ ts_endcmd (TC3, XS0_ILC, MSG_ACK | MSG_MILL | MSG_CFAIL); return SCPE_OK; } if ((fnc_flg[fnc] & FLG_MO) && /* mot+(vck|!att)? */ ((msgxs0 & XS0_VCK) || !(uptr->flags & UNIT_ATT))) { ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL); return SCPE_OK; } if ((fnc_flg[fnc] & FLG_WR) && /* write? */ sim_tape_wrp (uptr)) { /* write lck? */ ts_endcmd (TC3, XS0_WLE | XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL); return SCPE_OK; } if ((((fnc == FNC_READ) && (mod == 1)) || /* read rev */ ((fnc == FNC_POS) && (mod & 1))) && /* space rev */ sim_tape_bot (uptr)) { /* BOT? */ ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL); return SCPE_OK; } if ((fnc_flg[fnc] & FLG_AD) && (cmdadh & ADDRTEST)) { /* buf addr > 22b? */ ts_endcmd (TC3, XS0_ILA, MSG_ACK | MSG_MILL | MSG_CFAIL); return SCPE_OK; } 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 */ return SCPE_OK; case FNC_WCHR: /* write char */ if ((cmdadh & ADDRTEST) || (cmdadl & 1) || (cmdlnt < 6)) { ts_endcmd (TSSR_NBA | TC3, XS0_ILA, 0); break; } tsba = (cmdadh << 16) | cmdadl; 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? */ ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0); return SCPE_OK; } for (i = 0; i < (bc / 2); i++) /* copy packet */ tswchp[i] = cpy_buf[i]; if ((wchlnt < ((MSG_PLNT - 1) * 2)) || (wchadh & 0177700) || (wchadl & 1)) ts_endcmd (TSSR_NBA | TC3, 0, 0); else { msgxs2 = msgxs2 | XS2_XTF | 1; tssr = ts_updtssr (tssr & ~TSSR_NBA); ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); } return SCPE_OK; case FNC_CTL: /* control */ switch (mod) { /* case mode */ case 00: /* msg buf rls */ tssr = ts_updtssr (tssr | TSSR_SSR); /* set SSR */ if (wchopt & WCH_ERI) SET_INT (TS); ts_ownc = 0; ts_ownm = 1; /* keep msg */ break; case 01: /* rewind and unload */ if (!sim_tape_bot (uptr)) /* if tape moves */ msgxs0 = msgxs0 | XS0_MOT; sim_tape_detach (uptr); /* unload */ ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); break; case 02: /* clean */ ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); /* nop */ break; case 03: /* undefined */ ts_endcmd (TC3, XS0_ILC, MSG_ACK | MSG_MILL | MSG_CFAIL); return SCPE_OK; case 04: /* rewind */ if (!sim_tape_bot (uptr)) /* if tape moves */ msgxs0 = msgxs0 | XS0_MOT; sim_tape_rewind (uptr); ts_endcmd (TC0, XS0_BOT, MSG_ACK | MSG_CEND); break; } break; case FNC_READ: /* read */ switch (mod) { /* case mode */ case 00: /* fwd */ st0 = ts_readf (uptr, cmdlnt); /* read */ break; case 01: /* back */ st0 = ts_readr (uptr, cmdlnt); /* read */ break; case 02: /* reread fwd */ if (cmdhdr & CMD_OPP) { /* opposite? */ st0 = ts_readr (uptr, cmdlnt); st1 = ts_spacef (uptr, 1, FALSE); } else { st0 = ts_spacer (uptr, 1, FALSE); st1 = ts_readf (uptr, cmdlnt); } break; case 03: /* reread back */ if (cmdhdr & CMD_OPP) { /* opposite */ st0 = ts_readf (uptr, cmdlnt); st1 = ts_spacer (uptr, 1, FALSE); } else { st0 = ts_spacef (uptr, 1, FALSE); st1 = ts_readr (uptr, cmdlnt); } break; } ts_cmpendcmd (st0, st1); break; case FNC_WRIT: /* write */ switch (mod) { /* case mode */ case 00: /* write */ st0 = ts_write (uptr, cmdlnt); break; case 01: /* rewrite */ st0 = ts_spacer (uptr, 1, FALSE); st1 = ts_write (uptr, cmdlnt); break; } ts_cmpendcmd (st0, st1); break; case FNC_FMT: /* format */ switch (mod) { /* case mode */ case 00: /* write tmk */ st0 = ts_wtmk (uptr); break; case 01: /* erase */ break; case 02: /* retry tmk */ st0 = ts_spacer (uptr, 1, FALSE); st1 = ts_wtmk (uptr); break; } ts_cmpendcmd (st0, st1); break; case FNC_POS: /* position */ switch (mod) { /* case mode */ case 00: /* space fwd */ st0 = ts_spacef (uptr, cmdadl, TRUE); break; case 01: /* space rev */ st0 = ts_spacer (uptr, cmdadl, TRUE); break; case 02: /* space ffwd */ st0 = ts_skipf (uptr, cmdadl); break; case 03: /* space frev */ st0 = ts_skipr (uptr, cmdadl); break; case 04: /* rewind */ if (!sim_tape_bot (uptr)) /* if tape moves */ msgxs0 = msgxs0 | XS0_MOT; sim_tape_rewind (uptr); break; } ts_cmpendcmd (st0, 0); break; } return SCPE_OK; }
/* Handle processing of tape requests. */ t_stat mt_srv(UNIT * uptr) { int chan = uptr->u5 & MT_CHAN; int unit = uptr - mt_unit; int cmd = uptr->u5 & MT_CMD; DEVICE *dptr = find_dev_from_unit(uptr); t_mtrlnt reclen; t_stat r = SCPE_ARG; /* Force error if not set */ uint8 ch; int mode; t_mtrlnt loc; /* Simulate tape load delay */ if (uptr->u5 & MT_LOADED) { uptr->u5 &= ~MT_LOADED; uptr->u5 |= MT_BSY|MT_RDY; sim_debug(DEBUG_DETAIL, dptr, "Unit=%d Loaded\n", unit); sim_activate(uptr, 50000); return SCPE_OK; } if (uptr->u5 & MT_BSY) { uptr->u5 &= ~MT_BSY; sim_debug(DEBUG_DETAIL, dptr, "Unit=%d Online\n", unit); iostatus |= 1 << (uptr - mt_unit); if (uptr->u5 & MT_IDLE) sim_activate(uptr, 50000); return SCPE_OK; } if (uptr->u5 & MT_IDLE) { uptr->u5 &= ~MT_IDLE; if (uptr->u5 & MT_RDY) { sim_debug(DEBUG_DETAIL, dptr, "Unit=%d idling\n", unit); return SCPE_OK; } sim_debug(DEBUG_DETAIL, dptr, "Unit=%d start %02o\n", unit, cmd); } switch (cmd) { /* Handle interrogate */ case MT_INT: if (sim_tape_wrp(uptr)) chan_set_wrp(chan); uptr->u5 &= ~(MT_CMD|MT_BIN); uptr->u5 |= MT_RDY; chan_set_end(chan); sim_debug(DEBUG_DETAIL, dptr, "Status\n"); return SCPE_OK; case MT_RD: /* Read */ /* If at end of record, fill buffer */ if (BUF_EMPTY(uptr)) { sim_debug(DEBUG_DETAIL, dptr, "Read unit=%d %s ", unit, (uptr->u5 & MT_BIN)? "bin": "bcd"); if (sim_tape_eot(uptr)) { sim_activate(uptr, 4000); return mt_error(uptr, chan, MTSE_EOM, dptr); } r = sim_tape_rdrecf(uptr, &mt_buffer[chan][0], &reclen, BUFFSIZE); if (r != MTSE_OK) { if (r == MTSE_TMK) { sim_debug(DEBUG_DETAIL, dptr, "TM\n"); ch = 017; (void)chan_write_char(chan, &ch, 1); sim_activate(uptr, 4000); } else { sim_debug(DEBUG_DETAIL, dptr, "r=%d\n", r); sim_activate(uptr, 5000); } return mt_error(uptr, chan, r, dptr); } else { uptr->u5 &= ~(MT_BOT|MT_EOT); uptr->hwmark = reclen; } sim_debug(DEBUG_DETAIL, dptr, "%d chars\n", uptr->hwmark); uptr->u6 = 0; if ((uptr->u5 & MT_BIN) == 0) mode = 0100; else mode = 0; for (loc = 0; loc < reclen; loc++) { ch = mt_buffer[chan][loc] & 0177; if (((parity_table[ch & 077]) ^ (ch & 0100) ^ mode) == 0) { chan_set_error(chan); break; } } } ch = mt_buffer[chan][uptr->u6++] & 0177; /* 00 characters are not transfered in BCD mode */ if (ch == 0) { if (((uint32)uptr->u6) >= uptr->hwmark) { sim_activate(uptr, 4000); return mt_error(uptr, chan, MTSE_OK, dptr); } else { sim_activate(uptr, HT); return SCPE_OK; } } if (chan_write_char(chan, &ch, (((uint32)uptr->u6) >= uptr->hwmark) ? 1 : 0)) { sim_debug(DEBUG_DATA, dptr, "Read unit=%d %d EOR\n", unit, uptr->hwmark-uptr->u6); sim_activate(uptr, 4000); return mt_error(uptr, chan, MTSE_OK, dptr); } else { sim_debug(DEBUG_DATA, dptr, "Read data unit=%d %d %03o\n", unit, uptr->u6, ch); sim_activate(uptr, HT); } return SCPE_OK; case MT_RDBK: /* Read Backword */ /* If at end of record, fill buffer */ if (BUF_EMPTY(uptr)) { sim_debug(DEBUG_DETAIL, dptr, "Read back unit=%d %s ", unit, (uptr->u5 & MT_BIN)? "bin": "bcd"); if (sim_tape_bot(uptr)) { sim_activate(uptr, 4000); return mt_error(uptr, chan, MTSE_BOT, dptr); } r = sim_tape_rdrecr(uptr, &mt_buffer[chan][0], &reclen, BUFFSIZE); if (r != MTSE_OK) { if (r == MTSE_TMK) { sim_debug(DEBUG_DETAIL, dptr, "TM\n"); ch = 017; (void)chan_write_char(chan, &ch, 1); sim_activate(uptr, 4000); } else { uptr->u5 |= MT_BSY; sim_debug(DEBUG_DETAIL, dptr, "r=%d\n", r); sim_activate(uptr, 100); } return mt_error(uptr, chan, r, dptr); } else { uptr->u5 &= ~(MT_BOT|MT_EOT); uptr->hwmark = reclen; } sim_debug(DEBUG_DETAIL, dptr, "%d chars\n", uptr->hwmark); uptr->u6 = uptr->hwmark; if ((uptr->u5 & MT_BIN) == 0) mode = 0100; else mode = 0; for (loc = 0; loc < reclen; loc++) { ch = mt_buffer[chan][loc] & 0177; if (((parity_table[ch & 077]) ^ (ch & 0100) ^ mode) == 0) { chan_set_error(chan); break; } } } ch = mt_buffer[chan][--uptr->u6] & 0177; /* 00 characters are not transfered in BCD mode */ if (ch == 0) { if (uptr->u6 <= 0) { sim_activate(uptr, 4000); return mt_error(uptr, chan, MTSE_OK, dptr); } else { sim_activate(uptr, HT); return SCPE_OK; } } if (chan_write_char(chan, &ch, (uptr->u6 > 0) ? 0 : 1)) { sim_debug(DEBUG_DATA, dptr, "Read back unit=%d %d EOR\n", unit, uptr->hwmark-uptr->u6); sim_activate(uptr, 100); return mt_error(uptr, chan, MTSE_OK, dptr); } else { sim_debug(DEBUG_DATA, dptr, "Read back data unit=%d %d %03o\n", unit, uptr->u6, ch); sim_activate(uptr, HT); } return SCPE_OK; case MT_WR: /* Write */ /* Check if write protected */ if (uptr->u6 == 0 && sim_tape_wrp(uptr)) { sim_activate(uptr, 100); return mt_error(uptr, chan, MTSE_WRP, dptr); } if (chan_read_char(chan, &ch, (uptr->u6 > BUFFSIZE) ? 1 : 0)) { reclen = uptr->u6; /* If no transfer, then either erase */ if (reclen == 0) { sim_debug(DEBUG_DETAIL, dptr, "Erase\n"); r = MTSE_OK; } else if ((reclen == 1) && (cmd & MT_BIN) == 0 && (mt_buffer[chan][0] == 017)) { /* Check if write rtape mark */ sim_debug(DEBUG_DETAIL, dptr, "Write Mark unit=%d\n", unit); r = sim_tape_wrtmk(uptr); } else { sim_debug(DEBUG_DETAIL, dptr, "Write unit=%d Block %d %s chars\n", unit, reclen, (uptr->u5 & MT_BIN)? "bin": "bcd"); r = sim_tape_wrrecf(uptr, &mt_buffer[chan][0], reclen); } uptr->u5 &= ~(MT_BOT|MT_EOT); sim_activate(uptr, 4000); return mt_error(uptr, chan, r, dptr); /* Record errors */ } else { /* Copy data to buffer */ ch &= 077; ch |= parity_table[ch]; if ((uptr->u5 & MT_BIN)) ch ^= 0100; /* Don't write out even parity zeros */ if (ch != 0) mt_buffer[chan][uptr->u6++] = ch; sim_debug(DEBUG_DATA, dptr, "Write data unit=%d %d %03o\n", unit, uptr->u6, ch); uptr->hwmark = uptr->u6; } sim_activate(uptr, HT); return SCPE_OK; case MT_FSR: /* Space forward one record */ if (BUF_EMPTY(uptr)) { /* If at end of record, fill buffer */ sim_debug(DEBUG_DETAIL, dptr, "Space unit=%d ", unit); if (sim_tape_eot(uptr)) { uptr->u5 &= ~MT_BOT; sim_debug(DEBUG_DETAIL, dptr, "EOT\n"); sim_activate(uptr, 4000); return mt_error(uptr, chan, MTSE_EOM, dptr); } r = sim_tape_rdrecf(uptr, &mt_buffer[chan][0], &reclen, BUFFSIZE); if (r != MTSE_OK) { if (r == MTSE_TMK) { sim_debug(DEBUG_DETAIL, dptr, "TM "); reclen = 1; chan_set_eof(chan); } else { sim_debug(DEBUG_DETAIL, dptr, "r=%d ", r); reclen = 10; } } uptr->u5 &= ~(MT_BOT|MT_EOT); uptr->hwmark = reclen; sim_debug(DEBUG_DETAIL, dptr, "%d chars\n", uptr->hwmark); sim_activate(uptr, uptr->hwmark * HT); return SCPE_OK; } sim_activate(uptr, 4000); return mt_error(uptr, chan, MTSE_OK, dptr); case MT_BSR: /* Backspace record */ if (BUF_EMPTY(uptr)) { /* If at end of record, fill buffer */ sim_debug(DEBUG_DETAIL, dptr, "backspace unit=%d ", unit); if (sim_tape_bot(uptr)) { sim_debug(DEBUG_DETAIL, dptr, "BOT\n"); sim_activate(uptr, 100); return mt_error(uptr, chan, MTSE_BOT, dptr); } r = sim_tape_rdrecr(uptr, &mt_buffer[chan][0], &reclen, BUFFSIZE); if (r != MTSE_OK) { if (r == MTSE_TMK) { sim_debug(DEBUG_DETAIL, dptr, "TM "); reclen = 1; chan_set_eof(chan); } else { reclen = 10; sim_debug(DEBUG_DETAIL, dptr, "r=%d ", r); } } uptr->u5 &= ~(MT_BOT|MT_EOT); uptr->hwmark = reclen; sim_debug(DEBUG_DETAIL, dptr, "%d chars\n", uptr->hwmark); sim_activate(uptr, uptr->hwmark * HT); return SCPE_OK; } sim_activate(uptr, 4000); return mt_error(uptr, chan, MTSE_OK, dptr); case MT_REW: /* Rewind */ sim_debug(DEBUG_DETAIL, dptr, "Rewind unit=%d pos=%d\n", unit, uptr->pos); uptr->u5 &= ~(MT_CMD | MT_BIN | MT_IDLE | MT_RDY); uptr->u5 |= MT_BSY|MT_RDY; iostatus &= ~(1 << (uptr - mt_unit)); sim_activate(uptr, (uptr->pos/100) + 100); r = sim_tape_rewind(uptr); uptr->u5 &= ~MT_EOT; uptr->u5 |= MT_BOT; chan_set_end(chan); return r; } return mt_error(uptr, chan, r, dptr); }
t_stat sim_tape_rdlntr (UNIT *uptr, t_mtrlnt *bc) { uint8 c; t_bool all_eof; uint32 f = MT_GET_FMT (uptr); t_addr ppos; t_mtrlnt sbc; t_tpclnt tpcbc; MT_CLR_PNU (uptr); if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */ return MTSE_UNATT; if (sim_tape_bot (uptr)) /* at BOT? */ return MTSE_BOT; switch (f) { /* switch on fmt */ case MTUF_F_STD: case MTUF_F_E11: do { sim_fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET); sim_fread (bc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */ sbc = MTR_L (*bc); if (ferror (uptr->fileref)) /* error? */ return sim_tape_ioerr (uptr); if (feof (uptr->fileref)) /* eof? */ return MTSE_EOM; uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over rec lnt */ if (*bc == MTR_EOM) /* eom? */ return MTSE_EOM; if (*bc == MTR_TMK) /* tape mark? */ return MTSE_TMK; if ((*bc & MTR_M_RHGAP) == MTR_RHGAP) { /* half gap? */ uptr->pos = uptr->pos + sizeof (t_mtrlnt) / 2; /* half space rev */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* resync */ } else if (*bc != MTR_GAP) { uptr->pos = uptr->pos - sizeof (t_mtrlnt) - /* spc over record */ ((f == MTUF_F_STD)? ((sbc + 1) & ~1): sbc); sim_fseek (uptr->fileref, uptr->pos + sizeof (t_mtrlnt), SEEK_SET); } else if (sim_tape_bot (uptr)) /* backed into BOT? */ return MTSE_BOT; } while ((*bc == MTR_GAP) || (*bc == MTR_RHGAP)); break; case MTUF_F_TPC: ppos = sim_tape_tpc_fnd (uptr, (t_addr *) uptr->filebuf); /* find prev rec */ sim_fseek (uptr->fileref, ppos, SEEK_SET); /* position */ sim_fread (&tpcbc, sizeof (t_tpclnt), 1, uptr->fileref); *bc = tpcbc; /* save rec lnt */ if (ferror (uptr->fileref)) /* error? */ return sim_tape_ioerr (uptr); if (feof (uptr->fileref)) /* eof? */ return MTSE_EOM; uptr->pos = ppos; /* spc over record */ if (*bc == MTR_TMK) /* tape mark? */ return MTSE_TMK; sim_fseek (uptr->fileref, uptr->pos + sizeof (t_tpclnt), SEEK_SET); break; case MTUF_F_P7B: for (sbc = 1, all_eof = 1; (t_addr) sbc <= uptr->pos ; sbc++) { sim_fseek (uptr->fileref, uptr->pos - sbc, SEEK_SET); sim_fread (&c, sizeof (uint8), 1, uptr->fileref); if (ferror (uptr->fileref)) /* error? */ return sim_tape_ioerr (uptr); if (feof (uptr->fileref)) /* eof? */ return MTSE_EOM; if ((c & P7B_DPAR) != P7B_EOF) all_eof = 0; if (c & P7B_SOR) /* start of record? */ break; } uptr->pos = uptr->pos - sbc; /* update position */ *bc = sbc; /* save rec lnt */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for read */ if (all_eof) /* tape mark? */ return MTSE_TMK; break; default: return MTSE_FMT; } return MTSE_OK; }