/* * Common routine to change the equipment address of a peripheral. Some * devices (e.g. TT, PTR etc) cannot have their equipment address changed. */ t_stat set_equipment(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { DEVICE *dptr; IO_DEVICE *iod; t_value v; t_stat r; if (cptr == NULL) return SCPE_ARG; v = get_uint(cptr, DEV_RDX, 15, &r); if (r != SCPE_OK) return r; if (v == 0) return SCPE_ARG; /* * Check to see if any other, non-disabled device is already using this * address. */ if ((dptr = find_dev_from_unit(uptr)) != NULL) { if (checkDuplicate(dptr, v)) return sim_messagef(SCPE_ARG, "Equipment address already in use\n"); iod = (IO_DEVICE *)dptr->ctxt; iod->iod_equip = v; iod->iod_interrupt = 1 << v; return SCPE_OK; } return SCPE_NXDEV; }
t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { DEVICE* dptr; PNP_INFO* pnp; t_stat rc; uint16 newbase; if (!cptr) return SCPE_ARG; if (!uptr) return SCPE_IERR; if (!(dptr = find_dev_from_unit(uptr))) return SCPE_IERR; if (!(pnp = (PNP_INFO*)dptr->ctxt)) return SCPE_IERR; newbase = get_uint (cptr, 16, 0xFF, &rc); if (rc != SCPE_OK) return rc; if (dptr->flags & DEV_DIS) { printf("Device not enabled yet.\n"); pnp->io_base = newbase; } else { dptr->flags |= DEV_DIS; dptr->reset(dptr); pnp->io_base = newbase; dptr->flags &= ~DEV_DIS; dptr->reset(dptr); } return SCPE_OK; }
t_stat show_iobase(FILE *st, UNIT *uptr, int32 val, CONST void *desc) { DEVICE *dptr; PNP_INFO *pnp; if (!uptr) return SCPE_IERR; if (!(dptr = find_dev_from_unit(uptr))) return SCPE_IERR; if (!(pnp = (PNP_INFO *) dptr->ctxt)) return SCPE_IERR; fprintf(st, "I/O=0x%02X-0x%02X", pnp->io_base, pnp->io_base + pnp->io_size - pnp->io_incr); return SCPE_OK; }
/* find_unit_index find index of a unit Inputs: uptr = pointer to unit Outputs: result = index of device */ int32 find_unit_index (UNIT *uptr) { DEVICE *dptr; uint32 i; if (uptr == NULL) return (-1); dptr = find_dev_from_unit(uptr); for(i=0; i<dptr->numunits; i++) { if(dptr->units + i == uptr) { break; } } if(i == dptr->numunits) { return (-1); } return (i); }
/* 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); }
uint8 cdr_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) { DEVICE *dptr = find_dev_from_unit(uptr); int unit = (uptr - dptr->units); uint8 ch; if ((uptr->u3 & CDR_CMDMSK) != 0) { if ((uptr->flags & UNIT_ATT) != 0) return SNS_BSY; return SNS_DEVEND; } sim_debug(DEBUG_CMD, dptr, "CMD unit=%d %x\n", unit, cmd); if (cmd != 4 && sim_card_eof(uptr) == 1) { uint16 *image = (uint16 *)(uptr->up7); uptr->u5 = SNS_INTVENT; sim_read_card(uptr, image); /* Read in the EOF */ return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } if (cmd != 4 && (uptr->flags & UNIT_ATT) == 0) { uptr->u5 = SNS_INTVENT; return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } switch (cmd & 0x7) { case 2: /* Read command */ if ((cmd & 0xc0) != 0xc0) uptr->u3 &= ~CDR_CARD; uptr->u3 &= ~(CDR_CMDMSK); uptr->u3 |= (cmd & CDR_CMDMSK); sim_activate(uptr, 1000); /* Start unit off */ uptr->u4 = 0; uptr->u5 = 0; return 0; case 3: /* Control */ uptr->u5 = 0; uptr->u3 &= ~(CDR_CMDMSK|CDR_CARD); if (cmd == 0x3) return SNS_CHNEND|SNS_DEVEND; if ((cmd & 0x30) != 0x20 || (cmd & 0xc0) == 0xc0) { uptr->u5 |= SNS_CMDREJ; return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; } uptr->u3 |= (cmd & CDR_CMDMSK); uptr->u4 = 0; sim_activate(uptr, 1000); /* Start unit off */ return 0; case 0: /* Status */ break; case 4: /* Sense */ uptr->u3 &= ~(CDR_CMDMSK); uptr->u3 |= (cmd & CDR_CMDMSK); sim_activate(uptr, 10); return 0; default: /* invalid command */ uptr->u5 |= SNS_CMDREJ; break; } if (uptr->u5) return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; return SNS_CHNEND|SNS_DEVEND; }