예제 #1
0
t_stat sim_tape_wrtmk (UNIT *uptr)
{
if (MT_GET_FMT (uptr) == MTUF_F_P7B) {                  /* P7B? */
    uint8 buf = P7B_EOF;                                /* eof mark */
    return sim_tape_wrrecf (uptr, &buf, 1);             /* write char */
    }
return sim_tape_wrdata (uptr, MTR_TMK);
}
예제 #2
0
파일: sigma_mt.c 프로젝트: ProtoSD/simh
t_stat mt_flush_buf (UNIT *uptr)
{
t_stat st;

if (mt_blim == 0)                                       /* any output? */
    return SCPE_OK;
if (st = sim_tape_wrrecf (uptr, mt_xb, mt_blim))        /* write, err? */
    return mt_map_err (uptr, st);                       /* map error */
return SCPE_OK;
}
예제 #3
0
t_stat mt_clear (void)
{
t_stat st;

if (sim_is_active (&mtc_unit) &&                        /* write in prog? */
    (mtc_fnc == FNC_WC) && (mt_ptr > 0)) {              /* yes, bad rec */
    if (st = sim_tape_wrrecf (&mtc_unit, mtxb, mt_ptr | MTR_ERF))
        mt_map_err (&mtc_unit, st);
    }

if (((mtc_fnc == FNC_REW) || (mtc_fnc == FNC_RWS)) && sim_is_active (&mtc_unit))
    sim_cancel (&mtc_unit);

mtc_1st = mtc_dtf = 0;
mtc_sta = mtc_sta & STA_BOT;

return SCPE_OK;
}
예제 #4
0
t_stat mt_wrend (uint32 dev)
{
UNIT *uptr = mt_dev.units + (dev & MT_UNIT);
t_mtrlnt tbc;
t_stat st;

sim_cancel (uptr);                                      /* no more xfr's */
if (mt_bptr == 0)                                       /* buf empty? */
    return SCPE_OK;
if (!(uptr->flags & UNIT_ATT)) {                        /* attached? */
    mt_set_err (uptr);                                  /* no, err, disc */
    return SCPE_UNATT;
    }
if (sim_tape_wrp (uptr)) {                              /* write lock? */
    mt_set_err (uptr);                                  /* yes, err, disc */
    return SCPE_OK;
    }
if (dev & DEV_MTS) {                                    /* erase? */
    if (mt_inst & CHC_REV)                              /* reverse? */
        sim_tape_sprecr (uptr, &tbc);                   /* backspace */
    st = sim_tape_wreom (uptr);                         /* write eom */
    }
else {
    t_bool passed_eot = sim_tape_eot (uptr);            /* passed EOT? */
    if ((mt_bptr == 1) && (mtxb[0] == 017) &&           /* wr eof? */
        ((mt_inst & 01670) == 00050))
        st = sim_tape_wrtmk (uptr);                     /* write tape mark */
    else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr);    /* write record */
    if (!passed_eot && sim_tape_eot (uptr))             /* just passed EOT? */
        uptr->eotf = 1;
    }
mt_bptr = 0;
if (st != MTSE_OK)                                      /* error? */
    mt_set_err (uptr);
if (st == MTSE_IOERR)
    return SCPE_IOERR;
