diff --git a/sigma/Design Notes on the Sigma 7.doc b/sigma/Design Notes on the Sigma 7.doc index 21a67694..1a99ffaf 100644 Binary files a/sigma/Design Notes on the Sigma 7.doc and b/sigma/Design Notes on the Sigma 7.doc differ diff --git a/sigma/sigma_bugs.txt b/sigma/sigma_bugs.txt index 05ea979f..daa9d7b5 100644 --- a/sigma/sigma_bugs.txt +++ b/sigma/sigma_bugs.txt @@ -114,6 +114,10 @@ 108. DP: TIO status routine always returns DVS_AUTO instead of proper status. 109. DP: DP_SEEK definition is off by 1. 110. DP: reset does not properly initialize controller, seek threads. +111. DP: device address must include unit identifier everywhere, for interrupt generation. +112. DK: device address must include unit identifier everywhere, for interrupt generation. +113. MT: device address must include unit identifier everywhere, for interrupt generation. +114: RAD: device address must include unit identifier everywhere, for interrupt generation. Diagnostic Notes diff --git a/sigma/sigma_dk.c b/sigma/sigma_dk.c index 8fd75101..a1a31a44 100644 --- a/sigma/sigma_dk.c +++ b/sigma/sigma_dk.c @@ -1,6 +1,6 @@ /* sigma_dk.c: 7250/7251-7252 cartridge disk simulator - Copyright (c) 2007-2008, Robert M Supnik + Copyright (c) 2007-2022, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,8 @@ dk 7250/7251-7252 cartridge disk + 02-Jul-2022 RMS Fixed bugs in multi-unit operation + Transfers are always done a sector at a time. */ @@ -88,7 +90,7 @@ extern uint32 chan_ctl_time; uint32 dk_disp (uint32 op, uint32 dva, uint32 *dvst); uint32 dk_tio_status (uint32 un); uint32 dk_tdv_status (uint32 un); -t_stat dk_chan_err (uint32 st); +t_stat dk_chan_err (uint32 dva, uint32 st); t_stat dk_svc (UNIT *uptr); t_stat dk_reset (DEVICE *dptr); t_bool dk_inv_ad (uint32 *da); @@ -148,12 +150,17 @@ DEVICE dk_dev = { &dk_dib, DEV_DISABLE }; -/* DK: IO dispatch routine */ +/* DK: IO dispatch routine + + For all calls except AIO, dva is the full channel/device/unit address + For AIO, the handler must return the unit number +*/ uint32 dk_disp (uint32 op, uint32 dva, uint32 *dvst) { uint32 i; uint32 un = DVA_GETUNIT (dva); +int32 iu; UNIT *uptr; if ((un >= DK_NUMDR) || /* inv unit num? */ @@ -178,23 +185,28 @@ switch (op) { /* case on op */ break; case OP_HIO: /* halt I/O */ - chan_clr_chi (dk_dib.dva); /* clr int */ + chan_clr_chi (dva); /* clr int */ *dvst = dk_tio_status (un); /* get status */ if ((*dvst & DVS_CST) != 0) { /* ctrl busy? */ for (i = 0; i < DK_NUMDR; i++) { /* find busy unit */ uptr = &dk_unit[i]; if (sim_is_active (uptr)) { /* active? */ sim_cancel (uptr); /* stop */ - chan_uen (dk_dib.dva); /* uend */ + chan_uen (dk_dib.dva | i); /* uend on unit */ } /* end if active */ } /* end for */ } break; case OP_AIO: /* acknowledge int */ - chan_clr_chi (dk_dib.dva); /* clr int */ - *dvst = dk_tdv_status (un); /* status like TDV */ - break; + iu = chan_clr_chi (dk_dib.dva); /* clr int */ + if (iu < 0) { /* no int? */ + *dvst = 0; + return SCPE_IERR; + } + *dvst = dk_tdv_status (iu) | /* get status */ + (iu << DVT_V_UN); /* or in unit */ + break; default: *dvst = 0; @@ -210,18 +222,20 @@ t_stat dk_svc (UNIT *uptr) { uint32 i, sc, da, wd, wd1, cmd, c[3]; uint32 *fbuf = (uint32 *) uptr->filebuf; +uint32 un = uptr - dk_unit; +uint32 dva = dk_dib.dva | un; int32 t, dc; uint32 st; switch (dk_cmd) { case DKS_INIT: /* init state */ - st = chan_get_cmd (dk_dib.dva, &cmd); /* get command */ + st = chan_get_cmd (dva, &cmd); /* get command */ if (CHS_IFERR (st)) /* channel error? */ - return dk_chan_err (st); + return dk_chan_err (dva,st); if ((cmd == 0) || /* invalid cmd? */ ((cmd > DKS_CHECK) && (cmd != DKS_RDEES) && (cmd != DKS_TEST))) { - chan_uen (dk_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_OK; } dk_flags = 0; /* clear status */ @@ -240,9 +254,9 @@ switch (dk_cmd) { return SCPE_OK; case DKS_END: /* end state */ - st = chan_end (dk_dib.dva); /* set channel end */ + st = chan_end (dva); /* set channel end */ if (CHS_IFERR (st)) /* channel error? */ - return dk_chan_err (st); + return dk_chan_err (dva,st); if (st == CHS_CCH) { /* command chain? */ dk_cmd = DKS_INIT; /* restart thread */ sim_activate (uptr, chan_ctl_time); @@ -252,13 +266,13 @@ switch (dk_cmd) { case DKS_SEEK: /* seek */ c[0] = c[1] = 0; for (i = 0, st = 0; (i < 2) && (st != CHS_ZBC); i++) { - st = chan_RdMemB (dk_dib.dva, &c[i]); /* get byte */ + st = chan_RdMemB (dva, &c[i]); /* get byte */ if (CHS_IFERR (st)) /* channel error? */ - return dk_chan_err (st); + return dk_chan_err (dva,st); } dk_ad = ((c[0] & 0x7F) << 8) | c[1]; /* new address */ if (((i != 2) || (st != CHS_ZBC)) && /* length error? */ - chan_set_chf (dk_dib.dva, CHF_LNTE)) /* care? */ + chan_set_chf (dva, CHF_LNTE)) /* care? */ return SCPE_OK; dc = DKA_GETTK (dk_ad); /* desired track */ t = abs (uptr->UTRK - dc); /* get track diff */ @@ -272,7 +286,7 @@ switch (dk_cmd) { case DKS_SEEK2: /* seek complete */ if (uptr->UTRK >= DK_TKUN) { dk_flags |= DKV_BADS; - chan_uen (dk_dib.dva); + chan_uen (dva); return SCPE_OK; } break; /* seek done */ @@ -282,31 +296,31 @@ switch (dk_cmd) { c[1] = dk_ad & 0xFF; /* address */ c[2] = GET_PSC (dk_time); /* curr sector */ for (i = 0, st = 0; (i < DKS_NBY) && (st != CHS_ZBC); i++) { - st = chan_WrMemB (dk_dib.dva, c[i]); /* store char */ + st = chan_WrMemB (dva, c[i]); /* store char */ if (CHS_IFERR (st)) /* channel error? */ - return dk_chan_err (st); + return dk_chan_err (dva,st); } if (((i != DKS_NBY) || (st != CHS_ZBC)) && - chan_set_chf (dk_dib.dva, CHF_LNTE)) /* length error? */ + chan_set_chf (dva, CHF_LNTE)) /* length error? */ return SCPE_OK; break; case DKS_WRITE: /* write */ if (uptr->flags & UNIT_RO) { /* write locked? */ dk_flags |= DKV_WPE; /* set status */ - chan_uen (dk_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_OK; } if (dk_inv_ad (&da)) { /* invalid addr? */ - chan_uen (dk_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_OK; } for (i = 0, st = 0; i < DK_WDSC; da++, i++) { /* sector loop */ if (st != CHS_ZBC) { /* chan not done? */ - st = chan_RdMemW (dk_dib.dva, &wd); /* read word */ + st = chan_RdMemW (dva, &wd); /* read word */ if (CHS_IFERR (st)) { /* channel error? */ dk_inc_ad (); /* da increments */ - return dk_chan_err (st); + return dk_chan_err (dva,st); } } else wd = 0; @@ -322,20 +336,20 @@ switch (dk_cmd) { case DKS_CHECK: /* write check */ if (dk_inv_ad (&da)) { /* invalid addr? */ - chan_uen (dk_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_OK; } for (i = 0, st = 0; (i < (DK_WDSC * 4)) && (st != CHS_ZBC); ) { - st = chan_RdMemB (dk_dib.dva, &wd); /* read byte */ + st = chan_RdMemB (dva, &wd); /* read byte */ if (CHS_IFERR (st)) { /* channel error? */ dk_inc_ad (); /* da increments */ - return dk_chan_err (st); + return dk_chan_err (dva,st); } wd1 = (fbuf[da] >> (24 - ((i % 4) * 8))) & 0xFF; /* byte */ if (wd != wd1) { /* check error? */ dk_inc_ad (); /* da increments */ - chan_set_chf (dk_dib.dva, CHF_XMDE); /* set xmt err flag */ - chan_uen (dk_dib.dva); /* force uend */ + chan_set_chf (dva, CHF_XMDE); /* set xmt err flag */ + chan_uen (dva); /* force uend */ return SCPE_OK; } da = da + ((++i % 4) == 0); /* every 4th byte */ @@ -346,14 +360,14 @@ switch (dk_cmd) { case DKS_READ: /* read */ if (dk_inv_ad (&da)) { /* invalid addr? */ - chan_uen (dk_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_OK; } for (i = 0, st = 0; (i < DK_WDSC) && (st != CHS_ZBC); da++, i++) { - st = chan_WrMemW (dk_dib.dva, fbuf[da]); /* store in mem */ + st = chan_WrMemW (dva, fbuf[da]); /* store in mem */ if (CHS_IFERR (st)) { /* channel error? */ dk_inc_ad (); /* da increments */ - return dk_chan_err (st); + return dk_chan_err (dva,st); } } if (dk_end_sec (uptr, i, DK_WDSC, st)) /* transfer done? */ @@ -376,15 +390,18 @@ return SCPE_OK; t_bool dk_end_sec (UNIT *uptr, uint32 lnt, uint32 exp, uint32 st) { +uint32 un = uptr - dk_unit; +uint32 dva = dk_dib.dva | un; + if (st != CHS_ZBC) { /* end record? */ if (dk_inc_ad ()) /* inc addr, ovf? */ - chan_uen (dk_dib.dva); /* uend */ + chan_uen (dva); /* uend */ else sim_activate (uptr, dk_time * 16); /* no, next sector */ return TRUE; } dk_inc_ad (); /* just incr addr */ if ((lnt != exp) && /* length error? */ - chan_set_chf (dk_dib.dva, CHF_LNTE)) /* do we care? */ + chan_set_chf (dva, CHF_LNTE)) /* do we care? */ return TRUE; return FALSE; /* cmd done */ } @@ -443,9 +460,9 @@ return FALSE; /* Channel error */ -t_stat dk_chan_err (uint32 st) +t_stat dk_chan_err (uint32 dva, uint32 st) { -chan_uen (dk_dib.dva); /* uend */ +chan_uen (dva); /* uend */ if (st < CHS_ERR) return st; return SCPE_OK; diff --git a/sigma/sigma_dp.c b/sigma/sigma_dp.c index 48286c0d..47931aa1 100644 --- a/sigma/sigma_dp.c +++ b/sigma/sigma_dp.c @@ -25,6 +25,7 @@ dp moving head disk pack controller + 02-Jul-2022 RMS Fixed bugs in multi-unit operation 28-Jun-22 RMS Fixed off-by-1 error in DP_SEEK definition (Ken Rector) 07-Jun-22 RMS Removed unused variables (V4) 06-Jun-22 RMS Fixed incorrect return in TIO status (Ken Rector) @@ -548,7 +549,11 @@ DEVICE dp_dev[] = { } }; -/* DP: IO dispatch routine */ +/* DP: IO dispatch routine + + For all calls except AIO, dva is the full channel/device/unit address + For AIO, the handler must return the unit number +*/ uint32 dpa_disp (uint32 op, uint32 dva, uint32 *dvst) { @@ -612,7 +617,7 @@ switch (op) { /* case on op */ for (i = 0; i < DP_NUMDR; i++) { /* do every unit */ if (sim_is_active (&dp_unit[i])) { /* chan active? */ sim_cancel (&dp_unit[i]); /* cancel */ - chan_uen (dva); /* uend */ + chan_uen ((dva & ~DVA_M_UNIT) | i); /* uend */ } dp_clr_ski (cidx, i); /* clear seek int */ sim_cancel (&dp_unit[i + DP_SEEK]); /* cancel seek compl */ @@ -635,16 +640,16 @@ switch (op) { /* case on op */ return 0; } -/* Unit service */ +/* Unit service - reconstruct full device address on entry */ t_stat dp_svc (UNIT *uptr) { uint32 i, da, wd, wd1, c[DPS_NBY_16B]; uint32 cidx = uptr->UCTX; -uint32 dva = dp_dib[cidx].dva; -uint32 dtype = GET_DTYPE (uptr->flags); UNIT *dp_unit = dp_dev[cidx].units; uint32 un = uptr - dp_unit; +uint32 dva = dp_dib[cidx].dva | un; +uint32 dtype = GET_DTYPE (uptr->flags); DP_CTX *ctx = &dp_ctx[cidx]; int32 t, dc; uint32 st, cmd, sc; @@ -932,7 +937,8 @@ return SCPE_OK; t_bool dp_end_sec (UNIT *uptr, uint32 lnt, uint32 exp, uint32 st) { uint32 cidx = uptr->UCTX; -uint32 dva = dp_dib[cidx].dva; +uint32 un = uptr - dp_dev[cidx].units; +uint32 dva = dp_dib[cidx].dva | un; DP_CTX *ctx = &dp_ctx[cidx]; if (st != CHS_ZBC) { /* end record? */ @@ -1112,7 +1118,8 @@ return SCPE_OK; t_stat dp_ioerr (UNIT *uptr) { uint32 cidx = uptr->UCTX; -uint32 dva = dp_dib[cidx].dva; +uint32 un = uptr - dp_dev[cidx].units; +uint32 dva = dp_dib[cidx].dva | un; perror ("DP I/O error"); clearerr (uptr->fileref); diff --git a/sigma/sigma_mt.c b/sigma/sigma_mt.c index 7a869288..b999dbe7 100644 --- a/sigma/sigma_mt.c +++ b/sigma/sigma_mt.c @@ -25,6 +25,8 @@ mt 7320 and 7322/7323 magnetic tape + 02-Jul-2022 RMS Fixed bugs in multi-unit operation + 07-Jun-22 RMS Removed unused variables (V4) 26-Mar-22 RMS Added extra case points for new MTSE definitions 13-Mar-17 RMS Annotated fall through in switch @@ -129,7 +131,7 @@ extern uint8 ebcdic_to_ascii[256]; uint32 mt_disp (uint32 op, uint32 dva, uint32 *dvst); uint32 mt_tio_status (uint32 un); uint32 mt_tdv_status (uint32 un); -t_stat mt_chan_err (uint32 st); +t_stat mt_chan_err (uint32 dva, uint32 st); t_stat mtu_svc (UNIT *uptr); t_stat mtr_svc (UNIT *uptr); t_stat mt_reset (DEVICE *dptr); @@ -215,7 +217,11 @@ DEVICE mt_dev = { &mt_dib, DEV_DISABLE | DEV_TAPE }; -/* Magtape: IO dispatch routine */ +/* Magtape: IO dispatch routine + + For all calls except AIO, dva is the full channel/device/unit address + For AIO, the handler must return the unit number +*/ uint32 mt_disp (uint32 op, uint32 dva, uint32 *dvst) { @@ -256,7 +262,7 @@ switch (op) { /* case on op */ break; case OP_AIO: /* acknowledge int */ - un = mt_clr_int (mt_dib.dva); /* clr int, get unit */ + un = mt_clr_int (mt_dib.dva); /* clr int, get unit and flag */ *dvst = (mt_tdv_status (un) & MTAI_MASK) | /* device status */ (un & MTAI_INT) | /* device int flag */ ((un & DVA_M_UNIT) << DVT_V_UN); /* unit number */ @@ -270,12 +276,13 @@ switch (op) { /* case on op */ return 0; } -/* Unit service */ +/* Unit service - reconstruct full unit address at entry */ t_stat mtu_svc (UNIT *uptr) { uint32 cmd = uptr->UCMD; uint32 un = uptr - mt_unit; +uint32 dva = mt_dib.dva | un; uint32 c; uint32 st; int32 t; @@ -287,9 +294,9 @@ if (cmd == MCM_INIT) { /* init state */ sim_activate (uptr, t); /* retry later */ return SCPE_OK; } - st = chan_get_cmd (mt_dib.dva, &cmd); /* get command */ + st = chan_get_cmd (dva, &cmd); /* get command */ if (CHS_IFERR (st)) /* channel error? */ - return mt_chan_err (st); + return mt_chan_err (dva, st); if ((cmd & 0x80) || /* invalid cmd? */ (mt_op[cmd] == 0)) { uptr->UCMD = MCM_END; /* end state */ @@ -299,7 +306,7 @@ if (cmd == MCM_INIT) { /* init state */ else { /* valid cmd */ if ((mt_op[cmd] & O_REV) && /* reverse op */ (mt_unit[un].UST & MTDV_BOT)) { /* at load point? */ - chan_uen (mt_dib.dva); /* channel end */ + chan_uen (dva); /* uend */ return SCPE_OK; } uptr->UCMD = cmd; /* unit state */ @@ -312,9 +319,9 @@ if (cmd == MCM_INIT) { /* init state */ } if (cmd == MCM_END) { /* end state */ - st = chan_end (mt_dib.dva); /* set channel end */ + st = chan_end (dva); /* set channel end */ if (CHS_IFERR (st)) /* channel error? */ - return mt_chan_err (st); + return mt_chan_err (dva, st); if (st == CHS_CCH) { /* command chain? */ uptr->UCMD = MCM_INIT; /* restart thread */ sim_activate (uptr, chan_ctl_time); @@ -331,7 +338,7 @@ if ((mt_op[cmd] & O_ATT) && /* op req att and */ if ((mt_op[cmd] & O_WRE) && /* write op and */ sim_tape_wrp (uptr)) { /* write protected? */ uptr->UST |= MTDV_WLE; /* set status */ - chan_uen (mt_dib.dva); /* unusual end */ + chan_uen (dva); /* uend */ return SCPE_OK; } @@ -390,15 +397,15 @@ switch (cmd) { /* case on command */ mt_bptr = 0; /* init rec ptr */ } c = mt_xb[mt_bptr++]; /* get char */ - st = chan_WrMemB (mt_dib.dva, c); /* write to memory */ + st = chan_WrMemB (dva, c); /* write to memory */ if (CHS_IFERR (st)) /* channel error? */ - return mt_chan_err (st); + return mt_chan_err (dva, st); if ((st != CHS_ZBC) && (mt_bptr != mt_blim)) { /* not done? */ sim_activate (uptr, mt_time); /* continue thread */ return SCPE_OK; } if (((st == CHS_ZBC) ^ (mt_bptr == mt_blim)) && /* length err? */ - chan_set_chf (mt_dib.dva, CHF_LNTE)) /* uend taken? */ + chan_set_chf (dva, CHF_LNTE)) /* uend taken? */ return SCPE_OK; /* finished */ break; /* normal end */ @@ -412,23 +419,23 @@ switch (cmd) { /* case on command */ mt_bptr = mt_blim; /* init rec ptr */ } c = mt_xb[--mt_bptr]; /* get char */ - st = chan_WrMemBR (mt_dib.dva, c); /* write mem rev */ + st = chan_WrMemBR (dva, c); /* write mem rev */ if (CHS_IFERR (st)) /* channel error? */ - return mt_chan_err (st); + return mt_chan_err (dva, st); if ((st != CHS_ZBC) && (mt_bptr != 0)) { /* not done? */ sim_activate (uptr, mt_time); /* continue thread */ return SCPE_OK; } if (((st == CHS_ZBC) ^ (mt_bptr == 0)) && /* length err? */ - chan_set_chf (mt_dib.dva, CHF_LNTE)) /* uend taken? */ + chan_set_chf (dva, CHF_LNTE)) /* uend taken? */ return SCPE_OK; /* finished */ break; /* normal end */ case MCM_WRITE: /* write */ - st = chan_RdMemB (mt_dib.dva, &c); /* read char */ + st = chan_RdMemB (dva, &c); /* read char */ if (CHS_IFERR (st)) { /* channel error? */ mt_flush_buf (uptr); /* flush buffer */ - return mt_chan_err (st); + return mt_chan_err (dva, st); } mt_xb[mt_blim++] = c; /* store in buffer */ if (st != CHS_ZBC) { /* end record? */ @@ -473,42 +480,45 @@ return SCPE_OK; t_stat mt_map_err (UNIT *uptr, t_stat st) { +uint32 un = uptr - mt_unit; +uint32 dva = mt_dib.dva | un; + switch (st) { case MTSE_FMT: /* illegal fmt */ case MTSE_UNATT: /* not attached */ case MTSE_WRP: /* write protect */ default: /* unknown error*/ - chan_set_chf (mt_dib.dva, CHF_XMME); /* set err, fall through */ + chan_set_chf (dva, CHF_XMME); /* set err, fall through */ case MTSE_OK: /* no error */ - chan_uen (mt_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_IERR; case MTSE_TMK: /* end of file */ uptr->UST |= MTDV_EOF; /* set eof flag */ - chan_uen (mt_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return CHS_INACTV; case MTSE_IOERR: /* IO error */ uptr->UST |= MTDV_DTE; /* set DTE flag */ - chan_set_chf (mt_dib.dva, CHF_XMDE); - chan_uen (mt_dib.dva); /* force uend */ + chan_set_chf (dva, CHF_XMDE); + chan_uen (dva); /* uend */ return SCPE_IOERR; case MTSE_INVRL: /* invalid rec lnt */ uptr->UST |= MTDV_DTE; /* set DTE flag */ - chan_set_chf (mt_dib.dva, CHF_XMDE); - chan_uen (mt_dib.dva); /* force uend */ + chan_set_chf (dva, CHF_XMDE); + chan_uen (dva); /* uend */ return SCPE_MTRLNT; case MTSE_RECE: /* record in error */ case MTSE_EOM: /* end of medium */ uptr->UST |= MTDV_DTE; /* set DTE flag */ - return chan_set_chf (mt_dib.dva, CHF_XMDE); /* possible error */ + return chan_set_chf (dva, CHF_XMDE); /* possible error */ case MTSE_BOT: /* reverse into BOT */ uptr->UST |= MTDV_BOT; /* set BOT */ - chan_uen (mt_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return CHS_INACTV; } /* end switch */ @@ -555,9 +565,9 @@ return st; /* Channel error */ -t_stat mt_chan_err (uint32 st) +t_stat mt_chan_err (uint32 dva, uint32 st) { -chan_uen (mt_dib.dva); /* uend */ +chan_uen (dva); /* uend */ if (st < CHS_ERR) return st; return SCPE_OK; diff --git a/sigma/sigma_rad.c b/sigma/sigma_rad.c index 8542dd8d..8de5b490 100644 --- a/sigma/sigma_rad.c +++ b/sigma/sigma_rad.c @@ -1,6 +1,6 @@ /* sigma_rad.c: Sigma 7211/7212 or 7231/7232 fixed head disk simulator - Copyright (c) 2007-2008, Robert M Supnik + Copyright (c) 2007-2022, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,8 @@ rad 7211/7212 or 7231/7232 fixed head disk + 02-Jul-2022 RMS Fixed bugs in multi-unit operation + The RAD is a head-per-track disk. To minimize overhead, the entire RAD is buffered in memory. @@ -121,7 +123,7 @@ extern uint32 chan_ctl_time; uint32 rad_disp (uint32 op, uint32 dva, uint32 *dvst); uint32 rad_tio_status (uint32 un); uint32 rad_tdv_status (uint32 un); -t_stat rad_chan_err (uint32 st); +t_stat rad_chan_err (uint32 dva, uint32 st); t_stat rad_svc (UNIT *uptr); t_stat rad_reset (DEVICE *dptr); t_stat rad_settype (UNIT *uptr, int32 val, CONST char *cptr, void *desc); @@ -189,12 +191,17 @@ DEVICE rad_dev = { &rad_dib, DEV_DISABLE }; -/* RAD: IO dispatch routine */ +/* RAD: IO dispatch routine + + For all calls except AIO, dva is the full channel/device/unit address + For AIO, the handler must return the unit number +*/ uint32 rad_disp (uint32 op, uint32 dva, uint32 *dvst) { uint32 i; uint32 un = DVA_GETUNIT (dva); +int32 iu; UNIT *uptr; if ((un >= RAD_NUMDR) || /* inv unit num? */ @@ -219,22 +226,27 @@ switch (op) { /* case on op */ break; case OP_HIO: /* halt I/O */ - chan_clr_chi (rad_dib.dva); /* clr int*/ + chan_clr_chi (dva); /* clr int */ *dvst = rad_tio_status (un); /* get status */ if ((*dvst & DVS_CST) != 0) { /* ctrl busy? */ for (i = 0; i < RAD_NUMDR; i++) { /* find busy unit */ uptr = &rad_unit[i]; if (sim_is_active (uptr)) { /* active? */ sim_cancel (uptr); /* stop */ - chan_uen (rad_dib.dva); /* uend */ + chan_uen (rad_dib.dva | i); /* uend on drive */ } /* end if active */ } /* end for */ } break; case OP_AIO: /* acknowledge int */ - chan_clr_chi (rad_dib.dva); /* clr int */ - *dvst = rad_tdv_status (0); /* status like TDV */ + iu = chan_clr_chi (rad_dib.dva); /* clr int */ + if (iu < 0) { /* no int? */ + *dvst = 0; + return SCPE_IERR; + } + *dvst = rad_tdv_status (iu) | /* status like TDV */ + (iu << DVT_V_UN); /* or in unit */ break; default: @@ -251,18 +263,20 @@ t_stat rad_svc (UNIT *uptr) { uint32 i, sc, da, cmd, wd, wd1, c[4], gp; uint32 *fbuf = (uint32 *) uptr->filebuf; +uint32 un = uptr - rad_unit; +uint32 dva = rad_dib.dva | un; uint32 st; int32 t; switch (rad_cmd) { case RADS_INIT: /* init state */ - st = chan_get_cmd (rad_dib.dva, &cmd); /* get command */ + st = chan_get_cmd (dva, &cmd); /* get command */ if (CHS_IFERR (st)) /* channel error? */ - return rad_chan_err (st); + return rad_chan_err (dva, st); if ((cmd == 0) || /* invalid cmd? */ ((cmd > RADS_CHECK) && (cmd != RADS_RDEES))) { - chan_uen (rad_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_OK; } rad_flags = 0; /* clear status */ @@ -279,9 +293,9 @@ switch (rad_cmd) { return SCPE_OK; case RADS_END: /* end state */ - st = chan_end (rad_dib.dva); /* set channel end */ + st = chan_end (dva); /* set channel end */ if (CHS_IFERR (st)) /* channel error? */ - return rad_chan_err (st); + return rad_chan_err (dva, st); if (st == CHS_CCH) { /* command chain? */ rad_cmd = RADS_INIT; /* restart thread */ sim_activate (uptr, chan_ctl_time); @@ -291,13 +305,13 @@ switch (rad_cmd) { case RADS_SEEK: /* seek */ c[0] = c[1] = 0; for (i = 0, st = 0; (i < 2) && (st != CHS_ZBC); i++) { - st = chan_RdMemB (rad_dib.dva, &c[i]); /* get byte */ + st = chan_RdMemB (dva, &c[i]); /* get byte */ if (CHS_IFERR (st)) /* channel error? */ - return rad_chan_err (st); + return rad_chan_err (dva, st); } rad_ad = ((c[0] & 0x7F) << 8) | c[1]; /* new address */ if (((i != 2) || (st != CHS_ZBC)) && /* length error? */ - chan_set_chf (rad_dib.dva, CHF_LNTE)) /* care? */ + chan_set_chf (dva, CHF_LNTE)) /* care? */ return SCPE_OK; break; @@ -307,12 +321,12 @@ switch (rad_cmd) { c[2] = GET_PSC (rad_time); /* curr sector */ c[3] = 0; for (i = 0, st = 0; (i < rad_tab[rad_model].nbys) && (st != CHS_ZBC); i++) { - st = chan_WrMemB (rad_dib.dva, c[i]); /* store char */ + st = chan_WrMemB (dva, c[i]); /* store char */ if (CHS_IFERR (st)) /* channel error? */ - return rad_chan_err (st); + return rad_chan_err (dva, st); } if (((i != rad_tab[rad_model].nbys) || (st != CHS_ZBC)) && - chan_set_chf (rad_dib.dva, CHF_LNTE)) /* length error? */ + chan_set_chf (dva, CHF_LNTE)) /* length error? */ return SCPE_OK; break; @@ -321,19 +335,19 @@ switch (rad_cmd) { rad_tab[rad_model].tkun; if ((rad_wlk >> gp) & 1) { /* write lock set? */ rad_flags |= RADV_WPE; /* set status */ - chan_uen (rad_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_OK; } /* fall through */ if (rad_inv_ad (&da)) { /* invalid addr? */ - chan_uen (rad_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_OK; } for (i = 0, st = 0; i < RAD_WDSC; da++, i++) { /* write */ if (st != CHS_ZBC) { /* chan active? */ - st = chan_RdMemW (rad_dib.dva, &wd); /* get data */ + st = chan_RdMemW (dva, &wd); /* get data */ if (CHS_IFERR (st)) { /* channel error? */ rad_inc_ad (); /* da increments */ - return rad_chan_err (st); + return rad_chan_err (dva, st); } } else wd = 0; @@ -349,20 +363,20 @@ switch (rad_cmd) { case RADS_CHECK: /* write check */ if (rad_inv_ad (&da)) { /* invalid addr? */ - chan_uen (rad_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_OK; } for (i = 0, st = 0; (i < (RAD_WDSC * 4)) && (st != CHS_ZBC); ) { - st = chan_RdMemB (rad_dib.dva, &wd); /* read sector */ + st = chan_RdMemB (dva, &wd); /* read sector */ if (CHS_IFERR (st)) { /* channel error? */ rad_inc_ad (); /* da increments */ - return rad_chan_err (st); + return rad_chan_err (dva, st); } wd1 = (fbuf[da] >> (24 - ((i % 4) * 8))) & 0xFF; /* byte */ if (wd != wd1) { /* check error? */ rad_inc_ad (); /* da increments */ - chan_set_chf (rad_dib.dva, CHF_XMDE); /* set xmt err flag */ - chan_uen (rad_dib.dva); /* force uend */ + chan_set_chf (dva, CHF_XMDE); /* set xmt err flag */ + chan_uen (dva); /* force uend */ return SCPE_OK; } da = da + ((++i % 4) == 0); /* every 4th byte */ @@ -373,14 +387,14 @@ switch (rad_cmd) { case RADS_READ: /* read */ if (rad_inv_ad (&da)) { /* invalid addr? */ - chan_uen (rad_dib.dva); /* uend */ + chan_uen (dva); /* uend */ return SCPE_OK; } for (i = 0, st = 0; (i < RAD_WDSC) && (st != CHS_ZBC); da++, i++) { - st = chan_WrMemW (rad_dib.dva, fbuf[da]); /* store in mem */ + st = chan_WrMemW (dva, fbuf[da]); /* store in mem */ if (CHS_IFERR (st)) { /* channel error? */ rad_inc_ad (); /* da increments */ - return rad_chan_err (st); + return rad_chan_err (dva, st); } } if (rad_end_sec (uptr, i, RAD_WDSC, st)) /* transfer done? */ @@ -403,15 +417,18 @@ return SCPE_OK; t_bool rad_end_sec (UNIT *uptr, uint32 lnt, uint32 exp, uint32 st) { +uint32 un = uptr - rad_unit; +uint32 dva = rad_dib.dva | un; + if (st != CHS_ZBC) { /* end record? */ if (rad_inc_ad ()) /* inc addr, ovf? */ - chan_uen (rad_dib.dva); /* uend */ + chan_uen (dva); /* uend */ else sim_activate (uptr, rad_time * 16); /* no, next sector */ return TRUE; } rad_inc_ad (); /* just incr addr */ if ((lnt != exp) && /* length error? */ - chan_set_chf (rad_dib.dva, CHF_LNTE)) /* do we care? */ + chan_set_chf (dva, CHF_LNTE)) /* do we care? */ return TRUE; return FALSE; /* cmd done */ } @@ -483,9 +500,9 @@ return FALSE; /* Channel error */ -t_stat rad_chan_err (uint32 st) +t_stat rad_chan_err (uint32 dva, uint32 st) { -chan_uen (rad_dib.dva); /* uend */ +chan_uen (dva); /* uend */ if (st < CHS_ERR) return st; return SCPE_OK;