diff --git a/PDP11/pdp11_dmc.c b/PDP11/pdp11_dmc.c index 762311d5..09acdc3a 100644 --- a/PDP11/pdp11_dmc.c +++ b/PDP11/pdp11_dmc.c @@ -340,13 +340,13 @@ REG dmp_reg[] = { MTAB dmc_mod[] = { { MTAB_XTD | MTAB_VDV, 0, "PEER", "PEER=address:port" ,&dmc_setpeer, &dmc_showpeer, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "SPEED", "SPEED" ,&dmc_setspeed, &dmc_showspeed, NULL }, + { MTAB_XTD | MTAB_VDV, 0, "SPEED", "SPEED=bits/sec (0=unrestricted)" ,&dmc_setspeed, &dmc_showspeed, NULL }, #ifdef DMP { MTAB_XTD | MTAB_VDV, 0, "TYPE", "TYPE" ,&dmc_settype, &dmc_showtype, NULL }, #endif - { MTAB_XTD | MTAB_VDV, 0, "LINEMODE", "LINEMODE" ,&dmc_setlinemode, &dmc_showlinemode, NULL }, + { MTAB_XTD | MTAB_VDV, 0, "LINEMODE", "LINEMODE={PRIMARY|SECONDARY}" ,&dmc_setlinemode, &dmc_showlinemode, NULL }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATS", "STATS" ,&dmc_setstats, &dmc_showstats, NULL }, - { MTAB_XTD | MTAB_VDV, 0, "CONNECTPOLL", "CONNECTPOLL" ,&dmc_setconnectpoll, &dmc_showconnectpoll, NULL }, + { MTAB_XTD | MTAB_VDV, 0, "CONNECTPOLL", "CONNECTPOLL=seconds" ,&dmc_setconnectpoll, &dmc_showconnectpoll, NULL }, { MTAB_XTD | MTAB_VDV, 006, "ADDRESS", "ADDRESS", &set_addr, &show_addr, NULL }, { MTAB_XTD |MTAB_VDV, 0, "VECTOR", "VECTOR", &set_vec, &show_vec, NULL }, { 0 }, @@ -415,10 +415,10 @@ UNIT_STATS dmp_stats[DMP_NUMDEVICE]; CTLR dmc_ctrls[] = { - { &dmc_csrs[0], &dmc_dev[0], Initialised, Idle, 0, 0, &dmc_line[0], &dmc_receive_queues[0], &dmc_transmit_queues[0], &dmc_stats[0], INVALID_SOCKET, -1, 30, DMC }, - { &dmc_csrs[1], &dmc_dev[1], Initialised, Idle, 0, 0, &dmc_line[1], &dmc_receive_queues[1], &dmc_transmit_queues[1], &dmc_stats[1], INVALID_SOCKET, -1, 30, DMC }, - { &dmc_csrs[2], &dmc_dev[2], Initialised, Idle, 0, 0, &dmc_line[2], &dmc_receive_queues[2], &dmc_transmit_queues[2], &dmc_stats[2], INVALID_SOCKET, -1, 30, DMC }, - { &dmc_csrs[3], &dmc_dev[3], Initialised, Idle, 0, 0, &dmc_line[3], &dmc_receive_queues[3], &dmc_transmit_queues[3], &dmc_stats[3], INVALID_SOCKET, -1, 30, DMC }, + { &dmc_csrs[0], &dmc_dev[0], Initialised, Idle, 0, 0, &dmc_line[0], &dmc_receive_queues[0], &dmc_transmit_queues[0], &dmc_stats[0], INVALID_SOCKET, 30, DMC }, + { &dmc_csrs[1], &dmc_dev[1], Initialised, Idle, 0, 0, &dmc_line[1], &dmc_receive_queues[1], &dmc_transmit_queues[1], &dmc_stats[1], INVALID_SOCKET, 30, DMC }, + { &dmc_csrs[2], &dmc_dev[2], Initialised, Idle, 0, 0, &dmc_line[2], &dmc_receive_queues[2], &dmc_transmit_queues[2], &dmc_stats[2], INVALID_SOCKET, 30, DMC }, + { &dmc_csrs[3], &dmc_dev[3], Initialised, Idle, 0, 0, &dmc_line[3], &dmc_receive_queues[3], &dmc_transmit_queues[3], &dmc_stats[3], INVALID_SOCKET, 30, DMC }, #ifdef DMP { &dmp_csrs[0], &dmp_dev[0], Initialised, Idle, 0, 0, &dmp_line[0], &dmp_receive_queues[0], &dmp_transmit_queues[0], &dmp_stats[0], INVALID_SOCKET, -1, 30, DMP } #endif @@ -518,10 +518,6 @@ t_stat dmc_showpeer (FILE* st, UNIT* uptr, int32 val, void* desc) { fprintf(st, "peer=%s", controller->line->transmit_host); } - else - { - fprintf(st, "peer Unspecified"); - } return SCPE_OK; } @@ -553,7 +549,7 @@ t_stat dmc_showspeed (FILE* st, UNIT* uptr, int32 val, void* desc) } else { - fprintf(st, "speed=unrestricted"); + fprintf(st, "speed=0 (unrestricted)"); } return SCPE_OK; @@ -693,7 +689,7 @@ t_stat dmc_setstats (UNIT* uptr, int32 val, char* cptr, void* desc) t_stat dmc_showconnectpoll (FILE* st, UNIT* uptr, int32 val, void* desc) { CTLR *controller = dmc_get_controller_from_unit(uptr); - fprintf(st, "connect poll=%d", controller->connect_poll_interval); + fprintf(st, "connectpoll=%d", controller->connect_poll_interval); return SCPE_OK; } @@ -714,7 +710,7 @@ t_stat dmc_setconnectpoll (UNIT* uptr, int32 val, char* cptr, void* desc) t_stat dmc_showlinemode (FILE* st, UNIT* uptr, int32 val, void* desc) { CTLR *controller = dmc_get_controller_from_unit(uptr); - fprintf(st, "line mode=%s", controller->line->isPrimary? "PRIMARY" : "SECONDARY"); + fprintf(st, "linemode=%s", controller->line->isPrimary? "PRIMARY" : "SECONDARY"); return SCPE_OK; } diff --git a/VAX/vax610_defs.h b/VAX/vax610_defs.h index b03c3e46..dc0353a4 100644 --- a/VAX/vax610_defs.h +++ b/VAX/vax610_defs.h @@ -81,6 +81,7 @@ #define MT_IORESET 55 /* I/O Bus Reset */ #define MT_TBDATA 59 /* Translation Buffer Data */ #define MT_MBRK 60 /* microbreak */ +#define MT_MAX 63 /* last valid IPR */ /* Memory */ diff --git a/VAX/vax630_defs.h b/VAX/vax630_defs.h index 0f9e0aee..50b740f6 100644 --- a/VAX/vax630_defs.h +++ b/VAX/vax630_defs.h @@ -87,6 +87,7 @@ #define MT_IORESET 55 /* I/O Bus Reset */ #define MT_TBDATA 59 /* Translation Buffer Data */ #define MT_MBRK 60 /* microbreak */ +#define MT_MAX 63 /* last valid IPR */ /* CPU */ diff --git a/VAX/vax730_defs.h b/VAX/vax730_defs.h index 6e60bf5e..8bdfe5c2 100644 --- a/VAX/vax730_defs.h +++ b/VAX/vax730_defs.h @@ -94,6 +94,7 @@ #define MT_SBITA 53 /* SBI timeout addr */ #define MT_SBIQC 54 /* SBI timeout clear */ #define MT_UBINIT 55 /* Unibus Init */ +#define MT_MAX 63 /* last valid IPR */ /* Machine specific reserved operand tests */ diff --git a/VAX/vax730_sys.c b/VAX/vax730_sys.c index dfeddbba..c5224be1 100644 --- a/VAX/vax730_sys.c +++ b/VAX/vax730_sys.c @@ -525,8 +525,16 @@ if ((strncmp (regptr, "/R5:", 4) == 0) || if (r != SCPE_OK) return r; } -else if (*regptr != 0) - return SCPE_ARG; +else + if (*regptr == '/') { + r5v = (int32) get_uint (regptr + 1, 16, LMASK, &r); + if (r != SCPE_OK) + return r; + } + else { + if (*regptr != 0) + return SCPE_ARG; + } for (i = 0; boot_tab[i].name != NULL; i++) { if (strcmp (dptr->name, boot_tab[i].name) == 0) { R[0] = boot_tab[i].code; diff --git a/VAX/vax750_cmi.c b/VAX/vax750_cmi.c index 75cc641b..e036bf8a 100644 --- a/VAX/vax750_cmi.c +++ b/VAX/vax750_cmi.c @@ -609,8 +609,16 @@ if ((strncmp (regptr, "/R5:", 4) == 0) || if (r != SCPE_OK) return r; } -else if (*regptr != 0) - return SCPE_ARG; +else + if (*regptr == '/') { + r5v = (int32) get_uint (regptr + 1, 16, LMASK, &r); + if (r != SCPE_OK) + return r; + } + else { + if (*regptr != 0) + return SCPE_ARG; + } for (i = 0; boot_tab[i].name != NULL; i++) { if (strcmp (dptr->name, boot_tab[i].name) == 0) { R[0] = boot_tab[i].code; diff --git a/VAX/vax750_defs.h b/VAX/vax750_defs.h index 07b0b8ec..69d24f78 100644 --- a/VAX/vax750_defs.h +++ b/VAX/vax750_defs.h @@ -115,6 +115,7 @@ #define MT_CAER 39 /* Cache error */ #define MT_ACCS 40 /* FPA control */ #define MT_IORESET 55 /* Unibus Init */ +#define MT_MAX 63 /* last valid IPR */ /* Machine specific reserved operand tests */ diff --git a/VAX/vax780_defs.h b/VAX/vax780_defs.h index 1f38cb8e..cd29654c 100644 --- a/VAX/vax780_defs.h +++ b/VAX/vax780_defs.h @@ -120,6 +120,7 @@ #define MT_SBITA 53 /* SBI timeout addr */ #define MT_SBIQC 54 /* SBI timeout clear */ #define MT_MBRK 60 /* microbreak */ +#define MT_MAX 63 /* last valid IPR */ /* Machine specific reserved operand tests */ diff --git a/VAX/vax780_sbi.c b/VAX/vax780_sbi.c index 3bc28739..76f39006 100644 --- a/VAX/vax780_sbi.c +++ b/VAX/vax780_sbi.c @@ -668,8 +668,16 @@ if ((strncmp (regptr, "/R5:", 4) == 0) || if (r != SCPE_OK) return r; } -else if (*regptr != 0) - return SCPE_ARG; +else + if (*regptr == '/') { + r5v = (int32) get_uint (regptr + 1, 16, LMASK, &r); + if (r != SCPE_OK) + return r; + } + else { + if (*regptr != 0) + return SCPE_ARG; + } for (i = 0; boot_tab[i].name != NULL; i++) { if (strcmp (dptr->name, boot_tab[i].name) == 0) { R[0] = boot_tab[i].code; diff --git a/VAX/vax860_abus.c b/VAX/vax860_abus.c new file mode 100644 index 00000000..4ef20c15 --- /dev/null +++ b/VAX/vax860_abus.c @@ -0,0 +1,730 @@ +/* vax860_abus.c: VAX 8600 A-Bus + + 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). + + abus bus controller + + 26-Dec-2012 MB First Version +*/ + +#include "vax_defs.h" + +#ifdef DONT_USE_INTERNAL_ROM +#define BOOT_CODE_FILENAME "vmb.exe" +#else /* !DONT_USE_INTERNAL_ROM */ +#include "vax_vmb_exe.h" /* Defines BOOT_CODE_FILENAME and BOOT_CODE_ARRAY, etc */ +#endif /* DONT_USE_INTERNAL_ROM */ + +/* SBIA registers */ + +#define SBIER_TMO 0x00001000 /* timeout */ +#define SBIER_STA 0x00000C00 /* timeout status (0) */ +#define SBIER_CNF 0x00000100 /* error confirm */ +#define SBIER_MULT 0x00000004 /* multiple errors */ +#define SBIER_TMOW1C (SBIER_TMO|SBIER_STA|SBIER_CNF|SBIER_MULT) + +/* PAMM */ + +#define PAMM_IOA0 0x18 /* I/O adapter 0 */ +#define PAMM_IOA1 0x19 /* I/O adapter 1 */ +#define PAMM_IOA2 0x1A /* I/O adapter 2 */ +#define PAMM_IOA3 0x1B /* I/O adapter 3 */ +#define PAMM_NXM 0x1F /* Non-existant address */ + +#define PAMACC_ADDR 0x3FF00000 /* PAMM address */ +#define PAMACC_CODE 0x0000001F /* Configuration code */ + +#define PAMLOC_ADDR 0x3FF00000 /* PAMM address */ + +/* MBOX registers */ + +#define MSTAT1_V_CYC 26 /* MBOX cycle type */ +#define MSTAT1_M_CYC 0xF +#define MSTAT1_CPRD 0xE /* CP read */ + +#define MSTAT2_NXM 0x00000008 /* CP NXM */ + +#define MERG_V_MME 8 /* Mem mgmt en */ + +#define MDCTL_RW 0x00006F0F /* MBOX data control */ + +/* EBOX registers */ + +#define EBCS_MFTL 0x00008000 /* MBOX fatal error */ + +#define EHMSTS_PROCA 0x00020000 /* Process abort */ + +#define EHSR_VMSE 0x00000020 /* VMS entered */ + +/* VAX 8600 boot device definitions */ + +struct boot_dev { + char *name; + int32 code; + int32 let; + }; + +uint32 nexus_req[NEXUS_HLVL]; /* nexus int req */ +uint32 pamloc = 0; +uint32 cswp = 0; +uint32 ehsr = 0; +uint32 mdctl = 0; +int32 sys_model = 0; +char cpu_boot_cmd[CBUFSIZE] = { 0 }; /* boot command */ + +static struct boot_dev boot_tab[] = { + { "RP", BOOT_MB, 0 }, + { "HK", BOOT_HK, 0 }, + { "RL", BOOT_RL, 0 }, + { "RQ", BOOT_UDA, 1 << 24 }, + { "RQB", BOOT_UDA, 1 << 24 }, + { "RQC", BOOT_UDA, 1 << 24 }, + { "RQD", BOOT_UDA, 1 << 24 }, + { "TQ", BOOT_TK, 1 << 24 }, + { "CS", BOOT_CS, 0 }, + { NULL } + }; + +extern int32 R[16]; +extern int32 PSL; +extern int32 ASTLVL, SISR; +extern int32 mapen, pme, trpirq; +extern int32 in_ie; +extern int32 mchk_va, mchk_ref; +extern int32 crd_err, mem_err, hlt_pin; +extern int32 tmr_int, tti_int, tto_int, csi_int; +extern uint32 sbi_er; +extern jmp_buf save_env; +extern int32 p1; +extern int32 sim_switches; +extern DEVICE *sim_devices[]; +extern FILE *sim_log; +extern CTAB *sim_vm_cmd; +extern int32 fault_PC; /* fault PC */ +extern UNIT cpu_unit; + +void uba_eval_int (void); +t_stat abus_reset (DEVICE *dptr); +t_stat vax860_boot (int32 flag, char *ptr); +t_stat vax860_boot_parse (int32 flag, char *ptr); +t_stat cpu_boot (int32 unitno, DEVICE *dptr); + +extern t_stat (*nexusR[NEXUS_NUM])(int32 *dat, int32 ad, int32 md); +extern t_stat (*nexusW[NEXUS_NUM])(int32 dat, int32 ad, int32 md); +extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei); +extern int32 iccs_rd (void); +extern int32 nicr_rd (void); +extern int32 icr_rd (t_bool interp); +extern int32 todr_rd (void); +extern int32 rxcs_rd (void); +extern int32 rxdb_rd (void); +extern int32 txcs_rd (void); +extern int32 stxcs_rd (void); +extern int32 stxdb_rd (void); +extern void iccs_wr (int32 dat); +extern void nicr_wr (int32 dat); +extern void todr_wr (int32 dat); +extern void rxcs_wr (int32 dat); +extern void txcs_wr (int32 dat); +extern void txdb_wr (int32 dat); +extern void stxcs_wr (int32 data); +extern void stxdb_wr (int32 data); +extern void init_mbus_tab (void); +extern void init_ubus_tab (void); +extern void init_nexus_tab (void); +extern t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp); +extern t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp); +extern t_stat build_nexus_tab (DEVICE *dptr, DIB *dibp); +extern void sbi_set_tmo (int32 pa); +extern int32 sbia_rd (int32 pa, int32 lnt); +extern void sbia_wr (int32 pa, int32 val, int32 lnt); +extern t_stat sbi_rd (int32 pa, int32 *val, int32 lnt); +extern t_stat sbi_wr (int32 pa, int32 val, int32 lnt); + +/* ABUS data structures + + abus_dev A-Bus device descriptor + abus_unit A-Bus unit + abus_reg A-Bus register list +*/ + +UNIT abus_unit = { UDATA (NULL, 0, 0) }; + +REG abus_reg[] = { + { NULL } + }; + +DEVICE abus_dev = { + "ABUS", &abus_unit, abus_reg, NULL, + 1, 16, 16, 1, 16, 8, + NULL, NULL, &abus_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +/* Special boot command, overrides regular boot */ + +CTAB vax860_cmd[] = { + { "BOOT", &vax860_boot, RU_BOOT, + "bo{ot} {/R5:flg} boot device\n" }, + { NULL } + }; + +/* The VAX 8600 has three sources of interrupts + + - internal device interrupts (CPU, console, clock) + - nexus interupts (e.g. MBA, UBA) + - external device interrupts (Unibus) + + Internal devices vector to fixed SCB locations. + + Nexus interrupts vector to an SCB location based on this + formula: SCB_NEXUS + ((IPL - 0x14) * 0x40) + (TR# * 0x4) + + External device interrupts do not vector directly. + Instead, the interrupt handler for a given UBA IPL + reads a vector register that contains the Unibus vector + for that IPL. + +/* Find highest priority vectorable interrupt */ + +int32 eval_int (void) +{ +int32 ipl = PSL_GETIPL (PSL); +int32 i, t; + +static const int32 sw_int_mask[IPL_SMAX] = { + 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, /* 0 - 3 */ + 0xFFE0, 0xFFC0, 0xFF80, 0xFF00, /* 4 - 7 */ + 0xFE00, 0xFC00, 0xF800, 0xF000, /* 8 - B */ + 0xE000, 0xC000, 0x8000 /* C - E */ + }; + +if (hlt_pin) /* hlt pin int */ + return IPL_HLTPIN; +if ((ipl < IPL_MEMERR) && mem_err) /* mem err int */ + return IPL_MEMERR; +if ((ipl < IPL_CRDERR) && crd_err) /* crd err int */ + return IPL_CRDERR; +if ((ipl < IPL_CLKINT) && tmr_int) /* clock int */ + return IPL_CLKINT; +uba_eval_int (); /* update UBA */ +for (i = IPL_HMAX; i >= IPL_HMIN; i--) { /* chk hwre int */ + if (i <= ipl) /* at ipl? no int */ + return 0; + if (nexus_req[i - IPL_HMIN]) /* req != 0? int */ + return i; + } +if ((ipl < IPL_TTINT) && (tti_int || tto_int || csi_int)) /* console int */ + return IPL_TTINT; +if (ipl >= IPL_SMAX) /* ipl >= sw max? */ + return 0; +if ((t = SISR & sw_int_mask[ipl]) == 0) + return 0; /* eligible req */ +for (i = IPL_SMAX; i > ipl; i--) { /* check swre int */ + if ((t >> i) & 1) /* req != 0? int */ + return i; + } +return 0; +} + +/* Return vector for highest priority hardware interrupt at IPL lvl */ + +int32 get_vector (int32 lvl) +{ +int32 i, l; + +if (lvl == IPL_MEMERR) { /* mem error? */ + mem_err = 0; + return SCB_MEMERR; + } +if (lvl == IPL_CRDERR) { /* CRD error? */ + crd_err = 0; + return SCB_CRDERR; + } +if (lvl == IPL_CLKINT) { /* clock? */ + tmr_int = 0; /* clear req */ + return SCB_INTTIM; /* return vector */ + } +if (lvl > IPL_HMAX) { /* error req lvl? */ + ABORT (STOP_UIPL); /* unknown intr */ + } +if ((lvl <= IPL_HMAX) && (lvl >= IPL_HMIN)) { /* nexus? */ + l = lvl - IPL_HMIN; + for (i = 0; nexus_req[l] && (i < NEXUS_NUM); i++) { + if ((nexus_req[l] >> i) & 1) { + nexus_req[l] = nexus_req[l] & ~(1u << i); + return SCB_NEXUS + (l << 6) + (i << 2); /* return vector */ + } + } + } +if (lvl == IPL_TTINT) { /* console? */ + if (tti_int) { /* input? */ + tti_int = 0; /* clear req */ + return SCB_TTI; /* return vector */ + } + if (tto_int) { /* output? */ + tto_int = 0; /* clear req */ + return SCB_TTO; /* return vector */ + } + if (csi_int) { /* console storage? */ + csi_int = 0; /* clear req */ + return SCB_CSI; /* return vector */ + } + } +return 0; +} + +/* Used by CPU */ + +void rom_wr_B (int32 pa, int32 val) +{ +return; +} + +/* Read 8600 specific IPR's */ + +int32 ReadIPR (int32 rg) +{ +int32 val; + +switch (rg) { + + case MT_ICCS: /* ICCS */ + val = iccs_rd (); + break; + + case MT_NICR: /* NICR */ + val = nicr_rd (); + break; + + case MT_ICR: /* ICR */ + val = icr_rd (FALSE); + break; + + case MT_TODR: /* TODR */ + val = todr_rd (); + break; + + case MT_ACCS: /* ACCS (not impl) */ + val = 0; + break; + + case MT_RXCS: /* RXCS */ + val = rxcs_rd (); + break; + + case MT_RXDB: /* RXDB */ + val = rxdb_rd (); + break; + + case MT_TXCS: /* TXCS */ + val = txcs_rd (); + break; + + case MT_SID: /* SID */ + if (sys_model) + val = VAX860_SID | VAX865_TYP | VAX860_PLANT | VAX860_SN; + else + val = VAX860_SID | VAX860_TYP | VAX860_PLANT | VAX860_SN; + break; + + case MT_PAMACC: /* PAMACC */ + if (ADDR_IS_REG (pamloc)) + val = PAMM_IOA0; /* SBIA */ + else if (ADDR_IS_MEM (pamloc)) { + if (MEMSIZE < MAXMEMSIZE) + val = (pamloc >> 23); /* 4MB Boards */ + else + val = (pamloc >> 25); /* 16MB Boards */ + } + else val = PAMM_NXM; /* NXM */ + val = val | (pamloc & PAMACC_ADDR); + break; + + case MT_PAMLOC: /* PAMLOC */ + val = pamloc & PAMLOC_ADDR; + break; + + case MT_MDCTL: /* MDCTL */ + val = mdctl & MDCTL_RW; + + case MT_EHSR: /* EHSR */ + val = ehsr & EHSR_VMSE; + break; + + case MT_CSWP: /* CSWP */ + val = cswp & 0xF; + break; + + case MT_MERG: /* MERG */ + val = 0; + break; + + case MT_STXCS: /* STXCS */ + val = stxcs_rd (); + break; + + case MT_STXDB: /* STXDB */ + val = stxdb_rd (); + break; + + default: + RSVD_OPND_FAULT; + } + +return val; +} + +/* Write 8600 specific IPR's */ + +void WriteIPR (int32 rg, int32 val) +{ +switch (rg) { + + case MT_ICCS: /* ICCS */ + iccs_wr (val); + break; + + case MT_NICR: /* NICR */ + nicr_wr (val); + break; + + case MT_TODR: /* TODR */ + todr_wr (val); + break; + + case MT_ACCS: /* ACCS (not impl) */ + break; + + case MT_RXCS: /* RXCS */ + rxcs_wr (val); + break; + + case MT_TXCS: /* TXCS */ + txcs_wr (val); + break; + + case MT_TXDB: /* TXDB */ + txdb_wr (val); + break; + + case MT_PAMACC: /* PAMACC (not impl) */ + break; + + case MT_PAMLOC: /* PAMLOC */ + pamloc = val & PAMLOC_ADDR; + break; + + case MT_MDCTL: /* MDCTL */ + mdctl = val & MDCTL_RW; + break; + + case MT_EHSR: /* EHSR */ + ehsr = val & EHSR_VMSE; + break; + + case MT_CSWP: /* CSWP */ + cswp = val & 0xF; + break; + + case MT_MERG: /* MERG (not impl) */ + break; + + case MT_CRBT: /* CRBT (not impl) */ + break; + + case MT_STXCS: /* STXCS */ + stxcs_wr (val); + break; + + case MT_STXDB: /* STXDB */ + stxdb_wr (val); + break; + + default: + RSVD_OPND_FAULT; + } + +return; +} + +/* ReadReg - read register space + + Inputs: + pa = physical address + lnt = length (BWLQ) + Output: + longword of data +*/ + +int32 ReadReg (int32 pa, int32 lnt) +{ +int32 val; + +if (ADDR_IS_SBIA (pa)) return sbia_rd (pa, lnt); /* SBI adapter space? */ +if (ADDR_IS_REG (pa)) { /* reg space? */ + if (sbi_rd (pa, &val, lnt) == SCPE_OK) + return val; + } +MACH_CHECK (MCHK_RD_F); /* machine check */ +return 0; +} + +/* WriteReg - write register space + + Inputs: + pa = physical address + val = data to write, right justified in 32b longword + lnt = length (BWLQ) + Outputs: + none +*/ + +void WriteReg (int32 pa, int32 val, int32 lnt) +{ +if (ADDR_IS_SBIA (pa)) { /* SBI adapter space? */ + sbia_wr (pa, val, lnt); + SET_IRQL; + return; +} +if (ADDR_IS_REG (pa)) { /* reg space? */ + if (sbi_wr (pa, val, lnt) == SCPE_OK) + return; + } +mem_err = 1; /* interrupt */ +eval_int (); +return; +} + +/* Machine check */ + +int32 machine_check (int32 p1, int32 opc, int32 cc, int32 delta) +{ +int32 acc; +int32 mstat1, mstat2, mear, ebcs, merg, ehmsts; + +mstat1 = (MSTAT1_CPRD << MSTAT1_V_CYC); /* MBOX Status 1 */ +mstat2 = MSTAT2_NXM; /* MBOX Status 2 */ +mear = mchk_va; /* Memory error address */ +merg = (mchk_ref << MERG_V_MME); /* MBOX error generation word */ +ebcs = EBCS_MFTL; /* EBOX control/status */ +ehmsts = EHMSTS_PROCA; /* Error handling microcode status */ + +cc = intexc (SCB_MCHK, cc, 0, IE_SVE); /* take exception */ +acc = ACC_MASK (KERN); /* in kernel mode */ +in_ie = 1; +SP = SP - 92; /* push 25 words */ +Write (SP, 88, L_LONG, WA); /* # bytes */ +Write (SP + 4, ehmsts, L_LONG, WA); /* EHM.STS */ +Write (SP + 8, 0, L_LONG, WA); /* EVMQSAV */ +Write (SP + 12, ebcs, L_LONG, WA); /* EBCS */ +Write (SP + 16, 0, L_LONG, WA); /* EDPSR */ +Write (SP + 20, 0, L_LONG, WA); /* CSLINT */ +Write (SP + 24, 0, L_LONG, WA); /* IBESR */ +Write (SP + 28, 0, L_LONG, WA); /* EBXWD1 */ +Write (SP + 32, 0, L_LONG, WA); /* EBXWD2 */ +Write (SP + 36, 0, L_LONG, WA); /* IVASAV */ +Write (SP + 40, 0, L_LONG, WA); /* VIBASAV */ +Write (SP + 44, 0, L_LONG, WA); /* ESASAV */ +Write (SP + 48, 0, L_LONG, WA); /* ISASAV */ +Write (SP + 52, 0, L_LONG, WA); /* CPC */ +Write (SP + 56, mstat1, L_LONG, WA); /* MSTAT1 */ +Write (SP + 60, mstat2, L_LONG, WA); /* MSTAT2 */ +Write (SP + 64, 0, L_LONG, WA); /* MDECC */ +Write (SP + 68, merg, L_LONG, WA); /* MERG */ +Write (SP + 72, 0, L_LONG, WA); /* CSHCTL */ +Write (SP + 76, mear, L_LONG, WA); /* MEAR */ +Write (SP + 80, 0, L_LONG, WA); /* MEDR */ +Write (SP + 84, 0, L_LONG, WA); /* FBXERR */ +Write (SP + 88, 0, L_LONG, WA); /* CSES */ +in_ie = 0; +sbi_er = sbi_er & ~SBIER_TMOW1C; /* clr SBIER etc */ +ehsr = ehsr | EHSR_VMSE; /* VMS entered */ +return cc; +} + +/* Console entry */ + +int32 con_halt (int32 code, int32 cc) +{ +ABORT (STOP_HALT); +return cc; +} + +/* Special boot command - linked into SCP by initial reset + + Syntax: BOOT {/R5:val} + + Sets up R0-R5, calls SCP boot processor with effective BOOT CPU +*/ + +t_stat vax860_boot (int32 flag, char *ptr) +{ +t_stat r; + +r = vax860_boot_parse (flag, ptr); /* parse the boot cmd */ +if (r != SCPE_OK) /* error? */ + return r; +strncpy (cpu_boot_cmd, ptr, CBUFSIZE); /* save for reboot */ +return run_cmd (flag, "CPU"); +} + +/* Parse boot command, set up registers - also used on reset */ + +t_stat vax860_boot_parse (int32 flag, char *ptr) +{ +char gbuf[CBUFSIZE]; +char *slptr, *regptr; +int32 i, r5v, unitno; +DEVICE *dptr; +UNIT *uptr; +DIB *dibp; +uint32 ba; +t_stat r; + +regptr = get_glyph (ptr, gbuf, 0); /* get glyph */ +if (slptr = strchr (gbuf, '/')) { /* found slash? */ + regptr = strchr (ptr, '/'); /* locate orig */ + *slptr = 0; /* zero in string */ + } +dptr = find_unit (gbuf, &uptr); /* find device */ +if ((dptr == NULL) || (uptr == NULL)) + return SCPE_ARG; +dibp = (DIB *) dptr->ctxt; /* get DIB */ +if (dibp == NULL) + ba = 0; +else + ba = dibp->ba; +unitno = (int32) (uptr - dptr->units); +r5v = 0; +if ((strncmp (regptr, "/R5:", 4) == 0) || + (strncmp (regptr, "/R5=", 4) == 0) || + (strncmp (regptr, "/r5:", 4) == 0) || + (strncmp (regptr, "/r5=", 4) == 0)) { + r5v = (int32) get_uint (regptr + 4, 16, LMASK, &r); + if (r != SCPE_OK) + return r; + } +else + if (*regptr == '/') { + r5v = (int32) get_uint (regptr + 1, 16, LMASK, &r); + if (r != SCPE_OK) + return r; + } + else { + if (*regptr != 0) + return SCPE_ARG; + } +for (i = 0; boot_tab[i].name != NULL; i++) { + if (strcmp (dptr->name, boot_tab[i].name) == 0) { + R[0] = boot_tab[i].code; + if (dptr->flags & DEV_MBUS) { + R[1] = ba + TR_MBA0; + R[2] = unitno; + } + else { + R[1] = TR_UBA; + R[2] = boot_tab[i].let | (ba & UBADDRMASK); + } + R[3] = unitno; + R[4] = 0; + R[5] = r5v; + return SCPE_OK; + } + } +return SCPE_NOFNC; +} + +/* Bootstrap - finish up bootstrap process */ + +t_stat cpu_boot (int32 unitno, DEVICE *dptr) +{ +t_stat r; + +r = cpu_load_bootcode (BOOT_CODE_FILENAME, BOOT_CODE_ARRAY, BOOT_CODE_SIZE, FALSE, 0x200); +if (r != SCPE_OK) + return r; +SP = PC = 512; +return SCPE_OK; +} + +/* A-Bus reset */ + +t_stat abus_reset (DEVICE *dptr) +{ +sim_vm_cmd = vax860_cmd; +return SCPE_OK; +} + +/* Build dib_tab from device list */ + +t_stat build_dib_tab (void) +{ +uint32 i; +DEVICE *dptr; +DIB *dibp; +t_stat r; + +init_nexus_tab (); +init_ubus_tab (); +init_mbus_tab (); +for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ + dibp = (DIB *) dptr->ctxt; /* get DIB */ + if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */ + if (dptr->flags & DEV_NEXUS) { /* Nexus? */ + if (r = build_nexus_tab (dptr, dibp)) /* add to dispatch table */ + return r; + } + else if (dptr->flags & DEV_MBUS) { /* Massbus? */ + if (r = build_mbus_tab (dptr, dibp)) + return r; + } + else { /* no, Unibus device */ + if (r = build_ubus_tab (dptr, dibp)) /* add to dispatch tab */ + return r; + } /* end else */ + } /* end if enabled */ + } /* end for */ +return SCPE_OK; +} + +t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (cptr == NULL) return SCPE_ARG; +if (strcmp(cptr, "8600") == 0) + sys_model = 0; +else if (strcmp(cptr, "8650") == 0) + sys_model = 1; +else + return SCPE_ARG; +return SCPE_OK; +} + +t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "model=%s", (sys_model ? "8650" : "8600")); +return SCPE_OK; +} diff --git a/VAX/vax860_defs.h b/VAX/vax860_defs.h new file mode 100644 index 00000000..f12cb954 --- /dev/null +++ b/VAX/vax860_defs.h @@ -0,0 +1,522 @@ +/* vax860_defs.h: VAX 8600 model-specific definitions file + + 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). + + 26-Dec-2012 MB First Version + + This file covers the VAX 8600, the fourth VAX. + + System memory map + + 0000 0000 - 1FFF FFFF main memory + + 2000 0000 - 2001 FFFF SBI0 adapter space + 2002 0000 - 200F FFFF reserved + 2008 0000 - 2008 00BF SBI0 registers + 2008 00C0 - 200F FFFF reserved + 2010 0000 - 2013 FFFF Unibus address space, Unibus 0 + 2014 0000 - 2017 FFFF Unibus address space, Unibus 1 + 2018 0000 - 201B FFFF Unibus address space, Unibus 2 + 201C 0000 - 201F FFFF Unibus address space, Unibus 3 + 2020 0000 - 21FF FFFF reserved + + 2200 0000 - 2201 FFFF SBI1 adapter space + 2202 0000 - 220F FFFF reserved + 2208 0000 - 2208 00BF SBI1 registers + 2208 00C0 - 220F FFFF reserved + 2210 0000 - 2213 FFFF Unibus address space, Unibus 4 + 2214 0000 - 2217 FFFF Unibus address space, Unibus 5 + 2218 0000 - 221B FFFF Unibus address space, Unibus 6 + 221C 0000 - 221F FFFF Unibus address space, Unibus 7 + 2220 0000 - 23FF FFFF reserved + + 2400 0000 - 2401 FFFF SBI2 adapter space + 2402 0000 - 240F FFFF reserved + 2408 0000 - 2408 00BF SBI2 registers + 2408 00C0 - 240F FFFF reserved + 2410 0000 - 2413 FFFF Unibus address space, Unibus 8 + 2414 0000 - 2417 FFFF Unibus address space, Unibus 9 + 2418 0000 - 241B FFFF Unibus address space, Unibus 10 + 241C 0000 - 241F FFFF Unibus address space, Unibus 11 + 2420 0000 - 25FF FFFF reserved + + 2600 0000 - 2601 FFFF SBI3 adapter space + 2602 0000 - 260F FFFF reserved + 2608 0000 - 2608 00BF SBI3 registers + 2608 00C0 - 260F FFFF reserved + 2610 0000 - 2613 FFFF Unibus address space, Unibus 12 + 2614 0000 - 2617 FFFF Unibus address space, Unibus 13 + 2618 0000 - 261B FFFF Unibus address space, Unibus 14 + 261C 0000 - 261F FFFF Unibus address space, Unibus 15 + 2620 0000 - 3FFF FFFF reserved +*/ + +#ifndef FULL_VAX +#define FULL_VAX 1 +#endif + +#ifndef _VAX_860_DEFS_H_ +#define _VAX_860_DEFS_H_ 1 + +/* Microcode constructs */ + +#define VAX860_SID (4 << 24) /* system ID */ +#define VAX860_TYP (0 << 23) /* sys type: 8600 */ +#define VAX865_TYP (1 << 23) /* sys type: 8650 */ +#define VAX860_ECO (7 << 19) /* ucode revision */ +#define VAX860_PLANT (0 << 12) /* plant (Salem NH) */ +#define VAX860_SN (1234) +#define CON_HLTPIN 0x0200 /* external CPU halt */ +#define CON_HLTINS 0x0600 /* HALT instruction */ +#define MCHK_RD_F 0x00 /* read fault */ +#define MCHK_RD_A 0xF4 /* read abort */ +#define MCHK_IBUF 0x0D /* read istream */ +#define VER_UCODE 0x1 /* Microcode version */ + +/* Interrupts */ + +#define IPL_HMAX 0x17 /* highest hwre level */ +#define IPL_HMIN 0x14 /* lowest hwre level */ +#define IPL_HLVL (IPL_HMAX - IPL_HMIN + 1) /* # hardware levels */ +#define IPL_SMAX 0xF /* highest swre level */ + +/* SBI Nexus constants */ + +#define NEXUS_NUM 16 /* number of nexus */ +#define MCTL_NUM 2 /* number of mem ctrl */ +#define MBA_NUM 2 /* number of MBA's */ +#define TR_MCTL0 1 /* nexus assignments */ +#define TR_MCTL1 2 +#define TR_UBA 3 +#define TR_MBA0 8 +#define TR_MBA1 9 +#define TR_CI 14 +#define NEXUS_HLVL (IPL_HMAX - IPL_HMIN + 1) +#define SCB_NEXUS 0x100 /* nexus intr base */ +#define SBI_FAULTS 0xFC000000 /* SBI fault flags */ + +/* Internal I/O interrupts - relative except for clock and console */ + +#define IPL_CLKINT 0x18 /* clock IPL */ +#define IPL_TTINT 0x14 /* console IPL */ + +#define IPL_MCTL0 (0x15 - IPL_HMIN) +#define IPL_MCTL1 (0x15 - IPL_HMIN) +#define IPL_UBA (0x15 - IPL_HMIN) +#define IPL_MBA0 (0x15 - IPL_HMIN) +#define IPL_MBA1 (0x15 - IPL_HMIN) +#define IPL_CI (0x15 - IPL_HMIN) + +/* Nexus interrupt macros */ + +#define SET_NEXUS_INT(dv) nexus_req[IPL_##dv] |= (1 << TR_##dv) +#define CLR_NEXUS_INT(dv) nexus_req[IPL_##dv] &= ~(1 << TR_##dv) + +/* Machine specific IPRs */ + +#define MT_ACCS 40 /* FPA control */ +#define MT_PAMACC 64 +#define MT_PAMLOC 65 +#define MT_CSWP 66 +#define MT_MDECC 67 +#define MT_MENA 68 +#define MT_MDCTL 69 +#define MT_MCCTL 70 +#define MT_MERG 71 +#define MT_CRBT 72 /* Console reboot */ +#define MT_DFI 73 +#define MT_EHSR 74 +#define MT_STXCS 76 +#define MT_STXDB 77 +#define MT_ESPA 78 +#define MT_ESPD 79 +#define MT_MAX MT_ESPD /* last valid IPR */ + +/* Machine specific reserved operand tests */ + +/* 780 microcode patch 37 - only test LR<23:0> for appropriate length */ + +#define ML_LR_TEST(r) if (((uint32)((r) & 0xFFFFFF)) > 0x200000) RSVD_OPND_FAULT + +/* 780 microcode patch 38 - only test PxBR<31>=1, PxBR<30> = 0, and xBR<1:0> = 0 */ + +#define ML_PXBR_TEST(r) if (((((uint32)(r)) & 0x80000000) == 0) || \ + ((((uint32)(r)) & 0x40000003) != 0)) RSVD_OPND_FAULT +#define ML_SBR_TEST(r) if ((((uint32)(r)) & 0xC0000003) != 0) RSVD_OPND_FAULT + +/* 780 microcode patch 78 - only test xCBB<1:0> = 0 */ + +#define ML_PA_TEST(r) if ((((uint32)(r)) & 0x00000003) != 0) RSVD_OPND_FAULT + +#define LP_AST_TEST(r) if ((r) > AST_MAX) RSVD_OPND_FAULT +#define LP_MBZ84_TEST(r) if ((((uint32)(r)) & 0xF8C00000) != 0) RSVD_OPND_FAULT +#define LP_MBZ92_TEST(r) if ((((uint32)(r)) & 0x7FC00000) != 0) RSVD_OPND_FAULT + +/* CPU */ + +#define CPU_MODEL_MODIFIERS \ + { MTAB_XTD|MTAB_VDV, 0, "MODEL", "MODEL", \ + &cpu_set_model, &cpu_show_model }, +/* Memory */ + +#define MAXMEMWIDTH 25 /* max mem, 4MB boards */ +#define MAXMEMSIZE (1 << MAXMEMWIDTH) +#define MAXMEMWIDTH_X 27 /* max mem, 16MB boards */ +#define MAXMEMSIZE_X (1 << MAXMEMWIDTH_X) +#define INITMEMSIZE (1 << MAXMEMWIDTH) /* initial memory size */ +#define MEMSIZE (cpu_unit.capac) +#define ADDR_IS_MEM(x) (((uint32) (x)) < MEMSIZE) +#define MEM_MODIFIERS { UNIT_MSIZE, (1u << 23), NULL, "8M", &cpu_set_size }, \ + { UNIT_MSIZE, (1u << 24), NULL, "16M", &cpu_set_size }, \ + { UNIT_MSIZE, (1u << 25), NULL, "32M", &cpu_set_size }, \ + { UNIT_MSIZE, (1u << 25) + (1u << 24), NULL, "48M", &cpu_set_size }, \ + { UNIT_MSIZE, (1u << 26), NULL, "64M", &cpu_set_size }, \ + { UNIT_MSIZE, (1u << 27), NULL, "128M", &cpu_set_size } + +/* Unibus I/O registers */ + +#define UBADDRWIDTH 18 /* Unibus addr width */ +#define UBADDRSIZE (1u << UBADDRWIDTH) /* Unibus addr length */ +#define UBADDRMASK (UBADDRSIZE - 1) /* Unibus addr mask */ +#define IOPAGEAWIDTH 13 /* IO addr width */ +#define IOPAGESIZE (1u << IOPAGEAWIDTH) /* IO page length */ +#define IOPAGEMASK (IOPAGESIZE - 1) /* IO addr mask */ +#define UBADDRBASE 0x20100000 /* Unibus addr base */ +#define IOPAGEBASE 0x2013E000 /* IO page base */ +#define ADDR_IS_IO(x) ((((uint32) (x)) >= UBADDRBASE) && \ + (((uint32) (x)) < (UBADDRBASE + UBADDRSIZE))) +#define ADDR_IS_IOP(x) (((uint32) (x)) >= IOPAGEBASE) + +/* Nexus register space */ + +#define REGAWIDTH 17 /* REG addr width */ +#define REG_V_NEXUS 13 /* nexus number */ +#define REG_M_NEXUS 0xF +#define REG_V_OFS 2 /* register number */ +#define REG_M_OFS 0x7FF +#define REGSIZE (1u << REGAWIDTH) /* REG length */ +#define REGBASE 0x20000000 /* REG addr base */ +#define ADDR_IS_REG(x) ((((uint32) (x)) >= REGBASE) && \ + (((uint32) (x)) < (REGBASE + REGSIZE))) +#define NEXUS_GETNEX(x) (((x) >> REG_V_NEXUS) & REG_M_NEXUS) +#define NEXUS_GETOFS(x) (((x) >> REG_V_OFS) & REG_M_OFS) + +/* SBI adapter space */ + +#define SBIAWIDTH 19 +#define SBIABASE 0x20080000 +#define SBIASIZE (1u << SBIAWIDTH) +#define ADDR_IS_SBIA(x) ((((uint32) (x)) >= SBIABASE) && \ + (((uint32) (x)) < (SBIABASE + SBIASIZE))) + +/* ROM address space in memory controllers */ + +#define ROMAWIDTH 12 /* ROM addr width */ +#define ROMSIZE (1u << ROMAWIDTH) /* ROM size */ +#define ROM0BASE (REGBASE + (TR_MCTL0 << REG_V_NEXUS) + 0x1000) +#define ROM1BASE (REGBASE + (TR_MCTL1 << REG_V_NEXUS) + 0x1000) +#define ADDR_IS_ROM0(x) ((((uint32) (x)) >= ROM0BASE) && \ + (((uint32) (x)) < (ROM0BASE + ROMSIZE))) +#define ADDR_IS_ROM1(x) ((((uint32) (x)) >= ROM1BASE) && \ + (((uint32) (x)) < (ROM1BASE + ROMSIZE))) +#define ADDR_IS_ROM(x) (ADDR_IS_ROM0 (x) || ADDR_IS_ROM1 (x)) + +/* Other address spaces */ + +#define ADDR_IS_CDG(x) (0) +#define ADDR_IS_NVR(x) (0) + +/* Unibus I/O modes */ + +#define READ 0 /* PDP-11 compatibility */ +#define WRITE (L_WORD) +#define WRITEB (L_BYTE) + +/* Common CSI flags */ + +#define CSR_V_GO 0 /* go */ +#define CSR_V_IE 6 /* interrupt enable */ +#define CSR_V_DONE 7 /* done */ +#define CSR_V_BUSY 11 /* busy */ +#define CSR_V_ERR 15 /* error */ +#define CSR_GO (1u << CSR_V_GO) +#define CSR_IE (1u << CSR_V_IE) +#define CSR_DONE (1u << CSR_V_DONE) +#define CSR_BUSY (1u << CSR_V_BUSY) +#define CSR_ERR (1u << CSR_V_ERR) + +/* Timers */ + +#define TMR_CLK 0 /* 100Hz clock */ + +/* I/O system definitions */ + +#define DZ_MUXES 4 /* max # of DZV muxes */ +#define DZ_LINES 8 /* lines per DZV mux */ +#define VH_MUXES 4 /* max # of DHU muxes */ +#define DLX_LINES 16 /* max # of KL11/DL11's */ +#define DCX_LINES 16 /* max # of DC11's */ +#define MT_MAXFR (1 << 16) /* magtape max rec */ + +#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ +#define DEV_V_MBUS (DEV_V_UF + 1) /* Massbus */ +#define DEV_V_NEXUS (DEV_V_UF + 2) /* Nexus */ +#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */ +#define DEV_V_FFUF (DEV_V_UF + 4) /* first free flag */ +#define DEV_UBUS (1u << DEV_V_UBUS) +#define DEV_MBUS (1u << DEV_V_MBUS) +#define DEV_NEXUS (1u << DEV_V_NEXUS) +#define DEV_FLTA (1u << DEV_V_FLTA) +#define DEV_QBUS (0) +#define DEV_Q18 (0) + +#define UNIBUS TRUE /* Unibus only */ + +#define DEV_RDX 16 /* default device radix */ + +/* Device information block + + For Massbus devices, + ba = Massbus number + lnt = Massbus ctrl type + ack[0] = abort routine + + For Nexus devices, + ba = Nexus number + lnt = number of consecutive nexi */ + +#define VEC_DEVMAX 4 /* max device vec */ + +typedef struct { + uint32 ba; /* base addr */ + uint32 lnt; /* length */ + t_stat (*rd)(int32 *dat, int32 ad, int32 md); + t_stat (*wr)(int32 dat, int32 ad, int32 md); + int32 vnum; /* vectors: number */ + int32 vloc; /* locator */ + int32 vec; /* value */ + int32 (*ack[VEC_DEVMAX])(void); /* ack routine */ + } DIB; + +/* Unibus I/O page layout - XUB,RQB,RQC,RQD float based on number of DZ's + Massbus devices (RP, TU) do not appear in the Unibus IO page */ + +#define IOBA_FLOAT (0) /* Assigned by Auto Configure */ + +#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */ +#define IOLN_DZ 010 +#define IOBA_XUB (IOPAGEBASE + 000330 + (020 * (DZ_MUXES / 2))) +#define IOLN_XUB 010 +#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2))) +#define IOLN_RQB 004 +#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB) +#define IOLN_RQC 004 +#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC) +#define IOLN_RQD 004 +#define IOBA_RQ (IOPAGEBASE + 012150) /* UDA50 */ +#define IOLN_RQ 004 +#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */ +#define IOLN_TS 004 +#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */ +#define IOLN_RL 012 +#define IOBA_XQ (IOPAGEBASE + 014440) /* DEQNA/DELQA */ +#define IOLN_XQ 020 +#define IOBA_XQB (IOPAGEBASE + 014460) /* 2nd DEQNA/DELQA */ +#define IOLN_XQB 020 +#define IOBA_TQ (IOPAGEBASE + 014500) /* TMSCP */ +#define IOLN_TQ 004 +#define IOBA_XU (IOPAGEBASE + 014510) /* DEUNA/DELUA */ +#define IOLN_XU 010 +#define IOBA_CR (IOPAGEBASE + 017160) /* CD/CR/CM */ +#define IOLN_CR 010 +#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */ +#define IOLN_RX 004 +#define IOBA_RY (IOPAGEBASE + 017170) /* RXV21 */ +#define IOLN_RY 004 +#define IOBA_QDSS (IOPAGEBASE + 017400) /* QDSS */ +#define IOLN_QDSS 002 +#define IOBA_HK (IOPAGEBASE + 017440) /* RK611 */ +#define IOLN_HK 040 +#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */ +#define IOLN_LPT 004 +#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */ +#define IOLN_PTR 004 +#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */ +#define IOLN_PTP 004 + +/* Interrupt assignments; within each level, priority is right to left */ + +#define INT_V_DZRX 0 /* BR5 */ +#define INT_V_DZTX 1 +#define INT_V_HK 2 +#define INT_V_RL 3 +#define INT_V_RQ 4 +#define INT_V_TQ 5 +#define INT_V_TS 6 +#define INT_V_RY 7 +#define INT_V_XU 8 +#define INT_V_DMCRX 9 +#define INT_V_DMCTX 10 +#define INT_V_LPT 0 /* BR4 */ +#define INT_V_PTR 1 +#define INT_V_PTP 2 +#define INT_V_CR 3 +#define INT_V_VHRX 4 +#define INT_V_VHTX 5 + +#define INT_DZRX (1u << INT_V_DZRX) +#define INT_DZTX (1u << INT_V_DZTX) +#define INT_HK (1u << INT_V_HK) +#define INT_RL (1u << INT_V_RL) +#define INT_RQ (1u << INT_V_RQ) +#define INT_TQ (1u << INT_V_TQ) +#define INT_TS (1u << INT_V_TS) +#define INT_RY (1u << INT_V_RY) +#define INT_XU (1u << INT_V_XU) +#define INT_LPT (1u << INT_V_LPT) +#define INT_VHRX (1u << INT_V_VHRX) +#define INT_VHTX (1u << INT_V_VHTX) +#define INT_PTR (1u << INT_V_PTR) +#define INT_PTP (1u << INT_V_PTP) +#define INT_CR (1u << INT_V_CR) +#define INT_DMCRX (1u << INT_V_DMCRX) +#define INT_DMCTX (1u << INT_V_DMCTX) +#define IPL_DZRX (0x15 - IPL_HMIN) +#define IPL_DZTX (0x15 - IPL_HMIN) +#define IPL_HK (0x15 - IPL_HMIN) +#define IPL_RL (0x15 - IPL_HMIN) +#define IPL_RQ (0x15 - IPL_HMIN) +#define IPL_TQ (0x15 - IPL_HMIN) +#define IPL_TS (0x15 - IPL_HMIN) +#define IPL_RY (0x15 - IPL_HMIN) +#define IPL_XU (0x15 - IPL_HMIN) +#define IPL_LPT (0x14 - IPL_HMIN) +#define IPL_PTR (0x14 - IPL_HMIN) +#define IPL_PTP (0x14 - IPL_HMIN) +#define IPL_CR (0x14 - IPL_HMIN) +#define IPL_VHRX (0x14 - IPL_HMIN) +#define IPL_VHTX (0x14 - IPL_HMIN) +#define IPL_DMCRX (0x15 - IPL_HMIN) +#define IPL_DMCTX (0x15 - IPL_HMIN) + +/* Device vectors */ + +#define VEC_FLOAT (0) /* Assigned by Auto Configure */ + +#define VEC_QBUS 0 +#define VEC_Q 0000 +#define VEC_PTR 0070 +#define VEC_PTP 0074 +#define VEC_XQ 0120 +#define VEC_XU 0120 +#define VEC_RQ 0154 +#define VEC_RL 0160 +#define VEC_LPT 0200 +#define VEC_HK 0210 +#define VEC_TS 0224 +#define VEC_CR 0230 +#define VEC_TQ 0260 +#define VEC_RX 0264 +#define VEC_RY 0264 +#define VEC_DZRX 0300 +#define VEC_DZTX 0304 + +/* Interrupt macros */ + +#define IVCL(dv) ((IPL_##dv * 32) + INT_V_##dv) +#define NVCL(dv) ((IPL_##dv * 32) + TR_##dv) +#define IREQ(dv) int_req[IPL_##dv] +#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv) +#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv) +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ + +/* Logging */ + +#define LOG_CPU_I 0x1 /* intexc */ +#define LOG_CPU_R 0x2 /* REI */ +#define LOG_CPU_P 0x4 /* context */ + +/* Massbus definitions */ + +#define MBA_RP (TR_MBA0 - TR_MBA0) /* MBA for RP */ +#define MBA_TU (TR_MBA1 - TR_MBA0) /* MBA for TU */ +#define MBA_RMASK 0x1F /* max 32 reg */ +#define MBE_NXD 1 /* nx drive */ +#define MBE_NXR 2 /* nx reg */ +#define MBE_GOE 3 /* err on GO */ + +/* Boot definitions */ + +#define BOOT_MB 0 /* device codes */ +#define BOOT_HK 1 /* for VMB */ +#define BOOT_RL 2 +#define BOOT_UDA 17 +#define BOOT_TK 18 +#define BOOT_CS 64 + +/* Function prototypes for virtual memory interface */ + +int32 Read (uint32 va, int32 lnt, int32 acc); +void Write (uint32 va, int32 val, int32 lnt, int32 acc); + +/* Function prototypes for physical memory interface (inlined) */ + +SIM_INLINE int32 ReadB (uint32 pa); +SIM_INLINE int32 ReadW (uint32 pa); +SIM_INLINE int32 ReadL (uint32 pa); +SIM_INLINE int32 ReadLP (uint32 pa); +SIM_INLINE void WriteB (uint32 pa, int32 val); +SIM_INLINE void WriteW (uint32 pa, int32 val); +SIM_INLINE void WriteL (uint32 pa, int32 val); +void WriteLP (uint32 pa, int32 val); + +/* Function prototypes for I/O */ + +int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf); +int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf); +int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf); +int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf); + +int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf); +int32 mba_wrbufW (uint32 mbus, int32 bc, uint16 *buf); +int32 mba_chbufW (uint32 mbus, int32 bc, uint16 *buf); +int32 mba_get_bc (uint32 mbus); +void mba_upd_ata (uint32 mbus, uint32 val); +void mba_set_exc (uint32 mbus); +void mba_set_don (uint32 mbus); +void mba_set_enbdis (uint32 mbus, t_bool dis); +t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc); + +t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc); + +void sbi_set_errcnf (void); +int32 clk_cosched (int32 wait); + +t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc); + +#include "pdp11_io_lib.h" + +#endif diff --git a/VAX/vax860_sbia.c b/VAX/vax860_sbia.c new file mode 100644 index 00000000..50bdb83f --- /dev/null +++ b/VAX/vax860_sbia.c @@ -0,0 +1,359 @@ +/* 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 */ + +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 */ + +extern int32 R[16]; +extern int32 PSL; +extern int32 ASTLVL, SISR; +extern jmp_buf save_env; +extern int32 trpirq; +extern int32 p1; +extern int32 mchk_ref; +extern int32 crd_err; +extern int32 sim_switches; +extern DEVICE *sim_devices[]; +extern FILE *sim_log; +extern int32 fault_PC; /* fault PC */ +extern UNIT cpu_unit; + +t_stat sbia_reset (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 + }; + +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 */ + 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; +} + +/* Show nexus */ + +t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "nexus=%d", 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))) { + printf ("Nexus %s conflict at %d\n", sim_dname (dptr), dibp->ba); + if (sim_log) + fprintf (sim_log, "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; +} diff --git a/VAX/vax860_stddev.c b/VAX/vax860_stddev.c new file mode 100644 index 00000000..24f39c36 --- /dev/null +++ b/VAX/vax860_stddev.c @@ -0,0 +1,1154 @@ +/* vax860_stddev.c: VAX 8600 standard I/O devices + + Copyright (c) 2011-2012, Matt Burke + This module incorporates code from SimH, Copyright (c) 1998-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). + + tti console input + tto console output + cs console RL02 + todr TODR clock + tmr interval timer + + 26-Dec-2012 MB First Version +*/ + +#include "vax_defs.h" +#include + +/* Terminal definitions */ + +#define RXCS_V_DTR 16 /* logical carrier */ +#define RXCS_M_DTR 0xF +#define RXCS_DTR (RXCS_M_DTR << RXCS_V_DTR) +#define RXCS_RD (CSR_DONE + CSR_IE + RXCS_DTR) /* terminal input */ +#define RXCS_WR (CSR_IE) +#define RXDB_V_LC 16 /* logical carrier */ +#define RXDB_V_IDC 8 /* ID Code */ +#define RXDB_M_IDC 0xF +#define RXDB_IDC (TXCS_M_IDC << TXCS_V_IDC) +#define TXCS_V_IDC 8 /* ID Code */ +#define TXCS_M_IDC 0xF +#define TXCS_IDC (TXCS_M_IDC << TXCS_V_IDC) +#define TXCS_WMN 0x8000 /* Write mask now */ +#define TXCS_V_TEN 16 /* Transmitter en */ +#define TXCS_M_TEN 0xF +#define TXCS_TEN (TXCS_M_TEN << TXCS_V_TEN) +#define TXCS_RD (CSR_DONE + CSR_IE + TXCS_TEN + TXCS_IDC) /* terminal output */ +#define TXCS_WR (CSR_IE + TXCS_TEN) +#define ID_CT 0 /* console terminal */ +#define ID_RS 1 /* remote services */ +#define ID_EMM 2 /* environmental monitoring module */ +#define ID_LC 3 /* logical console */ +#define ID_M_CT (1u << ID_CT) +#define ID_M_RS (1u << ID_RS) +#define ID_M_EMM (1u << ID_EMM) +#define ID_M_LC (1u << ID_LC) +#define RDY u3 + +/* Clock definitions */ + +#define TMR_CSR_ERR 0x80000000 /* error W1C */ +#define TMR_CSR_DON 0x00000080 /* done W1C */ +#define TMR_CSR_IE 0x00000040 /* int enb RW */ +#define TMR_CSR_SGL 0x00000020 /* single WO */ +#define TMR_CSR_XFR 0x00000010 /* xfer WO */ +#define TMR_CSR_RUN 0x00000001 /* run RW */ +#define TMR_CSR_RD (TMR_CSR_W1C | TMR_CSR_WR) +#define TMR_CSR_W1C (TMR_CSR_ERR | TMR_CSR_DON) +#define TMR_CSR_WR (TMR_CSR_IE | TMR_CSR_RUN) +#define TMR_INC 10000 /* usec/interval */ +#define CLK_DELAY 5000 /* 100 Hz */ +#define TMXR_MULT 1 /* 100 Hz */ + +/* Logical console definitions */ + +#define LC_NUMBY 128 /* response buffer size */ + +#define LC_IDLE 0 /* idle state */ +#define LC_READDAT 1 /* read data */ + +#define LC_V_FNC 0 /* logical console function */ +#define LC_M_FNC 0xFF +#define LC_FNCCW 0x3 /* clear warm start flag */ +#define LC_FNCCS 0x4 /* clear cold start flag */ +#define LC_FNCMV 0x12 /* microcode version */ +#define LC_FNCAC 0x13 /* array configuration */ +#define LC_FNCSS 0x30 /* snapshot file status */ +#define LC_FNCCA 0x70 /* cancel all */ +#define LC_GETFNC(x) (((x) >> LC_V_FNC) & LC_M_FNC) + +/* Console storage definitions */ + +#define STXCS_FNC 0xF +#define STXCS_V_DA 8 +#define STXCS_M_DA 0xFFFF +#define STXCS_DA (STXCS_M_DA << STXCS_V_DA) +#define STXCS_GETDA(x) (((x) >> STXCS_V_DA) & STXCS_M_DA) +#define STXCS_V_STS 24 +#define STXCS_M_STS 0xFF +#define STXCS_STS (STXCS_M_STS << STXCS_V_STS) +#define STXCS_WR (STXCS_FNC | CSR_DONE | CSR_IE | STXCS_DA) + +#define STXDB_DAT 0xFFFF + +#define RL_NUMBY 256 /* bytes/sector */ +#define RL_NUMWD 128 /* words/sector */ +#define RL_NUMSC 40 /* sectors/surface */ +#define RL_NUMSF 2 /* surfaces/cylinder */ +#define RL_NUMCY 512 /* cylinders/drive */ +#define RL02_SIZE (RL_NUMCY * RL_NUMSF * RL_NUMSC * RL_NUMWD) /* words/drive */ + +/* Parameters in the unit descriptor */ + +#define TRK u3 /* current track */ +#define STAT u4 /* status */ + +#define UNIT_V_WLK (UNIT_V_UF + 0) /* hwre write lock */ +#define UNIT_WLK (1u << UNIT_V_WLK) + +#define RLCS_DRDY 0000001 /* drive ready */ +#define RLCS_M_DRIVE 03 +#define RLCS_V_DRIVE 8 +#define RLCS_INCMP 0002000 /* incomplete */ +#define RLCS_CRC 0004000 /* CRC error */ +#define RLCS_HDE 0010000 /* header error */ +#define RLCS_NXM 0020000 /* non-exist memory */ +#define RLCS_DRE 0040000 /* drive error */ +#define RLCS_ERR 0100000 /* error summary */ +#define RLCS_ALLERR (RLCS_ERR+RLCS_DRE+RLCS_NXM+RLCS_HDE+RLCS_CRC+RLCS_INCMP) +#define RLCS_RW 0001776 /* read/write */ + +/* RL Function Codes */ + +#define RLFC_NOP 0 /* No Operation */ +#define RLFC_CONT 2 /* Continue Transaction */ +#define RLFC_ABORT 3 /* Abort Current Transfer */ +#define RLFC_STS 4 /* Read Device Status */ +#define RLFC_WRITE 5 /* Write Block Data */ +#define RLFC_READ 6 /* Read Block Data */ + +/* RL Status Codes */ + +#define RLST_COMP 1 /* Transaction Complete */ +#define RLST_CONT 2 /* Continue Transaction */ +#define RLST_ABORT 3 /* Transaction Aborted */ +#define RLST_STS 4 /* Return Device Status */ +#define RLST_HERR 80 /* Handshake Error */ +#define RLST_HDERR 81 /* Hardware Error */ + +/* RL States */ + +#define RL_IDLE 0 +#define RL_READ 1 +#define RL_WRITE 2 +#define RL_STATUS 3 +#define RL_ABORT 4 + +#define RL_CSR 0 /* CSR selected */ +#define RL_MP 1 /* MP selected */ + +/* RLDS, NI = not implemented, * = kept in STAT, ^ = kept in TRK */ + +#define RLDS_LOAD 0 /* no cartridge */ +#define RLDS_LOCK 5 /* lock on */ +#define RLDS_BHO 0000010 /* brushes home NI */ +#define RLDS_HDO 0000020 /* heads out NI */ +#define RLDS_CVO 0000040 /* cover open NI */ +#define RLDS_HD 0000100 /* head select ^ */ +#define RLDS_RL02 0000200 /* RL02 */ +#define RLDS_DSE 0000400 /* drv sel err NI */ +#define RLDS_VCK 0001000 /* vol check * */ +#define RLDS_WGE 0002000 /* wr gate err * */ +#define RLDS_SPE 0004000 /* spin err * */ +#define RLDS_STO 0010000 /* seek time out NI */ +#define RLDS_WLK 0020000 /* wr locked */ +#define RLDS_HCE 0040000 /* hd curr err NI */ +#define RLDS_WDE 0100000 /* wr data err NI */ +#define RLDS_ATT (RLDS_HDO+RLDS_BHO+RLDS_LOCK) /* att status */ +#define RLDS_UNATT (RLDS_CVO+RLDS_LOAD) /* unatt status */ +#define RLDS_ERR (RLDS_WDE+RLDS_HCE+RLDS_STO+RLDS_SPE+RLDS_WGE+ \ + RLDS_VCK+RLDS_DSE) /* errors bits */ + +int32 tti_csr = 0; /* control/status */ +int32 tti_buf = 0; /* buffer */ +int32 tti_int = 0; /* interrupt */ +int32 tto_csr = 0; /* control/status */ +int32 tto_int = 0; /* interrupt */ + +int32 tmr_iccs = 0; /* interval timer csr */ +uint32 tmr_icr = 0; /* curr interval */ +uint32 tmr_nicr = 0; /* next interval */ +uint32 tmr_inc = 0; /* timer increment */ +int32 tmr_sav = 0; /* timer save */ +int32 tmr_int = 0; /* interrupt */ +int32 tmr_use_100hz = 1; /* use 100Hz for timer */ +int32 clk_tps = 100; /* ticks/second */ +int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */ +int32 tmr_poll = CLK_DELAY; /* pgm timer poll */ +int32 todr_reg = 0; /* TODR register */ +struct todr_battery_info { + uint32 toy_gmtbase; /* GMT base of set value */ + uint32 toy_gmtbasemsec; /* The milliseconds of the set value */ + }; +typedef struct todr_battery_info TOY; + +int32 lc_fnc = 0; /* function */ +int32 lc_cwait = 50; /* command time */ +int32 lc_xwait = 20; /* tr set time */ +uint8 lc_buf[LC_NUMBY] = { 0 }; /* response buffer */ +int32 lc_bptr = 0; /* buffer pointer */ +int32 lc_dlen = 0; /* buffer data len */ + +int32 csi_int = 0; /* interrupt */ +int32 cso_csr = 0; /* control/status */ +int32 cso_buf = 0; /* buffer */ + +int32 rlcs_swait = 10; /* command time */ +int32 rlcs_state = RL_IDLE; /* protocol state */ +int32 rlcs_sts_reg = RL_CSR; /* status register */ +int32 rlcs_csr = 0; /* control/status */ +int32 rlcs_mp = 0; +int32 rlcs_bcnt = 0; /* byte count */ +uint16 *rlcs_buf = NULL; + +extern int32 sim_switches; +extern jmp_buf save_env; +extern UNIT cpu_unit; +extern int32 brk_req; + +t_stat tti_svc (UNIT *uptr); +t_stat tto_svc (UNIT *uptr); +t_stat clk_svc (UNIT *uptr); +t_stat tmr_svc (UNIT *uptr); +t_stat lc_svc (UNIT *uptr); +t_stat rlcs_svc (UNIT *uptr); +t_stat tti_reset (DEVICE *dptr); +t_stat tto_reset (DEVICE *dptr); +t_stat clk_reset (DEVICE *dptr); +t_stat clk_attach (UNIT *uptr, char *cptr); +t_stat clk_detach (UNIT *uptr); +t_stat tmr_reset (DEVICE *dptr); +t_stat lc_reset (DEVICE *dptr); +t_stat rlcs_reset (DEVICE *dptr); +t_stat rlcs_attach (UNIT *uptr, char *cptr); +int32 icr_rd (t_bool interp); +void tmr_incr (uint32 inc); +void tmr_sched (void); +t_stat todr_resync (void); +t_stat lc_wr_txdb (int32 data); + +extern int32 con_halt (int32 code, int32 cc); + +/* TTI data structures + + tti_dev TTI device descriptor + tti_unit TTI unit descriptor + tti_reg TTI register list +*/ + +UNIT tti_unit[] = { + { UDATA (&tti_svc, TT_MODE_8B, 0), 0 }, + { UDATA (&tti_svc, TT_MODE_8B, 0), 0 }, + { UDATA (&tti_svc, TT_MODE_8B, 0), 0 }, + { UDATA (&tti_svc, TT_MODE_8B, 0), 0 }, + }; + +REG tti_reg[] = { + { HRDATA (RXDB, tti_buf, 32) }, + { HRDATA (RXCS, tti_csr, 32) }, + { FLDATA (INT, tti_int, 0) }, + { FLDATA (DONE, tti_csr, CSR_V_DONE) }, + { FLDATA (IE, tti_csr, CSR_V_IE) }, + { URDATA (POS, tti_unit[0].pos, 10, T_ADDR_W, 0, 4, PV_LEFT) }, + { URDATA (TIME, tti_unit[0].wait, 10, 24, 0, 4, PV_LEFT) }, + { NULL } + }; + +MTAB tti_mod[] = { + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { 0 } + }; + +DEVICE tti_dev = { + "TTI", tti_unit, tti_reg, tti_mod, + 4, 10, 31, 1, 16, 8, + NULL, NULL, &tti_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +/* TTO data structures + + tto_dev TTO device descriptor + tto_unit TTO unit descriptor + tto_reg TTO register list +*/ + +UNIT tto_unit[] = { + { UDATA (&tto_svc, TT_MODE_8B, 0), SERIAL_OUT_WAIT }, + { UDATA (&tto_svc, TT_MODE_8B, 0), SERIAL_OUT_WAIT }, + { UDATA (&tto_svc, TT_MODE_8B, 0), SERIAL_OUT_WAIT }, + { UDATA (&tto_svc, TT_MODE_8B, 0), SERIAL_OUT_WAIT }, + }; + +REG tto_reg[] = { + { URDATA (TXDB, tto_unit[0].buf, 16, 32, 0, 4, 0) }, + { HRDATA (TXCS, tto_csr, 32) }, + { FLDATA (INT, tto_int, 0) }, + { FLDATA (DONE, tto_csr, CSR_V_DONE) }, + { FLDATA (IE, tto_csr, CSR_V_IE) }, + { URDATA (POS, tto_unit[0].pos, 10, T_ADDR_W, 0, 4, PV_LEFT) }, + { URDATA (TIME, tto_unit[0].wait, 10, 24, 0, 4, PV_LEFT + REG_NZ) }, + { NULL } + }; + +MTAB tto_mod[] = { + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, + { 0 } + }; + +DEVICE tto_dev = { + "TTO", tto_unit, tto_reg, tto_mod, + 4, 10, 31, 1, 16, 8, + NULL, NULL, &tto_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +/* TODR and TMR data structures */ + +UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE+UNIT_FIX, sizeof(TOY)), CLK_DELAY };/* 100Hz */ + +REG clk_reg[] = { + { DRDATA (TODR, todr_reg, 32), PV_LEFT }, + { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, + { DRDATA (TPS, clk_tps, 8), REG_HIDDEN + REG_NZ + PV_LEFT }, +#if defined (SIM_ASYNCH_IO) + { DRDATA (LATENCY, sim_asynch_latency, 32), PV_LEFT }, + { DRDATA (INST_LATENCY, sim_asynch_inst_latency, 32), PV_LEFT }, +#endif + { NULL } + }; + +DEVICE clk_dev = { + "TODR", &clk_unit, clk_reg, NULL, + 1, 0, 8, 4, 0, 32, + NULL, NULL, &clk_reset, + NULL, &clk_attach, &clk_detach, + NULL, 0 + }; + +UNIT tmr_unit = { UDATA (&tmr_svc, 0, 0) }; /* timer */ + +REG tmr_reg[] = { + { HRDATA (ICCS, tmr_iccs, 32) }, + { HRDATA (ICR, tmr_icr, 32) }, + { HRDATA (NICR, tmr_nicr, 32) }, + { HRDATA (INCR, tmr_inc, 32), REG_HIDDEN }, + { HRDATA (SAVE, tmr_sav, 32), REG_HIDDEN }, + { FLDATA (USE100HZ, tmr_use_100hz, 0), REG_HIDDEN }, + { FLDATA (INT, tmr_int, 0) }, + { NULL } + }; + +DEVICE tmr_dev = { + "TMR", &tmr_unit, tmr_reg, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &tmr_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +/* Console storage structures + + rlcs_dev CS device descriptor + rlcs_unit CS unit list + rlcs_reg CS register list + rlcs_mod CS modifier list +*/ + +UNIT rlcs_unit = { UDATA (&rlcs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_ROABLE, RL02_SIZE) }; + +REG rlcs_reg[] = { + { HRDATA (CSR, rlcs_csr, 16) }, + { HRDATA (MP, rlcs_mp, 16) }, + { DRDATA (BCNT, rlcs_bcnt, 7) }, + { DRDATA (STIME, rlcs_swait, 24), PV_LEFT }, + { NULL } + }; + +MTAB rlcs_mod[] = { + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { 0 } + }; + +DEVICE rlcs_dev = { + "CS", &rlcs_unit, rlcs_reg, rlcs_mod, + 1, 10, 24, 1, 16, 16, + NULL, NULL, &rlcs_reset, + NULL, &rlcs_attach, NULL, + NULL, 0 + }; + +/* Terminal MxPR routines + + rxcs_rd/wr input control/status + rxdb_rd input buffer + txcs_rd/wr output control/status + txdb_wr output buffer +*/ + +int32 rxcs_rd (void) +{ +return (tti_csr & RXCS_RD); +} + +void rxcs_wr (int32 data) +{ +if ((data & CSR_IE) == 0) + tti_int = 0; +else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) + tti_int = 1; +tti_csr = (tti_csr & ~RXCS_WR) | (data & RXCS_WR); +return; +} + +int32 rxdb_rd (void) +{ +int32 t = tti_buf; +t = t | ((ID_M_LC | ID_M_EMM | ID_M_CT) << RXDB_V_LC); /* char + DTR for hard-wired lines */ +tti_csr = tti_csr & ~CSR_DONE; /* clr done */ +tti_int = 0; +return t; +} + +void tto_update_int (void) +{ +int32 id = 0; + +tto_csr = tto_csr & ~TXCS_IDC; +if ((tto_csr & (ID_M_LC << TXCS_V_TEN)) && + (tto_unit[ID_LC].RDY)) /* logical console enabled and ready? */ + id = ID_LC; +else if ((tto_csr & (ID_M_EMM << TXCS_V_TEN)) && + (tto_unit[ID_EMM].RDY)) /* EMM enabled and ready? */ + id = ID_EMM; +else if ((tto_csr & (ID_M_RS << TXCS_V_TEN)) && + (tto_unit[ID_RS].RDY)) /* remote services enabled and ready? */ + id = ID_RS; +else if ((tto_csr & (ID_M_CT << TXCS_V_TEN)) && + (tto_unit[ID_CT].RDY)) /* console terminal enabled and ready? */ + id = ID_CT; +else id = 0xF; /* no lines enabled */ +tto_csr = tto_csr | (id << TXCS_V_IDC); +tto_csr = tto_csr | CSR_DONE; +if (tto_csr & CSR_IE) + tto_int = 1; +} + +int32 txcs_rd (void) +{ +return (tto_csr & TXCS_RD); +} + +void txcs_wr (int32 data) +{ +tto_csr = (tto_csr & ~TXCS_WR) | (data & TXCS_WR); +if (data & TXCS_WMN) /* updating mask? */ + tto_update_int (); +if ((data & CSR_IE) == 0) + tto_int = 0; +else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) + tto_int = 1; +return; +} + +void txdb_wr (int32 data) +{ +int32 dest = (tto_csr >> TXCS_V_IDC) & TXCS_M_IDC; +if ((dest >= ID_CT) && (dest <= ID_LC)) { /* valid line? */ + tto_csr = tto_csr & ~CSR_DONE; /* clear flag */ + tto_int = 0; /* clear int */ + tto_unit[dest].buf = data & WMASK; + tto_unit[dest].RDY = 0; + sim_activate (&tto_unit[dest], tto_unit[dest].wait);/* activate unit */ + } +return; +} + +int32 stxcs_rd (void) +{ +return cso_csr; +} + +void stxcs_wr (int32 data) +{ +int32 fnc = data & STXCS_FNC; +cso_csr = (cso_csr & ~STXCS_WR) | (data & STXCS_WR); +cso_csr = cso_csr & ~STXCS_STS; + +switch (fnc) { + case RLFC_NOP: + break; + + case RLFC_CONT: + rlcs_bcnt = 0; + case RLFC_STS: + rlcs_state = RL_STATUS; + cso_csr = cso_csr & ~CSR_DONE; /* clear done */ + sim_activate (&rlcs_unit, rlcs_swait); + break; + + case RLFC_ABORT: + rlcs_state = RL_ABORT; + cso_csr = cso_csr & ~CSR_DONE; /* clear done */ + sim_activate (&rlcs_unit, rlcs_swait); + break; + + case RLFC_WRITE: + rlcs_state = RL_WRITE; + cso_csr = cso_csr & ~CSR_DONE; /* clear done */ + sim_activate (&rlcs_unit, rlcs_swait); + break; + + case RLFC_READ: + rlcs_state = RL_READ; + cso_csr = cso_csr & ~CSR_DONE; /* clear done */ + sim_activate (&rlcs_unit, rlcs_swait); + break; + + default: + printf ("CS: Unknown Command: %d\n", fnc); + } +} + +int32 stxdb_rd (void) +{ +return cso_buf & STXDB_DAT; +} + +void stxdb_wr (int32 data) +{ +cso_buf = data & STXDB_DAT; + +if (rlcs_state == RL_WRITE) { + rlcs_buf[rlcs_bcnt] = cso_buf; + rlcs_bcnt++; + } +} + +/* Terminal input service (poll for character) */ + +t_stat tti_svc (UNIT *uptr) +{ +int32 c; +int32 line = uptr - tti_dev.units; + +switch (line) { + + case ID_CT: /* console terminal */ + sim_activate (uptr, KBD_WAIT (uptr->wait, clk_cosched (tmr_poll))); + /* continue poll */ + if ((tti_csr & CSR_DONE) == 0) { /* prev data taken? */ + if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return c; + if (c & SCPE_BREAK) /* break? */ + tti_buf = 0; + else tti_buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags)); + } + break; + + case ID_LC: /* logical console */ + if (lc_bptr > 0) { + if ((tti_csr & CSR_DONE) == 0) { /* prev data taken? */ + tti_buf = lc_buf[--lc_bptr]; /* get next byte */ + tti_buf |= (ID_LC << RXDB_V_IDC); /* source = logical console */ + if (lc_bptr == 0) /* buffer empty? */ + break; /* done */ + } + sim_activate (uptr, lc_xwait); /* schedule next */ + } + break; + } +uptr->pos = uptr->pos + 1; +tti_csr = tti_csr | CSR_DONE; +if (tti_csr & CSR_IE) + tti_int = 1; +return SCPE_OK; +} + +/* Terminal input reset */ + +t_stat tti_reset (DEVICE *dptr) +{ +tti_buf = 0; +tti_csr = 0; +tti_int = 0; +sim_activate_abs (&tti_unit[ID_CT], KBD_WAIT (tti_unit[ID_CT].wait, tmr_poll)); +return SCPE_OK; +} + +/* Terminal output service (output character) */ + +t_stat tto_svc (UNIT *uptr) +{ +int32 c; +int32 line = uptr - tto_dev.units; +t_stat r; + +switch (line) { + + case ID_CT: /* console terminal */ + c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags)); + if (c >= 0) { + if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* retry */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } + } + break; + + case ID_LC: /* logical console */ + lc_wr_txdb (uptr->buf); + break; + } +uptr->pos = uptr->pos + 1; +uptr->RDY = 1; +tto_update_int (); +return SCPE_OK; +} + +/* Terminal output reset */ + +t_stat tto_reset (DEVICE *dptr) +{ +tto_csr = (ID_M_CT << TXCS_V_TEN) | CSR_DONE; /* console enabled + done */ +tto_int = 0; +tto_unit[ID_CT].RDY = 1; /* all lines ready */ +tto_unit[ID_RS].RDY = 1; +tto_unit[ID_EMM].RDY = 1; +tto_unit[ID_LC].RDY = 1; +sim_cancel (&tto_unit[ID_CT]); /* deactivate units */ +sim_cancel (&tto_unit[ID_RS]); +sim_cancel (&tto_unit[ID_EMM]); +sim_cancel (&tto_unit[ID_LC]); +return SCPE_OK; +} + +/* Programmable timer + + The architected VAX timer, which increments at 1Mhz, cannot be + accurately simulated due to the overhead that would be required + for 1M clock events per second. Instead, a hidden calibrated + 100Hz timer is run (because that's what VMS expects), and a + hack is used for the interval timer. + + When the timer is started, the timer interval is inspected. + + if the interval is >= 10msec, then the 100Hz timer drives the + next interval + if the interval is < 10mec, then count instructions + + If the interval register is read, then its value between events + is interpolated using the current instruction count versus the + count when the most recent event started, the result is scaled + to the calibrated system clock, unless the interval being timed + is less than a calibrated system clock tick (or the calibrated + clock is running very slowly) at which time the result will be + the elapsed instruction count. +*/ + +int32 iccs_rd (void) +{ +return tmr_iccs & TMR_CSR_RD; +} + +void iccs_wr (int32 val) +{ +if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */ + sim_cancel (&tmr_unit); /* cancel timer */ + tmr_use_100hz = 0; + if (tmr_iccs & TMR_CSR_RUN) /* run 1 -> 0? */ + tmr_icr = icr_rd (TRUE); /* update itr */ + } +tmr_iccs = tmr_iccs & ~(val & TMR_CSR_W1C); /* W1C csr */ +tmr_iccs = (tmr_iccs & ~TMR_CSR_WR) | /* new r/w */ + (val & TMR_CSR_WR); +if (val & TMR_CSR_XFR) tmr_icr = tmr_nicr; /* xfr set? */ +if (val & TMR_CSR_RUN) { /* run? */ + if (val & TMR_CSR_XFR) /* new tir? */ + sim_cancel (&tmr_unit); /* stop prev */ + if (!sim_is_active (&tmr_unit)) /* not running? */ + tmr_sched (); /* activate */ + } +else if (val & TMR_CSR_SGL) { /* single step? */ + tmr_incr (1); /* incr tmr */ + if (tmr_icr == 0) /* if ovflo, */ + tmr_icr = tmr_nicr; /* reload tir */ + } +if ((tmr_iccs & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */ + (TMR_CSR_DON | TMR_CSR_IE)) + tmr_int = 0; +return; +} + +int32 icr_rd (t_bool interp) +{ +uint32 delta; + +if (interp || (tmr_iccs & TMR_CSR_RUN)) { /* interp, running? */ + delta = sim_grtime () - tmr_sav; /* delta inst */ + if (tmr_use_100hz && (tmr_poll > TMR_INC)) /* scale large int */ + delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll); + if (delta >= tmr_inc) + delta = tmr_inc - 1; + return tmr_icr + delta; + } +return tmr_icr; +} + +int32 nicr_rd () +{ +return tmr_nicr; +} + +void nicr_wr (int32 val) +{ +tmr_nicr = val; +} + +/* 100Hz base clock unit service */ + +t_stat clk_svc (UNIT *uptr) +{ +tmr_poll = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */ +sim_activate (&clk_unit, tmr_poll); /* reactivate unit */ +tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */ +todr_reg = todr_reg + 1; /* incr TODR */ +if ((tmr_iccs & TMR_CSR_RUN) && tmr_use_100hz) /* timer on, std intvl? */ + tmr_incr (TMR_INC); /* do timer service */ +return SCPE_OK; +} + +/* Interval timer unit service */ + +t_stat tmr_svc (UNIT *uptr) +{ +tmr_incr (tmr_inc); /* incr timer */ +return SCPE_OK; +} + +/* Timer increment */ + +void tmr_incr (uint32 inc) +{ +uint32 new_icr = (tmr_icr + inc) & LMASK; /* add incr */ + +if (new_icr < tmr_icr) { /* ovflo? */ + tmr_icr = 0; /* now 0 */ + if (tmr_iccs & TMR_CSR_DON) /* done? set err */ + tmr_iccs = tmr_iccs | TMR_CSR_ERR; + else tmr_iccs = tmr_iccs | TMR_CSR_DON; /* set done */ + if (tmr_iccs & TMR_CSR_RUN) { /* run? */ + tmr_icr = tmr_nicr; /* reload */ + tmr_sched (); /* reactivate */ + } + if (tmr_iccs & TMR_CSR_IE) /* ie? set int req */ + tmr_int = 1; + else tmr_int = 0; + } +else { + tmr_icr = new_icr; /* no, update icr */ + if (tmr_iccs & TMR_CSR_RUN) /* still running? */ + tmr_sched (); /* reactivate */ + } +return; +} + +/* Timer scheduling */ + +void tmr_sched (void) +{ +tmr_sav = sim_grtime (); /* save intvl base */ +tmr_inc = (~tmr_icr + 1); /* inc = interval */ +if (tmr_inc == 0) tmr_inc = 1; +if (tmr_inc < TMR_INC) { /* 100Hz multiple? */ + sim_activate (&tmr_unit, tmr_inc); /* schedule timer */ + tmr_use_100hz = 0; + } +else tmr_use_100hz = 1; /* let clk handle */ +return; +} + +/* Clock coscheduling routine */ + +int32 clk_cosched (int32 wait) +{ +int32 t; + +t = sim_activate_time (&clk_unit); +return (t? t - 1: wait); +} + +/* 100Hz clock reset */ + +t_stat clk_reset (DEVICE *dptr) +{ +tmr_poll = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init 100Hz timer */ +sim_activate (&clk_unit, tmr_poll); /* activate 100Hz unit */ +tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */ +if (clk_unit.filebuf == NULL) { /* make sure the TODR is initialized */ + clk_unit.filebuf = calloc(sizeof(TOY), 1); + if (clk_unit.filebuf == NULL) + return SCPE_MEM; + todr_resync (); + } +return SCPE_OK; +} + +/* CLK attach */ + +t_stat clk_attach (UNIT *uptr, char *cptr) +{ +t_stat r; + +uptr->flags = uptr->flags | (UNIT_ATTABLE | UNIT_BUFABLE); +memset (uptr->filebuf, 0, (size_t)uptr->capac); +r = attach_unit (uptr, cptr); +if (r != SCPE_OK) + uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE); +else + uptr->hwmark = (uint32) uptr->capac; +return r; +} + +/* CLK detach */ + +t_stat clk_detach (UNIT *uptr) +{ +t_stat r; + +r = detach_unit (uptr); +if ((uptr->flags & UNIT_ATT) == 0) + uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE); +return r; +} + +/* Interval timer reset */ + +t_stat tmr_reset (DEVICE *dptr) +{ +tmr_iccs = 0; +tmr_icr = 0; +tmr_nicr = 0; +tmr_int = 0; +tmr_use_100hz = 1; +sim_cancel (&tmr_unit); /* cancel timer */ +todr_resync (); /* resync TODR */ +return SCPE_OK; +} + +/* TODR routines */ + +int32 todr_rd (void) +{ +TOY *toy = (TOY *)clk_unit.filebuf; +struct timespec base, now, val; + +clock_gettime(CLOCK_REALTIME, &now); /* get curr time */ +base.tv_sec = toy->toy_gmtbase; +base.tv_nsec = toy->toy_gmtbasemsec * 1000000; +sim_timespec_diff (&val, &now, &base); +return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */ +} + +void todr_wr (int32 data) +{ +TOY *toy = (TOY *)clk_unit.filebuf; +struct timespec now, val, base; + +/* Save the GMT time when set value was 0 to record the base for future + read operations in "battery backed-up" state */ + +if (-1 == clock_gettime(CLOCK_REALTIME, &now)) /* get curr time */ + return; /* error? */ +val.tv_sec = ((uint32)data) / 100; +val.tv_nsec = (((uint32)data) % 100) * 10000000; +sim_timespec_diff (&base, &now, &val); /* base = now - data */ +toy->toy_gmtbase = (uint32)base.tv_sec; +toy->toy_gmtbasemsec = base.tv_nsec/1000000; +} + +t_stat todr_resync (void) +{ +TOY *toy = (TOY *)clk_unit.filebuf; + +if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX860 */ + if (!toy->toy_gmtbase) /* Never set? */ + todr_wr (0); /* Start ticking from 0 */ + } +else { /* Not-Attached means */ + uint32 base; /* behave like simh VMS default */ + time_t curr; + struct tm *ctm; + + curr = time (NULL); /* get curr time */ + if (curr == (time_t) -1) /* error? */ + return SCPE_NOFNC; + ctm = localtime (&curr); /* decompose */ + if (ctm == NULL) /* error? */ + return SCPE_NOFNC; + base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */ + ctm->tm_hour) * 60) + + ctm->tm_min) * 60) + + ctm->tm_sec; + todr_wr ((base * 100) + 0x10000000); /* use VMS form */ + } +return SCPE_OK; +} + +/* Logical console write */ + +t_stat lc_wr_txdb (int32 data) +{ +int32 i; +int32 mask = 0; + +lc_fnc = LC_GETFNC (data); /* get function */ +if (lc_bptr > 0) /* cmd in prog? */ + switch (lc_fnc) { + + case LC_FNCCA: /* cancel */ + sim_cancel (&tti_unit[ID_LC]); + lc_bptr = 0; + break; + + default: /* all others */ + return SCPE_OK; + } + +else switch (lc_fnc) { /* idle, case */ + + case LC_FNCCW: /* clear warm start flag */ + break; + + case LC_FNCCS: /* clear cold start flag */ + break; + + case LC_FNCMV: /* microcode version */ + lc_buf[2] = LC_FNCMV; + lc_buf[1] = VER_UCODE & 0xFF; /* low byte */ + lc_buf[0] = (VER_UCODE >> 8) & 0xFF; /* high byte */ + lc_bptr = 3; + sim_activate (&tti_unit[ID_LC], lc_cwait); /* sched command */ + break; + + case LC_FNCAC: /* array configuration */ + lc_buf[3] = LC_FNCAC; + if (MEMSIZE < MAXMEMSIZE) { /* 4MB Boards */ + lc_buf[2] = (uint8)(MEMSIZE >> 22); /* slots in use */ + for (i = 0; i < lc_buf[2]; i++) { + mask |= (2 << (i * 2)); /* build array mask */ + } + } + else { + lc_buf[2] = (uint8)(MEMSIZE >> 24); /* 16MB Boards */ + for (i = 0; i < lc_buf[2]; i++) { + mask |= (1 << (i * 2)); /* build array mask */ + } + } + lc_buf[1] = mask & 0xFF; /* slots 1 - 4 */ + lc_buf[0] = (mask >> 8) & 0xFF; /* slots 5 - 8 */ + lc_bptr = 4; + sim_activate (&tti_unit[ID_LC], lc_cwait); /* sched command */ + break; + + case LC_FNCSS: /* snapshot file status */ + lc_buf[1] = LC_FNCSS; + lc_buf[0] = 0x0; /* both invalid */ + lc_bptr = 2; + sim_activate (&tti_unit[ID_LC], lc_cwait); /* sched command */ + break; + + default: /* all others */ + printf ("TTO3: Unknown console command: %X\n", lc_fnc); + break; + } +return SCPE_OK; +} + +/* Unit service; the action to be taken depends on the transfer state: + + RL_IDLE Should never get here + RL_READ Read byte, Set STXCS + RL_WRITE Write byte, Set STXCS + RL_ABORT Set STXCS + RL_STATUS Copy requested data to STXDB, Set STXCS +*/ + +t_stat rlcs_svc (UNIT *uptr) +{ +int32 bcnt; +uint32 da; + +switch (rlcs_state) { + + case RL_IDLE: + return SCPE_IERR; + + case RL_READ: + if ((cso_csr & CSR_DONE) == 0) { /* buf ready? */ + if (rlcs_bcnt == 0) { /* read in whole block */ + da = STXCS_GETDA(cso_csr) * 512; /* get byte offset */ + if (sim_fseek (uptr->fileref, da, SEEK_SET)) + return SCPE_IOERR; + bcnt = sim_fread (rlcs_buf, sizeof (int16), RL_NUMBY, uptr->fileref); + } + if (rlcs_bcnt < RL_NUMBY) { /* more data in buffer? */ + cso_buf = rlcs_buf[rlcs_bcnt++]; /* return next word */ + cso_csr = cso_csr | CSR_DONE | /* continue */ + (RLST_CONT << STXCS_V_STS); + } + else { + cso_csr = cso_csr | CSR_DONE | /* complete */ + (RLST_COMP << STXCS_V_STS); + rlcs_state = RL_IDLE; /* now idle */ + rlcs_bcnt = 0; + } + if (cso_csr & CSR_IE) + csi_int = 1; + break; + } + sim_activate (uptr, rlcs_swait); /* schedule next */ + break; + + case RL_WRITE: + if (rlcs_bcnt < RL_NUMBY) { /* more data to buffer? */ + cso_csr = cso_csr | CSR_DONE | /* continue */ + (RLST_CONT << STXCS_V_STS); + } + else { + da = STXCS_GETDA(cso_csr) * 512; /* get byte offset */ + if (sim_fseek (uptr->fileref, da, SEEK_SET)) + return SCPE_IOERR; + bcnt = sim_fwrite (rlcs_buf, sizeof (int16), RL_NUMBY, uptr->fileref); + rlcs_state = RL_IDLE; /* now idle */ + rlcs_bcnt = 0; + cso_csr = cso_csr | CSR_DONE | /* complete */ + (RLST_COMP << STXCS_V_STS); + } + if (cso_csr & CSR_IE) + csi_int = 1; + break; + + case RL_ABORT: + if ((cso_csr & CSR_DONE) == 0) { /* buf ready? */ + cso_csr = cso_csr | CSR_DONE | /* aborted */ + (RLST_ABORT << STXCS_V_STS); + cso_buf = 0; + rlcs_bcnt = 0; + rlcs_state = RL_IDLE; + if (cso_csr & CSR_IE) + csi_int = 1; + break; + } + sim_activate (uptr, rlcs_swait); /* schedule next */ + break; + + case RL_STATUS: + if ((cso_csr & CSR_DONE) == 0) { /* buf ready? */ + switch (rlcs_sts_reg) { /* which register? */ + + case RL_CSR: + if (rlcs_csr & RLCS_ALLERR) /* any errors? */ + rlcs_csr = rlcs_csr | RLCS_ERR; /* set master error bit */ + if (rlcs_bcnt > 0) /* transfer in progress? */ + rlcs_csr = rlcs_csr & ~RLCS_DRDY; + else rlcs_csr = rlcs_csr | RLCS_DRDY; + cso_buf = rlcs_csr; + rlcs_sts_reg = RL_MP; /* MP on next read */ + break; + + case RL_MP: + if ((uptr->flags & UNIT_ATT) == 0) /* update status */ + rlcs_mp = RLDS_UNATT; + else rlcs_mp = RLDS_ATT; + cso_buf = rlcs_mp; + rlcs_sts_reg = RL_CSR; /* MP on next read */ + break; + } + cso_csr = cso_csr | CSR_DONE | /* returning status */ + (RLST_STS << STXCS_V_STS); + rlcs_state = RL_IDLE; + if (cso_csr & CSR_IE) + csi_int = 1; + break; + } + sim_activate (uptr, rlcs_swait); /* schedule next */ + break; + } +return SCPE_OK; +} + +/* Reset */ + +t_stat rlcs_reset (DEVICE *dptr) +{ +cso_buf = 0; +cso_csr = CSR_DONE; +csi_int = 0; +rlcs_state = RL_IDLE; +rlcs_csr = 0; +rlcs_sts_reg = RL_CSR; +rlcs_bcnt = 0; +if (rlcs_buf == NULL) + rlcs_buf = (uint16 *) calloc (RL_NUMBY, sizeof (uint16)); +if (rlcs_buf == NULL) + return SCPE_MEM; +sim_cancel (&rlcs_unit); /* deactivate unit */ +return SCPE_OK; +} + +t_stat rlcs_attach (UNIT *uptr, char *cptr) +{ +uint32 p; +t_stat r; + +uptr->capac = RL02_SIZE; +r = attach_unit (uptr, cptr); /* attach unit */ +if (r != SCPE_OK) /* error? */ + return r; +uptr->TRK = 0; /* cylinder 0 */ +uptr->STAT = RLDS_VCK; /* new volume */ +if ((p = sim_fsize (uptr->fileref)) == 0) { /* new disk image? */ + if (uptr->flags & UNIT_RO) /* if ro, done */ + return SCPE_OK; + return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD); + } +return SCPE_OK; +} diff --git a/VAX/vax860_syslist.c b/VAX/vax860_syslist.c new file mode 100644 index 00000000..49767974 --- /dev/null +++ b/VAX/vax860_syslist.c @@ -0,0 +1,130 @@ +/* vax860_syslist.c: VAX 8600 device list + + Copyright (c) 2011-2012, Matt Burke + This module incorporates code from SimH, Copyright (c) 1998-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). + + 26-Dec-2012 MB First version +*/ + +#include "vax_defs.h" + +char sim_name[] = "VAX860"; + +extern DEVICE cpu_dev; +extern DEVICE tlb_dev; +extern DEVICE abus_dev; +extern DEVICE sbia_dev; +extern DEVICE uba_dev; +extern DEVICE mba_dev[MBA_NUM]; +extern DEVICE clk_dev; +extern DEVICE tmr_dev; +extern DEVICE tti_dev, tto_dev; +extern DEVICE rlcs_dev; +extern DEVICE cr_dev; +extern DEVICE lpt_dev; +extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; +extern DEVICE rl_dev; +extern DEVICE hk_dev; +extern DEVICE rp_dev; +extern DEVICE ry_dev; +extern DEVICE ts_dev; +extern DEVICE tq_dev; +extern DEVICE tu_dev; +extern DEVICE dz_dev; +extern DEVICE xu_dev, xub_dev; +extern DEVICE dmc_dev[]; + +extern int32 sim_switches; +extern UNIT cpu_unit; +extern void WriteB (uint32 pa, int32 val); + +DEVICE *sim_devices[] = { + &cpu_dev, + &tlb_dev, + &abus_dev, + &sbia_dev, + &uba_dev, + &mba_dev[0], + &mba_dev[1], + &clk_dev, + &tmr_dev, + &tti_dev, + &tto_dev, + &rlcs_dev, + &dz_dev, + &cr_dev, + &lpt_dev, + &rp_dev, + &rl_dev, + &hk_dev, + &rq_dev, + &rqb_dev, + &rqc_dev, + &rqd_dev, + &ry_dev, + &tu_dev, + &ts_dev, + &tq_dev, + &xu_dev, + &xub_dev, + &dmc_dev[0], + &dmc_dev[1], + &dmc_dev[2], + &dmc_dev[3], + NULL + }; + +/* Binary loader + + The binary loader handles absolute system images, that is, system + images linked /SYSTEM. These are simply a byte stream, with no + origin or relocation information. + + -o for memory, specify origin +*/ + +t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +{ +t_stat r; +int32 val; +uint32 origin, limit; + +if (flag) /* dump? */ + return SCPE_ARG; +origin = 0; /* memory */ +limit = (uint32) cpu_unit.capac; +if (sim_switches & SWMASK ('O')) { /* origin? */ + origin = (int32) get_uint (cptr, 16, 0xFFFFFFFF, &r); + if (r != SCPE_OK) + return SCPE_ARG; + } + +while ((val = getc (fileref)) != EOF) { /* read byte stream */ + if (origin >= limit) /* NXM? */ + return SCPE_NXM; + WriteB (origin, val); /* memory */ + origin = origin + 1; + } +return SCPE_OK; +} diff --git a/VAX/vax_cpu1.c b/VAX/vax_cpu1.c index d4e3ea32..e569bee7 100644 --- a/VAX/vax_cpu1.c +++ b/VAX/vax_cpu1.c @@ -1445,7 +1445,7 @@ int32 cc; if (PSL & PSL_CUR) /* must be kernel */ RSVD_INST_FAULT; -if (prn > 63) /* reg# > 63? fault */ +if (prn > MT_MAX) /* reg# > max? fault */ RSVD_OPND_FAULT; CC_IIZZ_L (val); /* set cc's */ switch (prn) { /* case on reg # */ @@ -1576,7 +1576,7 @@ int32 val; if (PSL & PSL_CUR) /* must be kernel */ RSVD_INST_FAULT; -if (prn > 63) /* reg# > 63? fault */ +if (prn > MT_MAX) /* reg# > max? fault */ RSVD_OPND_FAULT; switch (prn) { /* case on reg# */ diff --git a/VAX/vax_defs.h b/VAX/vax_defs.h index ac2adaab..dab14708 100644 --- a/VAX/vax_defs.h +++ b/VAX/vax_defs.h @@ -738,6 +738,8 @@ void cpu_idle (void); #include "vax610_defs.h" #elif defined (VAX_620) || defined (VAX_630) #include "vax630_defs.h" +#elif defined (VAX_860) +#include "vax860_defs.h" #else /* VAX 3900 */ #include "vaxmod_defs.h" #endif diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index 61c99010..806d4e82 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -96,6 +96,7 @@ #define MT_CONPC 42 #define MT_CONPSL 43 #define MT_IORESET 55 +#define MT_MAX 63 /* last valid IPR */ /* Memory system error register */ diff --git a/Visual Studio Projects/Simh.sln b/Visual Studio Projects/Simh.sln index 4452cc91..05265482 100644 --- a/Visual Studio Projects/Simh.sln +++ b/Visual Studio Projects/Simh.sln @@ -92,6 +92,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VAX630", "VAX630.vcproj", " EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TX-0", "TX-0.vcproj", "{24BC7F75-FB56-44A9-BB7C-78AE6A694D0C}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VAX860", "VAX860.vcproj", "{F5C22D72-460E-43CD-9AC6-6D6AC517BD1F}" + ProjectSection(ProjectDependencies) = postProject + {D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -238,6 +243,10 @@ Global {24BC7F75-FB56-44A9-BB7C-78AE6A694D0C}.Debug|Win32.Build.0 = Debug|Win32 {24BC7F75-FB56-44A9-BB7C-78AE6A694D0C}.Release|Win32.ActiveCfg = Release|Win32 {24BC7F75-FB56-44A9-BB7C-78AE6A694D0C}.Release|Win32.Build.0 = Release|Win32 + {F5C22D72-460E-43CD-9AC6-6D6AC517BD1F}.Debug|Win32.ActiveCfg = Debug|Win32 + {F5C22D72-460E-43CD-9AC6-6D6AC517BD1F}.Debug|Win32.Build.0 = Debug|Win32 + {F5C22D72-460E-43CD-9AC6-6D6AC517BD1F}.Release|Win32.ActiveCfg = Release|Win32 + {F5C22D72-460E-43CD-9AC6-6D6AC517BD1F}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Visual Studio Projects/VAX860.vcproj b/Visual Studio Projects/VAX860.vcproj new file mode 100644 index 00000000..7fa98ba9 --- /dev/null +++ b/Visual Studio Projects/VAX860.vcproj @@ -0,0 +1,479 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/display/win32.c b/display/win32.c index 45c5e453..3eb26802 100644 --- a/display/win32.c +++ b/display/win32.c @@ -278,7 +278,7 @@ ws_init2(void) { } #ifdef THREADS -static volatile init_done; +static volatile int init_done; static DWORD msgthread_id; static DWORD WINAPI diff --git a/doc/pdp10_doc.doc b/doc/pdp10_doc.doc index baddd5ff..930f7458 100644 Binary files a/doc/pdp10_doc.doc and b/doc/pdp10_doc.doc differ diff --git a/makefile b/makefile index a27f63a4..bac59a48 100644 --- a/makefile +++ b/makefile @@ -302,7 +302,11 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) else #Win32 Environments (via MinGW32) GCC = gcc - GCC_Path := $(dir $(shell where gcc.exe)) + ifeq (XP,$(findstring XP,$(shell ver))) + GCC_Path := C:\MinGW\bin\ + else + GCC_Path := $(dir $(shell where gcc.exe)) + endif GCC_VERSION = $(word 3,$(shell $(GCC) --version)) COMPILER_NAME = GCC Version: $(GCC_VERSION) LTO_EXCLUDE_VERSIONS = 4.5.2 @@ -529,6 +533,7 @@ VAX630 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ VAX620_OPT = -DVM_VAX -DVAX_620 -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} VAX630_OPT = -DVM_VAX -DVAX_630 -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} + VAX730 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ @@ -571,6 +576,20 @@ VAX780 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ VAX780_OPT = -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} +VAX860 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ + ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ + ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ + ${VAXD}/vax860_stddev.c ${VAXD}/vax860_sbia.c \ + ${VAXD}/vax860_abus.c ${VAXD}/vax780_uba.c ${VAXD}/vax7x0_mba.c \ + ${VAXD}/vax860_syslist.c \ + ${PDP11D}/pdp11_rl.c ${PDP11D}/pdp11_rq.c ${PDP11D}/pdp11_ts.c \ + ${PDP11D}/pdp11_dz.c ${PDP11D}/pdp11_lp.c ${PDP11D}/pdp11_tq.c \ + ${PDP11D}/pdp11_xu.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_cr.c \ + ${PDP11D}/pdp11_rp.c ${PDP11D}/pdp11_tu.c ${PDP11D}/pdp11_hk.c \ + ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_dmc.c ${PDP11D}/pdp11_io_lib.c +VAX860_OPT = -DVM_VAX -DVAX_860 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} + + PDP10D = PDP10 PDP10 = ${PDP10D}/pdp10_fe.c ${PDP11D}/pdp11_dz.c ${PDP10D}/pdp10_cpu.c \ ${PDP10D}/pdp10_ksio.c ${PDP10D}/pdp10_lp20.c ${PDP10D}/pdp10_mdfp.c \ @@ -581,7 +600,6 @@ PDP10 = ${PDP10D}/pdp10_fe.c ${PDP11D}/pdp11_dz.c ${PDP10D}/pdp10_cpu.c \ PDP10_OPT = -DVM_PDP10 -DUSE_INT64 -I ${PDP10D} -I ${PDP11D} - PDP8D = PDP8 PDP8 = ${PDP8D}/pdp8_cpu.c ${PDP8D}/pdp8_clk.c ${PDP8D}/pdp8_df.c \ ${PDP8D}/pdp8_dt.c ${PDP8D}/pdp8_lp.c ${PDP8D}/pdp8_mt.c \ @@ -729,7 +747,7 @@ ifeq ($(WIN32),) DISPLAY_OPT = endif else - DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/w32.c + DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/win32.c DISPLAY_OPT = -DUSE_DISPLAY endif @@ -743,7 +761,7 @@ TX0_OPT = -I ${TX0D} $(DISPLAY_OPT) # Build everything # ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \ - vax vax610 vax620 vax630 vax730 vax750 vax780 \ + vax vax610 vax620 vax630 vax730 vax750 vax780 vax860 \ nova eclipse hp2100 i1401 i1620 s3 altair altairz80 gri \ i7094 ibm1130 id16 id32 sds lgp h316 \ swtp6800mp-a swtp6800mp-a2 tx-0 @@ -869,6 +887,12 @@ ${BIN}vax780${EXE} : ${VAX780} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} ${CC} ${VAX780} ${SIM} ${VAX780_OPT} $(CC_OUTSPEC) ${LDFLAGS} +vax860 : ${BIN}vax860${EXE} + +${BIN}vax860${EXE} : ${VAX860} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX860} ${SIM} ${VAX860_OPT} $(CC_OUTSPEC) ${LDFLAGS} + nova : ${BIN}nova${EXE} ${BIN}nova${EXE} : ${NOVA} ${SIM} diff --git a/scp.c b/scp.c index fb48f579..11676794 100644 --- a/scp.c +++ b/scp.c @@ -2315,6 +2315,9 @@ if (cptr && (*cptr != 0)) fprintf (st, "%s simulator V%d.%d-%d", sim_name, vmaj, vmin, vpat); if (vdelt) fprintf (st, " delta %d", vdelt); +#if defined(SIM_VERSION_MODE) +fprintf (st, " %s", SIM_VERSION_MODE); +#endif if (flag) fprintf (st, " [%s, %s, %s]", sim_si64, sim_sa64, sim_snet); #if defined(SIM_GIT_COMMIT_ID) diff --git a/sim_rev.h b/sim_rev.h index 91c549b4..6ddd3b96 100644 --- a/sim_rev.h +++ b/sim_rev.h @@ -27,10 +27,22 @@ #ifndef _SIM_REV_H_ #define _SIM_REV_H_ 0 +#ifndef SIM_MAJOR #define SIM_MAJOR 4 +#endif +#ifndef SIM_MINOR #define SIM_MINOR 0 +#endif +#ifndef SIM_PATCH #define SIM_PATCH 0 +#endif +#ifndef SIM_DELTA #define SIM_DELTA 0 +#endif + +#ifndef SIM_VERSION_MODE +#define SIM_VERSION_MODE "Beta" +#endif /* The comment section below reflects the manual editing process which was in place diff --git a/sim_serial.c b/sim_serial.c index 1bba576f..ff9ba2b9 100644 --- a/sim_serial.c +++ b/sim_serial.c @@ -897,6 +897,15 @@ for (i=0; (ports < max) && (i < 64); ++i) { close (port); } } +for (i=0; (ports < max) && (i < 64); ++i) { + sprintf (list[ports].name, "/dev/ttyAMA%d", i); + port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ + if (port != -1) { /* open OK? */ + if (isatty (port)) /* is device a TTY? */ + ++ports; + close (port); + } + } for (i=1; (ports < max) && (i < 64); ++i) { sprintf (list[ports].name, "/dev/tty.serial%d", i); port = open (list[ports].name, O_RDWR | O_NOCTTY | O_NONBLOCK); /* open the port */ diff --git a/sim_tmxr.c b/sim_tmxr.c index 3299b695..966bfd84 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -783,6 +783,8 @@ for (i = 0; i < mp->lines; i++) { /* check each line in se lp->conn = TRUE; /* record connection */ lp->sock = lp->connecting; /* it now looks normal */ lp->connecting = 0; + lp->ipad = realloc (lp->ipad, 1+strlen (lp->destination)); + strcpy (lp->ipad, lp->destination); lp->cnms = sim_os_msec (); break; case -1: /* failed connection */ @@ -901,14 +903,8 @@ if ((lp->destination) && (!lp->serport)) { if (lp->connecting) sim_close_sock (lp->connecting, 0); lp->connecting = sim_connect_sock (lp->destination, "localhost", NULL); - lp->ipad = malloc (1 + strlen (lp->destination)); - strcpy (lp->ipad, lp->destination); - lp->cnms = sim_os_msec (); } -else { - tmxr_init_line (lp); /* initialize line state */ - } -lp->conn = FALSE; /* remove connection flag */ +tmxr_init_line (lp); /* initialize line state */ /* Revise the unit's connect string to reflect the current attachments */ lp->mp->uptr->filename = _mux_attach_string (lp->mp->uptr->filename, lp->mp); /* No connections or listeners exist, then we're equivalent to being fully detached. We should reflect that */