From 1d15966191daaec162ba3cb4695b34cf17ad553a Mon Sep 17 00:00:00 2001 From: Matt Burke Date: Sun, 21 Apr 2019 09:09:32 -0700 Subject: [PATCH] VAX: New simulator for VAX 8200 --- README.md | 3 +- VAX/vax820_bi.c | 826 +++++++++++++++++ VAX/vax820_defs.h | 452 +++++++++ VAX/vax820_ka.c | 365 ++++++++ VAX/vax820_mem.c | 212 +++++ VAX/vax820_stddev.c | 1216 +++++++++++++++++++++++++ VAX/vax820_syslist.c | 139 +++ VAX/vax820_uba.c | 996 ++++++++++++++++++++ VAX/vax_bi.h | 163 ++++ VAX/vax_defs.h | 3 + Visual Studio Projects/Simh.sln | 9 + Visual Studio Projects/VAX8200.vcproj | 681 ++++++++++++++ descrip.mms | 77 +- makefile | 27 +- 14 files changed, 5163 insertions(+), 6 deletions(-) create mode 100644 VAX/vax820_bi.c create mode 100644 VAX/vax820_defs.h create mode 100644 VAX/vax820_ka.c create mode 100644 VAX/vax820_mem.c create mode 100644 VAX/vax820_stddev.c create mode 100644 VAX/vax820_syslist.c create mode 100644 VAX/vax820_uba.c create mode 100644 VAX/vax_bi.h create mode 100644 Visual Studio Projects/VAX8200.vcproj diff --git a/README.md b/README.md index 1b22e1ac..c573a4c6 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,10 @@ VAX/11 730 VAX/11 750 + VAX 8200 VAX 8600/8650 MicroVAX I & VAXStation I - MicroVAX II & VAXStation II + MicroVAX II & VAXStation II & VAXStation II GPX rtVAX 1000 (or Industrial VAX 620) #### Howard Harte has implemented a Lincoln Labs TX-0 simulator. diff --git a/VAX/vax820_bi.c b/VAX/vax820_bi.c new file mode 100644 index 00000000..fc482525 --- /dev/null +++ b/VAX/vax820_bi.c @@ -0,0 +1,826 @@ +/* vax820_bi.c: VAX 8200 BI + + Copyright (c) 2019, 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). + + This module contains the VAX 8200 system-specific registers and devices. + + bi bus controller +*/ + +#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 */ + +/* KA820 specific IPRs */ + +/* Writeable control store */ + +#define WCSA_RW 0x3FFFFF /* writeable */ +#define WCSD_RD_VAL 0xFF /* fixed read val */ +#define WCSD_WR 0xFFFFFFFF /* write */ +#define MBRK_RW 0x1FFF /* microbreak */ + +/* KA820 boot device definitions */ + +struct boot_dev { + const char *name; + int32 code; + int32 let; + }; + +uint32 wcs_addr = 0; +uint32 wcs_data = 0; +uint32 nexus_req[NEXUS_HLVL]; /* nexus int req */ +int32 ipr_int = 0; +int32 rxcd_int = 0; +int32 ipir = 0; +int32 sys_model = 0; +int32 mchk_flag[KA_NUM] = { 0 }; +char cpu_boot_cmd[CBUFSIZE] = { 0 }; /* boot command */ + +static t_stat (*nexusR[NEXUS_NUM])(int32 *dat, int32 ad, int32 md); +static t_stat (*nexusW[NEXUS_NUM])(int32 dat, int32 ad, int32 md); + +static struct boot_dev boot_tab[] = { + { "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 }, + { "CS", BOOT_CS, 0 }, + { NULL } + }; + +extern int32 tmr_int, tti_int, tto_int, fl_int; +extern int32 cur_cpu; + +t_stat bi_reset (DEVICE *dptr); +t_stat vax820_boot (int32 flag, CONST char *ptr); +t_stat vax820_boot_parse (int32 flag, CONST char *ptr); +t_stat cpu_boot (int32 unitno, DEVICE *dptr); + +extern void uba_eval_int (void); +extern int32 uba_get_ubvector (int32 lvl); +extern void wtc_set_valid (void); +extern void wtc_set_invalid (void); +extern int32 iccs_rd (void); +extern int32 nicr_rd (void); +extern int32 icr_rd (void); +extern int32 todr_rd (void); +extern int32 rxcs_rd (void); +extern int32 rxdb_rd (void); +extern int32 txcs_rd (void); +extern int32 rxcd_rd (void); +extern int32 wtc_rd (int32 pa); +extern int32 pcsr_rd (int32 pa); +extern int32 fl_rd (int32 pa); +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 rxcd_wr (int32 val); +extern void wtc_wr (int32 pa, int32 val, int32 lnt); +extern void pcsr_wr (int32 pa, int32 val, int32 lnt); +extern void fl_wr (int32 pa, int32 val, int32 lnt); +extern void init_ubus_tab (void); +extern t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp); + +/* BI data structures + + bi_dev BI device descriptor + bi_unit BI unit + bi_reg BI register list +*/ + +UNIT bi_unit = { UDATA (NULL, 0, 0) }; + +REG bi_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 (WCSA, wcs_addr, 21) }, + { HRDATA (WCSD, wcs_data, 32) }, + { NULL } + }; + +DEVICE bi_dev = { + "BI", &bi_unit, bi_reg, NULL, + 1, 16, 16, 1, 16, 8, + NULL, NULL, &bi_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +/* Special boot command, overrides regular boot */ + +CTAB vax820_cmd[] = { + { "BOOT", &vax820_boot, RU_BOOT, + "bo{ot} {/R5:flg} boot device\n" + " type HELP CPU to see bootable devices\n", NULL, &run_cmd_message }, + { NULL } + }; + +/* The VAX 8200 has three sources of interrupts + + - internal device interrupts (CPU, console, clock) + - nexus interupts (e.g., memory controller, 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 cpu_msk = (1u << cur_cpu); +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_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_RXCDINT) && rxcd_int) /* rxcd int */ + return IPL_RXCDINT; +if ((ipl < IPL_IPRINT) && (ipir & cpu_msk)) /* ipr int */ + return IPL_IPRINT; +if ((ipl < IPL_FLINT) && fl_int) /* console floppy int */ + return IPL_FLINT; +if ((ipl < IPL_TTINT) && (tti_int && (cur_cpu == 0))) /* console int */ + return IPL_TTINT; +if ((ipl < IPL_TTINT) && (tto_int & cpu_msk)) /* 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; +int32 vec; +int32 cpu_msk = (1u << cur_cpu); + +if (lvl == IPL_CRDERR) { /* CRD error? */ + crd_err = 0; + return SCB_CRDERR; + } +if (lvl == IPL_CLKINT) { /* clock? */ + tmr_int = tmr_int & ~(1u << cur_cpu); /* 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; + if (nexus_req[l] & (1u << TR_UBA)) { /* unibus int? */ + nexus_req[l] = nexus_req[l] & ~(1u << TR_UBA); + vec = uba_get_ubvector(l); + return vec; /* return vector */ + } + for (i = 0; nexus_req[l] && (i < NEXUS_NUM); i++) { + if ((nexus_req[l] >> i) & 1) { + nexus_req[l] = nexus_req[l] & ~(1u << i); + vec = SCB_NEXUS + (l << 6) + (i << 2); + return vec; /* return vector */ + } + } + } +if (lvl == IPL_RXCDINT) { + if (rxcd_int) { + rxcd_int = 0; /* clear req */ + return SCB_RXCD; /* return vector */ + } + } +if (lvl == IPL_IPRINT) { /* inter-processor? */ + if (ipir & (1u << cur_cpu)) { + ipir = ipir & ~(1u << cur_cpu); /* clear req */ + return SCB_IPRINT; /* return vector */ + } + } +if (lvl == IPL_FLINT) { /* console floppy? */ + if (fl_int) { + fl_int = 0; /* clear req */ + return SCB_FLINT; /* return vector */ + } + } +if (lvl == IPL_TTINT) { /* console? */ + if (tti_int && (cur_cpu == 0)) { /* input? */ + tti_int = 0; /* clear req */ + return SCB_TTI; /* return vector */ + } + if (tto_int & cpu_msk) { /* output? */ + tto_int = 0; /* clear req */ + return SCB_TTO; /* return vector */ + } + } +return 0; +} + +/* Read 8200-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 (); + break; + + case MT_TODR: /* TODR */ + val = todr_rd (); + break; + + case MT_RXCS: /* RXCS */ + if (cur_cpu == 0) + val = rxcs_rd (); + else + val = 0; + break; + + case MT_RXDB: /* RXDB */ + if (cur_cpu == 0) + val = rxdb_rd (); + else + val = 0; + break; + + case MT_TXCS: /* TXCS */ + val = txcs_rd (); + break; + + case MT_TBDR: /* TBDR (not impl) */ + val = 0; + break; + + case MT_CADR: /* CADR (not impl) */ + val = 0; + break; + + case MT_ACCS: /* ACCS (not impl) */ + val = 0; + break; + + case MT_WCSA: /* WCSA */ + val = wcs_addr & WCSA_RW; + break; + + case MT_WCSD: /* WCSD */ + val = WCSD_RD_VAL; + break; + + case MT_SID: /* SID */ + if (sys_model) + val = VAX820_SID | VAX820_REV | VAX820_PATCH | VAX825_TYP | VAX820_UCODE; + else + val = VAX820_SID | VAX820_REV | VAX820_PATCH | VAX820_TYP | VAX820_UCODE; + break; + + case MT_RXCS1: /* RXCS1 */ + val = 0; + break; + + case MT_RXDB1: /* RXDB1 */ + val = 0; + break; + + case MT_TXCS1: /* TXCS1 */ + val = CSR_DONE; + break; + + case MT_RXCS2: /* RXCS2 */ + val = 0; + break; + + case MT_RXDB2: /* RXDB2 */ + val = 0; + break; + + case MT_TXCS2: /* TXCS2 */ + val = CSR_DONE; + break; + + case MT_RXCS3: /* RXCS3 */ + val = 0; + break; + + case MT_RXDB3: /* RXDB3 */ + val = 0; + break; + + case MT_TXCS3: /* TXCS3 */ + val = CSR_DONE; + break; + + case MT_BINID: /* BINID */ + val = TR_KA0 + cur_cpu; + break; + + case MT_RXCD: /* RXCD */ + val = rxcd_rd (); + break; + + default: + RSVD_OPND_FAULT; + } + +return val; +} + +/* Write 8200-specific IPR's */ + +void WriteIPR (int32 rg, int32 val) +{ +switch (rg) { + + case MT_IPIR: /* IPIR */ + ipir = val; + break; + + 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_RXCS: /* RXCS */ + if (cur_cpu == 0) + rxcs_wr (val); + break; + + case MT_TXCS: /* TXCS */ + txcs_wr (val); + break; + + case MT_TXDB: /* TXDB */ + txdb_wr (val); + break; + + case MT_TBDR: /* TBDR (not impl) */ + break; + + case MT_CADR: /* CADR (not impl) */ + break; + + case MT_MCESR: /* MCESR */ + mchk_flag[cur_cpu] = 0; + break; + + case MT_ACCS: /* ACCS (not impl) */ + break; + + case MT_WCSA: /* WCSA */ + wcs_addr = val & WCSA_RW; + break; + + case MT_WCSL: /* WCSL */ + wcs_data = val & WCSD_WR; + break; + + case MT_RXCS1: /* RXCS1 */ + case MT_TXCS1: /* TXCS1 */ + case MT_TXDB1: /* TXDB1 */ + case MT_RXCS2: /* RXCS2 */ + case MT_TXCS2: /* TXCS2 */ + case MT_TXDB2: /* TXDB2 */ + case MT_RXCS3: /* RXCS3 */ + case MT_TXCS3: /* TXCS3 */ + case MT_TXDB3: /* TXDB3 */ + case MT_CACHEX: /* CACHEX */ + case MT_BISTOP: /* BISTOP */ + break; + + case MT_RXCD: /* RXCD */ + rxcd_wr (val); + break; + + default: + RSVD_OPND_FAULT; + } + +return; +} + +struct reglink { /* register linkage */ + uint32 low; /* low addr */ + uint32 high; /* high addr */ + int32 (*read)(int32 pa); /* read routine */ + void (*write)(int32 pa, int32 val, int32 lnt); /* write routine */ + }; + +struct reglink regtable[] = { + { WATCHBASE, WATCHBASE+WATCHSIZE, &wtc_rd, &wtc_wr }, + { 0x20088000, 0x20088004, &pcsr_rd, &pcsr_wr }, + { 0x200B0000, 0x200B0020, &fl_rd, &fl_wr }, + { 0, 0, NULL, NULL } + }; + +/* ReadReg - read register space + + Inputs: + pa = physical address + lnt = length (BWLQ) + Output: + longword of data +*/ + +int32 ReadReg (uint32 pa, int32 lnt) +{ +int32 nexus, val; +struct reglink *p; + +if (ADDR_IS_REG (pa)) { /* reg space? */ + nexus = NEXUS_GETNEX (pa); /* get nexus */ + if (nexusR[nexus] && /* valid? */ + (nexusR[nexus] (&val, pa, lnt) == SCPE_OK)) { + SET_IRQL; + return val; + } + MACH_CHECK (MCHK_BIERR); /* machine check */ + return 0; + } +for (p = ®table[0]; p->low != 0; p++) { + if ((pa >= p->low) && (pa < p->high) && p->read) + return p->read (pa); + } +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 (uint32 pa, int32 val, int32 lnt) +{ +int32 nexus; +struct reglink *p; + +if (ADDR_IS_REG (pa)) { /* reg space? */ + nexus = NEXUS_GETNEX (pa); /* get nexus */ + if (nexusW[nexus] && /* valid? */ + (nexusW[nexus] (val, pa, lnt) == SCPE_OK)) { + SET_IRQL; + return; + } + } +for (p = ®table[0]; p->low != 0; p++) { + if ((pa >= p->low) && (pa < p->high) && p->write) { + p->write (pa, val, lnt); + return; + } + } +return; +} + +/* Machine check + + Error status word format + <2:0> = ASTLVL + <3> = PME + <6:4> = arith trap code + Rest will be zero +*/ + +int32 machine_check (int32 p1, int32 opc, int32 cc, int32 delta) +{ +int32 acc; + +if (mchk_flag[cur_cpu]) /* double error? */ + ABORT (STOP_INIE); /* halt */ +mchk_flag[cur_cpu] = 1; +if (in_ie) /* in exc? panic */ + ABORT (STOP_INIE); +cc = intexc (SCB_MCHK, cc, 0, IE_SVE); /* take exception */ +acc = ACC_MASK (KERN); /* in kernel mode */ +in_ie = 1; +SP = SP - 36; /* push 8 words */ +Write (SP, 32, L_LONG, WA); /* # bytes */ +Write (SP + 4, p1, L_LONG, WA); /* mcheck type */ +Write (SP + 8, 0, L_LONG, WA); /* parameter 1 */ +Write (SP + 12, mchk_va, L_LONG, WA); /* VA */ +Write (SP + 16, mchk_va, L_LONG, WA); /* VA prime */ +Write (SP + 20, 0, L_LONG, WA); /* memory address */ +Write (SP + 24, 0x00400000, L_LONG, WA); /* status word */ +Write (SP + 28, PC, L_LONG, WA); /* PC at failure */ +Write (SP + 32, 0, L_LONG, WA); /* uPC at failure */ +in_ie = 0; +return cc; +} + +/* Console entry - only reached if CONHALT is set (AUTORESTART is set */ + +int32 con_halt (int32 code, int32 cc) +{ +if ((cpu_boot_cmd[0] == 0) || /* saved boot cmd? */ + (vax820_boot_parse (0, cpu_boot_cmd) != SCPE_OK) || /* reparse the boot cmd */ + (reset_all (0) != SCPE_OK) || /* reset the world */ + (cpu_boot (0, NULL) != SCPE_OK)) /* set up boot code */ + ABORT (STOP_BOOT); /* any error? */ +sim_printf ("Rebooting...\n"); +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 vax820_boot (int32 flag, CONST char *ptr) +{ +t_stat r; + +r = vax820_boot_parse (flag, ptr); /* parse the boot cmd */ +if (r != SCPE_OK) { /* error? */ + if (r >= SCPE_BASE) { /* message available? */ + sim_printf ("%s\n", sim_error_text (r)); + r |= SCPE_NOMESSAGE; + } + return r; + } +strncpy (cpu_boot_cmd, ptr, CBUFSIZE-1); /* save for reboot */ +return run_cmd (flag, "CPU"); +} + +t_stat vax820_boot_parse (int32 flag, CONST char *ptr) +{ +char gbuf[CBUFSIZE]; +char *slptr; +const char *regptr; +int32 i, r5v, unitno; +DEVICE *dptr; +UNIT *uptr; +DIB *dibp; +t_stat r; + +if (!ptr || !*ptr) + return SCPE_2FARG; +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) + return SCPE_ARG; +unitno = (int32) (uptr - dptr->units); +r5v = 0; +/* coverity[NULL_RETURNS] */ +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 != 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; + R[1] = TR_UBA; + R[2] = boot_tab[i].let | (dibp->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; +} + +/* BI reset */ + +t_stat bi_reset (DEVICE *dptr) +{ +wcs_addr = 0; +wcs_data = 0; +ipr_int = 0; +rxcd_int = 0; +ipir = 0; +sim_vm_cmd = vax820_cmd; +return SCPE_OK; +} + +/* Show nexus */ + +t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, CONST 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))) { + sim_printf ("Nexus %s conflict at %d\n", sim_dname (dptr), dibp->ba); + return SCPE_STOP; + } +if (dibp->rd) /* set rd dispatch */ + nexusR[idx] = dibp->rd; +if (dibp->wr) /* set wr dispatch */ + nexusW[idx] = dibp->wr; +return SCPE_OK; +} + +/* 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 (); +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 { /* 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, CONST char *cptr, void *desc) +{ +if (cptr == NULL) + return SCPE_ARG; +if (strcmp(cptr, "8200") == 0) { + sys_model = 0; + strcpy (sim_name, "VAX 8200 (KA820)"); + } +else if (strcmp(cptr, "8250") == 0) { + sys_model = 1; + strcpy (sim_name, "VAX 8250 (KA825)"); + } +else + return SCPE_ARG; +return SCPE_OK; +} + +t_stat cpu_print_model (FILE *st) +{ +fprintf (st, "model=%s", (sys_model ? "8250" : "8200")); +return SCPE_OK; +} + +t_stat cpu_model_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "Initial memory size is 32MB.\n\n"); +fprintf (st, "The simulator is booted with the BOOT command:\n\n"); +fprintf (st, " sim> BO{OT} {/R5:flags}\n\n"); +fprintf (st, "where is one of:\n\n"); +fprintf (st, " HKn to boot from hkn\n"); +fprintf (st, " RLn to boot from rln\n"); +fprintf (st, " RQn to boot from rqn\n"); +fprintf (st, " RQBn to boot from rqbn\n"); +fprintf (st, " RQCn to boot from rqcn\n"); +fprintf (st, " RQDn to boot from rqdn\n"); +fprintf (st, " TQn to boot from tqn\n"); +fprintf (st, " CS to boot from console RL\n\n"); +return SCPE_OK; +} diff --git a/VAX/vax820_defs.h b/VAX/vax820_defs.h new file mode 100644 index 00000000..85cf7628 --- /dev/null +++ b/VAX/vax820_defs.h @@ -0,0 +1,452 @@ +/* vax820_defs.h: VAX 8200 model-specific definitions file + + Copyright (c) 2019, 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). + + This file covers the VAX 8200, the fifth VAX. + + System memory map + + 0000 0000 - 1FFF FFFF main memory + 2000 0000 - 2001 FFFF bi node space + 2002 0000 - 2007 FFFF reserved + 2008 0000 - 2008 00FC ka820 biic internal registers + 2008 0200 - 2008 0203 rxcd register + 2008 0204 - 2008 FFFF reserved + 2009 0000 - 2009 1FFF boot RAM + 2009 2000 - 2009 7FFF reserved + 2009 8000 - 2009 FFFF eeprom + 200A 0000 - 200A FFFF reserved + 200B 0000 - 200B 0017 rcx50 + 200B 0020 - 200B 7FFF reserved + 200B 8000 - 200B 807F watch chip + 200B 8080 - 203F FFFF reserved + 2040 0000 - 207F FFFF bi window space + 2080 0000 - 3FFF FFFF reserved +*/ + +#ifndef FULL_VAX +#define FULL_VAX 1 +#endif + +#ifndef _VAX_820_DEFS_H_ +#define _VAX_820_DEFS_H_ 1 + +/* Microcode constructs */ + +#define VAX820_SID (5 << 24) /* system ID */ +#define VAX820_TYP (0 << 23) /* sys type: 8200 */ +#define VAX825_TYP (1 << 23) /* sys type: 8250 */ +#define VAX820_REV (5 << 19) /* CPU revision */ +#define VAX820_PATCH (21 << 9) /* patch revision */ +#define VAX820_UCODE (20) /* ucode revision */ +#define CON_HLTPIN 0x0200 /* external CPU halt */ +#define CON_HLTINS 0x0600 /* HALT instruction */ +#define MCHK_BIERR 0x10 /* BI bus error */ +#define VER_FPLA 0x0C /* FPLA version */ +#define VER_WCSP (VER_FPLA) /* WCS primary version */ +#define VER_WCSS 0x12 /* WCS secondary version */ +#define VER_PCS ((VER_WCSS >> 4) & 0x3) /* PCS 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 */ + +/* Nexus constants */ + +#define NEXUS_NUM 16 /* number of nexus */ +#define KA_NUM 2 /* number of CPU's */ +#define MCTL_NUM 2 /* number of mem ctrl */ +#define MBA_NUM 2 /* number of MBA's */ +#define TR_KA0 0 /* nexus assignments */ +#define TR_KA1 1 +#define TR_MCTL0 2 +#define TR_MCTL1 3 +#define TR_UBA 4 +#define NEXUS_HLVL (IPL_HMAX - IPL_HMIN + 1) +#define SCB_NEXUS 0x100 /* nexus intr base */ + +/* Internal I/O interrupts - relative except for clock and console */ + +#define IPL_CLKINT 0x18 /* clock IPL */ +#define IPL_IPRINT 0x14 /* interprocessor IPL */ +#define IPL_RXCDINT 0x14 /* RXCD IPL */ +#define IPL_TTINT 0x14 /* console IPL */ +#define IPL_FLINT 0x14 /* console floppy IPL */ + +#define SCB_RXCD 0x58 +#define SCB_IPRINT 0x80 +#define SCB_FLINT 0xF0 + +#define IPL_MCTL0 (0x15 - IPL_HMIN) +#define IPL_MCTL1 (0x15 - IPL_HMIN) +#define IPL_UBA (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_IPIR 22 /* interprocessor interrupt */ +#define MT_TBDR 36 /* translation buffer disable */ +#define MT_CADR 37 /* cache disable */ +#define MT_MCESR 38 /* MCHK error summary */ +#define MT_ACCS 40 /* FPA control */ +#define MT_WCSA 44 /* WCS address */ +#define MT_WCSD 45 /* WCS data */ +#define MT_WCSL 46 /* WCS load */ +#define MT_RXCS1 80 /* Serial line 1 rx ctrl */ +#define MT_RXDB1 81 /* Serial line 1 rx data */ +#define MT_TXCS1 82 /* Serial line 1 tx ctrl */ +#define MT_TXDB1 83 /* Serial line 1 tx data */ +#define MT_RXCS2 84 /* Serial line 2 rx ctrl */ +#define MT_RXDB2 85 /* Serial line 2 rx data */ +#define MT_TXCS2 86 /* Serial line 2 tx ctrl */ +#define MT_TXDB2 87 /* Serial line 2 tx data */ +#define MT_RXCS3 88 /* Serial line 3 rx ctrl */ +#define MT_RXDB3 89 /* Serial line 3 rx data */ +#define MT_TXCS3 90 /* Serial line 3 tx ctrl */ +#define MT_TXDB3 91 /* Serial line 3 tx data */ +#define MT_RXCD 92 /* rx console data */ +#define MT_CACHEX 93 /* Cache invalidate */ +#define MT_BINID 94 /* BI node ident */ +#define MT_BISTOP 95 /* BI stop */ +#define MT_MAX 95 /* last valid IPR */ + +/* Machine specific reserved operand tests (all NOPs) */ + +#define ML_PA_TEST(r) +#define ML_LR_TEST(r) +#define ML_SBR_TEST(r) +#define ML_PXBR_TEST(r) +#define LP_AST_TEST(r) +#define LP_MBZ84_TEST(r) +#define LP_MBZ92_TEST(r) +#define MT_AST_TEST(r) r = (r) & 07; \ + if ((r) > AST_MAX) RSVD_OPND_FAULT + +/* CPU */ + +#define CPU_MODEL_MODIFIERS \ + { MTAB_XTD|MTAB_VDV, 0, "MODEL", "MODEL={8200|8250}", \ + &cpu_set_model, &cpu_show_model, NULL, "Set/Display processor model" } + +/* Memory */ + +#define MAXMEMWIDTH 22 /* max mem, std MS820 */ +#define MAXMEMSIZE (1 << MAXMEMWIDTH) +#define MAXMEMWIDTH_X 29 /* max mem, extended */ +#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 << 22), NULL, "4M", &cpu_set_size, NULL, NULL, "Set Memory to 4M bytes" }, \ + { UNIT_MSIZE, (1u << 23), NULL, "8M", &cpu_set_size, NULL, NULL, "Set Memory to 8M bytes" }, \ + { UNIT_MSIZE, (1u << 24), NULL, "16M", &cpu_set_size, NULL, NULL, "Set Memory to 16M bytes" }, \ + { UNIT_MSIZE, (1u << 25), NULL, "32M", &cpu_set_size, NULL, NULL, "Set Memory to 32M bytes" }, \ + { UNIT_MSIZE, (1u << 25) + (1u << 24), NULL, "48M", &cpu_set_size, NULL, NULL, "Set Memory to 48M bytes" }, \ + { UNIT_MSIZE, (1u << 26), NULL, "64M", &cpu_set_size, NULL, NULL, "Set Memory to 64M bytes" }, \ + { UNIT_MSIZE, (1u << 27), NULL, "128M", &cpu_set_size, NULL, NULL, "Set Memory to 128M bytes" }, \ + { UNIT_MSIZE, (1u << 28), NULL, "256M", &cpu_set_size, NULL, NULL, "Set Memory to 256M bytes" }, \ + { UNIT_MSIZE, (1u << 29), NULL, "512M", &cpu_set_size, NULL, NULL, "Set Memory to 512M bytes" }, \ + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "MEMORY", NULL, NULL, &cpu_show_memory, NULL, "Display memory configuration" } +extern t_stat cpu_show_memory (FILE* st, UNIT* uptr, int32 val, CONST void* desc); + +/* Node window space */ + +#define WINAWIDTH 18 /* VAXBI node window width */ +#define WINBASE 0x20400000 /* VAXBI node window base */ +#define WINADDR(n) (WINBASE + (n << WINAWIDTH)) /* node -> window addr */ + +/* 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 WINADDR(TR_UBA) /* Unibus addr base */ +#define IOPAGEBASE (UBADDRBASE + 0x3E000) /* 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) + +/* Watch Chip */ + +#define WATCHWIDTH 7 /* WATCH addr width */ +#define WATCHSIZE (1u << REGAWIDTH) /* WATCH length */ +#define WATCHBASE 0x200B8000 /* WATCH addr base */ + +/* Other address spaces */ + +#define ADDR_IS_ROM(x) (0) +#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 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 DUP_LINES 8 /* max # of DUP11'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_FFUF (DEV_V_UF + 3) /* 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_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 */ + uint32 ulnt; /* IO length per-device */ + /* Only need to be populated */ + /* when numunits != num devices */ + int32 numc; /* Number of controllers */ + /* this field handles devices */ + /* where multiple instances are */ + /* simulated through a single */ + /* DEVICE structure (e.g., DZ, VH, DL, DC). */ + /* Populated by auto-configure */ + DEVICE *dptr; /* back pointer to related device */ + /* Populated by auto-configure */ + } 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_AUTO (0) /* Assigned by Auto Configure */ + +/* Interrupt assignments; within each level, priority is right to left */ + +#define INT_V_DTA 0 /* BR6 */ +#define INT_V_CR 1 + +#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_DUPRX 11 +#define INT_V_DUPTX 12 +#define INT_V_RK 13 +#define INT_V_CH 14 + +#define INT_V_LPT 0 /* BR4 */ +#define INT_V_PTR 1 +#define INT_V_PTP 2 +//#define XXXXXXXX 3 /* Former CR */ +#define INT_V_VHRX 4 +#define INT_V_VHTX 5 +#define INT_V_TDRX 6 +#define INT_V_TDTX 7 + +#define INT_DTA (1u << INT_V_DTA) +#define INT_CR (1u << INT_V_CR) +#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_DMCRX (1u << INT_V_DMCRX) +#define INT_DMCTX (1u << INT_V_DMCTX) +#define INT_DUPRX (1u << INT_V_DUPRX) +#define INT_DUPTX (1u << INT_V_DUPTX) +#define INT_RK (1u << INT_V_RK) +#define INT_TDRX (1u << INT_V_TDRX) +#define INT_TDTX (1u << INT_V_TDTX) +#define INT_CH (1u << INT_V_CH) + +#define IPL_DTA (0x16 - IPL_HMIN) +#define IPL_CR (0x16 - IPL_HMIN) +#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_CH (0x15 - IPL_HMIN) +#define IPL_LPT (0x14 - IPL_HMIN) +#define IPL_PTR (0x14 - IPL_HMIN) +#define IPL_PTP (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) +#define IPL_DUPRX (0x15 - IPL_HMIN) +#define IPL_DUPTX (0x15 - IPL_HMIN) +#define IPL_RK (0x15 - IPL_HMIN) +#define IPL_TDRX (0x14 - IPL_HMIN) +#define IPL_TDTX (0x14 - IPL_HMIN) + +/* Device vectors */ + +#define VEC_AUTO (0) /* Assigned by Auto Configure */ +#define VEC_FLOAT (0) /* Assigned by Auto Configure */ + +#define VEC_QBUS 0 +#define VEC_Q 0000 + +/* 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 */ + +/* Boot definitions */ + +#define BOOT_MB 0 /* device codes */ +#define BOOT_HK 1 /* for VMB */ +#define BOOT_RL 2 +#define BOOT_UDA 17 +#define BOOT_CS 64 + +/* 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, const uint8 *buf); +int32 Map_WriteW (uint32 ba, int32 bc, const uint16 *buf); + +int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf); +int32 mba_wrbufW (uint32 mbus, int32 bc, const 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 (DEVICE *dptr); +t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, CONST void *desc); + +t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, CONST void *desc); + +/* Function prototypes for system-specific unaligned support + 8200 treats unaligned like aligned? */ + +#define ReadIOU(p,l) ReadIO (p,l) +#define ReadRegU(p,l) ReadReg (p,l) +#define WriteIOU(p,v,l) WriteIO (p, v, l) +#define WriteRegU(p,v,l) WriteReg (p, v, l) + +#include "pdp11_io_lib.h" +#include "vax_bi.h" + +/* Function prototypes for virtual and physical memory interface (inlined) */ + +#include "vax_mmu.h" + +#endif diff --git a/VAX/vax820_ka.c b/VAX/vax820_ka.c new file mode 100644 index 00000000..989fa79a --- /dev/null +++ b/VAX/vax820_ka.c @@ -0,0 +1,365 @@ +/* vax820_ka.c: VAX 8200 CPU + + Copyright (c) 2019, Matt Burke + + 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 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 of the author 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. + + This module contains the VAX 8200 CPU registers and devices. + + ka0, ka1 KA820 CPU +*/ + +#include "vax_defs.h" + +#define PCSR_RSTH 0x80000000 /* restart halt */ +#define PCSR_LCON 0x40000000 /* logical console */ +#define PCSR_CONEN 0x20000000 /* console enable */ +#define PCSR_BIRST 0x10000000 /* BI reset */ +#define PCSR_BISTF 0x08000000 /* self test fast/slow */ +#define PCSR_ENAPT 0x04000000 /* APT connection status */ +#define PCSR_STPASS 0x02000000 /* self test pass */ +#define PCSR_RUN 0x01000000 /* pgm mode run */ +#define PCSR_WWPE 0x00800000 /* write wrong parity, even */ +#define PCSR_EVLCK 0x00400000 /* event lock */ +#define PCSR_WMEM 0x00200000 /* write mem status */ +#define PCSR_V_EVENT 16 +#define PCSR_M_EVENT 0xF +#define PCSR_EVENT (PCSR_M_EVENT << PCSR_V_EVENT) /* BI event */ +#define PCSR_WWPO 0x00008000 /* write wrong parity, odd */ +#define PCSR_PER 0x00004000 /* parity error */ +#define PCSR_ENPIPE 0x00002000 /* enable BI pipeline */ +#define PCSR_TIMEOUT 0x00001000 /* timeout */ +#define PCSR_RSVD 0x00000800 /* reserved */ +#define PCSR_CONIE 0x00000400 /* console interrupt enable */ +#define PCSR_CONCLR 0x00000200 /* clear console interrupt */ +#define PCSR_V_CONINT 8 +#define PCSR_CONINT (1u << PCSR_V_CONINT) /* console interrupt req */ +#define PCSR_RXIE 0x00000080 /* RX50 interrupt enable */ +#define PCSR_RXCLR 0x00000040 /* clear RX50 interrupt */ +#define PCSR_RXINT 0x00000020 /* RX50 interrupt request */ +#define PCSR_IPCLR 0x00000010 /* clear IP interrupt */ +#define PCSR_V_IPINT 3 +#define PCSR_IPINT (1u << PCSR_V_IPINT) /* IP interrupt request */ +#define PCSR_CRDEN 0x00000004 /* enable CRD interrupts */ +#define PCSR_CRDCLR 0x00000002 /* clear CRD interrupt */ +#define PCSR_CRDINT 0x00000001 /* CRD interrupt request */ +#define PCSR_WR (PCSR_RUN | PCSR_WWPE | PCSR_WWPO | \ + PCSR_ENPIPE | PCSR_CONIE | PCSR_RXIE | \ + PCSR_CRDEN) +#define PCSR_W1C (PCSR_EVLCK | PCSR_PER | PCSR_TIMEOUT) + +int32 rxcd_count = 0; +char rxcd_ibuf[20]; +char rxcd_obuf[20]; +int32 rxcd_iptr = 0; +int32 rxcd_optr = 0; +char rxcd_char = '\0'; +BIIC ka_biic[KA_NUM]; +uint32 ka_rxcd[KA_NUM]; +uint32 ka_pcsr[KA_NUM]; + +extern int32 rxcd_int; +extern int32 ipir; +#if defined (VAX_MP) +extern int32 cur_cpu; +#else +int32 cur_cpu; +#endif + +t_stat ka_reset (DEVICE *dptr); +t_stat ka_rdreg (int32 *val, int32 pa, int32 mode); +t_stat ka_wrreg (int32 val, int32 pa, int32 mode); +t_stat ka_svc (UNIT *uptr); + +#if defined (VAX_MP) +extern void cpu_setreg (int32 cpu, int32 rg, int32 val); +extern void cpu_start (int32 cpu, uint32 addr); +#endif + +/* KAx data structures + + kax_dev KAx device descriptor + kax_unit KAx unit + kax_reg KAx register list +*/ + +DIB ka0_dib[] = { TR_KA0, 0, &ka_rdreg, &ka_wrreg, 0 }; + +UNIT ka0_unit = { UDATA (&ka_svc, 0, 0) }; + +REG ka0_reg[] = { + { NULL } + }; + +MTAB ka0_mod[] = { + { MTAB_XTD|MTAB_VDV, TR_KA0, "NEXUS", NULL, + NULL, &show_nexus }, + { 0 } + }; + +DIB ka1_dib[] = { TR_KA1, 0, &ka_rdreg, &ka_wrreg, 0 }; + +UNIT ka1_unit = { UDATA (&ka_svc, 0, 0) }; + +MTAB ka1_mod[] = { + { MTAB_XTD|MTAB_VDV, TR_KA1, "NEXUS", NULL, + NULL, &show_nexus }, + { 0 } }; + +REG ka1_reg[] = { + { NULL } + }; + +DEVICE ka_dev[] = { + { + "KA0", &ka0_unit, ka0_reg, ka0_mod, + 1, 16, 16, 1, 16, 8, + NULL, NULL, &ka_reset, + NULL, NULL, NULL, + &ka0_dib, DEV_NEXUS + }, + { + "KA1", &ka1_unit, ka1_reg, ka1_mod, + 1, 16, 16, 1, 16, 8, + NULL, NULL, &ka_reset, + NULL, NULL, NULL, + &ka1_dib, DEV_NEXUS | DEV_DISABLE | DEV_DIS + } + }; + +/* KA read */ + +t_stat ka_rdreg (int32 *val, int32 pa, int32 lnt) +{ +int32 ka, ofs; +t_bool extmem = MEMSIZE > MAXMEMSIZE; + +ka = NEXUS_GETNEX (pa) - TR_KA0; /* get CPU num */ +ofs = NEXUS_GETOFS (pa); /* get offset */ +switch (ofs) { + + case BI_DTYPE: + *val = DTYPE_KA820; + break; + + case BI_CSR: + *val = ka_biic[ka].csr & BICSR_RD; + break; + + case BI_BER: + *val = ka_biic[ka].ber & BIBER_RD; + break; + + case BI_EICR: + *val = ka_biic[ka].eicr & BIECR_RD; + break; + + case BI_IDEST: + *val = ka_biic[ka].idest & BIID_RD; + break; + + case BI_SA: + case BI_EA: + *val = 0; + break; + + default: + return SCPE_NXM; + } + +return SCPE_OK; +} + +/* KA write */ + +t_stat ka_wrreg (int32 val, int32 pa, int32 lnt) +{ +int32 ka, ofs; +t_bool extmem = MEMSIZE > MAXMEMSIZE; + +ka = NEXUS_GETNEX (pa) - TR_KA0; /* get CPU num */ +ofs = NEXUS_GETOFS (pa); /* get offset */ +switch (ofs) { + + case BI_CSR: + ka_biic[ka].csr = (ka_biic[ka].csr & ~BICSR_RW) | (val & BICSR_RW); + break; + + case BI_BER: + ka_biic[ka].ber = ka_biic[ka].ber & ~(val & BIBER_W1C); + break; + + case BI_EICR: + ka_biic[ka].eicr = (ka_biic[ka].eicr & ~BIECR_RW) | (val & BIECR_RW); + ka_biic[ka].eicr = ka_biic[ka].eicr & ~(val & BIECR_W1C); + break; + + case BI_IDEST: + ka_biic[ka].idest = val & BIID_RW; + break; + + case BI_IMSK: + break; + + default: + return SCPE_NXM; + } + +return SCPE_OK; +} + +/* KA reset */ + +t_stat ka_reset (DEVICE *dptr) +{ +int32 i; + +rxcd_count = 0; +ka_rxcd[0] = 0; +ka_rxcd[1] = 0; +for (i = 0; i < KA_NUM; i++) { + ka_biic[i].csr = (1u << BICSR_V_IF) | BICSR_STS | ((TR_KA0 + i) & BICSR_NODE); + ka_biic[i].ber = 0; + ka_biic[i].eicr = 0; + ka_biic[i].idest = 0; + } +ka_pcsr[0] = PCSR_CONEN | PCSR_ENAPT | PCSR_STPASS | PCSR_RUN; +ka_pcsr[1] = PCSR_RSTH | PCSR_LCON | PCSR_CONEN | PCSR_ENAPT | PCSR_STPASS | PCSR_RUN; +sim_cancel (&ka0_unit); +sim_cancel (&ka1_unit); +return SCPE_OK; +} + +t_stat ka_svc (UNIT *uptr) +{ +if ((rxcd_count > 0) && rxcd_int) + sim_activate (uptr, 20); +rxcd_int = 1; +return SCPE_OK; +} + +int32 rxcd_rd (void) +{ +int32 val; + +if (rxcd_count) { /* data available? */ + val = rxcd_obuf[rxcd_optr] | (1 << 8); + rxcd_optr++; + rxcd_count--; + if (rxcd_count) + sim_activate (&ka0_unit, 20); + } +else { + val = 0x52584344; /* "RXCD" */ + mxpr_cc_vc |= CC_V; /* set overflow */ + } + +return val; +} + +void rxcd_wr (int32 val) +{ +int32 cpu = (val >> 8) & 7; +int32 ch = val & 0xFF; +int32 rg; +int32 rval; +t_stat r; +char conv[10]; + +if (ka_rxcd[cpu] & 0x8000) { /* busy? */ + mxpr_cc_vc |= CC_V; /* set overflow */ + return; + } + +switch (ch) { + + case 0x0D: /* CR */ + rxcd_ibuf[rxcd_iptr++] = '\0'; /* terminator */ + printf (">>> %s\n", &rxcd_ibuf[0]); + if (rxcd_ibuf[0] == 'D') { /* DEPOSIT */ + snprintf (&conv[0], 2, "%s", &rxcd_ibuf[4]); + rg = (int32)get_uint (&conv[0], 16, 0xF, &r); /* get register number */ + snprintf (&conv[0], 9, "%s", &rxcd_ibuf[6]); + rval = (int32)get_uint (&conv[0], 16, 0xFFFFFFFF, &r); /* get deposit value */ +#if defined (VAX_MP) + cpu_setreg (cpu, rg, rval); +#endif + rxcd_count = 3; /* ready for next cmd */ + sprintf (&rxcd_obuf[0], ">>>"); + rxcd_optr = 0; + } + else if (rxcd_ibuf[0] == 'I') { /* INIT */ + rxcd_count = 3; /* ready for next cmd */ + sprintf (&rxcd_obuf[0], ">>>"); + rxcd_optr = 0; + } + else if (rxcd_ibuf[0] == 'S') { /* START */ + snprintf (&conv[0], 9, "%s", &rxcd_ibuf[2]); + rval = (int32)get_uint (&conv[0], 16, 0xFFFFFFFF, &r); +#if defined (VAX_MP) + cpu_start (cpu, rval); +#endif + } + rxcd_iptr = 0; + break; + + case 0x10: /* CTRL-P */ + rxcd_count = 3; /* ready for next cmd */ + sprintf (&rxcd_obuf[0], ">>>"); + rxcd_optr = 0; + break; + + default: + rxcd_count = 1; + rxcd_obuf[0] = ch; /* echo characters back */ + rxcd_optr = 0; + rxcd_ibuf[rxcd_iptr++] = ch; /* store incoming charactes */ + break; + } +if (rxcd_count) { + if (cpu == 0) + sim_activate (&ka0_unit, 20); + else + sim_activate (&ka1_unit, 20); + } +return; +} + +int32 pcsr_rd (int32 pa) +{ +int32 data; +int32 ip_int = (ipir >> cur_cpu) & 0x1; +data = ka_pcsr[cur_cpu] | (rxcd_int << PCSR_V_CONINT) | (ip_int << PCSR_V_IPINT); +printf ("pcsr_rd: %08X\n", data); +return data; +} + +void pcsr_wr (int32 pa, int32 val, int32 lnt) +{ +printf ("pcsr_wr: %08X\n", val); +ka_pcsr[cur_cpu] &= ~(val & PCSR_W1C); +ka_pcsr[cur_cpu] &= ~(PCSR_WR) | (val & PCSR_WR); +if (val & PCSR_CONCLR) + rxcd_int = 0; +if (val & PCSR_IPCLR) + ipir &= ~(1u << cur_cpu); +} diff --git a/VAX/vax820_mem.c b/VAX/vax820_mem.c new file mode 100644 index 00000000..75660257 --- /dev/null +++ b/VAX/vax820_mem.c @@ -0,0 +1,212 @@ +/* vax820_mem.c: VAX 8200 memory controllers + + Copyright (c) 2019, Matt Burke + + 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 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 of the author 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. + + mctl0, mctl1 MS820 memory controllers +*/ + +#include "vax_defs.h" + +/* Memory CSR 1 */ + +#define MCSR1_OF 0x40 +#define MCSR1_V_SIZE 18 /* memory size */ +#define MCSR1_M_SIZE 0x7FF +#define MCSR1_MWE 0x00000400 /* masked write error - NI */ +#define MCSR1_ICE 0x00000200 /* internal controller error - NI */ +#define MCSR1_CDI 0x00008000 /* CRD interrupt inhibit - NI */ + +/* Memory CSR 2 */ + +#define MCSR2_OF 0x41 + +uint32 mcsr_1[MCTL_NUM]; +uint32 mcsr_2[MCTL_NUM]; + +t_stat mctl_reset (DEVICE *dptr); +const char *mctl_description (DEVICE *dptr); +t_stat mctl_rdreg (int32 *val, int32 pa, int32 mode); +t_stat mctl_wrreg (int32 val, int32 pa, int32 mode); + +/* MCTLx data structures + + mctlx_dev MCTLx device descriptor + mctlx_unit MCTLx unit + mctlx_reg MCTLx register list +*/ + +DIB mctl0_dib[] = { TR_MCTL0, 0, &mctl_rdreg, &mctl_wrreg, 0 }; + +UNIT mctl0_unit = { UDATA (NULL, 0, 0) }; + +REG mctl0_reg[] = { + { HRDATA (CSR1, mcsr_1[0], 32) }, + { HRDATA (CSR2, mcsr_2[0], 32) }, + { NULL } + }; + +MTAB mctl0_mod[] = { + { MTAB_XTD|MTAB_VDV, TR_MCTL0, "NEXUS", NULL, + NULL, &show_nexus, NULL, "Display nexus" }, + { 0 } + }; + +DIB mctl1_dib[] = { TR_MCTL1, 0, &mctl_rdreg, &mctl_wrreg, 0 }; + +UNIT mctl1_unit = { UDATA (NULL, 0, 0) }; + +MTAB mctl1_mod[] = { + { MTAB_XTD|MTAB_VDV, TR_MCTL1, "NEXUS", NULL, + NULL, &show_nexus }, + { 0 } }; + +REG mctl1_reg[] = { + { HRDATA (CSR1, mcsr_1[1], 32) }, + { HRDATA (CSR2, mcsr_2[1], 32) }, + { NULL } + }; + +DEVICE mctl_dev[] = { + { + "MCTL0", &mctl0_unit, mctl0_reg, mctl0_mod, + 1, 16, 16, 1, 16, 8, + NULL, NULL, &mctl_reset, + NULL, NULL, NULL, + &mctl0_dib, DEV_NEXUS, 0, + NULL, NULL, NULL, NULL, NULL, NULL, + &mctl_description + }, + { + "MCTL1", &mctl1_unit, mctl1_reg, mctl1_mod, + 1, 16, 16, 1, 16, 8, + NULL, NULL, &mctl_reset, + NULL, NULL, NULL, + &mctl1_dib, DEV_NEXUS, 0, + NULL, NULL, NULL, NULL, NULL, NULL, + &mctl_description + } + }; + +/* Memory controller register read */ + +t_stat mctl_rdreg (int32 *val, int32 pa, int32 lnt) +{ +int32 mctl, ofs; +t_bool extmem = MEMSIZE > MAXMEMSIZE; + +mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */ +ofs = NEXUS_GETOFS (pa); /* get offset */ +switch (ofs) { + + case BI_DTYPE: + *val = DTYPE_MS820; + break; + + case BI_CSR: + case BI_BER: + case BI_EICR: + case BI_IDEST: + *val = 0; + break; + + case BI_SA: /* start address */ + *val = (mctl == 0) ? 0 : (int32)(MEMSIZE >> 1); + break; + + case BI_EA: /* end address */ + *val = (mctl == 0) ? (int32)(MEMSIZE >> 1) : (int32)MEMSIZE; + break; + + case MCSR1_OF: /* CSR 1 */ + *val = mcsr_1[mctl]; + break; + + case MCSR2_OF: /* CSR 2 */ + *val = mcsr_2[mctl]; + break; + + default: + return SCPE_NXM; + } + +return SCPE_OK; +} + +/* Memory controller register write */ + +t_stat mctl_wrreg (int32 val, int32 pa, int32 lnt) +{ +int32 mctl, ofs; +t_bool extmem = MEMSIZE > MAXMEMSIZE; + +mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */ +ofs = NEXUS_GETOFS (pa); /* get offset */ +switch (ofs) { + + case BI_CSR: + case BI_BER: + case BI_EICR: + case BI_IDEST: + break; + + case MCSR1_OF: /* CSR 1 */ + case MCSR2_OF: /* CSR 2 */ + break; + + default: + return SCPE_NXM; + } + +return SCPE_OK; +} + +/* Used by CPU and loader */ + +void rom_wr_B (int32 pa, int32 val) +{ +return; +} + +/* MEMCTL reset */ + +t_stat mctl_reset (DEVICE *dptr) +{ +int32 i; +for (i = 0; i < MCTL_NUM; i++) { /* init for MS820 */ + mcsr_1[i] = (MCSR1_M_SIZE << MCSR1_V_SIZE); + mcsr_2[i] = 0; + } +return SCPE_OK; +} + +const char *mctl_description (DEVICE *dptr) +{ +return "memory controller"; +} + +t_stat cpu_show_memory (FILE* st, UNIT* uptr, int32 val, CONST void* desc) +{ +// TODO +return SCPE_OK; +} diff --git a/VAX/vax820_stddev.c b/VAX/vax820_stddev.c new file mode 100644 index 00000000..b307257c --- /dev/null +++ b/VAX/vax820_stddev.c @@ -0,0 +1,1216 @@ +/* vax820_stddev.c: VAX 8200 standard I/O devices + + Copyright (c) 2019, 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 floppy + todr TODR clock + tmr interval timer +*/ + +#include "vax_defs.h" +#include "sim_tmxr.h" + +/* Terminal definitions */ + +#define RXCS_RD (CSR_DONE + CSR_IE) /* terminal input */ +#define RXCS_WR (CSR_IE) +#define RXDB_ERR 0x8000 /* error */ +#define RXDB_OVR 0x4000 /* overrun */ +#define RXDB_FRM 0x2000 /* framing error */ +#define TXCS_RD (CSR_DONE + CSR_IE) /* terminal output */ +#define TXCS_WR (CSR_IE) +#define TXDB_V_SEL 8 /* unit select */ +#define TXDB_M_SEL 0xF +#define TXDB_FDAT 0x1 /* floppy data */ +#define TXDB_COMM 0x3 /* console mem read */ +#define TXDB_FCMD 0x9 /* floppy cmd */ +#define TXDB_MISC 0xF /* console misc */ +#define COMM_LNT 0200 /* comm region lnt */ +#define COMM_MASK (COMM_LNT - 1) /* comm region mask */ +#define COMM_GH 0144 /* GH flag */ +#define COMM_WRMS 0145 /* warm start */ +#define COMM_CLDS 0146 /* cold start */ +#define COMM_APTL 0147 /* APT load */ +#define COMM_LAST 0150 /* last position */ +#define COMM_AUTO 0151 /* auto restart */ +#define COMM_PCSV 0152 /* PCS version */ +#define COMM_WCSV 0153 /* WCS version */ +#define COMM_WCSS 0154 /* WCS secondary */ +#define COMM_FPLV 0155 /* FPLA version */ +#define COMM_MTCH_785 0153 /* 785 PCS/WCS version */ +#define COMM_WCSP_785 0154 /* 785 WCS version */ +#define COMM_WCSS_785 0155 /* 785 WCS secondary */ +#define COMM_DATA 0x300 /* comm data return */ +#define MISC_MASK 0xFF /* console data mask */ +#define MISC_SWDN 0x1 /* software done */ +#define MISC_BOOT 0x2 /* reboot */ +#define MISC_CLWS 0x3 /* clear warm start */ +#define MISC_CLCS 0x4 /* clear cold start */ +#define TXDB_SEL (TXDB_M_SEL << TXDB_V_SEL) /* non-terminal */ +#define TXDB_GETSEL(x) (((x) >> TXDB_V_SEL) & TXDB_M_SEL) + +/* 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 */ + +static BITFIELD tmr_iccs_bits [] = { + BIT(RUN), /* Run */ + BITNCF(3), /* unused */ + BIT(XFR), /* Transfer */ + BIT(SGL), /* Single */ + BIT(IE), /* Interrupt Enable */ + BIT(DON), /* Done */ + BITNCF(23), /* unused */ + BIT(ERR), /* Error */ + ENDBITS + }; + +/* Floppy definitions */ + +#define FL_CS0 2 +#define FL_CS1 3 +#define FL_CS2 4 +#define FL_CS3 5 +#define FL_CS4 6 +#define FL_CS5 7 +#define FL_EB 8 +#define FL_CA 9 +#define FL_GO 10 +#define FL_FB 11 + +#define FLCS0_SS 0x01 /* side select */ +#define FLCS0_DKS 0x02 /* disk select */ +#define FLCS0_DS 0x04 /* drive select */ +#define FLCS0_EMT 0x08 /* extended motor timeout (write only) */ +#define FLCS0_DONE 0x08 /* done (read only) */ +#define FLCS0_V_FNC 4 /* function code */ +#define FLCS0_M_FNC 0x7 +#define FLCS0_FNC (FLCS0_M_FNC << FLCS0_V_FNC) +#define FL_FNCST 0x0 /* read status */ +#define FL_FNCMM 0x1 /* maintenance mode */ +#define FL_FNCRD 0x2 /* restore drive */ +#define FL_FNCIN 0x3 /* initialise */ +#define FL_FNCRS 0x4 /* read sector */ +#define FL_FNCEX 0x5 /* extended function */ +#define FL_FNCRA 0x6 /* read address */ +#define FL_FNCWS 0x7 /* write sector */ +#define FLCS0_ERR 0x80 /* error (read only) */ +#define FLCS0_WR 0x7F + +const char *fl_fncnames[] = { + "read status", + "maintenance status", + "restore drive", + "initialise", + "read sector", + "extended function", + "read address", + "write sector" + }; + +#define FLCS1_TRK 0x7F /* track number */ + +#define FLCS2_SECT 0x0F /* sector number */ +#define FLCS2_TRK 0x7F /* track number */ + +#define FLCS3_SECT 0x0F /* sector number */ + +#define FLCS4_D0AV 0x01 /* disk 0 available */ +#define FLCS4_D0DS 0x02 /* disk 0 double sided */ +#define FLCS4_D1AV 0x04 /* disk 1 available */ +#define FLCS4_D1DS 0x08 /* disk 1 double sided */ +#define FLCS4_D2AV 0x10 /* disk 2 available */ +#define FLCS4_D2DS 0x20 /* disk 2 double sided */ +#define FLCS4_D3AV 0x40 /* disk 3 available */ +#define FLCS4_D3DS 0x80 /* disk 3 double sided */ + +#define FLCS5_FUNC 0xFF /* extended function code */ + +#define FL_NUMTR 80 /* tracks/disk */ +#define FL_NUMSC 10 /* sectors/track */ +#define FL_NUMBY 512 /* bytes/sector */ +#define FL_INTL 5 /* interleave */ +#define FL_SIZE (FL_NUMTR * FL_NUMSC * FL_NUMBY)/* bytes/disk */ +#define UNIT_V_WLK (UNIT_V_UF) /* write locked */ +#define UNIT_WLK (1u << UNIT_V_UF) +#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ + +#define TRACK u3 /* current track */ +#define CALC_SC(t,s) (fl_intl[((t) - 1) % FL_INTL][((s) - 1)]) +#define CALC_DA(t,s) ((((t) - 1) * FL_NUMSC) + CALC_SC(t,s)) * FL_NUMBY + +int32 tti_csr = 0; /* control/status */ +uint32 tti_buftime; /* time input character arrived */ +int32 tti_buf = 0; /* buffer */ +int32 tti_int = 0; /* interrupt */ +int32 tto_csr[KA_NUM] = { 0 }; /* control/status */ +int32 tto_buf = 0; /* buffer */ +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_int = 0; /* interrupt */ +int32 clk_tps = 100; /* ticks/second */ +int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */ +int32 tmr_poll = CLK_DELAY; /* pgm timer poll */ +struct todr_battery_info { + uint32 toy_gmtbase; /* GMT base of set value */ + uint32 toy_gmtbasemsec; /* The milliseconds of the set value */ + uint32 toy_endian_plus2; /* 2 -> Big Endian, 3 -> Little Endian, invalid otherwise */ + }; +typedef struct todr_battery_info TOY; + +int32 fl_cs0 = 0; +int32 fl_cs1 = 0; +int32 fl_cs2 = 0; +int32 fl_cs3 = 0; +int32 fl_cs4 = 0; +int32 fl_cs5 = 0; + +int32 fl_int = 0; +int32 fl_fnc = 0; /* function */ +int32 fl_ecode = 0; /* error code */ +int32 fl_track = 0; /* desired track */ +int32 fl_sector = 0; /* desired sector */ +int32 fl_stopioe = 1; /* stop on error */ +int32 fl_swait = 100; /* seek, per track */ +int32 fl_cwait = 50; /* command time */ +int32 fl_xwait = 20; /* tr set time */ +uint8 fl_buf[FL_NUMBY] = { 0 }; /* sector buffer */ +int32 fl_bptr = 0; /* buffer pointer */ +static int32 fl_intl[FL_INTL][FL_NUMSC] = { + { 0, 5, 1, 6, 2, 7, 3, 8, 4, 9 }, + { 4, 9, 0, 5, 1, 6, 2, 7, 3, 8 }, + { 3, 8, 4, 9, 0, 5, 1, 6, 2, 7 }, + { 2, 7, 3, 8, 4, 9, 0, 5, 1, 6 }, + { 1, 6, 2, 7, 3, 8, 4, 9, 0, 5 } + }; + + +extern int32 cur_cpu; + +t_stat tti_svc (UNIT *uptr); +t_stat tto_svc (UNIT *uptr); +t_stat tmr_svc (UNIT *uptr); +t_stat tti_reset (DEVICE *dptr); +t_stat tto_reset (DEVICE *dptr); +t_stat clk_reset (DEVICE *dptr); +const char *tti_description (DEVICE *dptr); +const char *tto_description (DEVICE *dptr); +const char *clk_description (DEVICE *dptr); +const char *tmr_description (DEVICE *dptr); +const char *fl_description (DEVICE *dptr); +t_stat tti_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +t_stat tto_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +t_stat clk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +t_stat clk_attach (UNIT *uptr, CONST char *cptr); +t_stat clk_detach (UNIT *uptr); +t_stat tmr_reset (DEVICE *dptr); +t_stat fl_svc (UNIT *uptr); +t_stat fl_reset (DEVICE *dptr); +int32 icr_rd (void); +void tmr_sched (uint32 incr); +t_stat todr_resync (void); +t_bool fl_test_xfr (UNIT *uptr, t_bool wr); +void fl_protocol_error (void); + +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, UNIT_IDLE|TT_MODE_8B, 0), TMLN_SPD_9600_BPS }; + +REG tti_reg[] = { + { HRDATAD (RXDB, tti_buf, 16, "last data item processed") }, + { HRDATAD (RXCS, tti_csr, 16, "control/status register") }, + { FLDATAD (INT, tti_int, 0, "interrupt pending flag") }, + { FLDATAD (DONE, tti_csr, CSR_V_DONE, "device done flag (CSR<7>)") }, + { FLDATAD (IE, tti_csr, CSR_V_IE, "interrupt enable flag (CSR<6>)") }, + { DRDATAD (POS, tti_unit.pos, T_ADDR_W, "number of characters input"), PV_LEFT }, + { DRDATAD (TIME, tti_unit.wait, 24, "input polling interval"), PV_LEFT }, + { NULL } + }; + +MTAB tti_mod[] = { + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL, NULL, NULL, "Set 7 bit mode" }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL, NULL, NULL, "Set 8 bit mode" }, + { 0 } + }; + +DEVICE tti_dev = { + "TTI", &tti_unit, tti_reg, tti_mod, + 1, 10, 31, 1, 16, 8, + NULL, NULL, &tti_reset, + NULL, NULL, NULL, + NULL, 0, 0, NULL, NULL, NULL, &tti_help, NULL, NULL, + &tti_description + }; + +/* 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 } + }; + +REG tto_reg[] = { + { HRDATAD (TXDB, tto_buf, 16, "last data item processed") }, + { HRDATAD (TXCS, tto_csr, 16, "control/status register") }, + { FLDATAD (INT, tto_int, 0, "interrupt pending flag") }, + { FLDATAD (DONE, tto_csr, CSR_V_DONE, "device done flag (CSR<7>)") }, + { FLDATAD (IE, tto_csr, CSR_V_IE, "interrupt enable flag (CSR<6>)") }, + { DRDATAD (POS, tto_unit[0].pos, T_ADDR_W, "number of characters output"), PV_LEFT }, + { DRDATAD (TIME, tto_unit[0].wait, 24, "time from I/O initiation to interrupt"), PV_LEFT + REG_NZ }, + { NULL } + }; + +MTAB tto_mod[] = { + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL, NULL, NULL, "Set 7 bit mode" }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL, NULL, NULL, "Set 8 bit mode" }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL, NULL, NULL, "Set 7 bit mode (suppress non printing output)" }, + { 0 } + }; + +DEVICE tto_dev = { + "TTO", tto_unit, tto_reg, tto_mod, + 2, 10, 31, 1, 16, 8, + NULL, NULL, &tto_reset, + NULL, NULL, NULL, + NULL, 0, 0, NULL, NULL, NULL, &tto_help, NULL, NULL, + &tto_description + }; + +/* TODR and TMR data structures */ + +UNIT clk_unit = { UDATA (NULL, UNIT_FIX, sizeof(TOY))}; + +REG clk_reg[] = { + { DRDATAD (TIME, clk_unit.wait, 24, "initial poll interval"), REG_NZ + PV_LEFT }, + { DRDATAD (POLL, tmr_poll, 24, "calibrated poll interval"), REG_NZ + PV_LEFT + REG_HRO }, +#if defined (SIM_ASYNCH_IO) + { DRDATAD (ASYNCH, sim_asynch_enabled, 1, "asynch I/O enabled flag"), PV_LEFT }, + { DRDATAD (LATENCY, sim_asynch_latency, 32, "desired asynch interrupt latency"), PV_LEFT }, + { DRDATAD (INST_LATENCY, sim_asynch_inst_latency, 32, "calibrated instruction latency"), PV_LEFT }, +#endif + { NULL } + }; + +#define TMR_DB_TODR 0x10 /* TODR */ + +DEBTAB todr_deb[] = { + { "TODR", TMR_DB_TODR, "TODR activities"}, + { NULL, 0 } + }; + +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, DEV_DEBUG, 0, todr_deb, NULL, NULL, &clk_help, NULL, NULL, + &clk_description + }; + +UNIT tmr_unit = { UDATA (&tmr_svc, 0, 0) }; /* timer */ + +REG tmr_reg[] = { + { HRDATADF (ICCS, tmr_iccs, 32, "interval timer control and status", tmr_iccs_bits) }, + { HRDATAD (ICR, tmr_icr, 32, "interval count register") }, + { HRDATAD (NICR, tmr_nicr, 32, "next interval count register") }, + { FLDATAD (INT, tmr_int, 0, "interrupt request") }, + { DRDATAD (TPS, clk_tps, 8, "ticks per second"), REG_NZ + PV_LEFT }, + { HRDATA (INCR, tmr_inc, 32), REG_HIDDEN }, + { NULL } + }; + +#define TMR_DB_REG 0x01 /* Register Access */ +#define TMR_DB_TICK 0x02 /* Ticks */ +#define TMR_DB_SCHED 0x04 /* Scheduling */ +#define TMR_DB_INT 0x08 /* Interrupts */ + +DEBTAB tmr_deb[] = { + { "REG", TMR_DB_REG, "Register Access"}, + { "TICK", TMR_DB_TICK, "Ticks"}, + { "SCHED", TMR_DB_SCHED, "Scheduling"}, + { "INT", TMR_DB_INT, "Interrupts"}, + { NULL, 0 } + }; + +DEVICE tmr_dev = { + "TMR", &tmr_unit, tmr_reg, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &tmr_reset, + NULL, NULL, NULL, + NULL, DEV_DEBUG, 0, + tmr_deb, NULL, NULL, NULL, NULL, NULL, + &tmr_description + }; + +/* RX01 data structures + + fl_dev RX device descriptor + fl_unit RX unit list + fl_reg RX register list + fl_mod RX modifier list +*/ + +UNIT fl_unit[] = { + { UDATA (&fl_svc, + UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, FL_SIZE) }, + { UDATA (&fl_svc, + UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, FL_SIZE) } + }; + +REG fl_reg[] = { + { HRDATAD (FNC, fl_fnc, 8, "function select") }, + { HRDATAD (ECODE, fl_ecode, 8, "error code") }, + { HRDATAD (TA, fl_track, 8, "track address") }, + { HRDATAD (SA, fl_sector, 8, "sector address") }, + { DRDATAD (BPTR, fl_bptr, 7, "data buffer pointer") }, + { DRDATAD (CTIME, fl_cwait, 24, "command initiation delay"), PV_LEFT }, + { DRDATAD (STIME, fl_swait, 24, "seek time delay, per track"), PV_LEFT }, + { DRDATAD (XTIME, fl_xwait, 24, "transfer time delay, per byte"), PV_LEFT }, + { FLDATAD (STOP_IOE, fl_stopioe, 0, "stop on I/O error") }, + { BRDATAD (DBUF, fl_buf, 16, 8, FL_NUMBY, "data buffer") }, + { NULL } + }; + +MTAB fl_mod[] = { + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL, NULL, NULL, "Write enable floppy drive" }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL, NULL, NULL, "Write lock floppy drive" }, + { 0 } + }; + +#define FL_DB_REG 0x01 /* Register Access */ +#define FL_DB_FNC 0x02 /* Functions */ +#define FL_DB_INT 0x04 /* Interrupts */ + +DEBTAB fl_deb[] = { + { "REG", FL_DB_REG, "Register Access"}, + { "FNC", FL_DB_FNC, "Functions"}, + { "INT", FL_DB_INT, "Interrupts"}, + { NULL, 0 } + }; + +DEVICE fl_dev = { + "CS", fl_unit, fl_reg, fl_mod, + 2, DEV_RDX, 20, 1, DEV_RDX, 8, + NULL, NULL, &fl_reset, + NULL, NULL, NULL, + NULL, DEV_DEBUG, 0, + fl_deb, NULL, NULL, NULL, NULL, NULL, + &fl_description + }; + +const char *fl_regnames[] = { + "", /* 0 spare */ + "", /* 1 spare */ + "CS0", /* 2 */ + "CS1", /* 3 */ + "CS2", /* 4 */ + "CS3", /* 5 */ + "CS4", /* 6 */ + "CS5", /* 7 */ + "EB", /* 8 */ + "CA", /* 9 */ + "GO", /* 10 */ + "FB" /* 11 */ + }; + +/* 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); +} + +int32 rxdb_rd (void) +{ +int32 t = tti_buf; /* char + error */ + +if (tti_csr & CSR_DONE) { /* Input pending ? */ + tti_csr = tti_csr & ~CSR_DONE; /* clr done */ + tti_buf = tti_buf & BMASK; /* clr errors */ + tti_int = 0; + sim_activate_after_abs (&tti_unit, tti_unit.wait); /* check soon for more input */ + } +return t; +} + +int32 txcs_rd (void) +{ +return (tto_csr[cur_cpu] & TXCS_RD); +} + +void txcs_wr (int32 data) +{ +if ((data & CSR_IE) == 0) + tto_int &= ~(1u << cur_cpu); +else { + if ((tto_csr[cur_cpu] & (CSR_DONE + CSR_IE)) == CSR_DONE) + tto_int |= (1u << cur_cpu); + } +tto_csr[cur_cpu] = (tto_csr[cur_cpu] & ~TXCS_WR) | (data & TXCS_WR); +} + +void txdb_wr (int32 data) +{ +if (cur_cpu == 0) + tto_buf = data & WMASK; /* save data */ +tto_csr[cur_cpu] = tto_csr[cur_cpu] & ~CSR_DONE; /* clear flag */ +tto_int &= ~(1u << cur_cpu); /* clear int */ +sim_activate (&tto_unit[cur_cpu], tto_unit[cur_cpu].wait); +} + +/* Terminal input service (poll for character) */ + +t_stat tti_svc (UNIT *uptr) +{ +int32 c; + +sim_clock_coschedule (uptr, tmxr_poll); /* continue poll */ + +if ((tti_csr & CSR_DONE) && /* input still pending and < 500ms? */ + ((sim_os_msec () - tti_buftime) < 500)) + return SCPE_OK; +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return c; +if (c & SCPE_BREAK) /* break? */ + tti_buf = RXDB_ERR | RXDB_FRM; +else + tti_buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags)); +tti_buftime = sim_os_msec (); +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) +{ +tmxr_set_console_units (&tti_unit, &tto_unit[0]); +tti_buf = 0; +tti_csr = 0; +tti_int = 0; +sim_activate (&tti_unit, tmr_poll); +return SCPE_OK; +} + +t_stat tti_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "Console Terminal Input (TTI)\n\n"); +fprintf (st, "The terminal input (TTI) polls the console keyboard for input.\n\n"); +fprint_set_help (st, dptr); +fprint_show_help (st, dptr); +fprint_reg_help (st, dptr); +return SCPE_OK; +} + +const char *tti_description (DEVICE *dptr) +{ +return "console terminal input"; +} + +/* Terminal output service (output character) */ + +t_stat tto_svc (UNIT *uptr) +{ +int32 c; +t_stat r; +int32 cpu = uptr->u3; + +if (cpu == 0) { + if ((tto_buf & TXDB_SEL) == 0) { /* for console? */ + c = sim_tt_outcvt (tto_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 */ + } + } + uptr->pos = uptr->pos + 1; + } + } +tto_csr[cpu] = tto_csr[cpu] | CSR_DONE; +if (tto_csr[cpu] & CSR_IE) + tto_int |= (1u << cpu); +return SCPE_OK; +} + +/* Terminal output reset */ + +t_stat tto_reset (DEVICE *dptr) +{ +int32 i; + +tto_buf = 0; +tto_int = 0; +for (i = 0; i < KA_NUM; i++) { + tto_csr[i] = CSR_DONE; + tto_unit[i].u3 = i; + sim_cancel (&tto_unit[i]); /* deactivate unit */ + } +return SCPE_OK; +} + +t_stat tto_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "Console Terminal Output (TTO)\n\n"); +fprintf (st, "The terminal output (TTO) writes to the simulator console.\n\n"); +fprint_set_help (st, dptr); +fprint_show_help (st, dptr); +fprint_reg_help (st, dptr); +return SCPE_OK; +} + +const char *tto_description (DEVICE *dptr) +{ +return "console terminal output"; +} + +/* 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 1Mhz intervals are + derived from the calibrated instruction execution rate. + + If the interval register is read, then its value between events + is interpolated relative to the elapsed instruction count. +*/ + +int32 iccs_rd (void) +{ +sim_debug_bits_hdr (TMR_DB_REG, &tmr_dev, "iccs_rd()", tmr_iccs_bits, tmr_iccs, tmr_iccs, TRUE); +return tmr_iccs & TMR_CSR_RD; +} + +void iccs_wr (int32 val) +{ +sim_debug_bits_hdr (TMR_DB_REG, &tmr_dev, "iccs_wr()", tmr_iccs_bits, tmr_iccs, val, TRUE); +if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */ + if (tmr_iccs & TMR_CSR_RUN) { /* run 1 -> 0? */ + tmr_icr = icr_rd (); /* update itr */ + sim_rtcn_calb (0, TMR_CLK); /* stop timer */ + } + sim_cancel (&tmr_unit); /* cancel timer */ + } +if (val & CSR_DONE) /* Interrupt Acked? */ + sim_rtcn_tick_ack (20, TMR_CLK); /* Let timers know */ +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) /* xfr set? */ + tmr_icr = tmr_nicr; +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? */ + sim_rtcn_init_unit (&tmr_unit, CLK_DELAY, TMR_CLK); /* init timer */ + tmr_sched (tmr_icr); /* activate */ + } + } +else { + if (val & TMR_CSR_XFR) /* xfr set? */ + tmr_icr = tmr_nicr; + if (val & TMR_CSR_SGL) { /* single step? */ + tmr_icr = tmr_icr + 1; /* incr tmr */ + if (tmr_icr == 0) { /* if ovflo, */ + 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_IE) { /* ie? */ + tmr_int = 3; /* set int req */ + sim_debug (TMR_DB_INT, &tmr_dev, "tmr_incr() - INT=1\n"); + } + tmr_icr = tmr_nicr; /* reload tir */ + } + } + } +if ((tmr_iccs & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */ + (TMR_CSR_DON | TMR_CSR_IE)) { + if (tmr_int) { + tmr_int = 0; + sim_debug (TMR_DB_INT, &tmr_dev, "iccs_wr() - INT=0\n"); + } + } +} + +int32 icr_rd (void) +{ +int32 result; + +if (tmr_iccs & TMR_CSR_RUN) { /* running? */ + uint32 usecs_remaining = (uint32)sim_activate_time_usecs (&tmr_unit); + + result = (int32)(~usecs_remaining + 1); + } +else + result = (int32)tmr_icr; +sim_debug (TMR_DB_REG, &tmr_dev, "icr_rd() = 0x%08X%s\n", result, (tmr_iccs & TMR_CSR_RUN) ? " - interpolated" : ""); +return result; +} + +int32 nicr_rd (void) +{ +sim_debug (TMR_DB_REG, &tmr_dev, "nicr_rd() = 0x%08X\n", tmr_nicr); +return tmr_nicr; +} + +void nicr_wr (int32 val) +{ +sim_debug (TMR_DB_REG, &tmr_dev, "nicr_wr(0x%08X)\n", val); +tmr_nicr = val; +} + +/* Interval timer unit service */ + +t_stat tmr_svc (UNIT *uptr) +{ +sim_debug (TMR_DB_TICK, &tmr_dev, "tmr_svc()\n"); +tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */ +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_sched (tmr_nicr); /* reactivate */ +if (tmr_iccs & TMR_CSR_IE) { /* ie? set int req */ + tmr_int = 1; + sim_debug (TMR_DB_INT, &tmr_dev, "tmr_svc() - INT=1\n"); + } +else + tmr_int = 0; +AIO_SET_INTERRUPT_LATENCY(tmr_poll*clk_tps); /* set interrrupt latency */ +return SCPE_OK; +} + +/* Timer scheduling */ + +void tmr_sched (uint32 nicr) +{ +uint32 usecs = (nicr) ? (~nicr + 1) : 0xFFFFFFFF; + +clk_tps = (int32)((1000000.0 / usecs) + 0.5); + +sim_debug (TMR_DB_SCHED, &tmr_dev, "tmr_sched(nicr=0x%08X-usecs=0x%08X) - tps=%d\n", nicr, usecs, clk_tps); +tmr_poll = sim_rtcn_calb (clk_tps, TMR_CLK); +sim_activate_after (&tmr_unit, usecs); +} + +/* 100Hz TODR reset */ + +t_stat clk_reset (DEVICE *dptr) +{ +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; +} + +t_stat clk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "Real-Time Clock (%s)\n\n", dptr->name); +fprintf (st, "The real-time clock autocalibrates; the clock interval is adjusted up or down\n"); +fprintf (st, "so that the clock tracks actual elapsed time.\n\n"); +fprintf (st, "There are two modes of TODR operation:\n\n"); +fprintf (st, " Default VMS mode. Without initializing the TODR it returns the current\n"); +fprintf (st, " time of year offset which VMS would set the clock to\n"); +fprintf (st, " if VMS knew the correct time (i.e. by manual input).\n"); +fprintf (st, " This is correct almost all the time unless a VMS disk\n"); +fprintf (st, " hadn't been booted from in the current year. This mode\n"); +fprintf (st, " produces strange time results for non VMS OSes on each\n"); +fprintf (st, " system boot.\n"); +fprintf (st, " OS Agnostic mode. This mode behaves precisely like the VAX780 TODR and\n"); +fprintf (st, " works correctly for all OSes. This mode is enabled by\n"); +fprintf (st, " attaching the %s to a battery backup state file for the\n", dptr->name); +fprintf (st, " TOY clock (i.e. sim> attach %s TOY_CLOCK). When\n", dptr->name); +fprintf (st, " operating in OS Agnostic mode, the TODR will initially\n"); +fprintf (st, " start counting from 0 and be adjusted differently when\n"); +fprintf (st, " an OS specifically writes to the TODR. VMS determines\n"); +fprintf (st, " if the TODR currently contains a valid time if the value\n"); +fprintf (st, " it sees is less than about 1 month. If the time isn't\n"); +fprintf (st, " valid VMS will prompt to set the time during the system\n"); +fprintf (st, " boot. While prompting for the time it will wait for an\n"); +fprintf (st, " answer to the prompt for up to the SYSGEN parameter\n"); +fprintf (st, " TIMEPROMPTWAIT seconds. A value of 0 for TIMEPROMPTWAIT\n"); +fprintf (st, " will disable the clock setting prompt.\n"); +fprint_reg_help (st, dptr); +return SCPE_OK; +} + +const char *clk_description (DEVICE *dptr) +{ +return "time of year clock"; +} + +static uint32 sim_byteswap32 (uint32 data) +{ +uint8 *bdata = (uint8 *)&data; +uint8 tmp; + +tmp = bdata[0]; +bdata[0] = bdata[3]; +bdata[3] = tmp; +tmp = bdata[1]; +bdata[1] = bdata[2]; +bdata[2] = tmp; +return data; +} + +/* CLK attach */ + +t_stat clk_attach (UNIT *uptr, CONST 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 { + TOY *toy = (TOY *)uptr->filebuf; + + uptr->hwmark = (uint32) uptr->capac; + if ((toy->toy_endian_plus2 < 2) || (toy->toy_endian_plus2 > 3)) + memset (uptr->filebuf, 0, (size_t)uptr->capac); + else { + if (toy->toy_endian_plus2 != sim_end + 2) { /* wrong endian? */ + toy->toy_gmtbase = sim_byteswap32 (toy->toy_gmtbase); + toy->toy_gmtbasemsec = sim_byteswap32 (toy->toy_gmtbasemsec); + } + } + toy->toy_endian_plus2 = sim_end + 2; + todr_resync (); + } +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_poll = sim_rtcn_init_unit (&tmr_unit, CLK_DELAY, TMR_CLK); /* init timer */ +tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */ +tmr_iccs = 0; +tmr_nicr = 0; +tmr_int = 0; +sim_cancel (&tmr_unit); /* cancel timer */ +return SCPE_OK; +} + +const char *tmr_description (DEVICE *dptr) +{ +return "interval timer"; +} + +/* TODR routines */ + +static const char *todr_fmt_vms_todr (int32 val) +{ +static char buf[32]; +uint32 uval = (uint32)val; + +if (val < 0x10000000) + sprintf (buf, "Not VMS Time: 0x%08X", uval); +else { + int yday, hr, min, sec, msecs; + + uval -= 0x10000000; + msecs = (uval % 100) * 10; + uval /= 100; + sec = uval % 60; + uval /= 60; + min = uval % 60; + uval /= 60; + hr = uval % 24; + uval /= 24; + yday = uval; + sprintf (buf, "yday:%d %02d:%02d:%02d.%03d", yday, hr, min, sec, msecs); + } +return buf; +} + +int32 todr_rd (void) +{ +TOY *toy = (TOY *)clk_unit.filebuf; +struct timespec base, now, val; + +sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ +base.tv_sec = toy->toy_gmtbase; +base.tv_nsec = toy->toy_gmtbasemsec * 1000000; +sim_timespec_diff (&val, &now, &base); +sim_debug (TMR_DB_TODR, &clk_dev, "todr_rd() - TODR=0x%X - %s\n", (int32)(val.tv_sec*100 + val.tv_nsec/10000000), todr_fmt_vms_todr ((int32)(val.tv_sec*100 + val.tv_nsec/10000000))); +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; +time_t tbase; + +/* Save the GMT time when set value was 0 to record the base for + future read operations in "battery backed-up" state */ + +sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ +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; +tbase = (time_t)base.tv_sec; +toy->toy_gmtbasemsec = base.tv_nsec/1000000; +sim_debug (TMR_DB_TODR, &clk_dev, "todr_wr(0x%X) - %s - GMTBASE=%8.8s.%03d\n", data, todr_fmt_vms_todr (data), 11+ctime(&tbase), (int)(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 VAX TODR */ + 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; + struct timespec now; + + sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ + curr = (time_t)now.tv_sec; + 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 */ + (int32)(now.tv_nsec / 10000000)); + } +return SCPE_OK; +} + +int32 fl_rd (int32 pa) +{ +int32 rg = (pa >> 1) & 0xF; +int32 val; + +switch (rg) { + + case FL_CS0: + val = fl_cs0; + break; + + case FL_CS1: + val = fl_cs1; + break; + + case FL_CS2: + val = fl_cs2; + break; + + case FL_CS3: + val = fl_cs3; + break; + + case FL_CS4: + val = fl_cs4; + break; + + case FL_CS5: + val = fl_cs5; + break; + + case FL_EB: + val = fl_buf[fl_bptr]; + if (fl_bptr < (FL_NUMBY - 1)) + fl_bptr++; + break; + + case FL_CA: + fl_bptr = 0; + break; + + case FL_GO: + if (fl_cs0 & FLCS0_DKS) /* disk 1? */ + sim_activate (&fl_unit[1], fl_cwait); /* start operation */ + else /* no, disk 0 */ + sim_activate (&fl_unit[0], fl_cwait); /* start operation */ + break; + + default: + val = 0; + break; + } +sim_debug (FL_DB_REG, &fl_dev, "fl_rd(%s) data=0x%02X\n", fl_regnames[rg], val); +return val; +} + +void fl_wr (int32 pa, int32 val, int32 lnt) +{ +int32 rg = (pa >> 1) & 0xF; + +sim_debug (FL_DB_REG, &fl_dev, "fl_wr(%s) data=0x%02X\n", fl_regnames[rg], val); +switch (rg) { + + case FL_CS0: + fl_cs0 = (fl_cs0 & ~FLCS0_WR) | (val & FLCS0_WR); + break; + + case FL_CS1: + fl_cs1 = (val & FLCS1_TRK); + break; + + case FL_CS2: + fl_cs2 = (val & FLCS2_SECT); + break; + + case FL_CS5: + fl_cs5 = (val & FLCS5_FUNC); + break; + + case FL_CA: + fl_bptr = 0; + break; + + case FL_GO: + if (fl_cs0 & FLCS0_DKS) /* disk 1? */ + sim_activate (&fl_unit[1], fl_cwait); /* start operation */ + else /* no, disk 0 */ + sim_activate (&fl_unit[0], fl_cwait); /* start operation */ + break; + + case FL_FB: + fl_buf[fl_bptr] = val; + if (fl_bptr < (FL_NUMBY - 1)) + fl_bptr++; + break; + + default: + break; + } +} + +void fl_maint_status (void) +{ +fl_cs0 = fl_cs0 & (FLCS0_FNC | FLCS0_DS | FLCS0_DKS | FLCS0_SS); +fl_cs0 = fl_cs0 | FLCS0_DONE; +fl_cs1 = fl_ecode; +fl_cs2 = fl_track; +fl_cs3 = 0; /* FIXME */ +fl_cs4 = 0; /* FIXME */ +} + +void fl_xfer_status (void) +{ +fl_cs0 = fl_cs0 & (FLCS0_FNC | FLCS0_DS | FLCS0_DKS | FLCS0_SS); +fl_cs0 = fl_cs0 | FLCS0_DONE; +fl_cs1 = fl_ecode; +fl_cs2 = fl_track; +fl_cs3 = 0; /* FIXME */ +fl_cs4 = 0; /* FIXME */ +} + +/* Unit service; the action to be taken depends on the transfer state: + + FL_IDLE Should never get here + FL_RWDS Set TXCS (driver sends sector, sets FL_RWDT) + FL_RWDT Set TXCS (driver sends track, sets FL_READ/FL_FILL) + FL_READ Set TXCS, schedule FL_READ1 + FL_READ1 Read sector, schedule FL_EMPTY + FL_EMPTY Copy data to RXDB, set RXCS + if fl_bptr >= max, schedule completion, else continue + FL_FILL Set TXCS (driver sends next byte, sets FL_WRITE) + FL_WRITE Set TXCS, schedule FL_WRITE1 + FL_WRITE1 Write sector, schedule FL_DONE + FL_DONE Copy requested data to TXDB, set FL_IDLE +*/ + +t_stat fl_svc (UNIT *uptr) +{ +int32 fnc = (fl_cs0 >> FLCS0_V_FNC) & FLCS0_M_FNC; +int8 *fbuf = (int8 *)uptr->filebuf; +uint32 da; +int32 i; +int32 unit = (int32)(uptr - &fl_unit[0]); + +sim_debug (FL_DB_FNC, &fl_dev, "fl_svc(%d) - %s\n", unit, fl_fncnames[fnc]); +switch (fnc) { + + case FL_FNCST: /* read status */ + case FL_FNCMM: /* maintenance mode */ + fl_maint_status (); + break; + + case FL_FNCRD: /* restore drive */ + case FL_FNCIN: /* initialise */ + fl_track = 0; + fl_sector = 0; + fl_maint_status (); + break; + + case FL_FNCRS: /* read sector */ + fl_track = fl_cs1 & FLCS1_TRK; + fl_sector = fl_cs2 & FLCS2_SECT; + if (fl_test_xfr (uptr, FALSE)) { /* transfer ok? */ + da = CALC_DA (fl_track, fl_sector); /* get disk address */ + for (i = 0; i < FL_NUMBY; i++) /* copy sector to buf */ + fl_buf[i] = fbuf[da + i]; + } + sim_debug (FL_DB_INT, &fl_dev, "fl_int"); + fl_int = 1; + fl_xfer_status (); + break; + + case FL_FNCEX: /* extended function */ + break; + + case FL_FNCRA: /* read address */ + fl_xfer_status (); /* FIXME: maybe? */ + break; + + case FL_FNCWS: /* write sector */ + fl_track = fl_cs1 & FLCS1_TRK; + fl_sector = fl_cs2 & FLCS2_SECT; + if (fl_test_xfr (uptr, TRUE)) { /* transfer ok? */ + da = CALC_DA (fl_track, fl_sector); /* get disk address */ + for (i = 0; i < FL_NUMBY; i++) /* copy buf to sector */ + fbuf[da + i] = fl_buf[i]; + da = da + FL_NUMBY; + if (da > uptr->hwmark) /* update hwmark */ + uptr->hwmark = da; + } + sim_debug (FL_DB_INT, &fl_dev, "fl_int"); + fl_int = 1; + fl_xfer_status (); /* FIXME: maybe? */ + break; + } + +return SCPE_OK; +} + +/* Test for data transfer okay */ + +t_bool fl_test_xfr (UNIT *uptr, t_bool wr) +{ +if ((uptr->flags & UNIT_BUF) == 0) /* not buffered? */ + fl_ecode = 0x50; /* selected unit not ready */ +else if (fl_track >= FL_NUMTR) /* bad track? */ + fl_ecode = 0x20; /* tried to access a track > 79 */ +else if ((fl_sector == 0) || (fl_sector > FL_NUMSC)) /* bad sect? */ + fl_ecode = 0xB8; /* done, error */ +else if (wr && (uptr->flags & UNIT_WPRT)) /* write and locked? */ + fl_ecode = 0xB0; /* done, error */ +else + return TRUE; +return FALSE; +} + +/* Reset */ + +t_stat fl_reset (DEVICE *dptr) +{ +extern int32 sys_model; + +fl_ecode = 0; /* clear error */ +fl_sector = 0; /* clear addr */ +fl_track = 0; +fl_bptr = 0; +sim_cancel (&fl_unit[0]); /* cancel drive */ +sim_cancel (&fl_unit[1]); /* cancel drive */ +return SCPE_OK; +} + +const char *fl_description (DEVICE *dptr) +{ +return "console floppy"; +} diff --git a/VAX/vax820_syslist.c b/VAX/vax820_syslist.c new file mode 100644 index 00000000..dcbefd6d --- /dev/null +++ b/VAX/vax820_syslist.c @@ -0,0 +1,139 @@ +/* vax820_syslist.c: VAX 8200 device list + + Copyright (c) 2019, 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). +*/ + +#include "vax_defs.h" + +char sim_name[] = "VAX 8200 (KA820)"; + +void vax_init(void) +{ +sim_savename = "VAX820"; +} + +WEAK void (*sim_vm_init) (void) = &vax_init; + +extern DEVICE cpu_dev; +extern DEVICE tlb_dev; +extern DEVICE bi_dev; +extern DEVICE ka_dev[KA_NUM]; +extern DEVICE mctl_dev[MCTL_NUM]; +extern DEVICE uba_dev; +extern DEVICE clk_dev; +extern DEVICE tmr_dev; +extern DEVICE tti_dev, tto_dev; +extern DEVICE fl_dev; +extern DEVICE dt_dev; +extern DEVICE tdc_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 rk_dev; +extern DEVICE ry_dev; +extern DEVICE ts_dev; +extern DEVICE tq_dev; +extern DEVICE dz_dev; +extern DEVICE vh_dev; +extern DEVICE xu_dev, xub_dev; +extern DEVICE dmc_dev; +extern DEVICE ch_dev; + +extern UNIT cpu_unit; +extern void WriteB (uint32 pa, int32 val); +extern void rom_wr_B (int32 pa, int32 val); + +DEVICE *sim_devices[] = { + &cpu_dev, + &tlb_dev, + &bi_dev, + &ka_dev[0], + &ka_dev[1], + &mctl_dev[0], + &mctl_dev[1], + &uba_dev, + &clk_dev, + &tmr_dev, + &tti_dev, + &tto_dev, + &fl_dev, + &dt_dev, + &tdc_dev, + &dz_dev, + &vh_dev, + &cr_dev, + &lpt_dev, + &rl_dev, + &hk_dev, + &rk_dev, + &rq_dev, + &rqb_dev, + &rqc_dev, + &rqd_dev, + &ry_dev, + &ts_dev, + &tq_dev, + &xu_dev, + &xub_dev, + &dmc_dev, + &ch_dev, + 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, CONST char *cptr, CONST char *fnam, int flag) +{ +t_stat r; +int32 val; +uint32 origin, limit; + +if (flag) /* dump? */ + return sim_messagef (SCPE_NOFNC, "Command Not Implemented\n"); +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 = Fgetc (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/vax820_uba.c b/VAX/vax820_uba.c new file mode 100644 index 00000000..50643698 --- /dev/null +++ b/VAX/vax820_uba.c @@ -0,0 +1,996 @@ +/* vax820_uba.c: VAXBI Unibus adapter (DWBUA) + + Copyright (c) 2019, 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). + + uba DWBUA Unibus adapter +*/ + +#include "vax_defs.h" + +/* Unibus adapter */ + +#define UBA_NDPATH 6 /* number of data paths */ +#define UBA_NMAPR 512 /* number of map reg */ +#define UBA_NMAPU 496 /* number of usable map reg */ + +/* BI general purpose register 0 */ +#define BIGPR0_IEN 0x00FF0000 /* internal error number */ +#define BIGPR0_UPU 0x00000001 /* unibus power up */ + +/* Control/Status register */ + +#define UBACSR_OF 0x1C8 +#define UBACSR_ERR 0x80000000 /* error */ +#define UBACSR_BIF 0x10000000 /* VAXBI failure */ +#define UBACSR_TO 0x08000000 /* unibus ssyn timeout */ +#define UBACSR_UIE 0x04000000 /* unibus interlock error */ +#define UBACSR_IMR 0x02000000 /* invalid map reg */ +#define UBACSR_BDP 0x01000000 /* bad buffered datapath */ +#define UBACSR_EIE 0x00100000 /* error interrupt en */ +#define UBACSR_UPI 0x00020000 /* unibus power init */ +#define UBACSR_RD 0x00010000 /* register dump */ +#define UBACSR_ONE 0x00008000 /* must be one */ +#define UBACSR_IEN 0x000000FF /* internal error - NI */ +#define UBACSR_WR (UBACSR_EIE) +#define UBACSR_W1C (UBACSR_BIF | UBACSR_TO | UBACSR_UIE | \ + UBACSR_IMR | UBACSR_BDP) + +/* Vector offset register */ + +#define UBAVO_OF 0x1C9 +#define UBAVO_VEC 0x00003E00 + +/* Failing Unibus address - read only */ + +#define UBAFUBAR_OF 0x1CA +#define UBAFUBAR_RD 0xFFFF + +/* VAXBI failed address - read only */ + +#define UBABIFA_OF 0x1CB + +/* Microdiagnostic registers */ + +#define UBADR_OF 0x1CC + +/* Data path registers */ + +#define UBADPR_OF 0x1D4 +#define UBADPR_V_SEL 21 /* datapath select */ +#define UBADPR_M_SEL 0x7 +#define UBADPR_PURGE 0x00000001 /* purge datapath */ +#define UBADPR_RD (UBADPR_M_SEL << UBADPR_V_SEL) + +/* Buffered data path space */ + +#define UBABDPS_OF 0x1E4 + +/* Map registers */ + +#define UBAMAP_OF 0x200 +#define UBAMAP_VLD 0x80000000 /* valid */ +#define UBAMAP_IOAD 0x40000000 /* i/o address */ +#define UBAMAP_LWAE 0x04000000 /* LW access enb - ni */ +#define UBAMAP_ODD 0x02000000 /* odd byte */ +#define UBAMAP_V_DP 21 /* data path */ +#define UBAMAP_M_DP 0x7 +#define UBAMAP_DP (UBAMAP_M_DP << UBAMAP_V_DP) +#define UBAMAP_GETDP(x) (((x) >> UBAMAP_V_DP) & UBAMAP_M_DP) +#define UBAMAP_PAG 0x001FFFFF +#define UBAMAP_RD (0xC6000000 | UBAMAP_DP | UBAMAP_PAG) +#define UBAMAP_WR (UBAMAP_RD) + +/* Debug switches */ + +#define UBA_DEB_RRD 0x01 /* reg reads */ +#define UBA_DEB_RWR 0x02 /* reg writes */ +#define UBA_DEB_MRD 0x04 /* map reads */ +#define UBA_DEB_MWR 0x08 /* map writes */ +#define UBA_DEB_XFR 0x10 /* transfers */ +#define UBA_DEB_ERR 0x20 /* errors */ + +int32 int_req[IPL_HLVL] = { 0 }; /* intr, IPL 14-17 */ +BIIC uba_biic; /* BIIC standard registers */ +uint32 uba_csr = 0; /* control/status reg */ +uint32 uba_vo = 0; /* vector offset */ +uint32 uba_int = 0; /* UBA interrupt */ +uint32 uba_fubar = 0; /* failing Unibus addr */ +uint32 uba_bifa = 0; /* BI failing addr */ +uint32 uba_dpr[UBA_NDPATH] = { 0 }; /* number data paths */ +uint32 uba_map[UBA_NMAPR] = { 0 }; /* map registers */ +uint32 uba_aiip = 0; /* adapter init in prog */ +uint32 uba_uiip = 0; /* Unibus init in prog */ +uint32 uba_aitime = 250; /* adapter init time */ +uint32 uba_uitime = 12250; /* Unibus init time */ +int32 autcon_enb = 1; /* autoconfig enable */ + +extern uint32 nexus_req[NEXUS_HLVL]; + +t_stat uba_svc (UNIT *uptr); +t_stat uba_reset (DEVICE *dptr); +t_stat uba_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *uba_description (DEVICE *dptr); +t_stat uba_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); +t_stat uba_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw); +t_stat uba_rdreg (int32 *val, int32 pa, int32 mode); +t_stat uba_wrreg (int32 val, int32 pa, int32 lnt); +int32 uba_get_ubvector (int32 lvl); +void uba_ub_nxm (int32 ua); +void uba_bi_nxm (int32 ba); +void uba_inv_map (int32 ublk); +void uba_eval_int (void); +void uba_adap_set_int (); +void uba_adap_clr_int (); +void uba_ubpdn (int32 time); +t_bool uba_map_addr (uint32 ua, uint32 *ma); +t_stat set_autocon (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat uba_show_virt (FILE *st, UNIT *uptr, int32 val, CONST void *desc); + +extern int32 eval_int (void); +extern t_stat build_dib_tab (void); + +/* Unibus IO page dispatches */ + +t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md); +t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md); +DIB *iodibp[IOPAGESIZE >> 1]; + +/* Unibus interrupt request to interrupt action map */ + +int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */ + +/* Unibus interrupt request to vector map */ + +int32 int_vec[IPL_HLVL][32]; /* int req to vector */ + +/* Unibus adapter data structures + + uba_dev UBA device descriptor + uba_unit UBA units + uba_reg UBA register list +*/ + +DIB uba_dib = { TR_UBA, 0, &uba_rdreg, &uba_wrreg, 0, 0 }; + +UNIT uba_unit = { UDATA (&uba_svc, 0, 0) }; + +REG uba_reg[] = { + { HRDATA (IPL14, int_req[0], 32), REG_RO }, + { HRDATA (IPL15, int_req[1], 32), REG_RO }, + { HRDATA (IPL16, int_req[2], 32), REG_RO }, + { HRDATA (IPL17, int_req[3], 32), REG_RO }, + { HRDATA (CSR, uba_csr, 32) }, + { HRDATA (VO, uba_vo, 32) }, + { FLDATA (INT, uba_int, 0) }, + { FLDATA (NEXINT, nexus_req[IPL_UBA], TR_UBA) }, + { HRDATA (FUBAR, uba_fubar, 32) }, + { HRDATA (BIFA, uba_bifa, 32) }, + { HRDATA (BICSR, uba_biic.csr, 32) }, + { HRDATA (BIBER, uba_biic.ber, 32) }, + { HRDATA (BIECR, uba_biic.eicr, 32) }, + { HRDATA (BIDEST, uba_biic.idest, 32) }, + { HRDATA (BISRC, uba_biic.isrc, 32) }, + { HRDATA (BIMSK, uba_biic.imsk, 32) }, + { HRDATA (BIUIIC, uba_biic.uiic, 32) }, + { BRDATA (DPR, uba_dpr, 16, 32, 16) }, + { BRDATA (MAP, uba_map, 16, 32, UBA_NMAPR) }, + { FLDATA (AUTOCON, autcon_enb, 0), REG_HRO }, + { NULL } + }; + +MTAB uba_mod[] = { + { MTAB_XTD|MTAB_VDV, TR_UBA, "NEXUS", NULL, + NULL, &show_nexus }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL, + NULL, &show_iospace }, + { MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG", + &set_autocon, &show_autocon }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG", + &set_autocon, NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "VIRTUAL", NULL, + NULL, &uba_show_virt }, + { 0 } + }; + +DEBTAB uba_deb[] = { + { "REGREAD", UBA_DEB_RRD }, + { "REGWRITE", UBA_DEB_RWR }, + { "MAPREAD", UBA_DEB_MRD }, + { "MAPWRITE", UBA_DEB_MWR }, + { "XFER", UBA_DEB_XFR }, + { "ERROR", UBA_DEB_ERR }, + { NULL, 0 } + }; + +DEVICE uba_dev = { + "UBA", &uba_unit, uba_reg, uba_mod, + 1, 16, UBADDRWIDTH, 2, 16, 16, + &uba_ex, &uba_dep, &uba_reset, + NULL, NULL, NULL, + &uba_dib, DEV_NEXUS | DEV_DEBUG, 0, + uba_deb, NULL, NULL, &uba_help, NULL, NULL, + &uba_description + }; + +/* Read Unibus adapter register - aligned lw only */ + +t_stat uba_rdreg (int32 *val, int32 pa, int32 lnt) +{ +int32 idx, ofs; + +ofs = NEXUS_GETOFS (pa); /* get offset */ +if (uba_aiip && (ofs >= UBACSR_OF)) { /* init in prog? */ + *val = 0; + return SCPE_OK; /* only BIIC */ + } +if ((ofs >= UBABDPS_OF) && (ofs < UBABDPS_OF + 0x10)) { + *val = 0; + return SCPE_OK; + } +if (ofs >= UBAMAP_OF) { /* map? */ + idx = ofs - UBAMAP_OF; + if (idx >= UBA_NMAPR) /* valid? */ + return SCPE_NXM; + *val = uba_map[idx] & UBAMAP_RD; + if (DEBUG_PRI (uba_dev, UBA_DEB_MRD)) + fprintf (sim_deb, ">>UBA: map %d read, value = %X, PC = %X\n", idx, *val, fault_PC); + return SCPE_OK; + } + +switch (ofs) { /* case on offset */ + + case BI_DTYPE: + *val = DTYPE_DWBUA; + break; + + case BI_CSR: + *val = uba_biic.csr & BICSR_RD; + break; + + case BI_BER: + *val = uba_biic.ber & BIBER_RD; + break; + + case BI_EICR: + *val = uba_biic.eicr & BIECR_RD; + break; + + case BI_IDEST: + *val = uba_biic.idest & BIID_RD; + break; + + case BI_IMSK: + case BI_FIDEST: + case BI_ISRC: + *val = 0; + break; + + case BI_SA: + *val = UBADDRBASE; + //*val = uba_biic.sa; + break; + + case BI_EA: + *val = UBADDRBASE + 0x40000; + //*val = uba_biic.ea; + break; + + case BI_BCIC: + *val = uba_biic.bcic; + break; + + case BI_UIIC: + *val = uba_biic.uiic; + break; + + case BI_GPR0: + *val = uba_biic.gpr0; + break; + + case BI_GPR1: + case BI_GPR2: + case BI_GPR3: + *val = 0; + break; + + case UBACSR_OF: /* CSR */ + *val = uba_csr | UBACSR_ONE; + break; + + case UBAVO_OF: /* VO */ + *val = uba_vo & UBAVO_VEC; // should be UBAVO_RD? + break; + + case UBAFUBAR_OF: /* FUBAR */ + *val = uba_fubar & UBAFUBAR_RD; + break; + + case UBABIFA_OF: /* BIFA */ + *val = uba_bifa; + break; + + case UBADR_OF + 0: /* DR */ + case UBADR_OF + 1: + case UBADR_OF + 2: + case UBADR_OF + 3: + case UBADR_OF + 4: + *val = 0; + break; + + case UBADPR_OF + 0: /* DPR */ + case UBADPR_OF + 1: + case UBADPR_OF + 2: + case UBADPR_OF + 3: + case UBADPR_OF + 4: + case UBADPR_OF + 5: + idx = ofs - UBADPR_OF; + *val = uba_dpr[idx] & UBADPR_RD; + break; + + case UBADPR_OF + 6: + case UBADPR_OF + 7: + uba_csr |= UBACSR_BDP; + break; + + default: + return SCPE_NXM; + } + +if (DEBUG_PRI (uba_dev, UBA_DEB_RRD)) + fprintf (sim_deb, ">>UBA: reg %d read, value = %X\n", ofs, *val); +return SCPE_OK; +} + +/* Write Unibus adapter register */ + +t_stat uba_wrreg (int32 val, int32 pa, int32 lnt) +{ +int32 idx, ofs; + +ofs = NEXUS_GETOFS (pa); /* get offset */ +if (uba_aiip && (ofs >= UBACSR_OF)) { /* init in prog? */ + return SCPE_OK; /* only BIIC */ + } +if (ofs >= UBAMAP_OF) { /* map? */ + idx = ofs - UBAMAP_OF; + if (idx >= UBA_NMAPR) /* valid? */ + return SCPE_NXM; + uba_map[idx] = val & UBAMAP_WR; + if (DEBUG_PRI (uba_dev, UBA_DEB_MWR)) + fprintf (sim_deb, ">>UBA: map %d write, value = %X, PC = %X\n", idx, val, fault_PC); + return SCPE_OK; + } + +switch (ofs) { /* case on offset */ + + case BI_CSR: + if (val & BICSR_RST) { /* unibus power init */ + uba_reset (&uba_dev); /* reset adapter */ + uba_aiip = 1; /* set init in prog */ + uba_ubpdn (uba_aitime); /* power fail UB */ + } + uba_biic.csr = (uba_biic.csr & ~BICSR_RW) | (val & BICSR_RW); + break; + + case BI_BER: + uba_biic.ber = uba_biic.ber & ~(val & BIBER_W1C); + break; + + case BI_EICR: + uba_biic.eicr = (uba_biic.eicr & ~BIECR_RW) | (val & BIECR_RW); + uba_biic.eicr = uba_biic.eicr & ~(val & BIECR_W1C); + break; + + case BI_IDEST: + uba_biic.idest = val & BIID_RW; + break; + + case BI_UIIC: + break; + + case BI_GPR0: + case BI_GPR1: + case BI_GPR2: + case BI_GPR3: + break; + + case UBACSR_OF: /* CSR */ + if (val & UBACSR_UPI) { /* unibus power init */ + uba_aiip = 1; /* set init in prog */ + uba_ubpdn (uba_aitime); /* power fail UB */ + } + uba_csr = (uba_csr & ~UBACSR_WR) | (val & UBACSR_WR); + uba_csr = uba_csr & ~(val & UBACSR_W1C); + break; + + case UBAVO_OF: /* VO */ + uba_vo = val & UBAVO_VEC; + break; + + case UBADPR_OF + 0: /* DPR */ + case UBADPR_OF + 1: + case UBADPR_OF + 2: + case UBADPR_OF + 3: + case UBADPR_OF + 4: + case UBADPR_OF + 5: + break; + + case UBADPR_OF + 6: + case UBADPR_OF + 7: + uba_csr |= UBACSR_BDP; + break; + + default: + return SCPE_NXM; + } + +if (DEBUG_PRI (uba_dev, UBA_DEB_RWR)) + fprintf (sim_deb, ">>UBA: reg %d write, value = %X\n", ofs, val); +return SCPE_OK; +} + +/* Read and write Unibus I/O space */ + +int32 ReadUb (uint32 pa) +{ +int32 idx, val; + +if (ADDR_IS_IOP (pa)) { /* iopage,!init */ + idx = (pa & IOPAGEMASK) >> 1; + if (iodispR[idx]) { + iodispR[idx] (&val, pa, READ); + return val; + } + } +uba_biic.ber = uba_biic.ber | BIBER_RDS; +uba_ub_nxm (pa); /* UB nxm */ +//MACH_CHECK (MCHK_BIERR); /* machine check */ +return 0; +} + +void WriteUb (uint32 pa, int32 val, int32 mode) +{ +int32 idx; + +if (ADDR_IS_IOP (pa)) { /* iopage,!init */ + idx = (pa & IOPAGEMASK) >> 1; + if (iodispW[idx]) { + iodispW[idx] (val, pa, mode); + return; + } + } +uba_ub_nxm (pa); /* UB nxm */ +return; +} + +/* ReadIO - read from IO - UBA only responds to byte, aligned word + + Inputs: + pa = physical address + lnt = length (BWLQ) + Output: + longword of data +*/ + +int32 ReadIO (uint32 pa, int32 lnt) +{ +uint32 iod; + +if ((lnt == L_BYTE) || /* byte? */ + ((lnt == L_WORD) && ((pa & 1) == 0))) { /* aligned word? */ + iod = ReadUb (pa); /* DATI from Unibus */ + if (pa & 2) /* position */ + iod = iod << 16; + } +else { + printf (">>UBA: invalid read mask, pa = %x, lnt = %d\n", pa, lnt); + //TODO: Set error bit? + iod = 0; + } +SET_IRQL; +return iod; +} + +/* WriteIO - write to IO - UBA only responds to byte, aligned word + + Inputs: + pa = physical address + val = data to write, right justified in 32b longword + lnt = length (BWL) + Outputs: + none +*/ + +void WriteIO (uint32 pa, int32 val, int32 lnt) +{ +if (lnt == L_BYTE) /* byte? DATOB */ + WriteUb (pa, val, WRITEB); +else if (((lnt == L_WORD) || (lnt == L_LONG)) && ((pa & 1) == 0))/* aligned word? */ + WriteUb (pa, val, WRITE); /* DATO */ +else { + printf (">>UBA: invalid write mask, pa = %x, lnt = %d\n", pa, lnt); + //TODO: Set error bit? + } +SET_IRQL; /* update ints */ +return; +} + +/* Update UBA nexus interrupts */ + +void uba_eval_int (void) +{ +int32 i, lvl; + +// TODO: Check BIIC register? +if (uba_int) { + lvl = (uba_biic.eicr >> BIECR_V_LVL) & BIECR_M_LVL; + for (i = 0; i < (IPL_HMAX - IPL_HMIN); i++) { + if (lvl & (1u << i)) { + nexus_req[i] |= (1 << TR_UBA); + } + } + } +else { + for (i = 0; i < (IPL_HMAX - IPL_HMIN); i++) /* clear all UBA req */ + nexus_req[i] &= ~(1 << TR_UBA); + for (i = 0; i < (IPL_HMAX - IPL_HMIN); i++) { + if (int_req[i]) + nexus_req[i] |= (1 << TR_UBA); + } + } +//if (uba_int) /* adapter int? */ +// SET_NEXUS_INT (UBA); +return; +} + +/* Return vector for Unibus interrupt at relative IPL level [0-3] */ + +int32 uba_get_ubvector (int32 lvl) +{ +int32 i, vec; + +if ((uba_biic.eicr & (1u << (lvl + BIECR_V_LVL))) && uba_int) { /* UBA err lvl, int? */ +//if ((lvl == (IPL_UBA - IPL_HMIN)) && uba_int) { /* UBA lvl, int? */ + vec = uba_biic.eicr & BIECR_VEC; + uba_int = 0; /* clear int */ + } +else { + vec = uba_vo & UBAVO_VEC; + for (i = 0; int_req[lvl] && (i < 32); i++) { + if ((int_req[lvl] >> i) & 1) { + int_req[lvl] = int_req[lvl] & ~(1u << i); + if (int_ack[lvl][i]) + return (vec | int_ack[lvl][i]()); + return (vec | int_vec[lvl][i]); + } + } + } +return vec; +} + +/* Unibus I/O buffer routines + + Map_ReadB - fetch byte buffer from memory + Map_ReadW - fetch word buffer from memory + Map_WriteB - store byte buffer into memory + Map_WriteW - store word buffer into memory +*/ + +int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf) +{ +int32 i, j, pbc; +uint32 ma, dat; + +ba = ba & UBADDRMASK; /* mask UB addr */ +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (!uba_map_addr (ba + i, &ma)) /* page inv or NXM? */ + return (bc - i); + pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; + if (DEBUG_PRI (uba_dev, UBA_DEB_XFR)) + fprintf (sim_deb, ">>UBA: 8b read, ma = %X, bc = %X\n", ma, pbc); + if ((ma | pbc) & 3) { /* aligned LW? */ + for (j = 0; j < pbc; ma++, j++) { /* no, do by bytes */ + *buf++ = ReadB (ma); + } + } + else { /* yes, do by LW */ + for (j = 0; j < pbc; ma = ma + 4, j = j + 4) { + dat = ReadL (ma); /* get lw */ + *buf++ = dat & BMASK; /* low 8b */ + *buf++ = (dat >> 8) & BMASK; /* next 8b */ + *buf++ = (dat >> 16) & BMASK; /* next 8b */ + *buf++ = (dat >> 24) & BMASK; + } + } + } +return 0; +} + +int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf) +{ +int32 i, j, pbc; +uint32 ma, dat; + +ba = ba & UBADDRMASK; /* mask UB addr */ +bc = bc & ~01; +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (!uba_map_addr (ba + i, &ma)) /* page inv or NXM? */ + return (bc - i); + pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; + if (DEBUG_PRI (uba_dev, UBA_DEB_XFR)) + fprintf (sim_deb, ">>UBA: 16b read, ba = %X, ma = %X, bc = %X\n", ba, ma, pbc); + if ((ma | pbc) & 1) { /* aligned word? */ + for (j = 0; j < pbc; ma++, j++) { /* no, do by bytes */ + if ((i + j) & 1) { /* odd byte? */ + *buf = (*buf & BMASK) | (ReadB (ma) << 8); + buf++; + } + else *buf = (*buf & ~BMASK) | ReadB (ma); + } + } + else if ((ma | pbc) & 3) { /* aligned LW? */ + for (j = 0; j < pbc; ma = ma + 2, j = j + 2) { /* no, words */ + *buf++ = ReadW (ma); /* get word */ + } + } + else { /* yes, do by LW */ + for (j = 0; j < pbc; ma = ma + 4, j = j + 4) { + dat = ReadL (ma); /* get lw */ + *buf++ = dat & WMASK; /* low 16b */ + *buf++ = (dat >> 16) & WMASK; /* high 16b */ + } + } + } +return 0; +} + +int32 Map_WriteB (uint32 ba, int32 bc, const uint8 *buf) +{ +int32 i, j, pbc; +uint32 ma, dat; + +ba = ba & UBADDRMASK; /* mask UB addr */ +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (!uba_map_addr (ba + i, &ma)) /* page inv or NXM? */ + return (bc - i); + pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; + if (DEBUG_PRI (uba_dev, UBA_DEB_XFR)) + fprintf (sim_deb, ">>UBA: 8b write, ma = %X, bc = %X\n", ma, pbc); + if ((ma | pbc) & 3) { /* aligned LW? */ + for (j = 0; j < pbc; ma++, j++) { /* no, do by bytes */ + WriteB (ma, *buf); + buf++; + } + } + else { /* yes, do by LW */ + for (j = 0; j < pbc; ma = ma + 4, j = j + 4) { + dat = (uint32) *buf++; /* get low 8b */ + dat = dat | (((uint32) *buf++) << 8); /* merge next 8b */ + dat = dat | (((uint32) *buf++) << 16); /* merge next 8b */ + dat = dat | (((uint32) *buf++) << 24); /* merge hi 8b */ + WriteL (ma, dat); /* store lw */ + } + } + } +return 0; +} + +int32 Map_WriteW (uint32 ba, int32 bc, const uint16 *buf) +{ +int32 i, j, pbc; +uint32 ma, dat; + +ba = ba & UBADDRMASK; /* mask UB addr */ +bc = bc & ~01; +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (!uba_map_addr (ba + i, &ma)) /* page inv or NXM? */ + return (bc - i); + pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; + if (DEBUG_PRI (uba_dev, UBA_DEB_XFR)) + fprintf (sim_deb, ">>UBA: 16b write, ma = %X, bc = %X\n", ma, pbc); + if ((ma | pbc) & 1) { /* aligned word? */ + for (j = 0; j < pbc; ma++, j++) { /* no, bytes */ + if ((i + j) & 1) { + WriteB (ma, (*buf >> 8) & BMASK); + buf++; + } + else WriteB (ma, *buf & BMASK); + } + } + else if ((ma | pbc) & 3) { /* aligned LW? */ + for (j = 0; j < pbc; ma = ma + 2, j = j + 2) { /* no, words */ + WriteW (ma, *buf); /* write word */ + buf++; + } + } + else { /* yes, do by LW */ + for (j = 0; j < pbc; ma = ma + 4, j = j + 4) { + dat = (uint32) *buf++; /* get low 16b */ + dat = dat | (((uint32) *buf++) << 16); /* merge hi 16b */ + WriteL (ma, dat); /* store LW */ + } + } + } +return 0; +} + +/* Map an address via the translation map */ + +t_bool uba_map_addr (uint32 ua, uint32 *ma) +{ +uint32 ublk, umap, dpr; + +ublk = ua >> VA_V_VPN; /* Unibus blk */ +//if ((ublk < UBACR_GETDSB (uba_cr)) || /* map disabled? */ +if (ublk >= UBA_NMAPR) /* unimplemented? */ + return FALSE; +umap = uba_map[ublk]; /* get map */ +if (umap == 0xFFFFFFFF) + return FALSE; /* ignore transaction */ +if (umap & UBAMAP_VLD) { /* valid? */ + *ma = ((umap & UBAMAP_PAG) << VA_V_VPN) + VA_GETOFF (ua); + if ((umap & UBAMAP_DP) && (umap & UBAMAP_ODD)) { /* buffered dp? */ + if (umap & UBAMAP_LWAE) { + dpr = UBAMAP_GETDP (umap); /* get datapath */ + if ((dpr == 6) || (dpr == 7)) + return FALSE; /* ignore transfer */ + } + *ma = *ma + 1; /* byte offset? */ + } + if (ADDR_IS_MEM (*ma)) /* valid mem address */ + return TRUE; + if ((umap & UBAMAP_IOAD) && (ADDR_IS_IO (*ma))) /* valid i/o address */ + return TRUE; + uba_bi_nxm (*ma); + return FALSE; + } +uba_inv_map (ua); /* invalid map */ +return FALSE; +} + +/* Map an address via the translation map - console version (no status changes) */ + +t_bool uba_map_addr_c (uint32 ua, uint32 *ma) +{ +uint32 ublk, umap; + +ublk = ua >> VA_V_VPN; /* Unibus blk */ +//if ((ublk < UBACR_GETDSB (uba_cr)) || /* map disabled? */ +if (ublk >= UBA_NMAPR) /* unimplemented? */ + return FALSE; +umap = uba_map[ublk]; /* get map */ +if (umap & UBAMAP_VLD) { /* valid? */ + *ma = ((umap & UBAMAP_PAG) << VA_V_VPN) + VA_GETOFF (ua); + if ((umap & UBAMAP_DP) && (umap & UBAMAP_ODD)) /* buffered dp? */ + *ma = *ma + 1; /* byte offset? */ + return TRUE; /* legit addr */ + } +return FALSE; +} + +/* Error routines + + uba_ub_nxm SBI read/write to nx Unibus address + uba_inv_map Unibus reference to invalid map reg +*/ + +void uba_ub_nxm (int32 ua) +{ +if ((uba_csr & UBACSR_TO) == 0) { + uba_csr |= UBACSR_TO; + uba_fubar = (ua >> 2) & UBAFUBAR_RD; + uba_adap_set_int (); + } +sim_debug (UBA_DEB_ERR, &uba_dev, + ">>UBA: nxm error, ua = %X, PC = %X\n", ua, fault_PC); +return; +} + +void uba_bi_nxm (int32 ba) +{ +if ((uba_biic.ber & BIBER_BTO) == 0) { + uba_biic.ber |= BIBER_BTO; + uba_bifa = ba; + uba_adap_set_int (); + } +sim_debug (UBA_DEB_ERR, &uba_dev, + ">>UBA: BI nxm error, ba = %X, PC = %X\n", ba, fault_PC); +return; +} + +void uba_inv_map (int32 ublk) +{ +if ((uba_csr & UBACSR_IMR) == 0) { + uba_csr |= UBACSR_IMR; + uba_adap_set_int (); + } +sim_debug (UBA_DEB_ERR, &uba_dev, + ">>UBA: inv map error, ublk = %X\n", ublk); +return; +} + +/* Unibus power fail routines */ + +void uba_ubpdn (int32 time) +{ +int32 i; +DEVICE *dptr; + +uba_biic.gpr0 = uba_biic.gpr0 & ~BIGPR0_UPU; /* UB power down */ +sim_activate (&uba_unit, time); /* schedule */ +uba_uiip = 1; /* UB init in prog */ +for (i = 0; sim_devices[i] != NULL; i++) { /* reset Unibus */ + dptr = sim_devices[i]; + if (dptr->reset && (dptr->flags & DEV_UBUS)) + dptr->reset (dptr); + } +return; +} + +/* Init timeout service routine */ + +t_stat uba_svc (UNIT *uptr) +{ +if (uba_aiip) { /* adapter init? */ + uba_aiip = 0; /* clear in prog */ + sim_activate (uptr, uba_uitime); /* schedule UB */ + } +else { + uba_uiip = 0; /* no, UB */ + uba_biic.gpr0 = uba_biic.gpr0 | BIGPR0_UPU; /* UB power up */ + } +uba_adap_set_int (); /* possible int */ +return SCPE_OK; +} + +/* Interrupt routines */ + +void uba_adap_set_int () +{ +if (uba_csr & UBACSR_EIE) { + uba_int = 1; + sim_debug (UBA_DEB_ERR, &uba_dev, + ">>UBA: adapter int req, csr = %X\n", uba_csr); + } +return; +} + +void uba_adap_clr_int () +{ +if (!(uba_csr & UBACSR_EIE)) + uba_int = 0; +return; +} + +/* Reset Unibus adapter */ + +t_stat uba_reset (DEVICE *dptr) +{ +int32 i; + +uba_int = 0; +uba_aiip = uba_uiip = 0; +sim_cancel (&uba_unit); +for (i = 0; i < IPL_HLVL; i++) { + nexus_req[i] &= ~(1 << TR_UBA); + int_req[i] = 0; + } +for (i = 0; i < UBA_NMAPR; i++) { /* clear map registers */ + if (i < UBA_NMAPU) + uba_map[i] = 0; + else + uba_map[i] = 0xffffffff; + } +for (i = 0; i < UBA_NDPATH; i++) /* setup datapaths */ + uba_dpr[i] = (i << UBADPR_V_SEL); +uba_csr = 0; +uba_biic.csr = (1u << BICSR_V_IF) | BICSR_STS | (TR_UBA & BICSR_NODE); +uba_biic.ber = 0; +uba_biic.eicr = 0; +uba_biic.idest = 0; +uba_biic.uiic = BIICR_EXV; +uba_biic.gpr0 = BIGPR0_UPU; +return SCPE_OK; +} + +t_stat uba_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "Unibus Adapter (UBA)\n\n"); +fprintf (st, "The Unibus adapter (UBA) simulates the DWBUA.\n"); +fprint_set_help (st, dptr); +fprint_show_help (st, dptr); +fprintf (st, "\nThe UBA implements main memory examination and modification via the Unibus\n"); +fprintf (st, "map. The data width is always 16b:\n\n"); +fprintf (st, "EXAMINE UBA 0/10 examine main memory words corresponding\n"); +fprintf (st, " to Unibus addresses 0-10\n"); +fprint_reg_help (st, dptr); +return SCPE_OK; +} + +const char *uba_description (DEVICE *dptr) +{ +return "Unibus adapter"; +} + +/* Memory examine via map (word only) */ + +t_stat uba_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) +{ +uint32 ua = (uint32) exta, pa; + +if ((vptr == NULL) || (ua >= UBADDRSIZE)) + return SCPE_ARG; +if (uba_map_addr_c (ua, &pa) && ADDR_IS_MEM (pa)) { + *vptr = (uint32) ReadW (pa); + return SCPE_OK; + } +return SCPE_NXM; +} + +/* Memory deposit via map (word only) */ + +t_stat uba_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) +{ +uint32 ua = (uint32) exta, pa; + +if (ua >= UBADDRSIZE) + return SCPE_ARG; +if (uba_map_addr_c (ua, &pa) && ADDR_IS_MEM (pa)) { + WriteW (pa, (int32) val); + return SCPE_OK; + } +return SCPE_NXM; +} + +/* Show UBA virtual address */ + +t_stat uba_show_virt (FILE *of, UNIT *uptr, int32 val, CONST void *desc) +{ +t_stat r; +char *cptr = (char *) desc; +uint32 ua, pa; + +if (cptr) { + ua = (uint32) get_uint (cptr, 16, UBADDRSIZE - 1, &r); + if (r == SCPE_OK) { + if (uba_map_addr_c (ua, &pa)) + fprintf (of, "Unibus %-X = physical %-X\n", ua, pa); + else fprintf (of, "Unibus %-X: invalid mapping\n", ua); + return SCPE_OK; + } + } +fprintf (of, "Invalid argument\n"); +return SCPE_OK; +} diff --git a/VAX/vax_bi.h b/VAX/vax_bi.h new file mode 100644 index 00000000..bda620f6 --- /dev/null +++ b/VAX/vax_bi.h @@ -0,0 +1,163 @@ +/* vax_bi.h: VAXBI Standard Definitions + + Copyright (c) 2019, Matt Burke + + 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 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 of the author 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. + + This file covers the VAXBI registers that are contained in the BIIC chip + on each VAXBI node. +*/ + +#ifndef _VAXBI_DEFS_H_ +#define _VAXBI_DEFS_H_ 1 + +/* Register Offsets */ + +#define BI_DTYPE 0 /* device type */ +#define BI_CSR 1 /* control/status */ +#define BI_BER 2 /* bus error */ +#define BI_EICR 3 /* error interrupt control */ +#define BI_IDEST 4 /* interrupt destination */ +#define BI_IMSK 5 /* IPINTR mask */ +#define BI_FIDEST 6 /* force IPINTR destination */ +#define BI_ISRC 7 /* IPINTR source */ +#define BI_SA 8 /* start address */ +#define BI_EA 9 /* end address */ +#define BI_BCIC 10 /* BCI control */ +#define BI_WSTS 11 /* write status */ +#define BI_FICMD 12 /* force IPINTR command */ +#define BI_UIIC 16 /* user interface interrupt control */ +#define BI_GPR0 60 /* general purpose register 0 */ +#define BI_GPR1 61 /* general purpose register 1 */ +#define BI_GPR2 62 /* general purpose register 2 */ +#define BI_GPR3 63 /* general purpose register 3 */ +#define BI_SOSR 64 /* slave only status register */ +#define BI_RXCD 128 /* receive console data register */ + +/* VAXBI device types */ + +#define DTYPE_MS820 0x0001 /* MS820 MOS Memory */ +#define DTYPE_DWBUA 0x0102 /* DWBUA Unibus Adapter */ +#define DTYPE_KA820 0x0105 /* KA820 CPU */ +#define DTYPE_CIBCA 0x0105 /* CI Adapter */ +#define DTYPE_KDB50 0x010E /* Disk Adapter */ +#define DTYPE_DEBNA 0x410F /* Ethernet Adapter */ + +/* VAXBI control/status register */ + +#define BICSR_V_IR 24 /* interface revision */ +#define BICSR_M_IR 0xFF +#define BICSR_V_IF 16 /* interface type */ +#define BICSR_M_IF 0xFF +#define BICSR_HES 0x00004000 /* hard error summary */ +#define BICSR_SES 0x00004000 /* soft error summary */ +#define BICSR_INI 0x00002000 /* initialise */ +#define BICSR_BRK 0x00001000 /* broke - NI */ +#define BICSR_STS 0x00000800 /* self test status */ +#define BICSR_RST 0x00000400 /* node reset */ +#define BICSR_UWP 0x00000100 /* unlock write pending */ +#define BICSR_HIE 0x00000080 /* hard error interrupt en */ +#define BICSR_SIE 0x00000040 /* soft error interrupt en */ +#define BICSR_AC 0x00000030 /* arbitration control */ +#define BICSR_NODE 0x0000000F /* BI node ID */ +#define BICSR_RW (BICSR_HIE | BICSR_SIE | BICSR_AC) +#define BICSR_RD 0xFFFFFDFF + +/* VAXBI bus error register */ + +#define BIBER_NMR 0x40000000 /* no ACK to multi resp command */ +#define BIBER_MTCE 0x20000000 /* master transmit check error */ +#define BIBER_CTE 0x10000000 /* control transmit error */ +#define BIBER_MPE 0x08000000 /* master parity error */ +#define BIBER_ISE 0x04000000 /* interlock sequence error */ +#define BIBER_TDF 0x02000000 /* transmitter during fault */ +#define BIBER_IVE 0x01000000 /* ident vector error */ +#define BIBER_CPE 0x00800000 /* command parity error */ +#define BIBER_SPE 0x00400000 /* slave parity error */ +#define BIBER_RDS 0x00200000 /* read data substitute */ +#define BIBER_RTO 0x00100000 /* retry timeout */ +#define BIBER_STO 0x00080000 /* stall timeout */ +#define BIBER_BTO 0x00040000 /* bus timeout */ +#define BIBER_NEX 0x00020000 /* nonexistant address */ +#define BIBER_ICE 0x00010000 /* illegal confirmation error */ +#define BIBER_UPE 0x00000008 /* user parity enable */ +#define BIBER_IPE 0x00000004 /* ID parity error */ +#define BIBER_CRD 0x00000002 /* corrected read data */ +#define BIBER_NPE 0x00000001 /* null bus parity error */ +#define BIBER_RD 0xFFFF000F +#define BIBER_W1C 0xFFFF0007 + +/* VAXBI error interrupt control register */ + +#define BIECR_ABO 0x01000000 /* interrupt abort */ +#define BIECR_COM 0x00800000 /* interrupt complete */ +#define BIECR_SNT 0x00200000 /* interrupt sent */ +#define BIECR_FRC 0x00100000 /* force */ +#define BIECR_LVL 0x000F0000 /* interrupt level */ +#define BIECR_V_LVL 16 +#define BIECR_M_LVL 0xF +#define BIECR_VEC 0x00003FFC /* vector */ +#define BIECR_RW 0x001F3FFC +#define BIECR_W1C 0x01A00000 +#define BIECR_RD (BIECR_RW | BIECR_W1C) + +/* VAXBI interrupt destination register */ + +#define BIID_RW 0x0000FFFF +#define BIID_RD BIID_RW + +/* VAXBI user interface interrupt control register */ + +#define BIICR_ABO 0xF0000000 /* interrupt abort */ +#define BIICR_ITC 0x0F000000 /* interrupt complete */ +#define BIICR_SNT 0x00F00000 /* interrupt sent */ +#define BIICR_FRC 0x000F0000 /* force */ +#define BIICR_EXV 0x00008000 /* external vector */ +#define BIICR_VEC 0x00003FFC /* vector */ +#define BIICR_RW 0x000FBFFC +#define BIICR_W1C 0xFFF00000 +#define BIICR_RD (BIICR_RW | BIICR_W1C) + +typedef struct { + uint32 dtype; + uint32 csr; + uint32 ber; + uint32 eicr; + uint32 idest; + uint32 imsk; + uint32 fidest; + uint32 isrc; + uint32 sa; + uint32 ea; + uint32 bcic; + uint32 wsts; + uint32 ficmd; + uint32 uiic; + uint32 gpr0; + uint32 gpr1; + uint32 gpr2; + uint32 gpr3; + uint32 sosr; + uint32 rxcd; +} BIIC; + +#endif diff --git a/VAX/vax_defs.h b/VAX/vax_defs.h index 00ef1d88..e7a56634 100644 --- a/VAX/vax_defs.h +++ b/VAX/vax_defs.h @@ -817,6 +817,7 @@ extern int32 pcq_p; /* PC queue ptr */ extern int32 in_ie; /* in exc, int */ extern int32 ibcnt, ppc; /* prefetch ctl */ extern int32 hlt_pin; /* HLT pin intr */ +extern int32 mxpr_cc_vc; /* cc V & C bits from mtpr/mfpr operations */ extern int32 mem_err; extern int32 crd_err; @@ -912,6 +913,8 @@ extern void rom_wr_B (int32 pa, int32 val); #include "vax610_defs.h" #elif defined (VAX_620) || defined (VAX_630) #include "vax630_defs.h" +#elif defined (VAX_820) +#include "vax820_defs.h" #elif defined (VAX_860) #include "vax860_defs.h" #else /* VAX 3900 */ diff --git a/Visual Studio Projects/Simh.sln b/Visual Studio Projects/Simh.sln index 35b2f772..334dc8dd 100644 --- a/Visual Studio Projects/Simh.sln +++ b/Visual Studio Projects/Simh.sln @@ -303,6 +303,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UC15", "UC15.vcproj", "{B5E {D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VAX8200", "VAX8200.vcproj", "{B9BA7B49-AFAD-4950-B8DC-2FAD61AE8B7E}" + ProjectSection(ProjectDependencies) = postProject + {D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -553,6 +558,10 @@ Global {B5E9D32E-53F9-4C9B-B037-5A2D34E370CF}.Debug|Win32.Build.0 = Debug|Win32 {B5E9D32E-53F9-4C9B-B037-5A2D34E370CF}.Release|Win32.ActiveCfg = Release|Win32 {B5E9D32E-53F9-4C9B-B037-5A2D34E370CF}.Release|Win32.Build.0 = Release|Win32 + {B9BA7B49-AFAD-4950-B8DC-2FAD61AE8B7E}.Debug|Win32.ActiveCfg = Debug|Win32 + {B9BA7B49-AFAD-4950-B8DC-2FAD61AE8B7E}.Debug|Win32.Build.0 = Debug|Win32 + {B9BA7B49-AFAD-4950-B8DC-2FAD61AE8B7E}.Release|Win32.ActiveCfg = Release|Win32 + {B9BA7B49-AFAD-4950-B8DC-2FAD61AE8B7E}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Visual Studio Projects/VAX8200.vcproj b/Visual Studio Projects/VAX8200.vcproj new file mode 100644 index 00000000..264bd6bb --- /dev/null +++ b/Visual Studio Projects/VAX8200.vcproj @@ -0,0 +1,681 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/descrip.mms b/descrip.mms index cf05ff4d..ce154d6b 100644 --- a/descrip.mms +++ b/descrip.mms @@ -56,6 +56,7 @@ # VAX730 Just Build The DEC VAX730. # VAX750 Just Build The DEC VAX750. # VAX780 Just Build The DEC VAX780. +# VAX8200 Just Build The DEC VAX8200. # VAX8600 Just Build The DEC VAX8600. # CLEAN Will Clean Files Back To Base Kit. # @@ -921,6 +922,37 @@ VAX780_OPTIONS = /INCL=($(SIMH_DIR),$(VAX780_DIR),$(PDP11_DIR)$(PCAP_INC))\ VAX780_SIMH_LIB = $(SIMH_LIB) .ENDIF +# Digital Equipment VAX8200 Simulator Definitions. +# +VAX8200_DIR = SYS$DISK:[.VAX] +VAX8200_LIB1 = $(LIB_DIR)VAX820L1-$(ARCH).OLB +VAX8200_SOURCE1 = $(VAX8200_DIR)VAX_CPU.C,$(VAX8200_DIR)VAX_CPU1.C,\ + $(VAX8200_DIR)VAX_FPA.C,$(VAX8200_DIR)VAX_CIS.C,\ + $(VAX8200_DIR)VAX_OCTA.C,$(VAX8200_DIR)VAX_CMODE.C,\ + $(VAX8200_DIR)VAX_MMU.C,$(VAX8200_DIR)VAX_SYS.C,\ + $(VAX8200_DIR)VAX_SYSCM.C,$(VAX8200_DIR)VAX_WATCH.C,\ + $(VAX8200_DIR)VAX820_STDDEV.C,$(VAX8200_DIR)VAX820_BI.C,\ + $(VAX8200_DIR)VAX820_MEM.C,$(VAX8200_DIR)VAX820_UBA.C,\ + $(VAX8200_DIR)VAX820_KA.C,$(VAX8200_DIR)VAX820_SYSLIST.C +VAX8200_LIB2 = $(LIB_DIR)VAX820L2-$(ARCH).OLB +VAX8200_SOURCE2 = $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ + $(PDP11_DIR)PDP11_TS.C,$(PDP11_DIR)PDP11_DZ.C,\ + $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_TD.C,$(PDP11_DIR)PDP11_TQ.C,\ + $(PDP11_DIR)PDP11_XU.C,$(PDP11_DIR)PDP11_RY.C,\ + $(PDP11_DIR)PDP11_CR.C,$(PDP11_DIR)PDP11_HK.C,\ + $(PDP11_DIR)PDP11_VH.C,$(PDP11_DIR)PDP11_DMC.C,\ + $(PDP11_DIR)PDP11_TC.C,$(PDP11_DIR)PDP11_RK.C,\ + $(PDP11_DIR)PDP11_CH.C,$(PDP11_DIR)PDP11_IO_LIB.C +.IFDEF ALPHA_OR_IA64 +VAX8200_OPTIONS = /INCL=($(SIMH_DIR),$(VAX8200_DIR),$(PDP11_DIR)$(PCAP_INC))\ + /DEF=($(CC_DEFS),"VM_VAX=1","USE_ADDR64=1","USE_INT64=1"$(PCAP_DEFS),"VAX_820=1") +VAX8200_SIMH_LIB = $(SIMH_LIB64) +.ELSE +VAX8200_OPTIONS = /INCL=($(SIMH_DIR),$(VAX8200_DIR),$(PDP11_DIR)$(PCAP_INC))\ + /DEF=($(CC_DEFS),"VM_VAX=1"$(PCAP_DEFS),"VAX_860=1") +VAX8200_SIMH_LIB = $(SIMH_LIB) +.ENDIF + # Digital Equipment VAX8600 Simulator Definitions. # VAX8600_DIR = SYS$DISK:[.VAX] @@ -970,8 +1002,8 @@ I7094_OPTIONS = /INCL=($(SIMH_DIR),$(I7094_DIR))/DEF=($(CC_DEFS)) .IFDEF ALPHA_OR_IA64 ALL : ALTAIR ALTAIRZ80 CDC1700 ECLIPSE GRI LGP H316 HP2100 HP3000 I1401 I1620 \ IBM1130 ID16 ID32 NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP10 PDP11 PDP15 S3 \ - VAX MICROVAX3900 MICROVAX1 RTVAX1000 MICROVAX2 VAX730 VAX750 VAX780 VAX8600 \ - SDS I7094 SWTP6800MP-A SWTP6800MP-A2 SSEM BESM6 B5500 + VAX MICROVAX3900 MICROVAX1 RTVAX1000 MICROVAX2 VAX730 VAX750 VAX780 \ + VAX8200 VAX8600 SDS I7094 SWTP6800MP-A SWTP6800MP-A2 SSEM BESM6 B5500 $! No further actions necessary .ELSE # @@ -979,8 +1011,8 @@ ALL : ALTAIR ALTAIRZ80 CDC1700 ECLIPSE GRI LGP H316 HP2100 HP3000 I1401 I1620 \ # ALL : ALTAIR GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 \ - VAX MICROVAX3900 MICROVAX1 RTVAX1000 MICROVAX2 VAX730 VAX750 VAX780 VAX8600 \ - SDS SWTP6800MP-A SWTP6800MP-A2 SSEM + VAX MICROVAX3900 MICROVAX1 RTVAX1000 MICROVAX2 VAX730 VAX750 VAX780 \ + VAX8200 VAX8600 SDS SWTP6800MP-A SWTP6800MP-A2 SSEM $! No further actions necessary .ENDIF @@ -1668,6 +1700,28 @@ $(VAX780_LIB2) : $(VAX780_SOURCE2) $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* +$(VAX8200_LIB1) : $(VAX8200_SOURCE1) + $! + $! Building The $(VAX8200_LIB1) Library. + $! + $ $(CC)$(VAX8200_OPTIONS)/OBJ=$(VAX8200_DIR) - + /OBJ=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + +$(VAX8200_LIB2) : $(VAX8200_SOURCE2) + $! + $! Building The $(VAX8200_LIB2) Library. + $! + $ $(CC)$(VAX8200_OPTIONS)/OBJ=$(VAX8200_DIR) - + /OBJ=$(BLD_DIR) $(MMS$CHANGED_LIST) + $ IF (F$SEARCH("$(MMS$TARGET)").EQS."") THEN - + LIBRARY/CREATE $(MMS$TARGET) + $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + $(VAX8600_LIB1) : $(VAX8600_SOURCE1) $! $! Building The $(VAX8600_LIB1) Library. @@ -2307,6 +2361,21 @@ $(BIN_DIR)VAX780-$(ARCH).EXE : $(SIMH_MAIN) $(VAX780_SIMH_LIB) $(PCAP_LIBD) $(VA $(VAX780_SIMH_LIB)/LIBRARY$(PCAP_LIBR) $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* +VAX8200 : $(BIN_DIR)VAX8200-$(ARCH).EXE + $! VAX8200 done + +$(BIN_DIR)VAX8200-$(ARCH).EXE : $(SIMH_MAIN) $(VAX8200_SIMH_LIB) $(PCAP_LIBD) $(VAX8200_LIB1) $(VAX8200_LIB2) $(PCAP_EXECLET) + $! + $! Building The $(BIN_DIR)VAX8200-$(ARCH).EXE Simulator. + $! + $ $(CC)$(VAX8200_OPTIONS)/OBJ=$(BLD_DIR) SCP.C + $ LINK $(LINK_DEBUG)$(LINK_SECTION_BINDING)- + /EXE=$(BIN_DIR)VAX8200-$(ARCH).EXE - + $(BLD_DIR)SCP.OBJ,- + $(VAX8200_LIB1)/LIBRARY,$(VAX8200_LIB2)/LIBRARY,- + $(VAX8200_SIMH_LIB)/LIBRARY$(PCAP_LIBR) + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + VAX8600 : $(BIN_DIR)VAX8600-$(ARCH).EXE $! VAX8600 done diff --git a/makefile b/makefile index a746c06d..4f39f406 100644 --- a/makefile +++ b/makefile @@ -1382,6 +1382,21 @@ 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} +VAX8200 = ${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}/vax_watch.c ${VAXD}/vax820_stddev.c ${VAXD}/vax820_bi.c \ + ${VAXD}/vax820_mem.c ${VAXD}/vax820_uba.c ${VAXD}/vax820_ka.c \ + ${VAXD}/vax820_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_hk.c ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_dmc.c \ + ${PDP11D}/pdp11_td.c ${PDP11D}/pdp11_tc.c ${PDP11D}/pdp11_rk.c \ + ${PDP11D}/pdp11_io_lib.c ${PDP11D}/pdp11_ch.c +VAX8200_OPT = -DVM_VAX -DVAX_820 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} + + VAX8600 = ${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 \ @@ -1849,7 +1864,8 @@ ATT3B2_OPT = -DUSE_INT64 -DUSE_ADDR64 -I ${ATT3B2D} ${NETWORK_OPT} # Build everything (not the unsupported/incomplete or experimental simulators) # ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \ - vax microvax3900 microvax1 rtvax1000 microvax2 vax730 vax750 vax780 vax8600 \ + vax microvax3900 microvax1 rtvax1000 microvax2 vax730 vax750 vax780 \ + vax8200 vax8600 \ nova eclipse hp2100 hp3000 i1401 i1620 s3 altair altairz80 gri \ i7094 ibm1130 id16 id32 sds lgp h316 cdc1700 \ swtp6800mp-a swtp6800mp-a2 tx-0 ssem b5500 isys8010 isys8020 \ @@ -2042,6 +2058,15 @@ ifneq (,$(call find_test,$(VAXD),vax-diag)) $@ $(call find_test,$(VAXD),vax-diag) $(TEST_ARG) endif +vax8200 : ${BIN}vax8200${EXE} + +${BIN}vax8200${EXE} : ${VAX8200} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX8200} ${SIM} ${VAX8200_OPT} $(CC_OUTSPEC) ${LDFLAGS} +ifneq (,$(call find_test,$(VAXD),vax-diag)) + $@ $(call find_test,$(VAXD),vax-diag) $(TEST_ARG) +endif + vax8600 : ${BIN}BuildROMs${EXE} ${BIN}vax8600${EXE} ${BIN}vax8600${EXE} : ${VAX8600} ${SIM} ${BUILD_ROMS}