These changes facilitate more robust parameter type checking and helps to identify unexpected coding errors. Most simulators can now also be compiled with a C++ compiler without warnings. Additionally, these changes have also been configured to facilitate easier backporting of simulator and device simulation modules to run under the simh v3.9+ SCP framework.
350 lines
12 KiB
C
350 lines
12 KiB
C
/* vax860_sbia.c: VAX 8600 SBIA
|
|
|
|
Copyright (c) 2011-2012, Matt Burke
|
|
This module incorporates code from SimH, Copyright (c) 2004-2008, 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"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name(s) of the author(s) shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from the author(s).
|
|
|
|
sbia SBI adapter
|
|
|
|
26-Dec-2012 MB First Version
|
|
*/
|
|
|
|
#include "vax_defs.h"
|
|
|
|
/* SBIA registers */
|
|
|
|
#define SBICSR_MIE 0x80000000 /* master int en */
|
|
#define SBICSR_SCOEN 0x40000000 /* SBI cycles out enable */
|
|
#define SBICSR_SCIEN 0x20000000 /* SBI cycles in enable */
|
|
#define SBICSR_WR (SBICSR_MIE | SBICSR_SCOEN | SBICSR_SCIEN)
|
|
|
|
#define SBIFS_RD (0x031F0000|SBI_FAULTS) /* SBI faults */
|
|
#define SBIFS_WR 0x03140000
|
|
#define SBIFS_W1C 0x00080000
|
|
|
|
#define SBISC_RD 0xFFFF0000 /* SBI silo comp */
|
|
#define SBISC_WR 0x7FFF0000
|
|
#define SBISC_LOCK 0x80000000 /* lock */
|
|
|
|
#define SBIMT_RD 0xFFFFFF00 /* SBI maint */
|
|
#define SBIMT_WR 0xFFFFF900
|
|
|
|
#define SBIER_CRDIE 0x00008000 /* SBI error, CRD IE */
|
|
#define SBIER_CRD 0x00004000 /* CRD */
|
|
#define SBIER_RDS 0x00002000 /* RDS */
|
|
#define SBIER_TMO 0x00001000 /* timeout */
|
|
#define SBIER_STA 0x00000C00 /* timeout status (0) */
|
|
#define SBIER_CNF 0x00000100 /* error confirm */
|
|
#define SBIER_IBRDS 0x00000080
|
|
#define SBIER_IBTMO 0x00000040
|
|
#define SBIER_IBSTA 0x00000030
|
|
#define SBIER_IBCNF 0x00000008
|
|
#define SBIER_MULT 0x00000004 /* multiple errors */
|
|
#define SBIER_FREE 0x00000002 /* SBI free */
|
|
#define SBIER_RD 0x0000FDFE
|
|
#define SBIER_WR 0x00008000
|
|
#define SBIER_W1C 0x000070C0
|
|
#define SBIER_TMOW1C (SBIER_TMO|SBIER_STA|SBIER_CNF|SBIER_MULT)
|
|
#define SBIER_IBTW1C (SBIER_IBTMO|SBIER_STA|SBIER_IBCNF)
|
|
|
|
#define SBITMO_V_MODE 30 /* mode */
|
|
#define SBITMO_VIRT 0x20000000 /* physical */
|
|
|
|
#define SBIQC_MBZ 0xC0000007 /* MBZ */
|
|
|
|
extern uint32 nexus_req[NEXUS_HLVL]; /* nexus int req */
|
|
uint32 sbi_fs = 0; /* SBI fault status */
|
|
uint32 sbi_sc = 0; /* SBI silo comparator */
|
|
uint32 sbi_mt = 0; /* SBI maintenance */
|
|
uint32 sbi_er = 0; /* SBI error status */
|
|
uint32 sbi_tmo = 0; /* SBI timeout addr */
|
|
uint32 sbi_csr = 0; /* SBI control/status */
|
|
|
|
t_stat sbia_reset (DEVICE *dptr);
|
|
const char *sbia_description (DEVICE *dptr);
|
|
void sbi_set_tmo (int32 pa);
|
|
t_stat (*nexusR[NEXUS_NUM])(int32 *dat, int32 ad, int32 md);
|
|
t_stat (*nexusW[NEXUS_NUM])(int32 dat, int32 ad, int32 md);
|
|
|
|
extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei);
|
|
extern int32 eval_int (void);
|
|
|
|
/* SBIA data structures
|
|
|
|
sbia_dev SBIA device descriptor
|
|
sbia_unit SBIA unit
|
|
sbia_reg SBIA register list
|
|
*/
|
|
|
|
UNIT sbia_unit = { UDATA (NULL, 0, 0) };
|
|
|
|
REG sbia_reg[] = {
|
|
{ HRDATA (NREQ14, nexus_req[0], 16) },
|
|
{ HRDATA (NREQ15, nexus_req[1], 16) },
|
|
{ HRDATA (NREQ16, nexus_req[2], 16) },
|
|
{ HRDATA (NREQ17, nexus_req[3], 16) },
|
|
{ HRDATA (SBIFS, sbi_fs, 32) },
|
|
{ HRDATA (SBISC, sbi_sc, 32) },
|
|
{ HRDATA (SBIMT, sbi_mt, 32) },
|
|
{ HRDATA (SBIER, sbi_er, 32) },
|
|
{ HRDATA (SBITMO, sbi_tmo, 32) },
|
|
{ HRDATA (SBICSR, sbi_csr, 32) },
|
|
{ NULL }
|
|
};
|
|
|
|
DEVICE sbia_dev = {
|
|
"SBIA", &sbia_unit, sbia_reg, NULL,
|
|
1, 16, 16, 1, 16, 8,
|
|
NULL, NULL, &sbia_reset,
|
|
NULL, NULL, NULL,
|
|
NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&sbia_description
|
|
};
|
|
|
|
int32 sbia_rd (int32 pa, int32 lnt)
|
|
{
|
|
int32 rg = (pa >> 2) & 0x1F;
|
|
|
|
switch (rg) {
|
|
case 0: /* SBICNF */
|
|
return 0x00400010; /* 8MB + SBIA Abus code */
|
|
|
|
case 1: /* SBICSR */
|
|
return sbi_csr;
|
|
|
|
case 2: /* SBIES (not impl) */
|
|
case 3: /* SBIDCR (not impl) */
|
|
case 4: /* DMAI CMD (not impl) */
|
|
case 5: /* DMAI ID (not impl) */
|
|
case 6: /* DMAA CMD (not impl) */
|
|
case 7: /* DMAA ID (not impl) */
|
|
case 8: /* DMAB CMD (not impl) */
|
|
case 9: /* DMAB ID (not impl) */
|
|
case 0xa: /* DMAC CMD (not impl) */
|
|
case 0xb: /* DMAC ID (not impl) */
|
|
case 0xc: /* SBIS (not impl) */
|
|
return 0;
|
|
|
|
case 0xd: /* SBIER */
|
|
return sbi_er & SBIER_RD;
|
|
|
|
case 0xe: /* SBITA */
|
|
return sbi_tmo;
|
|
|
|
case 0xf: /* SBIFS */
|
|
return sbi_fs & SBIFS_RD;
|
|
|
|
case 0x10: /* SBISC */
|
|
return sbi_sc & SBISC_RD;
|
|
|
|
case 0x11: /* SBIMT */
|
|
return sbi_mt & SBIMT_RD;
|
|
|
|
default: /* Anything else is not impl */
|
|
return 0;
|
|
|
|
}
|
|
}
|
|
|
|
void sbia_wr (int32 pa, int32 val, int32 lnt)
|
|
{
|
|
int32 rg = (pa >> 2) & 0x1F;
|
|
|
|
switch (rg) {
|
|
case 0: /* SBICNF */
|
|
break;
|
|
|
|
case 1: /* SBICSR */
|
|
sim_printf ("sbi_csr wr: %08X\n", val);
|
|
sbi_csr = sbi_csr & SBICSR_WR;
|
|
break;
|
|
|
|
case 2: /* SBIES (not impl) */
|
|
case 3: /* SBIDCR (not impl) */
|
|
case 4: /* DMAI CMD (not impl) */
|
|
case 5: /* DMAI ID (not impl) */
|
|
case 6: /* DMAA CMD (not impl) */
|
|
case 7: /* DMAA ID (not impl) */
|
|
case 8: /* DMAB CMD (not impl) */
|
|
case 9: /* DMAB ID (not impl) */
|
|
case 0xa: /* DMAC CMD (not impl) */
|
|
case 0xb: /* DMAC ID (not impl) */
|
|
case 0xc: /* SBIS (not impl) */
|
|
break;
|
|
|
|
case 0xd: /* SBIER */
|
|
sbi_er = (sbi_er & ~SBIER_WR) | (val & SBIER_WR);
|
|
sbi_er = sbi_er & ~(val & SBIER_W1C);
|
|
if (val & SBIER_TMO)
|
|
sbi_er = sbi_er & ~SBIER_TMOW1C;
|
|
if (val & SBIER_IBTMO)
|
|
sbi_er = sbi_er & ~SBIER_IBTW1C;
|
|
if ((sbi_er & SBIER_CRDIE) && (sbi_er & SBIER_CRD))
|
|
crd_err = 1;
|
|
else crd_err = 0;
|
|
break;
|
|
|
|
case 0xe: /* SBITA */
|
|
break;
|
|
|
|
case 0xf: /* SBIFS */
|
|
sbi_fs = (sbi_fs & ~SBIFS_WR) | (val & SBIFS_WR);
|
|
sbi_fs = sbi_fs & ~(val & SBIFS_W1C);
|
|
break;
|
|
|
|
case 0x10: /* SBISC */
|
|
sbi_sc = (sbi_sc & ~(SBISC_LOCK|SBISC_WR)) | (val & SBISC_WR);
|
|
break;
|
|
|
|
case 0x11: /* SBIMT */
|
|
sbi_mt = (sbi_mt & ~SBIMT_WR) | (val & SBIMT_WR);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
t_stat sbi_rd (int32 pa, int32 *val, int32 lnt)
|
|
{
|
|
int32 nexus;
|
|
|
|
nexus = NEXUS_GETNEX (pa); /* get nexus */
|
|
if ((sbi_csr & SBICSR_SCOEN) && /* SBI en? */
|
|
nexusR[nexus] && /* valid? */
|
|
(nexusR[nexus] (val, pa, lnt) == SCPE_OK)) {
|
|
SET_IRQL;
|
|
return SCPE_OK;
|
|
}
|
|
else sbi_set_tmo (pa); /* timeout */
|
|
return SCPE_NXM;
|
|
}
|
|
|
|
t_stat sbi_wr (int32 pa, int32 val, int32 lnt)
|
|
{
|
|
int32 nexus;
|
|
|
|
nexus = NEXUS_GETNEX (pa); /* get nexus */
|
|
if ((sbi_csr & SBICSR_SCOEN) && /* SBI en? */
|
|
nexusW[nexus] && /* valid? */
|
|
(nexusW[nexus] (val, pa, lnt) == SCPE_OK)) {
|
|
SET_IRQL;
|
|
return SCPE_OK;
|
|
}
|
|
else sbi_set_tmo (pa); /* timeout */
|
|
return SCPE_NXM;
|
|
}
|
|
|
|
/* Set SBI timeout - machine checks only on reads */
|
|
|
|
void sbi_set_tmo (int32 pa)
|
|
{
|
|
if ((sbi_er & SBIER_TMO) == 0) { /* not yet set? */
|
|
sbi_tmo = pa >> 2; /* save addr */
|
|
if (mchk_ref == REF_V) /* virt? add mode */
|
|
sbi_tmo |= SBITMO_VIRT | (PSL_GETCUR (PSL) << SBITMO_V_MODE);
|
|
sbi_er |= SBIER_TMO; /* set tmo flag */
|
|
}
|
|
else sbi_er |= SBIER_MULT; /* yes, multiple */
|
|
return;
|
|
}
|
|
|
|
/* Set SBI error confirmation - always machine checks */
|
|
|
|
void sbi_set_errcnf (void)
|
|
{
|
|
if (sbi_er & SBIER_CNF)
|
|
sbi_er |= SBIER_MULT;
|
|
else sbi_er |= SBIER_CNF;
|
|
MACH_CHECK (MCHK_RD_F);
|
|
return;
|
|
}
|
|
|
|
/* SBI reset */
|
|
|
|
t_stat sbia_reset (DEVICE *dptr)
|
|
{
|
|
sbi_fs = 0;
|
|
sbi_sc = 0;
|
|
sbi_mt = 0;
|
|
sbi_er = 0;
|
|
sbi_tmo = 0;
|
|
sbi_csr = SBICSR_SCOEN | SBICSR_SCIEN;
|
|
return SCPE_OK;
|
|
}
|
|
|
|
const char *sbia_description (DEVICE *dptr)
|
|
{
|
|
return "SBI adapter";
|
|
}
|
|
|
|
/* Show nexus */
|
|
|
|
t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
|
{
|
|
fprintf (st, "nexus=%d, address=%X", val, NEXUSBASE + ((1 << REG_V_NEXUS) * val));
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Init nexus tables */
|
|
|
|
void init_nexus_tab (void)
|
|
{
|
|
uint32 i;
|
|
|
|
for (i = 0; i < NEXUS_NUM; i++) {
|
|
nexusR[i] = NULL;
|
|
nexusW[i] = NULL;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Build nexus tables
|
|
|
|
Inputs:
|
|
dptr = pointer to device
|
|
dibp = pointer to DIB
|
|
Outputs:
|
|
status
|
|
*/
|
|
|
|
t_stat build_nexus_tab (DEVICE *dptr, DIB *dibp)
|
|
{
|
|
uint32 idx;
|
|
|
|
if ((dptr == NULL) || (dibp == NULL))
|
|
return SCPE_IERR;
|
|
idx = dibp->ba;
|
|
if (idx >= NEXUS_NUM)
|
|
return SCPE_IERR;
|
|
if ((nexusR[idx] && dibp->rd && /* conflict? */
|
|
(nexusR[idx] != dibp->rd)) ||
|
|
(nexusW[idx] && dibp->wr &&
|
|
(nexusW[idx] != dibp->wr))) {
|
|
sim_printf ("Nexus %s conflict at %d\n", sim_dname (dptr), dibp->ba);
|
|
return SCPE_STOP;
|
|
}
|
|
if (dibp->rd) /* set rd dispatch */
|
|
nexusR[idx] = dibp->rd;
|
|
if (dibp->wr) /* set wr dispatch */
|
|
nexusW[idx] = dibp->wr;
|
|
return SCPE_OK;
|
|
}
|