int32 ts_write (UNIT *uptr, int32 fc) { int32 i, t; uint32 wa; t_stat st; msgrfc = fc; if (fc == 0) /* byte count */ fc = 0200000; tsba = (cmdadh << 16) | cmdadl; /* buf addr */ if (cmdhdr & CMD_SWP) { /* swapped? */ for (i = 0; i < fc; i++) { /* copy mem to buf */ wa = tsba ^ 1; /* apply OPP */ if (Map_ReadB (wa, 1, &tsxb[i])) { /* fetch byte, nxm? */ tssr = ts_updtssr (tssr | TSSR_NXM); return TC5; } tsba = tsba + 1; } } else { t = Map_ReadB (tsba, fc, tsxb); /* fetch record */ tsba = tsba + (fc - t); /* update tsba */ if (t) { /* nxm? */ tssr = ts_updtssr (tssr | TSSR_NXM); return TC5; } } if ((st = sim_tape_wrrecf (uptr, tsxb, fc))) /* write rec, err? */ return ts_map_status (st); /* return status */ msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */ msgrfc = 0; if (sim_tape_eot (&ts_unit)) /* EOT on write? */ return XTC (XS0_EOT, TC2); return 0; }
t_stat ry_svc (UNIT *uptr) { int32 i, t, func, bps; static uint8 estat[8]; uint32 ba, da; int8 *fbuf = uptr->filebuf; func = RYCS_GETFNC (ry_csr); /* get function */ bps = (ry_csr & RYCS_DEN)? RY_NUMBY: RX_NUMBY; /* get sector size */ ba = (RYCS_GETUAE (ry_csr) << 16) | ry_ba; /* get mem addr */ switch (ry_state) { /* case on state */ case IDLE: /* idle */ return SCPE_IERR; case FEWC: /* word count */ ry_wc = ry_dbr & 0377; /* save WC */ ry_csr = ry_csr | RYCS_TR; /* set TR */ ry_state = FEBA; /* next state */ return SCPE_OK; case FEBA: /* buffer address */ ry_ba = ry_dbr; /* save buf addr */ ry_state = FEXFR; /* next state */ sim_activate (uptr, ry_cwait); /* schedule xfer */ return SCPE_OK; case FEXFR: /* transfer */ if ((ry_wc << 1) > bps) { /* wc too big? */ ry_done (RYES_WCO, 0230); /* error */ break; } if (func == RYCS_FILL) { /* fill? read */ for (i = 0; i < RY_NUMBY; i++) rx2xb[i] = 0; t = Map_ReadB (ba, ry_wc << 1, rx2xb); } else t = Map_WriteB (ba, ry_wc << 1, rx2xb); ry_wc = t >> 1; /* adjust wc */ ry_done (t? RYES_NXM: 0, 0); /* done */ break; case RWDS: /* wait for sector */ ry_sector = ry_dbr & RX_M_SECTOR; /* save sector */ ry_csr = ry_csr | RYCS_TR; /* set xfer */ ry_state = RWDT; /* advance state */ return SCPE_OK; case RWDT: /* wait for track */ ry_track = ry_dbr & RX_M_TRACK; /* save track */ ry_state = RWXFR; /* next state */ sim_activate (uptr, /* sched xfer */ ry_swait * abs (ry_track - uptr->TRACK)); return SCPE_OK; case RWXFR: /* read/write */ if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ ry_done (0, 0110); /* done, error */ return IORETURN (ry_stopioe, SCPE_UNATT); } if (ry_track >= RX_NUMTR) { /* bad track? */ ry_done (0, 0040); /* done, error */ break; } uptr->TRACK = ry_track; /* now on track */ if ((ry_sector == 0) || (ry_sector > RX_NUMSC)) { /* bad sect? */ ry_done (0, 0070); /* done, error */ break; } if (((uptr->flags & UNIT_DEN) != 0) ^ ((ry_csr & RYCS_DEN) != 0)) { /* densities agree? */ ry_done (RYES_DERR, 0240); /* no, error */ break; } da = CALC_DA (ry_track, ry_sector, bps); /* get disk address */ if (func == RYCS_WRDEL) /* del data? */ ry_esr = ry_esr | RYES_DD; if (func == RYCS_READ) { /* read? */ for (i = 0; i < bps; i++) rx2xb[i] = fbuf[da + i]; } else { if (uptr->flags & UNIT_WPRT) { /* write and locked? */ ry_done (0, 0100); /* done, error */ break; } for (i = 0; i < bps; i++) /* write */ fbuf[da + i] = rx2xb[i]; da = da + bps; if (da > uptr->hwmark) uptr->hwmark = da; } ry_done (0, 0); /* done */ break; case SDCNF: /* confirm set density */ if ((ry_dbr & 0377) != 0111) { /* confirmed? */ ry_done (0, 0250); /* no, error */ break; } ry_state = SDXFR; /* next state */ sim_activate (uptr, ry_cwait * 100); /* schedule operation */ break; case SDXFR: /* erase disk */ for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0; uptr->hwmark = (uint32) uptr->capac; if (ry_csr & RYCS_DEN) uptr->flags = uptr->flags | UNIT_DEN; else uptr->flags = uptr->flags & ~UNIT_DEN; ry_done (0, 0); break; case ESBA: ry_ba = ry_dbr; /* save WC */ ry_state = ESXFR; /* next state */ sim_activate (uptr, ry_cwait); /* schedule xfer */ return SCPE_OK; case ESXFR: estat[0] = ry_ecode; /* fill 8B status */ estat[1] = ry_wc; estat[2] = ry_unit[0].TRACK; estat[3] = ry_unit[1].TRACK; estat[4] = ry_track; estat[5] = ry_sector; estat[6] = ((ry_csr & RYCS_DRV)? 0200: 0) | ((ry_unit[1].flags & UNIT_DEN)? 0100: 0) | ((uptr->flags & UNIT_ATT)? 0040: 0) | ((ry_unit[0].flags & UNIT_DEN)? 0020: 0) | ((ry_csr & RYCS_DEN)? 0001: 0); estat[7] = uptr->TRACK; t = Map_WriteB (ba, 8, estat); /* DMA to memory */ ry_done (t? RYES_NXM: 0, 0); /* done */ break; case CMD_COMPLETE: /* command complete */ ry_done (0, 0); break; case INIT_COMPLETE: /* init complete */ ry_unit[0].TRACK = 1; /* drive 0 to trk 1 */ ry_unit[1].TRACK = 0; /* drive 1 to trk 0 */ if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ ry_done (RYES_ID, 0010); /* init done, error */ break; } da = CALC_DA (1, 1, bps); /* track 1, sector 1 */ for (i = 0; i < bps; i++) /* read sector */ rx2xb[i] = fbuf[da + i]; ry_done (RYES_ID, 0); /* set done */ if ((ry_unit[1].flags & UNIT_ATT) == 0) ry_ecode = 0020; break; } /* end case state */ return SCPE_OK; }