Exemple #1
0
/* Map simH errors into machine errors */
t_stat mt_error(UNIT * uptr, int chan, t_stat r, DEVICE * dptr)
{
    switch (r) {
    case MTSE_OK:               /* no error */
        sim_debug(DEBUG_EXP, dptr, "OK ");
        break;

    case MTSE_EOM:              /* end of medium */
        sim_debug(DEBUG_EXP, dptr, "EOT ");
        if (uptr->u5 & MT_BOT) {
           chan_set_blank(chan);
        } else {
           uptr->u5 &= ~MT_BOT;
           uptr->u5 |= MT_EOT;
           chan_set_eot(chan);
        }
        break;

    case MTSE_TMK:              /* tape mark */
        sim_debug(DEBUG_EXP, dptr, "MARK ");
        uptr->u5 &= ~(MT_BOT|MT_EOT);
        chan_set_eof(chan);
        break;

    case MTSE_WRP:              /* write protected */
        sim_debug(DEBUG_EXP, dptr, "WriteLocked ");
        chan_set_wrp(chan);
        break;

    case MTSE_INVRL:            /* invalid rec lnt */
    case MTSE_IOERR:            /* IO error */
    case MTSE_FMT:              /* invalid format */
    case MTSE_RECE:             /* error in record */
        chan_set_error(chan);   /* Force redundency error */
        sim_debug(DEBUG_EXP, dptr, "ERROR %d ", r);
        break;
    case MTSE_BOT:              /* beginning of tape */
        uptr->u5 &= ~MT_EOT;
        uptr->u5 |= MT_BOT;
        chan_set_bot(chan);     /* Set flag */
        sim_debug(DEBUG_EXP, dptr, "BOT ");
        break;
    case MTSE_UNATT:            /* unattached */
    default: 
        sim_debug(DEBUG_EXP, dptr, "%d ", r);
    }
    uptr->u5 &= ~(MT_CMD|MT_BIN);
    uptr->u5 |= MT_RDY|MT_IDLE;
    chan_set_end(chan);
    return SCPE_OK;
}
Exemple #2
0
/* Handle processing terminal controller commands */
t_stat dtc_srv(UNIT * uptr)
{
    int                 chan = uptr->CMD & DTC_CHAN;
    uint8               ch;
    int                 ttu;
    int                 buf;
    int                 i;
    int                 line = uptr->LINE;


    /* Process interrage command */
    if (uptr->CMD & DTC_INQ) {
        if (line == -1) {
            buf = -1;
            for(i = 0; i < DTC_MLINES; i++) {
                if (dtc_lstatus[i]& BufIRQ) {
                   if ((dtc_lstatus[i] & BufSMASK) == BufReadRdy)
                      buf = i;
                   if ((dtc_lstatus[i] & BufSMASK) == BufWriteRdy ||
                       (dtc_lstatus[i] & BufSMASK) == BufIdle) {
                      line = i;
                      break;
                   }
                }
            }
            sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm inqury found %d %d ",
                line, buf);
            if (line != -1) {
                if ((dtc_lstatus[line] & BufSMASK) == BufWriteRdy) {
                     chan_set_eof(chan);
                     sim_debug(DEBUG_DETAIL, &dtc_dev, " writerdy ");
                } else {
                     sim_debug(DEBUG_DETAIL, &dtc_dev, " idle ");
                }
            } else if (buf != -1) {
                chan_set_read(chan);
                sim_debug(DEBUG_DETAIL, &dtc_dev, " readrdy ");
                line = buf;
            }

            if (line != -1) {
                if (dtc_lstatus[line] & BufAbnormal) {
                    chan_set_wcflg(chan);
                    sim_debug(DEBUG_DETAIL, &dtc_dev, " abnormal ");
                }
                dtc_lstatus[line] &= ~BufIRQ;
            }
        } else {
            if (line > dtc_desc.lines) {
                chan_set_notrdy(chan);
            } else {
                switch(dtc_lstatus[line] & BufSMASK) {
                case BufReadRdy:
                      chan_set_read(chan);
                      sim_debug(DEBUG_DETAIL, &dtc_dev, " readrdy ");
                      break;
                case BufWriteRdy:
                      chan_set_eof(chan);
                      sim_debug(DEBUG_DETAIL, &dtc_dev, " writerdy ");
                      break;
                case BufIdle:
                      sim_debug(DEBUG_DETAIL, &dtc_dev, " idle ");
                      break;
                default:
                      chan_set_error(chan);
                      sim_debug(DEBUG_DETAIL, &dtc_dev, " busy ");
                      break;
                }
            }
            if (dtc_lstatus[line] & BufAbnormal) {
                chan_set_wcflg(chan);
                sim_debug(DEBUG_DETAIL, &dtc_dev, " abnormal ");
            }
            dtc_lstatus[line] &= ~BufIRQ;
            chan_set_wc(uptr->LINE, 0);
            chan_set_end(chan);
            sim_debug(DEBUG_DETAIL, &dtc_dev, " %03o ", dtc_lstatus[line]);
        }
        if (line != -1) {
            for (ttu = 1; line > 15; ttu++)
                line -= 15;
        } else {
            ttu = line = 0;
        }
        chan_set_wc(chan, (ttu << 5) | line);
        chan_set_end(chan);
        uptr->CMD = DTC_RDY;
        sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm inqury %d %d\n",
                ttu, line);
    }
    /* Process for each unit */
    if (uptr->CMD & DTC_WR) {
        if (line > dtc_desc.lines || line == -1 || dtc_lstatus[line] & BufDisco) {
            sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm write invalid %d\n",
                         line);
            chan_set_notrdy(chan);
            chan_set_end(chan);
            uptr->CMD = DTC_RDY;
            return SCPE_OK;
        }
        /* Validate that we can send data to buffer */
        i = dtc_lstatus[line] & BufSMASK;
        switch(i) {
        case BufNotReady:
                chan_set_notrdy(chan);
                /* Fall through */
        case BufInputBusy:
                /* Fall through */
        case BufRead:
                /* Fall through */
        case BufReadRdy:
                chan_set_error(chan);
                /* Fall through */
        case BufOutBusy:
                chan_set_eof(chan);
                chan_set_end(chan);
                uptr->CMD = DTC_RDY;
                sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm write busy %d %d\n",
                        line, i);
                return SCPE_OK;

        /* Ok to start filling */
        case BufIdle:
        case BufWriteRdy:
                dtc_bufptr[line] = 0;
                dtc_bsize[line] = 0;
                sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm write start %d\n",
                         line);
                break;

        /* Continue filling */
        case BufWrite:
                break;
        }

        if (chan_read_char(chan, &ch, dtc_bufptr[line] >= dtc_blimit[line])) {
                sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm write done %d %d ",
                         line, dtc_bufptr[line]);
                dtc_bsize[line] = dtc_bufptr[line];
                dtc_bufptr[line] = 0;
                if (dtc_lstatus[line] & BufAbnormal) {
                    chan_set_wcflg(chan);
                }
                /* Empty write, clears flags */
                if (dtc_bsize[line] == 0) {
                    sim_debug(DEBUG_DETAIL, &dtc_dev, "empty\n");
                    if ((dtc_lstatus[line] & BufSMASK) != BufIdle) {
                        dtc_lstatus[line] = BufIRQ|BufIdle;
                        IAR |= IRQ_12;
                    }
                /* Check if we filled up buffer */
                } else if (dtc_bsize[line] >= dtc_blimit[line]) {
                     dtc_lstatus[line] = BufOutBusy;
                     chan_set_gm(chan);
                     sim_debug(DEBUG_DETAIL, &dtc_dev, "full ");
                } else {
                     dtc_lstatus[line] = BufOutBusy|BufGM;
                     sim_debug(DEBUG_DETAIL, &dtc_dev, "gm ");
                }
                sim_debug(DEBUG_DETAIL, &dtc_dev, "\n");
                for (ttu = 1; line > 15; ttu++)
                    line -= 15;
                chan_set_wc(chan, (ttu << 5) | line);
                chan_set_end(chan);
                uptr->CMD = DTC_RDY;
                return SCPE_OK;
        } else {
              dtc_lstatus[line] = BufWrite;
              dtc_buf[line][dtc_bufptr[line]++] = ch & 077;
              sim_debug(DEBUG_DATA, &dtc_dev, "Datacomm write data %d %02o %d\n",
                          line, ch&077, dtc_bufptr[line]);
        }
        sim_activate(uptr, 5000);
    }

    if (uptr->CMD & DTC_RD) {
        if (line > dtc_desc.lines || line == -1 || dtc_lstatus[line] & BufDisco) {
            sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm read nothing %d\n",
                 line);
            chan_set_notrdy(chan);
            chan_set_end(chan);
            uptr->CMD = DTC_RDY;
            return SCPE_OK;
        }
        /* Validate that we can send data to buffer */
        i = dtc_lstatus[line] & BufSMASK;
        switch(i) {
        case BufNotReady:
                chan_set_notrdy(chan);
                /* Fall through */
        case BufInputBusy:
                chan_set_error(chan);
                /* Fall through */
        case BufWriteRdy:
                /* Fall through */
        case BufOutBusy:
                /* Fall through */
        case BufIdle:
                /* Fall through */
        case BufWrite:
                chan_set_eof(chan);
                chan_set_end(chan);
                uptr->CMD = DTC_RDY;
                sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm read busy %d %d\n",
                         line, i);
                return SCPE_OK;

        /* Ok to start filling */
        case BufReadRdy:
                dtc_lstatus[line] = (dtc_lstatus[line] & 030) | BufRead;
                dtc_bufptr[line] = 0;
                sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm read starting %d\n",
                         line);
                break;

        /* Continue filling */
        case BufRead:
                break;
        }

        ch = dtc_buf[line][dtc_bufptr[line]++];
        /* If no buffer, error out */
        if (chan_write_char(chan, &ch, dtc_bufptr[line] >= dtc_bsize[line])) {
                /* Check if we filled up buffer */
                if (dtc_lstatus[line] & BufGM) {
                     chan_set_gm(chan);
                     sim_debug(DEBUG_DETAIL, &dtc_dev, "gm ");
                }
                if (dtc_lstatus[line] & BufAbnormal)
                     chan_set_wcflg(chan);
                if (dtc_ldsc[line].conn == 0)   /* connected? */
                    dtc_lstatus[line] = BufIRQ|BufAbnormal|BufIRQ|BufIdle;
                else
                    dtc_lstatus[line] = BufIRQ|BufIdle;
                dtc_bsize[line] = 0;
                sim_debug(DEBUG_DETAIL, &dtc_dev, "Datacomm read done %d\n",
                         line);
                for (ttu = 1; line > 15; ttu++)
                    line -= 15;
                chan_set_wc(chan, (ttu << 5) | line);
                chan_set_end(chan);
                uptr->CMD = DTC_RDY;
                IAR |= IRQ_12;
                return SCPE_OK;
        } else {
             sim_debug(DEBUG_DATA, &dtc_dev, "Datacomm read data %d %02o %d\n",
                          line, ch & 077, dtc_bufptr[line]);
        }
        sim_activate(uptr, 5000);
    }
    return SCPE_OK;
}
Exemple #3
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);
}