From 8563ad07df7db3cee8e7f0b2a5f41e234803c157 Mon Sep 17 00:00:00 2001 From: Tony Lawrence Date: Sun, 16 Nov 2025 18:05:45 -0500 Subject: [PATCH] PDP-11: RP-11: Fixing device register read / write consistency 1. Making sure that only expected values appear on the bus when registers are read by CPU; 2. Fix order of I/O cancellation in case of disk detachment with pending I/O; 3. Fix WLOA bug and make protection consistent with documentation; 4. Added more comments. --- PDP11/pdp11_rr.c | 262 +++++++++++++++++++++++++---------------------- 1 file changed, 139 insertions(+), 123 deletions(-) diff --git a/PDP11/pdp11_rr.c b/PDP11/pdp11_rr.c index def47d1f..08ac22b2 100644 --- a/PDP11/pdp11_rr.c +++ b/PDP11/pdp11_rr.c @@ -34,19 +34,22 @@ #include "sim_disk.h" /* const_assert() */ - -#define _Cx(a, b) a ## b -#define _Ax(x) _Cx(_assert, x) -#define _Sx(n) (((n) << 1) - 1) -#define const_assert(c) do { static const char _Ax(__LINE__)[-_Sx(!(c))] \ - = {!(c)}; (void) _Ax(__LINE__); } while (0) +#ifndef NDEBUG +# define _Cx(a, b) a ## b +# define _Ax(x) _Cx(_assert, x) +# define _Sx(n) (((n) << 1) - 1) +# define const_assert(c) do { static const char _Ax(__LINE__)[-_Sx(!(c))] \ + = {!(c)}; (void) _Ax(__LINE__); } while (0) +#else +# define const_assert(c) (void) 0 +#endif /* Constants */ #define RPCONTR uint16 #define RPWRDSZ 16 -#define MAP_RDW(a,c,b) (Map_ReadW (a, (c) << 1, b) >> 1) -#define MAP_WRW(a,c,b) (Map_WriteW(a, (c) << 1, b) >> 1) +#define MAP_RDW(a,c,b) (Map_ReadW ((a), (c) << 1, (b)) >> 1) +#define MAP_WRW(a,c,b) (Map_WriteW((a), (c) << 1, (b)) >> 1) /* RP02/RPR02 parameters; RP03 doubles # of cylinders (both total and spare) */ #define RP_NUMWD 256 /* words/sector */ @@ -93,7 +96,7 @@ /* 12 real UNIBUS registers, so 16 registers total: 32 addresses */ #define RP_IOLN 040 -/* RP(R)02/RP03 particulars (all disks rotated at 2400rpm) */ +/* RP(R)02/RP03(RP02P) particulars (all disks rotated at 2400rpm) */ static struct drv_typ { const char* name; /* device type name */ int32 cyl; /* cylinders */ @@ -103,8 +106,8 @@ static struct drv_typ { int32 seek_ave; /* average seek, 0.1ms */ int32 seek_max; /* maximal seek, 0.1ms */ } drv_tab[] = { - { RP_RP02, RP_NUMCY, RP_NUMBL, RP_SPARE, 200, 500, 800 }, - { RP_RP03, RP_NUMCY*2, RP_NUMBL*2, RP_SPARE*2, 75, 290, 550 } + { RP_RP02, RP_NUMCY, RP_NUMBL, RP_SPARE, 200, 500, 800 }, + { RP_RP03, RP_NUMCY*2, RP_NUMBL*2, RP_SPARE*2, 75, 290, 550 } }; /* RPDS 776710, selected drive status, read-only except for the attention bits */ @@ -129,7 +132,7 @@ static BITFIELD rp_ds_bits[] = { BIT(RDY), ENDBITS }; -#define RPDS_REAL 0017400 /* bits stored */ +#define RPDS_REAL 0017000 /* bits stored */ #define RPDS_DKER (RPDS_HNF | RPDS_INC) /* drive error */ #define RPER_DKER(x) ((x) & RPDS_DKER ? RPER_DRE : 0)/* DRE for RPER */ @@ -185,31 +188,32 @@ static const char* rp_funcs[] = { }; static BITFIELD rp_cs_bits[] = { /* CSR_GO */ /* the GO! bit */ - BIT(GO), + BIT(GO), /* 0000001 */ #define RPCS_V_FUNC 1 #define RPCS_M_FUNC 7 -#define RPCS_FUNC (RPCS_M_FUNC << RPCS_V_FUNC) /* function */ -#define RPCS_RESET 0 -#define RPCS_WRITE 1 -#define RPCS_READ 2 -#define RPCS_WCHK 3 -#define RPCS_SEEK 4 -#define RPCS_WR_NOSEEK 5 -#define RPCS_HOME 6 -#define RPCS_RD_NOSEEK 7 - BITFNAM(FUNC,3,rp_funcs), +#define RPCS_FUNC (RPCS_M_FUNC << RPCS_V_FUNC) /* function: */ +#define RPCS_RESET 0 /* Idle (Reset), i */ +#define RPCS_WRITE 1 /* Write, x */ +#define RPCS_READ 2 /* Read, x */ +#define RPCS_WCHK 3 /* Write Check, x */ +#define RPCS_SEEK 4 /* Seek, i */ +#define RPCS_WR_NOSEEK 5 /* Write (No Seek), x */ +#define RPCS_HOME 6 /* Home Seek, i */ +#define RPCS_RD_NOSEEK 7 /* Read (No Seek), x */ + BITFNAM(FUNC,3,rp_funcs), /* i: Initiate; x: Execute */ + /* 0000016 */ #define RPCS_V_MEX 4 #define RPCS_M_MEX 3 #define RPCS_MEX (RPCS_M_MEX << RPCS_V_MEX) /* memory extension */ - BITF(MEX,2), + BITF(MEX,2), /* 0000060 */ /* CSR_IE */ /* interrupt enable */ - BIT(IE), + BIT(IE), /* 0000100 */ /* CSR_DONE */ /* controller ready */ - BIT(DONE), + BIT(DONE), /* 0000200 */ #define RPCS_V_DRV 8 #define RPCS_M_DRV 7 #define RPCS_DRV (RPCS_M_DRV << RPCS_V_DRV) /* drive id */ - BITFFMT(DRV,3,%u), + BITFFMT(DRV,3,%u),/*0003400 */ #define RPCS_HDR 0004000 /* header operation */ BIT(HDR), #define RPCS_MODE 0010000 /* 0=PDP-11; 1=PDP-10/-15 or format */ @@ -219,7 +223,7 @@ static BITFIELD rp_cs_bits[] = { #define RPCS_HERR 0040000 /* hard error */ BIT(HERR), #define RPCS_ERR CSR_ERR /* error (hard or soft) */ - BIT(ERR), + BIT(ERR), /* 0100000 */ #define RPCS_REAL 0037776 /* bits kept here */ #define RPCS_RW 0037576 /* read/write */ #define GET_FUNC(x) (((x) & RPCS_FUNC) >> RPCS_V_FUNC) @@ -230,49 +234,48 @@ static BITFIELD rp_cs_bits[] = { /* RPWC 776716, two's complement word count */ /* For PDP-11 must be even for data, and in multiples of 3 for format */ static BITFIELD rp_wc_bits[] = { -#define RPWC_IMP 0177777 /* implemented */ BITFFMT(WC,16,%u), +#define RPWC_IMP 0177777 /* implemented */ ENDBITS }; /* RPBA 776720, bus address */ static BITFIELD rp_ba_bits[] = { -#define RPBA_IMP 0177776 /* implemented */ BITF(BA,16), +#define RPBA_IMP 0177776 /* implemented */ ENDBITS }; /* RPCA 776722, cylinder address */ static BITFIELD rp_ca_bits[] = { -#define RPCA_IMP 0177777 /* implemented */ -#define RPCA_RW 0000777 /* RP11: 0377 */ BITFFMT(CYL,9,%u), +#define RPCA_RW 0000777 /* RP11: 0377 */ ENDBITS }; static BITFIELD rp_ca11_bits[] = { /* RP11 version */ #define RPCA_M_CYL 0000377 BITFFMT(CYL,8,%u), #define RPCA_V_SUCA 8 -#define RPCA_M_SUCA 0000377 -#define RPCA_SUCA (RPCA_M_SUCA << RPCA_V_SUCA) - BITFFMT(SUCA,8,%u), +#define RPCA_SUCA (RPCA_M_CYL << RPCA_V_SUCA) + BITFFMT(SUCA,8,%u),/*177400*/ +#define RPCA_IMP 0177777 /* implemented */ ENDBITS }; /* RPDA 776724, disk address (track/sector) */ static BITFIELD rp_da_bits[] = { -#define RPDA_IMP 0017777 /* implemented */ -#define RPDA_RW 0017417 /* bits here */ #define RPDA_M_SECT 017 #define RPDA_SECT RPDA_M_SECT /* sector */ - BITFFMT(SECT,4,%u), + BITFFMT(SECT,4,%u),/*000017*/ #define RPDA_V_SOT 4 #define RPDA_SOT (RPDA_M_SECT << RPDA_V_SOT) /* current sect on track */ - BITFFMT(SOT,4,%u), + BITFFMT(SOT,4,%u), /*000360*/ #define RPDA_V_TRACK 8 #define RPDA_M_TRACK 037 #define RPDA_TRACK (RPDA_M_TRACK << RPDA_V_TRACK) /* track */ - BITFFMT(SURF,5,%u), + BITFFMT(SURF,5,%u),/*017400*/ +#define RPDA_RW 0017417 /* read/write */ +#define RPDA_IMP 0017777 /* implemented */ #define GET_SECT(x) ((x) & RPDA_SECT) #define GET_TRACK(x) (((x) & RPDA_TRACK) >> RPDA_V_TRACK) ENDBITS @@ -286,8 +289,8 @@ static BITFIELD rp_da_bits[] = { /* SUCA 776734 selected unit cylinder address, read-only */ static BITFIELD rp_suca_bits[] = { -#define SUCA_IMP 0000777 /* RP11: 0377 */ BITFFMT(CYL,9,%u), /* RP11: RPCA<15:08> */ +#define SUCA_IMP 0000777 /* RP11: 0377 */ ENDBITS }; @@ -296,19 +299,17 @@ static BITFIELD rp_suca_bits[] = { /* Maintenance Write Lockout Address (LOA) (the switches on the maint. panel) */ static const char* offon[] = { "OFF", "ON" }; static BITFIELD rp_wloa_bits[] = { -#define RPWLOA_IMP 03777 -#define RPWLOA_CYL 0377 /* cyls locked */ +#define RPWLOA_CYL 0000377 /* cyls locked */ BITFFMT(CYL,8,%u), #define RPWLOA_V_DRV 8 #define RPWLOA_M_DRV 7 #define RPWLOA_DRV (RPWLOA_M_DRV << RPWLOA_V_DRV) /* drives locked */ - BITFFMT(DRV,3,%u), -#define GET_WLOACYL(x) (rr_dev.flags & DEV_RP11CE \ - ? (((x) & RPWLOA_CYL) << 1) | 1 /* x2 + 1 */ \ - : ((x) & RPWLOA_CYL)) -#define GET_WLOADRV(x) (((x) & RPWLOA_DRV) >> RPWLOA_V_DRV) + BITFFMT(DRV,3,%u),/*0003400*/ +#define RPWLOA_IMP 0003777 /* implemented */ +#define GET_WLOA(n, c) (((n) << RPWLOA_V_DRV) | \ + (rr_dev.flags & DEV_RP11CE ? (c) >> 1 : (c))) BITNCF(4), -#define RPWLOA_ON 0100000 +#define RPWLOA_ON 0100000 /* sw on/off switch */ BITFNAM(PROTECT,1,offon), ENDBITS }; @@ -583,7 +584,7 @@ static t_stat rr_rd (int32 *data, int32 PA, int32 access) rpds &= RPDS_ATTN; /* attention bits */ if (!(uptr->flags & UNIT_DIS)) { /* not disabled? */ rpds |= RPDS_ONLN; - if (GET_DTYPE(uptr->flags)) + if (GET_DTYPE(uptr->flags)) /* RP03? */ rpds |= RPDS_RP03; if (uptr->flags & UNIT_ATT) { /* attached? */ rpds |= uptr->STATUS & RPDS_REAL; @@ -609,28 +610,29 @@ static t_stat rr_rd (int32 *data, int32 PA, int32 access) break; case 3: /* RPWC */ - *data = rpwc; + *data = rpwc & RPWC_IMP; break; case 4: /* RPBA */ - *data = rpba; + *data = rpba & RPBA_IMP; break; case 5: /* RPCA */ - *data = rpca; - if (!(rr_dev.flags & DEV_RP11CE)) { - assert(!(suca & ~RPCA_M_SUCA)); - *data |= suca << RPCA_V_SUCA; - bits = rp_ca11_bits; - } + const_assert(RPCA_M_CYL == (RPCA_RW >> 1)); + if (!(rr_dev.flags & DEV_RP11CE)) { /* RP11? */ + *data = (suca << RPCA_V_SUCA) | (rpca & RPCA_M_CYL); + bits = rp_ca11_bits; /* RP11 */ + } else + *data = rpca & RPCA_RW; break; case 6: /* RPDA */ - rpda &= RPDA_RW; uptr = rr_dev.units + GET_DRIVE(rpcs); - if (uptr->flags & UNIT_ATT) + if (uptr->flags & UNIT_ATT) { + rpda &= ~RPDA_SOT; rpda |= (rand() % RP_NUMSC) << RPDA_V_SOT; /* inject a random sect */ - *data = rpda; + } + *data = rpda & RPDA_IMP; break; case 10: /* SUCA */ @@ -657,6 +659,7 @@ static t_stat rr_wr (int32 data, int32 PA, int32 access) int32 n, oval = rn < 0 ? 0 : *rr_regs[rn].valp; int16 func; + assert(rn < (int32)(sizeof(rr_regs)/sizeof(rr_regs[0]))); if (access == WRITEB && 2 <= rn && rn <= 6) data = RR_DATOB(oval, data); switch (rn) { @@ -685,7 +688,7 @@ static t_stat rr_wr (int32 data, int32 PA, int32 access) sim_debug(RRDEB_INT, &rr_dev, "rr_wr(CSR:CLR_INT)\n"); CLR_INT(RR); /* clr int request */ } - rpcs &= ~RPCS_RW; + rpcs &= ~(RPCS_RW | CSR_GO); rpcs |= data & RPCS_RW; n = GET_DRIVE(rpcs); /* get drive no */ if (n != GET_DRIVE(oval)) { @@ -713,11 +716,12 @@ static t_stat rr_wr (int32 data, int32 PA, int32 access) break; case 5: /* RPCA */ - const_assert(RPCA_M_CYL == (RPCA_RW >> 1)); + const_assert((RPCA_RW >> 1) == RPCA_M_CYL); rpca = data & (rr_dev.flags & DEV_RP11CE ? RPCA_RW : RPCA_M_CYL); break; case 6: /* RPDA */ + rpda &= RPDA_IMP; rpda &= ~RPDA_RW; rpda |= data & RPDA_RW; break; @@ -792,7 +796,7 @@ static void rr_go (int16 func) uptr = rr_dev.units + i; /* selected unit */ assert(uptr->action == rr_svc); assert(uptr->SEEKING || !uptr->FUNC); /* SEEK underway or idle */ - uptr->STATUS &= ~(RPDS_DKER | RPDS_WLK); /* clear drive errors */ + uptr->STATUS &= ~RPDS_DKER; /* clear drive errors */ if (!(uptr->flags & UNIT_ATT)) { /* not attached? */ rr_set_done(RPER_PGE); /* unit offline */ @@ -821,30 +825,31 @@ static void rr_go (int16 func) rd = func == RPCS_READ || func == RPCS_RD_NOSEEK || func == RPCS_WCHK; wr = func == RPCS_WRITE || func == RPCS_WR_NOSEEK; + if (wr && (uptr->flags & UNIT_WPRT)) /* write and locked? */ + rper |= RPER_WPV; + + type = GET_DTYPE(uptr->flags); /* get drive type */ + + if (func == RPCS_HOME) { + cyl = 0; + head = 0; + } else if (func == RPCS_RD_NOSEEK || func == RPCS_WR_NOSEEK) { + cyl = uptr->CYL; + head = uptr->HEAD; + assert(head < RP_NUMSF && cyl < drv_tab[type].cyl); + } else { + cyl = rpca; + head = GET_TRACK(rpda); + if (cyl >= drv_tab[type].cyl) /* bad cyl? */ + rper |= RPER_NXC; + if (head >= RP_NUMSF) /* bad head? */ + rper |= RPER_NXT; + } if (rd | wr) { int32 sect = GET_SECT(rpda); /* get sect */ if (sect >= RP_NUMSC) /* sect out of range? */ rper |= RPER_NXS; } - type = GET_DTYPE(uptr->flags); /* get drive type */ - if (func == RPCS_HOME) { - head = 0; - cyl = 0; - } else if (func == RPCS_RD_NOSEEK || func == RPCS_WR_NOSEEK) { - head = uptr->HEAD; - cyl = uptr->CYL; - assert(uptr->CYL < drv_tab[type].cyl && uptr->HEAD < RP_NUMSF); - } else { - head = GET_TRACK(rpda); - cyl = rpca; - if (head >= RP_NUMSF) /* bad head? */ - rper |= RPER_NXT; - if (cyl >= drv_tab[type].cyl) /* bad cyl? */ - rper |= RPER_NXC; - } - - if (wr && (uptr->flags & UNIT_WPRT)) /* write and locked? */ - rper |= RPER_WPV; if (rper) { /* any errors? */ rr_set_done(0); /* set done (w/errors) */ @@ -881,7 +886,7 @@ static void rr_go (int16 func) * just prior to when the test clears it. Thus, the test is unable to * confirm the interrupt for all remaining cylinders. ZRPB-E fixes both * bugs by initializing INTFLG before firing up SEEK/AIE, and also by - * using the more correct "MOVB @#RPDS, @#RPDS", instead of BIC. */ + * using a more correct "MOVB @#RPDS, @#RPDS", instead of the BIC. */ } else { if (cyl != uptr->CYL || head != uptr->HEAD) { assert(func != RPCS_RD_NOSEEK && func != RPCS_WR_NOSEEK); @@ -889,7 +894,7 @@ static void rr_go (int16 func) } i += RP_ROT_12; /* I/O takes longer */ assert(i); - /* XXDP ZRPB-E / ZRPF-B have two data race conditions in Test 5 (data + /* XXDP ZRPF-B / ZRPB-E have two data race conditions in Test 5 (data * reliability), which in ZRPB-E can be worked around with the following * multiplier for all 15 steady patterns, but it does not help eliminate * the second race in the last (random) pattern test, despite showing no @@ -904,7 +909,7 @@ static void rr_go (int16 func) assert(suca == uptr->CYL); /* actually */ uptr->FUNC = func; /* save new func */ uptr->HEAD = head; /* save head too */ - uptr->CYL = cyl; /* put on cylinder */ + uptr->CYL = cyl; /* put on cylinder */ suca += n >> 2; /* show motion */ return; } @@ -958,7 +963,7 @@ static t_stat rr_svc (UNIT *uptr) assert(0 < func && func < sizeof(rp_funcs)/sizeof(rp_funcs[0])); assert(!uptr->SEEKING && !(uptr->STATUS & RPDS_SEEK)); if (func == RPCS_HOME || func == RPCS_SEEK) - return SCPE_OK; /* all done */ + return SCPE_OK; /* all done with seeks! */ assert(~(rpcs & CSR_DONE)); @@ -975,20 +980,17 @@ static t_stat rr_svc (UNIT *uptr) n = (int32)(uptr - rr_dev.units); /* get drive no */ + cyl = uptr->CYL; + if (wr /* write and ... */ + && (((wloa & RPWLOA_ON) && + GET_WLOA(n, cyl) <= (wloa & RPWLOA_IMP)) /* DA write-protected? */ + || (uptr->flags & UNIT_WPRT))) { /* unit write-locked? */ + rper |= RPER_WPV; + } + head = uptr->HEAD; sect = GET_SECT(rpda); /* get sect */ if (sect >= RP_NUMSC) /* sect out of range? */ rper |= RPER_NXS; - head = uptr->HEAD; - cyl = uptr->CYL; - - if (wr) { - if ((wloa & RPWLOA_ON) && !rper/*valid DA*/ - && (n <= GET_WLOADRV(wloa) || cyl <= GET_WLOACYL(wloa))) { - uptr->STATUS |= RPDS_WLK; /* DA write-locked */ - rper |= RPER_WPV; - } else if (uptr->flags & UNIT_WPRT) - rper |= RPER_WPV; /* unit write-locked */ - } if (rper) { /* control in error? */ rr_set_done(0); @@ -1011,14 +1013,14 @@ static t_stat rr_svc (UNIT *uptr) else if ((!wr && wc != 3) || (wr && wc % 3)) /* DEC-11-HRPCA-C-D 3.8 */ rper |= RPER_PGE; else if (wr) - n *= 3; /* 3 wds per sector */ - else /* a typo in doc??? */ - n = 3; /* can only read 3 wds */ + n *= 3; /* 3 wds of HDR per sector */ + else + n = 3; /* can only read 3 wds of HDR */ } else { /* no: regular R/W */ /* RP11 can actually handle the PDP-10/-15 (18b) mode on PDP-11 using 3 - * words per transfer, combined as two 18b words in a disk sector (for - * the bit assignments in the triplet, see rr_svc() for format reading). - * However, a sector written in this mode is marked as such and cannot be + * words per transfer, combined as two 18b words on a disk sector (for + * bit assignments in the triplet, see below BR<35:0> in format reading). + * However, a sector written in 18b mode is marked as such and cannot be * read back in the PDP-11 (16b) mode (but only in the 18b mode). Since * the disk containers do not have sector format information, this mode * cannot be supported (and for all intents and purposes it's not needed @@ -1067,8 +1069,10 @@ static t_stat rr_svc (UNIT *uptr) if (!wr) { /* read: */ if (rpcs & RPCS_HDR) { /* format? */ + assert(wc <= 3); /* Sector header is loaded in the 36-bit Buffer Register(BR): - 17 0-bits, 9-bit cyl, 5-bit track, a spare bit, 4-bit sect */ + 17 0-bits, 9-bit cyl, 5-bit track, a spare bit, 4-bit sect; + which is then split into 3 PDP-11 (16b) words as following */ rpxb[0] = 0; /* BR<35:20> */ rpxb[1] = (cyl << 6) | (head << 1); /* BR<19:04> */ rpxb[2] = sect; /* BR<03:00> */ @@ -1082,7 +1086,7 @@ static t_stat rr_svc (UNIT *uptr) sim_disk_data_trace(uptr, (uint8*) rpxb, da, n * sizeof(*rpxb), "rr_read", RRDEB_DAT & (dptr->dctrl | uptr->dctrl), RRDEB_OPS); assert(done <= todo); - if (done >= todo) + if (done >= todo) /* NB: done == todo */ ioerr = 0; /* good stuff */ else if (ioerr) wc = n; /* short, adj wd cnt */ @@ -1125,6 +1129,7 @@ static t_stat rr_svc (UNIT *uptr) if (wc && !(rpcs & RPCS_HDR)) { /* regular write? */ DEVICE* dptr = find_dev_from_unit(uptr); int32 m = (wc + (RP_NUMWD - 1)) & ~(RP_NUMWD - 1); /* clr to... */ + assert(m <= RP_MAXFR); memset(rpxb + wc, 0, (m - wc) * sizeof(*rpxb)); /* ...end of sect */ sim_disk_data_trace(uptr, (uint8*) rpxb, da, m * sizeof(*rpxb), "rr_write", RRDEB_DAT & (dptr->dctrl | uptr->dctrl), RRDEB_OPS); @@ -1145,7 +1150,7 @@ static t_stat rr_svc (UNIT *uptr) ioerr = 0; /* good stuff */ } else { ioerr = 0; /* good stuff */ - done = wc / 3; + done = (wc + 2) / 3; if (n) rper |= RPER_NXM; /* NXM? set flg */ } @@ -1284,7 +1289,7 @@ static t_stat rr_reset (DEVICE *dptr) sim_debug(RRDEB_INT, dptr, "rr_reset(CLR_INT)\n"); CLR_INT(RR); if (rpxb == NULL) - rpxb = (RPCONTR*) calloc(RP_MAXFR, sizeof (*rpxb)); + rpxb = (RPCONTR*) calloc(RP_MAXFR, sizeof(*rpxb)); if (rpxb == NULL) return SCPE_MEM; return auto_config(NULL, 0); @@ -1309,19 +1314,20 @@ static t_stat rr_attach (UNIT *uptr, CONST char *cptr) static t_stat rr_detach (UNIT *uptr) { - int16 func = uptr->FUNC; + int16 func; + sim_cancel(uptr); + func = uptr->FUNC; rr_seek_done(uptr, 1/*cancel*/); - if (func) { + if (func) { /* anything unfinished? */ uptr->FUNC = 0; /* idle now */ - sim_cancel(uptr); if (func == RPCS_SEEK) uptr->STATUS |= RPDS_INC; /* seek incomplete */ else if (func != RPCS_HOME) { uptr->STATUS |= RPDS_HNF; /* sector not found */ - rr_set_done(RPER_TE); + rr_set_done(RPER_TE); /* ...and timing error */ } + uptr->STATUS |= RPDS_UNSAFE; /* must reset before use */ } - uptr->STATUS |= RPDS_UNSAFE; /* must reset before use */ assert(!sim_is_active(uptr)); assert(!uptr->SEEKING); uptr->action = rr_svc; @@ -1396,7 +1402,7 @@ static t_stat rr_set_wloa (UNIT *uptr, int32 val, CONST char *cptr, void *desc) #define BOOT_ENTRY (BOOT_START + 002) /* entry */ #define BOOT_UNIT (BOOT_START + 010) /* unit number */ #define BOOT_CSR (BOOT_START + 014) /* CSR + 12 */ -#define BOOT_LEN (sizeof (rr_boot_rom) / sizeof (rr_boot_rom[0])) +#define BOOT_LEN (sizeof(rr_boot_rom)/sizeof(rr_boot_rom[0])) static const uint16 rr_boot_rom[] = { /* EXPECTED M9312 REGISTER USE FOR BOOT PROMS (IN THE BOOTED SOFTWARE): * @@ -1462,7 +1468,7 @@ static t_stat rr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const cha "In default configuration " RP_RP11 " responds to the range 17776700 - 17776736\n" "with the first 4 word locations not occupied by any device registers (and\n" "so 17776710 is the first used location). Some operating systems want you\n" - "to specify the extended range (e.g. RSTS/E), but some -- the relevant range\n" + "to specify the extended range (e.g. RSTS), but some -- the relevant range\n" "(17776710 - 17776736), yet some just want to know where the CSR is located\n" "(17776714 by default), so they can auto-calculate the range on their own.\n\n" "Disk drive parameters (all decimal):\n\n" @@ -1481,13 +1487,23 @@ static t_stat rr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const cha } fputs("\n" "The implementation does not include any maintenance registers or disk/sector\n" - "formatting operations yet supports the Write Lockout Address (LOA) register,\n" - "which can be set with a PROTECT command:\n\n" - " sim> set RR PROTECT=ON;0407\n\n" - "to turn the protection on (in this case, the entire units 0 and 1, and\n", st); - fprintf(st, "cylinders 0 thru 7%s in unit 2 will become write-locked).\n", + "formatting operations yet supports the Write Lockout Address (LOA) register.\n" + "It can be set with the PROTECT command using the keyword \"ON\" followed by a\n" + "value representing the number of continuously protected drives and cylinders:\n" + " bits <10:8> represent the highest protected unit number;\n" + " bits <07:0> encode the last protected cylinder on the unit number specified\n" + "above (all units preceding that unit become fully write-protected).\n" + "For example,\n\n" + " sim> set RR PROTECT=ON;0407\n\n", st); + fprintf(st, + "write-protects the entire drive unit 0 and cylinders 0 thru 7%s\n", dptr->flags & DEV_RP11CE ? " x 2 + 1 = 15(10)" : ""); fputs( + "on drive unit 1. The value is accepted in either decimal, octal (if it starts\n" + "with 0), or hexadecimal (if it starts with 0x) notation (so \"0x107\" in the\n" + "above example effects the same setting). Alternatively, a deposit command\n" + "can be used, but it only allows native (octal) values:\n\n" + " sim> deposit RR WLOA 100407\n\n" "The current setting can be obtained by examining the WLOA register in\n" "the device (the sign bit not present in hardware controls the feature):\n\n" " sim> examine RR WLOA\n" @@ -1496,8 +1512,8 @@ static t_stat rr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const cha " sim> set RR PROTECT=OFF\n" " sim> examine RR WLOA\n" " WLOA: 000407 PROTECT=OFF DRV=1 CYL=7\n\n" - "Note that it does not clear the address but turns the feature off. Also,\n" - "the WLOA register is unaffected by the device RESET.\n", st); + "Note that it does not clear the address but turns the feature off.\n" + "The WLOA register is unaffected by the device RESET.\n", st); fprint_set_help (st, dptr); fprint_show_help(st, dptr); fprintf(st, @@ -1549,5 +1565,5 @@ static t_stat rr_show_ctrl (FILE *st, UNIT *uptr, int32 val, CONST void *desc) } #elif !defined(UC15) -#error "RP11/-C/-E can only be used in PDP-11 configuration" +# error "RP11/-C/-E can only be used in PDP-11 configuration" #endif /*VM_PDP11 && !UC15*/