return SCPE_OK;
}
예제 #5
0
int32 ts_write (UNIT *uptr, int32 fc)
{
int32 i, t;
uint32 wa;
t_stat st;

msgrfc = fc;
if (fc == 0)                                            /* byte count */
    fc = 0200000;
tsba = (cmdadh << 16) | cmdadl;                         /* buf addr */
if (cmdhdr & CMD_SWP) {                                 /* swapped? */
    for (i = 0; i < fc; i++) {                          /* copy mem to buf */
        wa = tsba ^ 1;                                  /* apply OPP */
        if (Map_ReadB (wa, 1, &tsxb[i])) {              /* fetch byte, nxm? */
            tssr = ts_updtssr (tssr | TSSR_NXM);
            return TC5;
            }
        tsba = tsba + 1;
        }
    }
else {
    t = Map_ReadB (tsba, fc, tsxb);                     /* fetch record */
    tsba = tsba + (fc - t);                             /* update tsba */
    if (t) {                                            /* 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 */
msgrfc = 0;
if (sim_tape_eot (&ts_unit))                            /* EOT on write? */
    return XTC (XS0_EOT, TC2);
return 0;
}
예제 #6
0
t_stat mtc_svc (UNIT *uptr)
{
t_mtrlnt tbc;
t_stat st, r = SCPE_OK;

if ((mtc_unit.flags & UNIT_ATT) == 0) {                 /* offline? */
    mtc_sta = STA_LOCAL | STA_REJ;                      /* rejected */
    mtcio (mtc_dib.devno, ioENF, 0);                    /* set cch flg */
    return IORETURN (mtc_stopioe, SCPE_UNATT);
    }

switch (mtc_fnc) {                                      /* case on function */

    case FNC_REW:                                       /* rewind */
        sim_tape_rewind (uptr);                         /* BOT */
        mtc_sta = STA_BOT;                              /* update status */
        break;

    case FNC_RWS:                                       /* rewind and offline */
        sim_tape_rewind (uptr);                         /* clear position */
        return sim_tape_detach (uptr);                  /* don't set cch flg */

    case FNC_WFM:                                       /* write file mark */
        if (st = sim_tape_wrtmk (uptr))                 /* write tmk, err? */
            r = mt_map_err (uptr, st);                  /* map error */
        mtc_sta = STA_EOF;                              /* set EOF status */
        break;

    case FNC_GAP:                                       /* erase gap */
        break;

    case FNC_FSR:                                       /* space forward */
        if (st = sim_tape_sprecf (uptr, &tbc))          /* space rec fwd, err? */
            r = mt_map_err (uptr, st);                  /* map error */
        break;

    case FNC_BSR:                                       /* space reverse */
        if (st = sim_tape_sprecr (uptr, &tbc))          /* space rec rev, err? */
            r = mt_map_err (uptr, st);                  /* map error */
        break;

    case FNC_RC:                                        /* read */
        if (mtc_1st) {                                  /* first svc? */
            mtc_1st = mt_ptr = 0;                       /* clr 1st flop */
            st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */
            if (st == MTSE_RECE) mtc_sta = mtc_sta | STA_PAR;   /* rec in err? */
            else if (st != MTSE_OK) {                   /* other error? */
                r = mt_map_err (uptr, st);              /* map error */
                if (r == SCPE_OK) {                     /* recoverable? */
                    sim_activate (uptr, mtc_gtime);     /* sched IRG */
                    mtc_fnc = 0;                        /* NOP func */
                    return SCPE_OK;
                    }
                break;                                  /* non-recov, done */
                }
            if (mt_max < 12) {                          /* record too short? */
                mtc_sta = mtc_sta | STA_PAR;            /* set flag */
                break;
                }
            }
        if (mtc_dtf && (mt_ptr < mt_max)) {             /* more chars? */
            if (mtd_flag) mtc_sta = mtc_sta | STA_TIM;
            mtc_unit.buf = mtxb[mt_ptr++];              /* fetch next */
            mtdio (mtd_dib.devno, ioENF, 0);            /* set dch flg */
            sim_activate (uptr, mtc_xtime);             /* re-activate */
            return SCPE_OK;
            }
        sim_activate (uptr, mtc_gtime);                 /* schedule gap */
        mtc_fnc = 0;                                    /* nop */
        return SCPE_OK;

    case FNC_WC:                                                /* write */
        if (mtc_1st) mtc_1st = 0;                       /* no xfr on first */
        else {
            if (mt_ptr < DBSIZE) {                      /* room in buffer? */
                mtxb[mt_ptr++] = mtc_unit.buf;
                mtc_sta = mtc_sta & ~STA_BOT;           /* clear BOT */
                }
            else mtc_sta = mtc_sta | STA_PAR;
            }
        if (mtc_dtf) {                                  /* xfer flop set? */
            mtdio (mtd_dib.devno, ioENF, 0);            /* set dch flg */
            sim_activate (uptr, mtc_xtime);             /* re-activate */
            return SCPE_OK;
            }
        if (mt_ptr) {                                   /* write buffer */
            if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) {    /* write, err? */
                r = mt_map_err (uptr, st);              /* map error */
                break;                                  /* done */
                }
            }
        sim_activate (uptr, mtc_gtime);                 /* schedule gap */
        mtc_fnc = 0;                                    /* nop */
        return SCPE_OK;

    default:                                            /* unknown */
        break;
        }

mtcio (mtc_dib.devno, ioENF, 0);                        /* set cch flg */
mtc_sta = mtc_sta & ~STA_BUSY;                          /* not busy */
return r;
}
예제 #7
0
/* 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);
}
예제 #8
0
파일: id_mt.c 프로젝트: ST3ALth/simh
t_stat mt_svc (UNIT *uptr)
{
uint32 i;
int32 u = uptr - mt_dev.units;
uint32 dev = mt_dib.dno + (u * o_MT0);
t_mtrlnt tbc;
t_bool passed_eot;
t_stat st, r = SCPE_OK;

if ((uptr->flags & UNIT_ATT) == 0) {                    /* not attached? */
    uptr->UCMD = 0;                                     /* clr cmd */
    uptr->UST = 0;                                      /* set status */
    mt_xfr = 0;                                         /* clr op flags */
    mt_sta = STA_ERR | STA_EOM;                         /* set status */
    if (mt_arm[u])                                      /* interrupt */
        SET_INT (v_MT + u);
    return IORETURN (mt_stopioe, SCPE_UNATT);
    }

