t_stat ptr_svc (UNIT *uptr) { int32 temp; if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */ ptr_set_err (); /* no, err, disc */ CRETIOE (ptr_stopioe, SCPE_UNATT); } if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */ ptr_set_err (); /* yes, err, disc */ if (feof (ptr_unit.fileref)) { /* end of file? */ if (ptr_stopioe) sim_printf ("PTR end of file\n"); else return SCPE_OK; } else perror ("PTR I/O error"); /* I/O error */ clearerr (ptr_unit.fileref); return SCPE_IOERR; } ptr_unit.pos = ptr_unit.pos + 1; /* inc position */ if (temp) { /* leader/gap? */ ptr_unit.buf = temp & 0177; /* no, save char */ xfr_req = xfr_req | XFR_PTR; /* set xfr flag */ ptr_sor = 0; /* in record */ } else if (!ptr_sor) /* end record? */ chan_set_flag (ptr_dib.chan, CHF_EOR); /* ignore leader */ sim_activate (&ptr_unit, ptr_unit.wait); /* get next char */ return SCPE_OK; }
t_stat ptp_out (int32 dat) { if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */ ptp_set_err (); /* no, disc, err */ CRETIOE (ptp_stopioe, SCPE_UNATT); } if (putc (dat, ptp_unit.fileref) == EOF) { /* I/O error? */ ptp_set_err (); /* yes, disc, err */ perror ("PTP I/O error"); /* print msg */ clearerr (ptp_unit.fileref); return SCPE_IOERR; } ptp_unit.pos = ptp_unit.pos + 1; /* inc position */ return SCPE_OK; }
t_stat lpt_status (UNIT *uptr) { if (uptr->flags & UNIT_ATT) { /* attached? */ uptr->pos = ftell (uptr->fileref); /* update position */ if (ferror (uptr->fileref)) { /* I/O error? */ lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */ perror ("LPT I/O error"); /* print msg */ clearerr (uptr->fileref); return SCPE_IOERR; /* ret error */ } } else { lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */ CRETIOE (lpt_stopioe, SCPE_UNATT); /* ret error */ } return SCPE_OK; }
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 dp (uint32 op, uint32 pa, uint32 f0, uint32 f1) { int32 drv, sa, sec, psec, cnt, qwc, qnr, t; UNIT *uptr; t_stat r; if (pa & 1) /* dcf must be even */ return STOP_INVDCF; ind[IN_DACH] = ind[IN_DWLR] = 0; /* clr indicators */ ind[IN_DERR] = ind[IN_DCYO] = 0; sa = ADDR_A (pa, DCF_SEC); /* ptr to sector */ if (((dp_unit[0].flags & UNIT_DIS) == 0) && /* only drive 0? */ (dp_unit[1].flags & UNIT_DIS) && (dp_unit[2].flags & UNIT_DIS) && (dp_unit[3].flags & UNIT_DIS)) drv = 0; /* ignore drv select */ else drv = (((M[pa] & 1)? M[pa]: M[sa]) & 0xE) >> 1; /* drive # */ if (drv >= DP_NUMDR) /* invalid? */ return STOP_INVDRV; uptr = dp_dev.units + drv; /* get unit ptr */ if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */ ind[IN_DERR] = 1; /* no, error */ CRETIOE (dp_stop, SCPE_UNATT); } sec = dp_cvt_bcd (sa, DCF_SEC_LEN); /* cvt sector */ if ((sec < 0) || (sec >= (DP_NUMDR * DP_TOTSC))) /* bad sector? */ return STOP_INVDSC; if (op == OP_K) { /* seek? */ if (f1 != FNC_SEEK) /* really? */ return STOP_INVFNC; uptr->CYL = (sec / (DP_NUMSF * DP_NUMSC)) % /* set cyl # */ DP_NUMCY; return SCPE_OK; /* done! */ } cnt = dp_cvt_bcd (ADDR_A (pa, DCF_CNT), DCF_CNT_LEN); /* get count */ t = dp_cvt_bcd (ADDR_A (pa, DCF_ADR), DCF_ADR_LEN); /* get address */ if ((t < 0) || (t & 1)) /* bad address? */ return STOP_INVDBA; dp_ba = t; /* save addr */ if (f1 >= FNC_WRI) /* invalid func? */ return STOP_INVFNC; if (op == OP_RN) /* read? set wch */ qwc = f1 & FNC_WCH; else if (op == OP_WN) { /* write? */ if (op & FNC_WCH) /* cant check */ return STOP_INVFNC; f1 = f1 + FNC_WRI; /* offset fnc */ } else return STOP_INVFNC; /* not R or W */ qnr = f1 & FNC_NRL; /* no rec check? */ switch (f1 & ~(FNC_WCH | FNC_NRL)) { /* case on function */ case FNC_SEC: /* read sectors */ if (cnt <= 0) /* bad count? */ return STOP_INVDCN; psec = dp_fndsec (uptr, sec, TRUE); /* find sector */ if (psec < 0) /* error? */ CRETIOE (dp_stop, STOP_DACERR); do { /* loop on count */ if ((r = dp_rdsec (uptr, psec, qnr, qwc))) /* read sector */ break; sec++; psec++; /* next sector */ } while ((--cnt > 0) && ((r = dp_nexsec (uptr, sec, psec, TRUE)) == SCPE_OK)); break; /* done, clean up */ case FNC_TRK: /* read track */ psec = dp_trkop (drv, sec); /* start of track */ for (cnt = 0; cnt < DP_NUMSC; cnt++) { /* full track */ if ((r = dp_rdadr (uptr, psec, qnr, qwc))) /* read addr */ break; /* error? */ if ((r = dp_rdsec (uptr, psec, qnr, qwc))) /* read data */ break; /* error? */ psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } break; /* done, clean up */ case FNC_SEC + FNC_WRI: /* write */ if (cnt <= 0) /* bad count? */ return STOP_INVDCN; psec = dp_fndsec (uptr, sec, FALSE); /* find sector */ if (psec < 0) /* error? */ CRETIOE (dp_stop, STOP_DACERR); do { /* loop on count */ if ((r = dp_tstgm (M[dp_ba], qnr))) /* start with gm? */ break; if ((r = dp_wrsec (uptr, psec, qnr))) /* write data */ break; sec++; psec++; /* next sector */ } while ((--cnt > 0) && ((r = dp_nexsec (uptr, sec, psec, FALSE)) == SCPE_OK)); break; /* done, clean up */ case FNC_TRK + FNC_WRI: /* write track */ if ((uptr->flags & UNIT_WAE) == 0) /* enabled? */ return STOP_WRADIS; psec = dp_trkop (drv, sec); /* start of track */ for (cnt = 0; cnt < DP_NUMSC; cnt++) { /* full track */ if ((r = dp_tstgm (M[dp_ba], qnr))) /* start with gm? */ break; if ((r = dp_wradr (uptr, psec, qnr))) /* write addr */ break; if ((r = dp_wrsec (uptr, psec, qnr))) /* write data */ break; psec = dp_trkop (drv, sec) + ((psec + 1) % DP_NUMSC); } break; /* done, clean up */ default: /* unknown */ return STOP_INVFNC; } if ((r == SCPE_OK) && !qnr) { /* eor check? */ if ((M[dp_ba] & DIGIT) != GRP_MARK) { /* GM at end? */ ind[IN_DWLR] = ind[IN_DERR] = 1; /* no, error */ r = STOP_WRLERR; } } if ((r != SCPE_OK) && /* error? */ (dp_stop || !ind[IN_DERR])) /* iochk or stop? */ return r; return SCPE_OK; /* continue */ }