From ed57f061e2f0f2362de51f1533424946623da6b8 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Thu, 8 Oct 2015 04:43:21 -0700 Subject: [PATCH] All VAX: Always return the correct Qbus/Unibus interrupt vector bits for all devices. Fix #239 Vector values contained in device information blocks are the true bus relative vector values. CPU specific biased vector values are produced by the respective vector fetching logic and vector values are limited to 9 bits with <1:0> = 0 as specified in both the Unibus and Qbus documents. --- PDP10/pdp10_defs.h | 1 - PDP10/pdp10_ksio.c | 10 ++--- PDP11/pdp11_defs.h | 2 - PDP11/pdp11_io.c | 3 +- PDP11/pdp11_io_lib.c | 89 +++++++++++++++++++++++++++++++++++++++----- PDP11/pdp11_rq.c | 2 - PDP11/pdp11_tq.c | 2 - PDP11/pdp11_xq.c | 4 +- VAX/vax610_defs.h | 2 +- VAX/vax610_io.c | 13 ++++++- VAX/vax630_defs.h | 2 +- VAX/vax630_io.c | 13 ++++++- VAX/vax730_defs.h | 4 +- VAX/vax730_sys.c | 2 +- VAX/vax730_uba.c | 13 +++++-- VAX/vax750_defs.h | 5 ++- VAX/vax750_uba.c | 18 ++++++--- VAX/vax780_defs.h | 4 +- VAX/vax780_uba.c | 5 ++- VAX/vax860_defs.h | 4 +- VAX/vax_cpu1.c | 10 +++-- VAX/vax_io.c | 13 ++++++- VAX/vax_vc.c | 12 +++++- VAX/vaxmod_defs.h | 2 +- 24 files changed, 176 insertions(+), 59 deletions(-) diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h index 907f5cba..d30a8808 100644 --- a/PDP10/pdp10_defs.h +++ b/PDP10/pdp10_defs.h @@ -751,7 +751,6 @@ typedef struct pdp_dib DIB; #define INT_IPL5 0x000FFF00 #define INT_IPL4 0x7FF00000 -#define VEC_Q 0000 /* vector base */ #define VEC_TU 0224 /* interrupt vectors */ #define VEC_RP 0254 #define VEC_LP20 0754 diff --git a/PDP10/pdp10_ksio.c b/PDP10/pdp10_ksio.c index 2c1d51cf..7066cf1c 100644 --- a/PDP10/pdp10_ksio.c +++ b/PDP10/pdp10_ksio.c @@ -1773,9 +1773,9 @@ if (dptr == NULL) dibp = (DIB *) dptr->ctxt; if (dibp == NULL) return SCPE_IERR; -newvec = (uint32) get_uint (cptr, 8, VEC_Q + 01000, &r); -if ((r != SCPE_OK) || (newvec == VEC_Q) || - ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || +newvec = (uint32) get_uint (cptr, 8, 01000, &r); +if ((r != SCPE_OK) || + ((newvec + (dibp->vnum * 4)) >= (01000)) || (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; dibp->vec = newvec; @@ -2217,7 +2217,7 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */ t_stat auto_config (const char *name, int32 nctrl) { uint32 csr = IOPAGEBASE + AUTO_CSRBASE; -uint32 vec = VEC_Q + AUTO_VECBASE; +uint32 vec = AUTO_VECBASE; AUTO_CON *autp; DEVICE *dptr; DIB *dibp; @@ -2260,7 +2260,7 @@ for (autp = auto_tab; autp->numc >= 0; autp++) { /* loop thru table */ if (autp->numv) { /* vec needed? */ if (autp->fixv[j]) { /* fixed vec avail? */ if (autp->numv > 0) - dibp->vec = VEC_Q + autp->fixv[j]; /* use it */ + dibp->vec = autp->fixv[j]; /* use it */ } else { /* no fixed left */ uint32 numv = abs (autp->numv); /* get num vec */ diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h index 49eed930..d19f4ac5 100644 --- a/PDP11/pdp11_defs.h +++ b/PDP11/pdp11_defs.h @@ -765,8 +765,6 @@ typedef struct pdp_dib DIB; #define VEC_AUTO (0) /* Assigned by Auto Configure */ #define VEC_FLOAT (0) /* Assigned by Auto Configure */ -#define VEC_Q 0000 /* vector base */ - /* Processor specific internal fixed vectors */ #define VEC_PIRQ 0240 #define VEC_TTI 0060 diff --git a/PDP11/pdp11_io.c b/PDP11/pdp11_io.c index 612bb68d..41dd2ea0 100644 --- a/PDP11/pdp11_io.c +++ b/PDP11/pdp11_io.c @@ -157,7 +157,8 @@ for (i = IPL_HLVL - 1; i > nipl; i--) { /* loop thru lvls */ int_req[i] = int_req[i] & ~(1u << j); /* clr irq */ if (int_ack[i][j]) vec = int_ack[i][j](); - else vec = int_vec[i][j]; + else + vec = int_vec[i][j]; return vec; /* return vector */ } /* end if t */ } /* end for j */ diff --git a/PDP11/pdp11_io_lib.c b/PDP11/pdp11_io_lib.c index 757759f1..13249cb0 100644 --- a/PDP11/pdp11_io_lib.c +++ b/PDP11/pdp11_io_lib.c @@ -39,6 +39,12 @@ extern int32 autcon_enb; extern int32 int_vec[IPL_HLVL][32]; +#if !defined(VEC_SET) +#define VEC_SET 0 +#endif +#if (VEC_SET != 0) +extern int32 int_vec_set[IPL_HLVL][32]; /* bits to set in vector */ +#endif extern int32 (*int_ack[IPL_HLVL][32])(void); extern t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md); extern t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md); @@ -47,6 +53,8 @@ extern t_stat build_dib_tab (void); static DIB *iodibp[IOPAGESIZE >> 1]; +static void build_vector_tab (void); + #if !defined(UNIMEMSIZE) #define UNIMEMSIZE 001000000 /* 2**18 */ #endif @@ -181,10 +189,10 @@ if (dptr == NULL) dibp = (DIB *) dptr->ctxt; if (dibp == NULL) return SCPE_IERR; -newvec = (uint32) get_uint (cptr, DEV_RDX, VEC_Q + 01000, &r); -if ((r != SCPE_OK) || (newvec == VEC_Q) || - ((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) || - (newvec & ((dibp->vnum > 1)? 07: 03))) +newvec = (uint32) get_uint (cptr, DEV_RDX, 01000, &r); +if ((r != SCPE_OK) || + ((newvec + (dibp->vnum * 4)) >= 01000) || /* total too big? */ + (newvec & ((dibp->vnum > 1)? 07: 03))) /* properly aligned value? */ return SCPE_ARG; dibp->vec = newvec; autcon_enb = 0; /* autoconfig off */ @@ -214,10 +222,15 @@ if (sim_switches & SWMASK ('O')) vec = dibp->vec; if (arg) numvec = arg; -else numvec = dibp->vnum; +else + numvec = dibp->vnum; if (vec == 0) fprintf (st, "no vector"); else { +#if (VEC_SET != 0) + vec |= (int_vec_set[dibp->vloc / 32][dibp->vloc % 32] & ~3); + vec &= (int_vec_set[dibp->vloc / 32][dibp->vloc % 32] | 0x1FF); +#endif fprintf (st, "vector="); fprint_val (st, (t_value) vec, DEV_RDX, 16, PV_LEFT); if (radix != DEV_RDX) { @@ -235,7 +248,7 @@ else { } } } -if (vec >= VEC_Q + AUTO_VECBASE) +if (vec >= ((VEC_SET | AUTO_VECBASE) & ~3)) fprintf (st, "*"); return SCPE_OK; } @@ -257,6 +270,7 @@ void init_ubus_tab (void) { size_t i, j; +build_vector_tab (); for (i = 0; i < IPL_HLVL; i++) { /* clear intr tab */ for (j = 0; j < 32; j++) { int_vec[i][j] = 0; @@ -285,6 +299,12 @@ if ((dptr == NULL) || (dibp == NULL)) /* validate args */ if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; vec = dibp->vec; +ilvl = dibp->vloc / 32; +ibit = dibp->vloc % 32; +#if (VEC_SET != 0) +if (vec) + vec |= (int_vec_set[ilvl][ibit] & ~3); +#endif /* hivec & cdhivec are first vector AFTER device */ hivec = vec + (dibp->vnum * 4 * (dibp->ulnt? dibp->lnt/dibp->ulnt: (dptr->numunits? dptr->numunits: 1))); @@ -296,10 +316,17 @@ 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; + ilvl = cdibp->vloc / 32; + ibit = cdibp->vloc % 32; +#if (VEC_SET != 0) + if (cdvec) + cdvec |= (int_vec_set[ilvl][ibit] & ~3); +#endif cdhivec = cdvec + (cdibp->vnum * 4 * (cdibp->ulnt? cdibp->lnt/cdibp->ulnt: (cdptr->numunits? cdptr->numunits: 1))); @@ -326,6 +353,10 @@ for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */ vec = dibp->vec? (dibp->vec + (i * 4)): 0; /* vector addr */ ilvl = idx / 32; ibit = idx % 32; +#if (VEC_SET != 0) + if (vec) + vec |= (int_vec_set[ilvl][ibit] & ~3); +#endif if ((int_ack[ilvl][ibit] && dibp->ack[i] && /* conflict? */ (int_ack[ilvl][ibit] != dibp->ack[i])) || (int_vec[ilvl][ibit] && vec && @@ -336,8 +367,10 @@ for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */ } if (dibp->ack[i]) int_ack[ilvl][ibit] = dibp->ack[i]; - else if (vec) - int_vec[ilvl][ibit] = 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 */ @@ -750,10 +783,44 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */ #define DEV_NEXUS 0 #endif #endif + +static void build_vector_tab (void) +{ +int32 ilvl, ibit; +static t_bool done = FALSE; +AUTO_CON *autp; +DEVICE *dptr; +DIB *dibp; +uint32 j, k; + +if (done) + return; +/* Locate all Unibus/Qbus devices and make sure vector masks are set */ +for (j = 0; (dptr = sim_devices[j]) != NULL; j++) { + if ((dptr->flags & (DEV_UBUS | DEV_QBUS)) == 0) + continue; + for (autp = auto_tab; autp->numc >= 0; autp++) { + for (k=0; autp->dnam[k]; k++) { + if (!strcmp(dptr->name, autp->dnam[k])) { + dibp = (DIB *)dptr->ctxt; + ilvl = dibp->vloc / 32; + ibit = dibp->vloc % 32; +#if (VEC_SET != 0) + int_vec_set[ilvl][ibit] = VEC_SET; +#endif + break; + } + } + } + } +done = TRUE; +} + t_stat auto_config (const char *name, int32 nctrl) { uint32 csr = IOPAGEBASE + AUTO_CSRBASE; -uint32 vec = VEC_Q + AUTO_VECBASE; +uint32 vec = AUTO_VECBASE; +int32 ilvl, ibit; extern UNIT cpu_unit; AUTO_CON *autp; DEVICE *dptr; @@ -803,6 +870,8 @@ for (autp = auto_tab; autp->numc >= 0; autp++) { /* loop thru table */ dibp = (DIB *) dptr->ctxt; /* get DIB */ if (dibp == NULL) /* not there??? */ return SCPE_IERR; + ilvl = dibp->vloc / 32; + ibit = dibp->vloc % 32; if (autp->fixa[j]) /* fixed csr avail? */ dibp->ba = IOPAGEBASE + autp->fixa[j]; /* use it */ else { /* no fixed left */ @@ -812,7 +881,7 @@ for (autp = auto_tab; autp->numc >= 0; autp++) { /* loop thru table */ if (autp->numv) { /* vec needed? */ if (autp->fixv[j]) { /* fixed vec avail? */ if (autp->numv > 0) - dibp->vec = VEC_Q + autp->fixv[j]; /* use it */ + dibp->vec = autp->fixv[j]; /* use it */ } else { /* no fixed left */ uint32 numv = abs (autp->numv); /* get num vec */ diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c index fbf77d9b..e1cafa69 100644 --- a/PDP11/pdp11_rq.c +++ b/PDP11/pdp11_rq.c @@ -1465,8 +1465,6 @@ if (cp->csta < CST_UP) { /* still init? */ else { cp->s1dat = cp->saw; /* save data */ dibp->vec = (cp->s1dat & SA_S1H_VEC) << 2; /* get vector */ - if (dibp->vec) /* if nz, bias */ - dibp->vec = dibp->vec + VEC_Q; cp->sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (cp->s1dat); cp->csta = CST_S2; /* now in step 2 */ rq_init_int (cp); /* intr if req */ diff --git a/PDP11/pdp11_tq.c b/PDP11/pdp11_tq.c index d4b6e391..b38e6513 100644 --- a/PDP11/pdp11_tq.c +++ b/PDP11/pdp11_tq.c @@ -678,8 +678,6 @@ if (tq_csta < CST_UP) { /* still init? */ else { tq_s1dat = tq_saw; /* save data */ tq_dib.vec = (tq_s1dat & SA_S1H_VEC) << 2; /* get vector */ - if (tq_dib.vec) /* if nz, bias */ - tq_dib.vec = tq_dib.vec + VEC_Q; tq_sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (tq_s1dat); tq_csta = CST_S2; /* now in step 2 */ tq_init_int (); /* intr if req */ diff --git a/PDP11/pdp11_xq.c b/PDP11/pdp11_xq.c index f3ec9c44..f69f6d34 100644 --- a/PDP11/pdp11_xq.c +++ b/PDP11/pdp11_xq.c @@ -2183,7 +2183,7 @@ t_stat xq_wr_var(CTLR* xq, int32 data) /* set vector of SIMH device */ if (data & XQ_VEC_IV) - xq->dib->vec = (data & XQ_VEC_IV) + VEC_Q; + xq->dib->vec = (data & XQ_VEC_IV); else xq->dib->vec = 0; @@ -2361,7 +2361,7 @@ t_stat xq_wr_srqr(CTLR* xq, int32 data) xq_debug_turbo_setup(xq); - xq->dib->vec = xq->var->init.vector + VEC_Q; + xq->dib->vec = xq->var->init.vector; xq->var->tbindx = xq->var->rbindx = 0; if ((xq->var->sanity.enabled) && (xq->var->init.options & XQ_IN_OP_HIT)) { xq->var->sanity.quarter_secs = 4*xq->var->init.hit_timeout; diff --git a/VAX/vax610_defs.h b/VAX/vax610_defs.h index 7476898a..6bf3156d 100644 --- a/VAX/vax610_defs.h +++ b/VAX/vax610_defs.h @@ -308,7 +308,7 @@ typedef struct { #define VEC_FLOAT (0) /* Assigned by Auto Configure */ #define VEC_QBUS 1 /* Qbus system */ -#define VEC_Q 0x200 /* Qbus vector offset */ +#define VEC_SET 0x201 /* Vector bits to set in Qbus vectors */ /* Interrupt macros */ diff --git a/VAX/vax610_io.c b/VAX/vax610_io.c index 8d5c7179..eee4994c 100644 --- a/VAX/vax610_io.c +++ b/VAX/vax610_io.c @@ -32,6 +32,7 @@ #include "vax_defs.h" int32 int_req[IPL_HLVL] = { 0 }; /* intr, IPL 14-17 */ +int32 int_vec_set[IPL_HLVL][32] = { 0 }; /* bits to set in vector */ int32 autcon_enb = 1; /* autoconfig enable */ extern int32 PSL, SISR, trpirq, mem_err, hlt_pin; @@ -92,6 +93,8 @@ int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */ int32 int_vec[IPL_HLVL][32]; /* int req to vector */ +#define QB_VEC_MASK 0x1FC /* Interrupt Vector value mask */ + /* The KA610 handles errors in I/O space as follows - read: machine check @@ -310,10 +313,16 @@ if (lvl > IPL_HMAX) { /* error req lvl? */ } for (i = 0; int_req[l] && (i < 32); i++) { if ((int_req[l] >> i) & 1) { + int32 vec; + int_req[l] = int_req[l] & ~(1u << i); if (int_ack[l][i]) - return int_ack[l][i](); - return int_vec[l][i]; + vec =int_ack[l][i](); + else + vec = int_vec[l][i]; + vec |= int_vec_set[l][i]; + vec &= (int_vec_set[l][i] | QB_VEC_MASK); + return vec; } } return 0; diff --git a/VAX/vax630_defs.h b/VAX/vax630_defs.h index 0bfba8fe..82fad7d5 100644 --- a/VAX/vax630_defs.h +++ b/VAX/vax630_defs.h @@ -364,7 +364,7 @@ typedef struct { #define VEC_FLOAT (0) /* Assigned by Auto Configure */ #define VEC_QBUS 1 /* Qbus system */ -#define VEC_Q 0x200 /* Qbus vector offset */ +#define VEC_SET 0x201 /* Vector bits to set in Qbus vectors */ /* Interrupt macros */ diff --git a/VAX/vax630_io.c b/VAX/vax630_io.c index 2f6a1a39..fa771e84 100644 --- a/VAX/vax630_io.c +++ b/VAX/vax630_io.c @@ -61,11 +61,14 @@ BITFIELD qb_ipc_bits[] = { #define QBMAP_RD (QBMAP_VLD | QBMAP_PAG) #define QBMAP_WR (QBMAP_VLD | QBMAP_PAG) +#define QB_VEC_MASK 0x1FC /* Interrupt Vector value mask */ + /* KA630 Memory system error register */ #define MSER_NXM 0x00000080 /* CPU NXM */ int32 int_req[IPL_HLVL] = { 0 }; /* intr, IPL 14-17 */ +int32 int_vec_set[IPL_HLVL][32] = { 0 }; /* bits to set in vector */ int32 qb_ipc = 0; /* IPC */ int32 qb_map[QBNMAPR] = { 0 }; /* map registers */ int32 autcon_enb = 1; /* autoconfig enable */ @@ -375,10 +378,16 @@ if (lvl > IPL_HMAX) { /* error req lvl? */ } for (i = 0; int_req[l] && (i < 32); i++) { if ((int_req[l] >> i) & 1) { + int32 vec; + int_req[l] = int_req[l] & ~(1u << i); if (int_ack[l][i]) - return int_ack[l][i](); - return int_vec[l][i]; + vec =int_ack[l][i](); + else + vec = int_vec[l][i]; + vec |= int_vec_set[l][i]; + vec &= (int_vec_set[l][i] | QB_VEC_MASK); + return vec; } } return 0; diff --git a/VAX/vax730_defs.h b/VAX/vax730_defs.h index 53531bbb..d25054dc 100644 --- a/VAX/vax730_defs.h +++ b/VAX/vax730_defs.h @@ -322,8 +322,8 @@ typedef struct { #define VEC_AUTO (0) /* Assigned by Auto Configure */ #define VEC_FLOAT (0) /* Assigned by Auto Configure */ -#define VEC_QBUS 0 -#define VEC_Q 0x200 +#define VEC_QBUS 0 /* Unibus system */ +#define VEC_SET 0x200 /* Vector bits to set in Unibus vectors */ /* Interrupt macros */ diff --git a/VAX/vax730_sys.c b/VAX/vax730_sys.c index 81e72829..ff6e853e 100644 --- a/VAX/vax730_sys.c +++ b/VAX/vax730_sys.c @@ -546,7 +546,7 @@ for (i = 0; boot_tab[i].name != NULL; i++) { R[0] = boot_tab[i].code; if (boot_tab[i].code == BOOT_RB) { /* vector set by console for RB730 */ extern DIB rb_dib; - R[0] = R[0] | ((rb_dib.vec - VEC_Q) << 16); + R[0] = R[0] | ((rb_dib.vec) << 16); } R[1] = TR_UBA; R[2] = boot_tab[i].let | (ba & UBADDRMASK); diff --git a/VAX/vax730_uba.c b/VAX/vax730_uba.c index 6ebe88ff..76ecaf85 100644 --- a/VAX/vax730_uba.c +++ b/VAX/vax730_uba.c @@ -55,6 +55,8 @@ /* Vector registers - read only */ #define UBA_UVEC 0x80000000 +#define UBA_VEC_MASK 0x1FC /* Vector value mask */ + /* RB730 registers */ @@ -85,7 +87,8 @@ #define UBA_DEB_ERR 0x20 /* errors */ int32 int_req[IPL_HLVL] = { 0 }; /* intr, IPL 14-17 */ -uint32 uba_csr = 0; /* control & status reg */ +int32 int_vec_set[IPL_HLVL][32] = { 0 }; /* bits to set in vector */ +uint32 uba_csr = 0; /* control & status reg */ uint32 uba_fmer = 0; /* failing map reg */ uint32 uba_map[UBA_NMAPR] = { 0 }; /* map registers */ int32 autcon_enb = 1; /* autoconfig enable */ @@ -385,8 +388,12 @@ for (i = 0; int_req[lvl] && (i < 32); i++) { if ((int_req[lvl] >> i) & 1) { int_req[lvl] = int_req[lvl] & ~(1u << i); if (int_ack[lvl][i]) - return (vec | int_ack[lvl][i]()); - return (vec | int_vec[lvl][i]); + vec = int_ack[lvl][i](); + else + vec = int_vec[lvl][i]; + vec |= int_vec_set[lvl][i]; + vec &= (int_vec_set[lvl][i] | UBA_VEC_MASK); + return vec; } } return vec; diff --git a/VAX/vax750_defs.h b/VAX/vax750_defs.h index cf45e9bc..3bd2ae07 100644 --- a/VAX/vax750_defs.h +++ b/VAX/vax750_defs.h @@ -361,8 +361,9 @@ typedef struct { #define VEC_AUTO (0) /* Assigned by Auto Configure */ #define VEC_FLOAT (0) /* Assigned by Auto Configure */ -#define VEC_QBUS 0 -#define VEC_Q 0x200 +#define VEC_QBUS 0 /* Unibus system */ +#define VEC_SET 0x200 /* Vector bits to set in Unibus vectors */ +#define VEC_MASK 0x3FF /* Vector bits to return in Unibus vectors */ /* Interrupt macros */ diff --git a/VAX/vax750_uba.c b/VAX/vax750_uba.c index 2c009d56..431cb374 100644 --- a/VAX/vax750_uba.c +++ b/VAX/vax750_uba.c @@ -64,6 +64,8 @@ #define UBADPR_RD 0xE0000000 #define UBADPR_W1C 0xC0000000 +#define UBA_VEC_MASK 0x1FC /* Vector value mask */ + /* Map registers */ #define UBAMAP_OF 0x200 @@ -136,6 +138,7 @@ int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */ /* Unibus interrupt request to vector map */ int32 int_vec[IPL_HLVL][32]; /* int req to vector */ +int32 int_vec_set[IPL_HLVL][32] = { 0 }; /* bits to set in vector */ /* Unibus adapter data structures @@ -424,21 +427,26 @@ return; int32 uba_get_ubvector (int32 lvl) { -int32 i, vec; +int32 i; -vec = 0; if ((lvl == (IPL_UBA - IPL_HMIN)) && uba_int) { /* UBA lvl, int? */ uba_int = 0; /* clear int */ } for (i = 0; int_req[lvl] && (i < 32); i++) { if ((int_req[lvl] >> i) & 1) { + int32 vec; + int_req[lvl] = int_req[lvl] & ~(1u << i); if (int_ack[lvl][i]) - return (vec | int_ack[lvl][i]()); - return (vec | int_vec[lvl][i]); + vec = int_ack[lvl][i](); + else + vec = int_vec[lvl][i]; + vec |= int_vec_set[lvl][i]; + vec &= (int_vec_set[lvl][i] | UBA_VEC_MASK); + return vec; } } -return vec; +return 0; } /* Unibus I/O buffer routines diff --git a/VAX/vax780_defs.h b/VAX/vax780_defs.h index 5bb9b253..9c4088ca 100644 --- a/VAX/vax780_defs.h +++ b/VAX/vax780_defs.h @@ -375,8 +375,8 @@ typedef struct { #define VEC_AUTO (0) /* Assigned by Auto Configure */ #define VEC_FLOAT (0) /* Assigned by Auto Configure */ -#define VEC_QBUS 0 -#define VEC_Q 0000 +#define VEC_QBUS 0 /* Unibus system */ +#define VEC_SET 0x000 /* Vector bits to set in Unibus vectors */ /* Interrupt macros */ diff --git a/VAX/vax780_uba.c b/VAX/vax780_uba.c index 3dd369bb..66cf8ba1 100644 --- a/VAX/vax780_uba.c +++ b/VAX/vax780_uba.c @@ -122,6 +122,7 @@ #define UBABRRVR_OF 0x0C #define UBA_UVEC 0x80000000 +#define UBA_VEC_MASK 0x1FC /* Vector value mask */ /* Data path registers */ @@ -595,8 +596,8 @@ if (((uba_dr & UBADR_DINTR) == 0) && !uba_uiip && /* intr enabled? */ if ((int_req[lvl] >> i) & 1) { int_req[lvl] = int_req[lvl] & ~(1u << i); if (int_ack[lvl][i]) - return (vec | int_ack[lvl][i]()); - return (vec | int_vec[lvl][i]); + return ((UBA_VEC_MASK|UBA_UVEC) & (vec | int_ack[lvl][i]())); + return ((UBA_VEC_MASK|UBA_UVEC) & (vec | int_vec[lvl][i])); } } } diff --git a/VAX/vax860_defs.h b/VAX/vax860_defs.h index 209c8838..e8e17a91 100644 --- a/VAX/vax860_defs.h +++ b/VAX/vax860_defs.h @@ -405,8 +405,8 @@ typedef struct { #define VEC_AUTO (0) /* Assigned by Auto Configure */ #define VEC_FLOAT (0) /* Assigned by Auto Configure */ -#define VEC_QBUS 0 -#define VEC_Q 0000 +#define VEC_QBUS 0 /* Unibus system */ +#define VEC_SET 0x000 /* Vector bits to set in Unibus vectors */ /* Interrupt macros */ diff --git a/VAX/vax_cpu1.c b/VAX/vax_cpu1.c index 9447a505..869dbf3c 100644 --- a/VAX/vax_cpu1.c +++ b/VAX/vax_cpu1.c @@ -1138,13 +1138,15 @@ else { } if (ei > 0) { /* if int, new IPL */ int32 newipl; - if (VEC_QBUS && ((vec & VEC_Q) != 0)) /* Qbus and Qbus vector? */ + if ((VEC_QBUS & vec) != 0) /* Qbus vector? */ newipl = PSL_IPL17; /* force IPL 17 */ - else newipl = ipl << PSL_V_IPL; /* otherwise, int IPL */ + else + newipl = ipl << PSL_V_IPL; /* otherwise, int IPL */ PSL = newpsl | newipl; } -else PSL = newpsl | /* exc, old IPL/1F */ - ((newpc & 1)? PSL_IPL1F: (oldpsl & PSL_IPL)) | (oldcur << PSL_V_PRV); +else + PSL = newpsl | /* exc, old IPL/1F */ + ((newpc & 1)? PSL_IPL1F: (oldpsl & PSL_IPL)) | (oldcur << PSL_V_PRV); sim_debug (LOG_CPU_I, &cpu_dev, "PC=%08x, PSL=%08x, SP=%08x, VEC=%08x, nPSL=%08x, nSP=%08x\n", PC, oldpsl, oldsp, vec, PSL, SP); acc = ACC_MASK (KERN); /* new mode is kernel */ diff --git a/VAX/vax_io.c b/VAX/vax_io.c index fb96970d..5f5d3366 100644 --- a/VAX/vax_io.c +++ b/VAX/vax_io.c @@ -103,7 +103,10 @@ #define CQMAP_VLD 0x80000000 /* valid */ #define CQMAP_PAG 0x000FFFFF /* mem page */ +#define QB_VEC_MASK 0x1FC /* Interrupt Vector value mask */ + int32 int_req[IPL_HLVL] = { 0 }; /* intr, IPL 14-17 */ +int32 int_vec_set[IPL_HLVL][32] = { 0 }; /* bits to set in vector */ int32 cq_scr = 0; /* SCR */ int32 cq_dser = 0; /* DSER */ int32 cq_mear = 0; /* MEAR */ @@ -427,10 +430,16 @@ if (lvl > IPL_HMAX) { /* error req lvl? */ } for (i = 0; int_req[l] && (i < 32); i++) { if ((int_req[l] >> i) & 1) { + int32 vec; + int_req[l] = int_req[l] & ~(1u << i); if (int_ack[l][i]) - return int_ack[l][i](); - return int_vec[l][i]; + vec = int_ack[l][i](); + else + vec = int_vec[l][i]; + vec |= int_vec_set[l][i]; + vec &= (int_vec_set[l][i] | QB_VEC_MASK); + return vec; } } return 0; diff --git a/VAX/vax_vc.c b/VAX/vax_vc.c index 56464bc0..ba6b4258 100644 --- a/VAX/vax_vc.c +++ b/VAX/vax_vc.c @@ -566,7 +566,15 @@ switch (rg) { else if (vc_intc.ptr == 9) /* ACR */ vc_intc.acr = data & 0xFFFF; else - vc_intc.vec[vc_intc.ptr] = data & 0xFFFF; /* Vector */ + /* + Masking the vector with 0x1FC is probably storing + one more bit than the original hardware did. + Doing this allows a maximal simulated hardware + configuration use a reasonable vector where real + hardware could never be assembled with that many + devices. + */ + vc_intc.vec[vc_intc.ptr] = data & 0x1FC; /* Vector */ break; case 7: /* ICSR */ @@ -860,7 +868,7 @@ for (i = 0; i < 8; i++) { vc_intc.isr &= ~(1u << i); else vc_intc.isr |= (1u << i); vc_checkint(); - result = (vc_intc.vec[i] + VEC_Q); + result = vc_intc.vec[i]; sim_debug (DBG_INT, &vc_dev, "Int Ack Vector: 0%03o (0x%X)\n", result, result); return result; } diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index 4bf1239b..9ae7dc32 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -414,7 +414,7 @@ typedef struct { #define VEC_FLOAT (0) /* Assigned by Auto Configure */ #define VEC_QBUS 1 /* Qbus system */ -#define VEC_Q 0x200 /* Qbus vector offset */ +#define VEC_SET 0x201 /* Vector bits to set in Qbus vectors */ /* Interrupt macros */