/* 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; }
/* 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; }
/* 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); }
/* Handle transfer of data for card reader */ t_stat cdr_srv(UNIT *uptr) { int chan = UNIT_G_CHAN(uptr->flags); int u = (uptr - cdr_unit); uint16 *image = (uint16 *)(uptr->up7); /* Waiting for disconnect */ if (uptr->u5 & URCSTA_WDISCO) { if (chan_stat(chan, DEV_DISCO)) { chan_clear(chan, DEV_SEL|DEV_WEOR); uptr->u5 &= ~ URCSTA_WDISCO; } else { /* No disco yet, try again in a bit */ sim_activate(uptr, 50); return SCPE_OK; } /* If still busy, schedule another wait */ if (uptr->u5 & URCSTA_BUSY) sim_activate(uptr, uptr->wait); } if (uptr->u5 & URCSTA_BUSY) { uptr->u5 &= ~URCSTA_BUSY; #ifdef I7070 switch(uptr->flags & (ATTENA|ATTENB)) { case ATTENA: chan_set_attn_a(chan); break; case ATTENB: chan_set_attn_b(chan); break; } #endif } /* Check if new card requested. */ if (uptr->u4 == 0 && uptr->u5 & URCSTA_READ && (uptr->u5 & URCSTA_CARD) == 0) { switch(sim_read_card(uptr, image)) { case CDSE_EOF: sim_debug(DEBUG_DETAIL, &cdr_dev, "%d: EOF\n", u); /* Fall through */ case CDSE_EMPTY: chan_set_eof(chan); chan_set_attn(chan); chan_clear(chan, DEV_SEL); uptr->u5 |= URCSTA_EOF; uptr->u5 &= ~(URCSTA_BUSY|URCSTA_READ); return SCPE_OK; case CDSE_ERROR: sim_debug(DEBUG_DETAIL, &cdr_dev, "%d: ERF\n", u); uptr->u5 |= URCSTA_ERR; uptr->u5 &= ~(URCSTA_BUSY|URCSTA_READ); chan_set_attn(chan); chan_clear(chan, DEV_SEL); return SCPE_OK; case CDSE_OK: uptr->u5 |= URCSTA_CARD; #ifdef I7010 chan_set_attn_urec(chan, cdr_dib.addr); #endif break; } #ifdef I7070 /* Check if load card. */ if (uptr->capac && (image[uptr->capac-1] & 0x800)) { uptr->u5 |= URCSTA_LOAD; chan_set_load_mode(chan); } else { uptr->u5 &= ~URCSTA_LOAD; } #endif } if (uptr->u5 & URCSTA_NOXFER) { uptr->u5 &= ~(URCSTA_NOXFER|URCSTA_READ); return SCPE_OK; } /* Copy next column over */ if (uptr->u5 & URCSTA_READ && uptr->u4 < 80) { uint8 ch = 0; #ifdef I7080 /* Detect RSU */ if (image[uptr->u4] == 0x924) { uptr->u5 &= ~URCSTA_READ; uptr->u5 |= URCSTA_WDISCO; chan_set(chan, DEV_REOR); sim_activate(uptr, 10); return SCPE_OK; } #endif ch = sim_hol_to_bcd(image[uptr->u4]); /* Handle invalid punch */ if (ch == 0x7f) { #ifdef I7080 uptr->u5 &= ~(URCSTA_READ|URCSTA_BUSY); sim_debug(DEBUG_DETAIL, &cdr_dev, "%d: bad punch %d\n", u, uptr->u4); chan_set_attn(chan); chan_set_error(chan); chan_clear(chan, DEV_SEL); #else uptr->u5 |= URCSTA_ERR; ch = 017; #endif } #ifdef I7070 /* During load, only sign on every 10 columns */ if (uptr->u5 & URCSTA_LOAD && (uptr->u4 % 10) != 9) ch &= 0xf; #endif switch(chan_write_char(chan, &ch, (uptr->u4 == 79)? DEV_REOR: 0)) { case TIME_ERROR: case END_RECORD: uptr->u5 |= URCSTA_WDISCO|URCSTA_BUSY; uptr->u5 &= ~URCSTA_READ; break; case DATA_OK: uptr->u4++; break; } sim_debug(DEBUG_DATA, &cdr_dev, "%d: Char > %02o\n", u, ch); sim_activate(uptr, 10); } return SCPE_OK; }
/* * Device entry points for card reader. */ uint32 cdr_cmd(UNIT * uptr, uint16 cmd, uint16 dev) { int chan = UNIT_G_CHAN(uptr->flags); int u = (uptr - cdr_unit); int stk = dev & 017; /* Are we currently tranfering? */ if (uptr->u5 & URCSTA_READ) return SCPE_BUSY; /* Test ready */ if (cmd == IO_TRS && uptr->flags & UNIT_ATT) { sim_debug(DEBUG_CMD, &cdr_dev, "%d: Test Rdy\n", u); return SCPE_OK; } if (stk == 10) stk = 0; #ifdef STACK_DEV uptr->u5 &= ~0xF0000; uptr->u5 |= stk << 16; #endif if (uptr->u5 & (URCSTA_EOF|URCSTA_ERR)) return SCPE_IOERR; /* Process commands */ switch(cmd) { case IO_RDS: sim_debug(DEBUG_CMD, &cdr_dev, "%d: Cmd RDS %02o\n", u, dev & 077); #ifdef I7010 if (stk!= 9) #endif uptr->u5 &= ~(URCSTA_CARD|URCSTA_ERR); break; case IO_CTL: sim_debug(DEBUG_CMD, &cdr_dev, "%d: Cmd CTL %02o\n", u, dev & 077); #ifdef I7010 uptr->u5 |= URCSTA_NOXFER; #endif break; default: chan_set_attn(chan); return SCPE_IOERR; } /* If at eof, just return EOF */ if (uptr->u5 & URCSTA_EOF) { chan_set_eof(chan); chan_set_attn(chan); return SCPE_OK; } uptr->u5 |= URCSTA_READ; uptr->u4 = 0; if ((uptr->u5 & URCSTA_NOXFER) == 0) chan_set_sel(chan, 0); /* Wake it up if not busy */ if ((uptr->u5 & URCSTA_BUSY) == 0) sim_activate(uptr, 50); return SCPE_OK; }