if (uptr->UCMD & MTC_STOP2) {                           /* stop, gen NMTN? */
    uptr->UCMD = 0;                                     /* clr cmd */
    uptr->UST = uptr->UST | STA_NMTN;                   /* set nmtn */
    mt_xfr = 0;                                         /* clr xfr */
    if (mt_arm[u])                                      /* set intr */
        SET_INT (v_MT + u);
    return SCPE_OK;
    }

if (uptr->UCMD & MTC_STOP1) {                           /* stop, gen EOM? */
    uptr->UCMD = uptr->UCMD | MTC_STOP2;                /* clr cmd */
    mt_sta = (mt_sta & ~STA_BSY) | STA_EOM;             /* clr busy, set eom */
    if (mt_arm[u])                                      /* set intr */
        SET_INT (v_MT + u);
    sim_activate (uptr, mt_rtime);                      /* schedule */
    return SCPE_OK;
    }

passed_eot = sim_tape_eot (uptr);                       /* passed EOT? */
switch (uptr->UCMD) {                                   /* case on function */

    case MTC_REW:                                       /* rewind */
        sim_tape_rewind (uptr);                         /* reposition */
        uptr->UCMD = 0;                                 /* clr cmd */
        uptr->UST = STA_NMTN | STA_EOT;                 /* update status */
        mt_sta = mt_sta & ~STA_BSY;                     /* don't set EOM */
        if (mt_arm[u])                                  /* interrupt */
            SET_INT (v_MT + u);
        return SCPE_OK;

/* For read, busy = 1 => buffer empty
   For write, busy = 1 => buffer full
   For read, data transfers continue for the full length of the
        record, or the maximum size of the transfer buffer
   For write, data transfers continue until a write is attempted
        and the buffer is empty
*/

    case MTC_RD:                                        /* read */
        if (mt_blnt == 0) {                             /* first time? */
            st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
            if (st == MTSE_RECE)                        /* rec in err? */
                mt_sta = mt_sta | STA_ERR;
            else if (st != SCPE_OK) {                   /* other error? */
                r = mt_map_err (uptr, st);              /* map error */
                if (sch_actv (mt_dib.sch, dev))         /* if sch, stop */
                    sch_stop (mt_dib.sch);
                break;
                }
            mt_blnt = tbc;                              /* set buf lnt */
            }

        if (sch_actv (mt_dib.sch, dev)) {               /* sch active? */
            i = sch_wrmem (mt_dib.sch, mtxb, mt_blnt);  /* store rec in mem */
            if (sch_actv (mt_dib.sch, dev))             /* sch still active? */
                sch_stop (mt_dib.sch);                  /* stop chan, long rd */
            else if (i < mt_blnt)                       /* process entire rec? */
                mt_sta = mt_sta | STA_ERR;              /* no, overrun error */
            }
        else if (mt_bptr < mt_blnt) {                   /* no, if !eor */
            if (!(mt_sta & STA_BSY))                    /* busy still clr? */
                mt_sta = mt_sta | STA_ERR;              /* read overrun */
            mt_db = mtxb[mt_bptr++];                    /* get next byte */
            mt_sta = mt_sta & ~STA_BSY;                 /* !busy = buf full */
            if (mt_arm[u])                              /* set intr */
                SET_INT (v_MT + u);
            sim_activate (uptr, mt_wtime);              /* reschedule */
            return SCPE_OK;
            }
        break;                                          /* record done */

    case MTC_WR:                                        /* write */
        if (sch_actv (mt_dib.sch, dev)) {               /* sch active? */
            mt_bptr = sch_rdmem (mt_dib.sch, mtxb, MT_MAXFR); /* get rec */
            if (sch_actv (mt_dib.sch, dev))             /* not done? */
                sch_stop (mt_dib.sch);                  /* stop chan */
            }
        else if (mt_sta & STA_BSY) {                    /* no, if !eor */
            if (mt_bptr < MT_MAXFR)                     /* if room */
                mtxb[mt_bptr++] = mt_db;                /* store in buf */
            mt_sta = mt_sta & ~STA_BSY;                 /* !busy = buf emp */
            if (mt_arm[u])                              /* set intr */
                SET_INT (v_MT + u);
            sim_activate (uptr, mt_wtime);              /* reschedule */
            return SCPE_OK;
            }

        if (mt_bptr) {                                  /* any chars? */
            if ((st = sim_tape_wrrecf (uptr, mtxb, mt_bptr)))/* write, err? */
                r = mt_map_err (uptr, st);              /* map error */
            }
        break;                                          /* record done */

    case MTC_WEOF:                                      /* write eof */
        if ((st = sim_tape_wrtmk (uptr)))               /* write tmk, err? */
            r = mt_map_err (uptr, st);                  /* map error */
        mt_sta = mt_sta | STA_EOF;                      /* set eof */
        if (mt_arm[u])                                  /* set intr */
            SET_INT (v_MT + u);
        break;

    case MTC_SKFF:                                      /* skip file fwd */
        while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
        if (st == MTSE_TMK) {                           /* stopped by tmk? */
            mt_sta = mt_sta | STA_EOF;                  /* set eof */
            if (mt_arm[u])                              /* set intr */
                SET_INT (v_MT + u);
            }
        else r = mt_map_err (uptr, st);                 /* map error */
        break;

    case MTC_SKFR:                                      /* skip file rev */
        while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
        if (st == MTSE_TMK) {                           /* stopped by tmk? */
            mt_sta = mt_sta | STA_EOF;                  /* set eof */
            if (mt_arm[u])                              /* set intr */
                SET_INT (v_MT + u);
            }
        else r = mt_map_err (uptr, st);                 /* map error */
        break;

    case MTC_SPCR:                                      /* backspace */
        if ((st = sim_tape_sprecr (uptr, &tbc)))        /* skip rec rev, err? */
            r = mt_map_err (uptr, st);                  /* map error */
        break;
        }                                               /* end case */

