diff --git a/PDP11/pdp11_io_lib.c b/PDP11/pdp11_io_lib.c index d6ebb6ad..74e4c96f 100644 --- a/PDP11/pdp11_io_lib.c +++ b/PDP11/pdp11_io_lib.c @@ -107,6 +107,7 @@ t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc) { DEVICE *dptr; DIB *dibp; +uint32 radix = DEV_RDX; if (uptr == NULL) return SCPE_IERR; @@ -116,11 +117,25 @@ if (dptr == NULL) dibp = (DIB *) dptr->ctxt; if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) return SCPE_IERR; +if (sim_switches & SWMASK ('H')) + radix = 16; +if (sim_switches & SWMASK ('O')) + radix = 8; fprintf (st, "address="); fprint_val (st, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT); +if (radix != DEV_RDX) { + fprintf (st, "("); + fprint_val (st, (t_value) dibp->ba, radix, 32, PV_LEFT); + fprintf (st, ")"); + } if (dibp->lnt > 1) { fprintf (st, "-"); fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, DEV_RDX, 32, PV_LEFT); + if (radix != DEV_RDX) { + fprintf (st, "("); + fprint_val (st, (t_value) dibp->ba + dibp->lnt - 1, radix, 32, PV_LEFT); + fprintf (st, ")"); + } } if (dibp->ba < IOPAGEBASE + AUTO_CSRBASE + AUTO_CSRMAX) fprintf (st, "*"); @@ -178,7 +193,7 @@ t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) { DEVICE *dptr; DIB *dibp; -uint32 vec, numvec; +uint32 vec, numvec, radix = DEV_RDX; if (uptr == NULL) return SCPE_IERR; @@ -188,6 +203,10 @@ if (dptr == NULL) dibp = (DIB *) dptr->ctxt; if (dibp == NULL) return SCPE_IERR; +if (sim_switches & SWMASK ('H')) + radix = 16; +if (sim_switches & SWMASK ('O')) + radix = 8; vec = dibp->vec; if (arg) numvec = arg; @@ -197,9 +216,19 @@ if (vec == 0) else { fprintf (st, "vector="); fprint_val (st, (t_value) vec, DEV_RDX, 16, PV_LEFT); + if (radix != DEV_RDX) { + fprintf (st, "("); + fprint_val (st, (t_value) vec, radix, 16, PV_LEFT); + fprintf (st, ")"); + } if (numvec > 1) { fprintf (st, "-"); fprint_val (st, (t_value) vec + (4 * (numvec - 1)), DEV_RDX, 16, PV_LEFT); + if (radix != DEV_RDX) { + fprintf (st, "("); + fprint_val (st, (t_value) vec + (4 * (numvec - 1)), radix, 16, PV_LEFT); + fprintf (st, ")"); + } } } if (vec >= VEC_Q + AUTO_VECBASE) @@ -242,12 +271,58 @@ return; t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp) { -int32 i, idx, vec, ilvl, ibit; +int32 i, idx, vec, hivec, ilvl, ibit; +DEVICE *cdptr; +size_t j; +char *cdname; if ((dptr == NULL) || (dibp == NULL)) /* validate args */ return SCPE_IERR; if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; +vec = dibp->vec; +/* hivec & cdhivec are first vector AFTER device */ +hivec = vec + (dibp->vnum * 4 * (dibp->ulnt? dibp->lnt/dibp->ulnt: + (dptr->numunits? dptr->numunits: 1))); +/* Check for vector conflict with any other enabled device. + * Skip vector checks if device (currently) doesn't have a vector assigned. + * Also skip if power-up reset to allow for auto-configure. + */ +if (vec && !(sim_switches & SWMASK ('P'))) { + for (j = 0; vec && (cdptr = sim_devices[j]) != NULL; j++) { + DIB *cdibp = (DIB *)(cdptr->ctxt); + int32 cdvec, cdhivec; + if (!cdibp || (cdptr->flags & DEV_DIS)) { + continue; + } + cdvec = cdibp->vec; + cdhivec = cdvec + (cdibp->vnum * 4 * + (cdibp->ulnt? cdibp->lnt/cdibp->ulnt: + (cdptr->numunits? cdptr->numunits: 1))); + if (cdptr == dptr || !cdvec || !dibp->vnum) { + continue; + } + if (hivec <= cdvec || vec >= cdhivec) { + continue; + } + cdname = cdptr? sim_dname(cdptr): NULL; + if (!cdname) { + cdname = "CPU"; + } + printf ("Device %s interrupt vector conflict with %s at ", + sim_dname (dptr), cdname); + fprint_val (stdout, (t_value) dibp->vec, DEV_RDX, 32, PV_LEFT); + printf ("\n"); + if (sim_log) { + fprintf (sim_log, "Device %s interrupt vector conflict with %s at ", + sim_dname (dptr), cdname); + fprint_val (sim_log, (t_value) dibp->vec, DEV_RDX, 32, PV_LEFT); + fprintf (sim_log, "\n"); + } + return SCPE_STOP; + } + } +/* Interrupt slot assignment and conflict check. */ for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */ idx = dibp->vloc + i; /* vector index */ vec = dibp->vec? (dibp->vec + (i * 4)): 0; /* vector addr */ @@ -269,17 +344,39 @@ for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */ else if (vec) int_vec[ilvl][ibit] = vec; } +/* Register I/O space address and check for conflicts */ for (i = 0; i < (int32) dibp->lnt; i = i + 2) { /* create entries */ idx = ((dibp->ba + i) & IOPAGEMASK) >> 1; /* index into disp */ if ((iodispR[idx] && dibp->rd && /* conflict? */ (iodispR[idx] != dibp->rd)) || (iodispW[idx] && dibp->wr && (iodispW[idx] != dibp->wr))) { - printf ("Device %s address conflict at \n", sim_dname (dptr)); + for (j = 0; (cdptr = sim_devices[j]) != NULL; j++) { /* Find conflicting device */ + DIB *cdibp = (DIB *)(cdptr->ctxt); + if ((cdptr->flags & DEV_DIS) || !cdibp || cdibp == dibp) { + continue; + } + if ((iodispR[idx] && dibp->rd && + (iodispR[idx] != dibp->rd) && + (cdibp->rd == iodispR[idx])) || + (iodispW[idx] && dibp->wr && + (iodispW[idx] != dibp->wr) && + (cdibp->wr == iodispW[idx]))) { + break; + } + } + cdname = cdptr? sim_dname(cdptr): NULL; + if (!cdname) { + cdname = "CPU"; + } + printf ("Device %s address conflict with %s at ", sim_dname (dptr), cdname); fprint_val (stdout, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT); + printf ("\n"); if (sim_log) { - fprintf (sim_log, "Device %s address conflict at \n", sim_dname (dptr)); + fprintf (sim_log, "Device %s address conflict with %s at ", sim_dname (dptr), + cdname); fprint_val (sim_log, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT); + fprintf (sim_log, "\n"); } return SCPE_STOP; } @@ -304,6 +401,12 @@ int32 maxvec, vecwid; int32 brbase = 0; char valbuf[40]; +#if defined DEV_RDX && DEV_RDX == 16 +#define VEC_FMT "X" +#else +#define VEC_FMT "o" +#endif + if (build_dib_tab ()) /* build IO page */ return SCPE_OK; @@ -339,7 +442,7 @@ for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ } /* end if */ } /* end for i */ maxaddr = fprint_val (NULL, (t_value) dibp->ba, DEV_RDX, 32, PV_LEFT); -sprintf (valbuf, "%03o", maxvec); +sprintf (valbuf, "%03" VEC_FMT, maxvec); vecwid = maxvec = (int32) strlen (valbuf); if (vecwid < 3) vecwid = 3; @@ -402,9 +505,11 @@ for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ if (dibp->vec == 0) fprintf (st, "%*s", ((vecwid*2)+1+1), " "); else { - fprintf (st, "%0*o", vecwid, dibp->vec); + fprintf (st, "%0*" VEC_FMT, vecwid, dibp->vec); if (dibp->vnum > 1) - fprintf (st, "-%0*o", vecwid, dibp->vec + (4 * (dibp->vnum - 1))); + fprintf (st, "-%0*" VEC_FMT, vecwid, dibp->vec + (4 * + (dibp->ulnt? dibp->lnt/dibp->ulnt: + (dptr? dptr->numunits: 1)) * dibp->vnum) - 4); else fprintf (st, " %*s", vecwid, " "); fprintf (st, "%1s", (dibp->vnum >= AUTO_VECBASE)? "*": " "); @@ -419,6 +524,7 @@ for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ } /* end if */ } /* end for i */ return SCPE_OK; +#undef VEC_FMT } /* Autoconfiguration @@ -544,10 +650,10 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */ { { NULL }, 1, 3, 0, 8, {015000, 015040, 015100, 015140, }}, /* DV11 */ { { NULL }, 1, 2, 8, 8 }, /* LK11A */ - { { "DMC0", "DMC1", "DMC2", "DMC3" }, + { { "DMC" }, 1, 2, 8, 8 }, /* DMC11 */ { { "DZ" }, 1, 2, 8, 8 }, /* DZ11 */ - { { "KMC" }, 1, 2, 8, 8 }, /* KMC11 */ + { { "KDP" }, 1, 2, 8, 8 }, /* KMC11 */ { { NULL }, 1, 2, 8, 8 }, /* LPP11 */ { { NULL }, 1, 2, 8, 8 }, /* VMV21 */ { { NULL }, 1, 2, 16, 8 }, /* VMV31 */