t_stat inq_io (int32 flag, int32 mod) { int32 i, t, wm_seen = 0; ind[IN_INC] = 0; /* clear inq clear */ switch (mod) { /* case on mod */ case BCD_R: /* input */ /* if (ind[IN_INR] == 0) return SCPE_OK; /* return if no req */ ind[IN_INR] = 0; /* clear req */ puts_tty ("[Enter]\r\n"); /* prompt */ for (i = 0; M[BS] != (BCD_GRPMRK + WM); i++) { /* until GM + WM */ while (((t = sim_poll_kbd ()) == SCPE_OK) || (t & SCPE_BREAK)) { if (stop_cpu) return SCPE_STOP; } /* interrupt? */ if (t < SCPE_KFLAG) return t; /* if not char, err */ t = t & 0177; if ((t == '\r') || (t == '\n')) break; if (t == inq_char) { /* cancel? */ ind[IN_INC] = 1; /* set indicator */ puts_tty ("\r\n[Canceled]\r\n"); return SCPE_OK; } if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); sim_putchar (t); /* echo */ if (flag == MD_WM) { /* word mark mode? */ if ((t == '~') && (wm_seen == 0)) wm_seen = WM; else { M[BS] = wm_seen | ascii_to_bcd[t]; wm_seen = 0; } } else M[BS] = (M[BS] & WM) | ascii_to_bcd[t]; if (!wm_seen) BS++; if (ADDR_ERR (BS)) { BS = BA | (BS % MAXMEMSIZE); return STOP_NXM; } } puts_tty ("\r\n"); M[BS++] = BCD_GRPMRK + WM; return SCPE_OK; case BCD_W: /* output */ for (i = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); i++) { if ((flag == MD_WM) && (t & WM)) { if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); sim_putchar ('~'); } if (i && ((i % INQ_WIDTH) == 0)) puts_tty ("\r\n"); sim_putchar (bcd_to_ascii[t & CHAR]); if (ADDR_ERR (BS)) { BS = BA | (BS % MAXMEMSIZE); return STOP_NXM; } } puts_tty ("\r\n"); return SCPE_OK; default: return STOP_INVM; } /* invalid mod */ }
t_stat dp_io (int32 fnc, int32 flg, int32 mod) { int32 dcf, drv, sec, psec, cnt, qwc, qzr, diff; UNIT *uptr; t_stat r; dcf = BS; /* save DCF addr */ qwc = 0; /* not wcheck */ ind[IN_DPW] = ind[IN_LNG] = ind[IN_UNA] = 0; /* clr indicators */ ind[IN_DSK] = ind[IN_ACC] = ind[IN_DBY] = 0; if (sim_is_active (&dp_unit[0])) { /* ctlr busy? */ ind[IN_DBY] = ind[IN_DSK] = 1; /* set indicators */ return SCPE_OK; } /* done */ AS = dcf + 6; /* AS for most ops */ BS = dcf + DCF_CNT - 1; /* minimum DCF */ if (ADDR_ERR (BS)) return STOP_WRAP; /* DCF in memory? */ if (M[dcf] & BBIT) drv = M[dcf + DCF_SEC + 1] & 0xE; /* impl sel? cyl 8-4-2 */ else drv = M[dcf] & DIGIT; /* get drive sel */ if ((drv == 0) || (drv & 1) || (drv > BCD_ZERO)) /* bad drive #? */ return STOP_INVDSK; drv = bcd_to_bin[drv] >> 1; /* convert */ uptr = dp_dev.units + drv; /* get unit ptr */ if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ ind[IN_DSK] = ind[IN_ACC] = 1; /* no, error */ CRETIOE (iochk, SCPE_UNATT); } if ((fnc == FNC_SEEK) && /* seek and */ (M[dcf + DCF_DIR_FL] & DCF_DSEEK) == DCF_DSEEK) { /* direct flag? */ diff = dp_cvt_bcd (dcf + DCF_DIR, DCF_DIR_LEN); /* cvt diff */ if (diff < 0) return STOP_INVDSC; /* error? */ diff = diff >> 1; /* diff is *2 */ if ((M[dcf + DCF_DIR + DCF_DIR_LEN - 1] & ZONE) == BBIT) diff = -diff; /* get sign */ uptr->CYL = uptr->CYL + diff; /* bound seek */ if (uptr->CYL < 0) uptr->CYL = 0; else if (uptr->CYL >= DP_NUMCY) { /* too big? */ uptr->CYL = 0; /* system hangs */ return STOP_INVDCY; } sim_activate (&dp_unit[0], dp_time); /* set ctlr busy */ return SCPE_OK; } /* done! */
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); }