if (!passed_eot && sim_tape_eot (uptr))                 /* just passed EOT? */
    uptr->UST = uptr->UST | STA_EOT;
uptr->UCMD = uptr->UCMD | MTC_STOP1;                    /* set stop stage 1 */
sim_activate (uptr, mt_rtime);                          /* schedule */
return r;
}
예제 #9
0
t_stat mt_io (int32 unit, int32 flag, int32 mod)
{
int32 t, wm_seen;
t_mtrlnt i, tbc;
t_stat st;
t_bool passed_eot;
UNIT *uptr;

ind[IN_TAP] = 0;                                        /* clear error */
if ((uptr = mt_sel_unit (unit)) == NULL)                /* sel unit, save */
    return STOP_INVMTU;                                 /* (not valid) */
if ((uptr->flags & UNIT_ATT) == 0)                      /* attached? */
    return SCPE_UNATT;

switch (mod) {

    case BCD_R:                                         /* read */
        if (DEBUG_PRS (mt_dev))
            fprintf (sim_deb, ">>MT%d: read from %d", unit, BS);
        wm_seen = 0;                                    /* no word mk seen */
        st = sim_tape_rdrecf (uptr, dbuf, &tbc, MT_MAXFR); /* read rec */
        if (st != MTSE_TMK) {                           /* not tmk? */
            if (st == MTSE_RECE)                        /* rec in error? */
                ind[IN_TAP] = 1;
            else if (st != MTSE_OK) {                   /* stop on error */
                if (DEBUG_PRS (mt_dev))
                    fprintf (sim_deb, ", stopped by status = %d\n", st);
                break;
                }
            if (!(flag & MD_BIN) &&                     /* BCD tape and */
                ((dbuf[0] & CHAR)  == BCD_TAPMRK))      /* first char TMK? */
                uptr->IND = 1;                          /* set indicator */
            }
        for (i = 0; i < tbc; i++) {                     /* loop thru buf */
            if (!(flag & MD_BOOT) &&                    /* not boot? check */
                (M[BS] == (BCD_GRPMRK + WM))) {         /* GWM in memory? */
                if (DEBUG_PRS (mt_dev))
                    fprintf (sim_deb, " to %d, stopped by GMWM\n", BS);
                BS++;                                   /* incr BS */
                if (ADDR_ERR (BS)) {                    /* test for wrap */
                    BS = BA | (BS % MAXMEMSIZE);
                    return STOP_WRAP;
                    }
                return SCPE_OK;                         /* done */
                }
            t = dbuf[i] & CHAR;                         /* get char, strip parity */
            if (!(flag & MD_BIN) && (t == BCD_ALT))     /* BCD mode alt blank? */
                t = BCD_BLANK;                          /* real blank */
            if (flag & MD_WM) {                         /* word mk mode? */
                if ((t == BCD_WM) && (wm_seen == 0))    /* WM char, none prev? */
                    wm_seen = WM;                       /* set flag */
                else {
                    M[BS] = wm_seen | (t & CHAR);       /* char + wm seen */
                    wm_seen = 0;                        /* clear flag */
                    }
                }
            else M[BS] = (M[BS] & WM) | (t & CHAR);     /* preserve mem WM */
            if (!wm_seen)
                BS++;
            if (ADDR_ERR (BS)) {                        /* check next BS */
                BS = BA | (BS % MAXMEMSIZE);
                return STOP_WRAP;
                }
            }
        if (M[BS] != (BCD_GRPMRK + WM)) {               /* not GM+WM at end? */
            if (flag & MD_WM)                           /* LCA: clear WM */
                M[BS] = BCD_GRPMRK;
            else M[BS] = (M[BS] & WM) | BCD_GRPMRK;     /* MCW: save WM */
            }
        if (DEBUG_PRS (mt_dev))
            fprintf (sim_deb, " to %d, stopped by EOR\n", BS);
        BS++;                                           /* adv BS */
        if (ADDR_ERR (BS)) {                            /* check final BS */
            BS = BA | (BS % MAXMEMSIZE);
            return STOP_WRAP;
            }
        break;

    case BCD_W:
        if (sim_tape_wrp (uptr))                        /* locked? */
            return STOP_MTL;
        if (M[BS] == (BCD_GRPMRK + WM))                 /* eor? */
            return STOP_MTZ;
        if (DEBUG_PRS (mt_dev))
            fprintf (sim_deb, ">>MT%d: write from %d", unit, BS);
        for (tbc = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); ) {
            if ((t & WM) && (flag & MD_WM))             /* WM in wm mode? */
                dbuf[tbc++] = BCD_WM;
            if (((t & CHAR) == BCD_BLANK) && !(flag & MD_BIN))
                dbuf[tbc++] = BCD_ALT;
            else dbuf[tbc++] = t & CHAR;
            if (ADDR_ERR (BS)) {                        /* check next BS */
                BS = BA | (BS % MAXMEMSIZE);
                return STOP_WRAP;
                }
            }
        if (DEBUG_PRS (mt_dev))
            fprintf (sim_deb, " to %d\n", BS - 1);
        passed_eot = sim_tape_eot (uptr);               /* passed EOT? */
        st = sim_tape_wrrecf (uptr, dbuf, tbc);         /* write record */
        if (!passed_eot && sim_tape_eot (uptr))         /* just passed EOT? */
            ind[IN_END] = 1;
        if (ADDR_ERR (BS)) {                            /* check final BS */
            BS = BA | (BS % MAXMEMSIZE);
            return STOP_WRAP;
            }
        break;

    default:
        return STOP_INVM;
        }

return mt_map_status (st);
}