t_stat rx_svc (UNIT *uptr) { int32 i, func; uint32 da; int8 *fbuf = uptr->filebuf; func = RXCS_GETFNC (rx_csr); /* get function */ switch (rx_state) { /* case on state */ case IDLE: /* idle */ return SCPE_IERR; /* done */ case EMPTY: /* empty buffer */ if (rx_bptr >= RX_NUMBY) /* done all? */ rx_done (0, 0); else { rx_dbr = rx_buf[rx_bptr]; /* get next */ rx_bptr = rx_bptr + 1; rx_csr = rx_csr | RXCS_TR; /* set xfer */ } break; case FILL: /* fill buffer */ rx_buf[rx_bptr] = rx_dbr; /* write next */ rx_bptr = rx_bptr + 1; if (rx_bptr < RX_NUMBY) /* more? set xfer */ rx_csr = rx_csr | RXCS_TR; else rx_done (0, 0); /* else done */ break; case RWDS: /* wait for sector */ rx_sector = rx_dbr & RX_M_SECTOR; /* save sector */ rx_csr = rx_csr | RXCS_TR; /* set xfer */ rx_state = RWDT; /* advance state */ return SCPE_OK; case RWDT: /* wait for track */ rx_track = rx_dbr & RX_M_TRACK; /* save track */ rx_state = RWXFR; sim_activate (uptr, /* sched done */ rx_swait * abs (rx_track - uptr->TRACK)); return SCPE_OK; case RWXFR: if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */ rx_done (0, 0110); /* done, error */ return IORETURN (rx_stopioe, SCPE_UNATT); } if (rx_track >= RX_NUMTR) { /* bad track? */ rx_done (0, 0040); /* done, error */ break; } uptr->TRACK = rx_track; /* now on track */ if ((rx_sector == 0) || (rx_sector > RX_NUMSC)) { /* bad sect? */ rx_done (0, 0070); /* done, error */ break; } da = CALC_DA (rx_track, rx_sector); /* get disk address */ if (func == RXCS_WRDEL) /* del data? */ rx_esr = rx_esr | RXES_DD; if (func == RXCS_READ) { /* read? */ for (i = 0; i < RX_NUMBY; i++) rx_buf[i] = fbuf[da + i]; } else { if (uptr->flags & UNIT_WPRT) { /* write and locked? */ rx_done (RXES_WLK, 0100); /* done, error */ break; } for (i = 0; i < RX_NUMBY; i++) /* write */ fbuf[da + i] = rx_buf[i]; da = da + RX_NUMBY; if (da > uptr->hwmark) uptr->hwmark = da; } rx_done (0, 0); /* done */ break; case CMD_COMPLETE: /* command complete */ if (func == RXCS_ECODE) { /* read ecode? */ rx_dbr = rx_ecode; /* set dbr */ rx_done (0, -1); /* don't update */ } else rx_done (0, 0); break; case INIT_COMPLETE: /* init complete */ rx_unit[0].TRACK = 1; /* drive 0 to trk 1 */ rx_unit[1].TRACK = 0; /* drive 1 to trk 0 */ if ((rx_unit[0].flags & UNIT_BUF) == 0) { /* not buffered? */ rx_done (RXES_ID, 0010); /* init done, error */ break; } da = CALC_DA (1, 1); /* track 1, sector 1 */ for (i = 0; i < RX_NUMBY; i++) /* read sector */ rx_buf[i] = fbuf[da + i]; rx_done (RXES_ID, 0); /* set done */ if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020; break; } /* end case state */ return SCPE_OK; }
t_stat fl_svc (UNIT *uptr) { int32 i, t; uint32 da; int8 *fbuf = uptr->filebuf; switch (fl_state) { /* case on state */ case FL_IDLE: /* idle */ return SCPE_IERR; /* done */ case FL_READ: case FL_WRITE: /* read, write */ fl_state = fl_state + 1; /* set next state */ t = abs (fl_track - uptr->TRACK); /* # tracks to seek */ if (t == 0) /* minimum 1 */ t = 1; sim_activate (uptr, fl_swait * t); /* schedule seek */ /* fall thru, set flag */ case FL_RWDS: case FL_RWDT: case FL_FILL: /* rwds, rwdt, fill */ tto_csr = tto_csr | CSR_DONE; /* set output done */ if (tto_csr & CSR_IE) tto_int = 1; break; case FL_READ1: /* read, seek done */ if (fl_test_xfr (uptr, FALSE)) { /* transfer ok? */ da = CALC_DA (fl_track, fl_sector); /* get disk address */ for (i = 0; i < FL_NUMBY; i++) /* copy sector to buf */ fl_buf[i] = fbuf[da + i]; tti_buf = fl_esr | FL_CDONE; /* completion code */ tti_csr = tti_csr | CSR_DONE; /* set input flag */ if (tti_csr & CSR_IE) tti_int = 1; fl_state = FL_EMPTY; /* go empty */ } else fl_state = FL_DONE; /* error? cmd done */ sim_activate (uptr, fl_xwait); /* schedule next */ break; case FL_EMPTY: /* empty buffer */ if ((tti_csr & CSR_DONE) == 0) { /* prev data taken? */ tti_buf = FL_CDATA | fl_buf[fl_bptr++]; /* get next byte */ tti_csr = tti_csr | CSR_DONE; /* set input flag */ if (tti_csr & CSR_IE) tti_int = 1; if (fl_bptr >= FL_NUMBY) { /* buffer empty? */ fl_state = FL_IDLE; /* cmd done */ break; } } sim_activate (uptr, fl_xwait); /* schedule next */ break; case FL_WRITE1: /* write, seek done */ if (fl_test_xfr (uptr, TRUE)) { /* transfer ok? */ da = CALC_DA (fl_track, fl_sector); /* get disk address */ for (i = 0; i < FL_NUMBY; i++) /* copy buf to sector */ fbuf[da + i] = fl_buf[i]; da = da + FL_NUMBY; if (da > uptr->hwmark) /* update hwmark */ uptr->hwmark = da; } if (fl_fnc == FL_FNCWD) /* wrdel? set status */ fl_esr |= FL_STADDA; fl_state = FL_DONE; /* command done */ sim_activate (uptr, fl_xwait); /* schedule */ break; case FL_DONE: /* command done */ if (tti_csr & CSR_DONE) /* input buf empty? */ sim_activate (uptr, fl_xwait); /* no, wait */ else { /* yes */ tti_buf = fl_esr | FL_CDONE; /* completion code */ tti_csr = tti_csr | CSR_DONE; /* set input flag */ if (tti_csr & CSR_IE) tti_int = 1; fl_state = FL_IDLE; /* floppy idle */ } break; case FL_READSTA: /* read status */ if ((tti_csr & CSR_DONE) == 0) { /* input buf empty? */ tti_buf = fl_ecode; /* return err code */ tti_csr = tti_csr | CSR_DONE; /* set input flag */ if (tti_csr & CSR_IE) tti_int = 1; fl_state = FL_DONE; /* command done */ } sim_activate (uptr, fl_xwait); break; } return SCPE_OK; }
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; }