From a12e4a1c397bd67f7ed376324b2b11609e5ce8f7 Mon Sep 17 00:00:00 2001 From: Bob Supnik Date: Mon, 23 Jan 2006 20:01:00 -0800 Subject: [PATCH] Notes For V3.5-1 The source set has been extensively overhauled. For correct viewing, set Visual C++ or Emacs to have tab stops every 4 characters. 1. New Features 1.1 3.5-0 1.1.1 All Ethernet devices - Added Windows user-defined adapter names (from Timothe Litt) 1.1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors - Added support for SET n DISCONNECT 1.1.3 VAX - Added latent QDSS support - Revised autoconfigure to handle QDSS 1.1.4 PDP-11 - Revised autoconfigure to handle more cases 1.2 3.5-1 No new features 1.3 3.5-2 1.3.1 All ASCII terminals - Most ASCII terminal emulators have supported 7-bit and 8-bit operation; where required, they have also supported an upper- case only or KSR-emulation mode. This release adds a new mode, 7P, for 7-bit printing characters. In 7P mode, non-printing characters in the range 0-31 (decimal), and 127 (decimal), are automatically suppressed. This prevents printing of fill characters under Windows. The printable character set for ASCII code values 0-31 can be changed with the SET CONSOLE PCHAR command. Code value 127 (DELETE) is always suppressed. 1.3.2 VAX-11/780 - First release. The VAX-11/780 has successfully run VMS V7.2. The commercial instructions and compatability mode have not been extensively tested. The Ethernet controller is not working yet and is disabled. 2. Bugs Fixed 2.1 3.5-0 2.1.1 SCP and libraries - Trim trailing spaces on all input (for example, attach file names) - Fixed sim_sock spurious SIGPIPE error in Unix/Linux - Fixed sim_tape misallocation of TPC map array for 64b simulators 2.1.2 1401 - Fixed bug, CPU reset was clearing SSB through SSG 2.1.3 PDP-11 - Fixed bug in VH vector display routine - Fixed XU runt packet processing (found by Tim Chapman) 2.1.4 Interdata - Fixed bug in SHOW PAS CONN/STATS - Fixed potential integer overflow exception in divide 2.1.5 SDS - Fixed bug in SHOW MUX CONN/STATS 2.1.6 HP - Fixed bug in SHOW MUX CONN/STATS 2.1.7 PDP-8 - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.1.8 PDP-18b - Fixed bug in SHOW TTIX CONN/STATS - Fixed bug in SET/SHOW TTOXn LOG 2.1.9 Nova, Eclipse - Fixed potential integer overflow exception in divide 2.2 3.5-1 2.2.1 1401 - Changed character encodings to be compatible with Pierce 709X simulator - Added mode for old/new character encodings 2.2.2 1620 - Changed character encodings to be compatible with Pierce 709X simulator 2.2.3 PDP-10 - Changed MOVNI to eliminate GCC warning 2.2.4 VAX - Fixed bug in structure definitions with 32b compilation options - Fixed bug in autoconfiguration table 2.2.5 PDP-11 - Fixed bug in autoconfiguration table 2.3 3.5-2 2.3.1 PDP-10 - RP: fixed drive clear not to clear disk address 2.3.2 PDP-11 (VAX, VAX-11/780, for shared peripherals) - HK: fixed overlap seek interaction with drive select, drive clear, etc - RQ, TM, TQ, TS, TU: widened address display to 64b when USE_ADDR64 option selected - TU: changed default adapter from TM02 to TM03 (required by VMS) - RP: fixed drive clear not to clear disk address - RP, TU: fixed device enable/disable to enabled/disable Massbus adapter as well - XQ: fixed register access alignment bug (found by Doug Carman) 2.3.3 PDP-8 - RL: fixed IOT 61 decoding bug (found by David Gesswein) - DF, DT, RF: fixed register access alignment bug (found by Doug Carman) 2.3.4 VAX - Fixed CVTfi to trap on integer overflow if PSW is set - Fixed breakpoint detection when USE_ADDR64 option selected --- 0readme_35.txt | 51 +- GRI/gri_doc.txt | 29 +- GRI/gri_stddev.c | 58 +- H316/h316_doc.txt | 32 +- H316/h316_stddev.c | 54 +- HP2100/hp2100_cpu.c | 55 +- HP2100/hp2100_doc.txt | 53 +- HP2100/hp2100_dp.c | 1 - HP2100/hp2100_dq.c | 2 - HP2100/hp2100_ds.c | 1 - HP2100/hp2100_ms.c | 1 - HP2100/hp2100_mux.c | 71 +-- HP2100/hp2100_stddev.c | 69 +-- I1401/i1401_cpu.c | 2 +- I1401/i1401_doc.txt | 13 +- I1401/i1401_mt.c | 2 +- Interdata/id_doc.txt | 78 ++- Interdata/id_pas.c | 37 +- Interdata/id_tt.c | 44 +- Interdata/id_ttp.c | 42 +- PDP10/pdp10_doc.txt | 15 +- PDP10/pdp10_rp.c | 6 +- PDP11/pdp11_defs.h | 1 + PDP11/pdp11_doc.txt | 31 +- PDP11/pdp11_dz.c | 19 +- PDP11/pdp11_hk.c | 101 +-- PDP11/pdp11_rh.c | 254 ++++---- PDP11/pdp11_rp.c | 8 +- PDP11/pdp11_rq.c | 13 +- PDP11/pdp11_stddev.c | 38 +- PDP11/pdp11_sys.c | 6 +- PDP11/pdp11_tm.c | 3 +- PDP11/pdp11_tq.c | 5 +- PDP11/pdp11_ts.c | 3 +- PDP11/pdp11_tu.c | 12 +- PDP11/pdp11_vh.c | 42 +- PDP11/pdp11_xq.c | 25 +- PDP11/pdp11_xu.c | 285 +++++++-- PDP11/pdp11_xu.h | 5 +- PDP18B/pdp18b_doc.txt | 46 +- PDP18B/pdp18b_stddev.c | 49 +- PDP18B/pdp18b_tt1.c | 59 +- PDP8/pdp8_df.c | 7 +- PDP8/pdp8_doc.txt | 48 +- PDP8/pdp8_dt.c | 11 +- PDP8/pdp8_rf.c | 7 +- PDP8/pdp8_rl.c | 7 +- PDP8/pdp8_tt.c | 58 +- PDP8/pdp8_ttx.c | 35 +- VAX/ka655.bin | Bin 131072 -> 0 bytes VAX/vax780_bugs.txt | 17 + VAX/vax780_defs.h | 403 ++++++++++++ VAX/vax780_doc.txt | 1093 +++++++++++++++++++++++++++++++++ VAX/vax780_mba.c | 770 +++++++++++++++++++++++ VAX/vax780_mem.c | 276 +++++++++ VAX/vax780_sbi.c | 745 ++++++++++++++++++++++ VAX/vax780_stddev.c | 931 ++++++++++++++++++++++++++++ VAX/vax780_syslist.c | 135 ++++ VAX/vax780_uba.c | 1325 ++++++++++++++++++++++++++++++++++++++++ VAX/vax_cis.c | 11 +- VAX/vax_cpu.c | 52 +- VAX/vax_defs.h | 7 +- VAX/vax_doc.txt | 43 +- VAX/vax_io.c | 125 +++- VAX/vax_octa.c | 12 +- VAX/vax_stddev.c | 36 +- VAX/vax_sys.c | 5 +- VAX/vax_sysdev.c | 5 +- VAX/vaxmod_defs.h | 8 +- descrip.mms | 57 +- makefile | 12 +- scp.c | 91 ++- scp.h | 8 +- sim_console.c | 40 ++ sim_console.h | 20 + sim_defs.h | 26 +- sim_ether.c | 88 ++- sim_ether.h | 14 +- sim_fio.c | 13 + sim_rev.h | 50 +- sim_sock.c | 4 +- sim_tape.c | 53 +- sim_tape.h | 10 +- simh_doc.txt | 79 +-- simh_swre.txt | 2 +- 85 files changed, 7425 insertions(+), 1035 deletions(-) delete mode 100644 VAX/ka655.bin create mode 100644 VAX/vax780_bugs.txt create mode 100644 VAX/vax780_defs.h create mode 100644 VAX/vax780_doc.txt create mode 100644 VAX/vax780_mba.c create mode 100644 VAX/vax780_mem.c create mode 100644 VAX/vax780_sbi.c create mode 100644 VAX/vax780_stddev.c create mode 100644 VAX/vax780_syslist.c create mode 100644 VAX/vax780_uba.c diff --git a/0readme_35.txt b/0readme_35.txt index ad4a33c6..08780619 100644 --- a/0readme_35.txt +++ b/0readme_35.txt @@ -23,7 +23,34 @@ characters. 1.1.4 PDP-11 -- Revised autoconfigure to handle more casees +- Revised autoconfigure to handle more cases + +1.2 3.5-1 + +No new features + +1.3 3.5-2 + +1.3.1 All ASCII terminals + +- Most ASCII terminal emulators have supported 7-bit and 8-bit + operation; where required, they have also supported an upper- + case only or KSR-emulation mode. This release adds a new mode, + 7P, for 7-bit printing characters. In 7P mode, non-printing + characters in the range 0-31 (decimal), and 127 (decimal), are + automatically suppressed. This prevents printing of fill + characters under Windows. + + The printable character set for ASCII code values 0-31 can be + changed with the SET CONSOLE PCHAR command. Code value 127 + (DELETE) is always suppressed. + +1.3.2 VAX-11/780 + +- First release. The VAX-11/780 has successfully run VMS V7.2. The + commercial instructions and compatability mode have not been + extensively tested. The Ethernet controller is not working yet + and is disabled. 2. Bugs Fixed @@ -95,5 +122,27 @@ characters. - Fixed bug in autoconfiguration table +2.3 3.5-2 +2.3.1 PDP-10 +- RP: fixed drive clear not to clear disk address + +2.3.2 PDP-11 (VAX, VAX-11/780, for shared peripherals) + +- HK: fixed overlap seek interaction with drive select, drive clear, etc +- RQ, TM, TQ, TS, TU: widened address display to 64b when USE_ADDR64 option selected +- TU: changed default adapter from TM02 to TM03 (required by VMS) +- RP: fixed drive clear not to clear disk address +- RP, TU: fixed device enable/disable to enabled/disable Massbus adapter as well +- XQ: fixed register access alignment bug (found by Doug Carman) + +2.3.3 PDP-8 + +- RL: fixed IOT 61 decoding bug (found by David Gesswein) +- DF, DT, RF: fixed register access alignment bug (found by Doug Carman) + +2.3.4 VAX + +- Fixed CVTfi to trap on integer overflow if PSW is set +- Fixed breakpoint detection when USE_ADDR64 option selected diff --git a/GRI/gri_doc.txt b/GRI/gri_doc.txt index 295a22d3..80b2b06b 100644 --- a/GRI/gri_doc.txt +++ b/GRI/gri_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik Subj: GRI-909 Simulator Usage -Date: 15-Feb-2004 +Date: 01-Dec-2005 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2004, written by Robert M Supnik - Copyright (c) 1993-2004, Robert M Supnik + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -196,12 +196,23 @@ Error handling is as follows: 2.2.3 S42-001 Teletype Input (TTI) -The Teletype interfaces (TTI, TTO) can be set to one of three modes: -KSR, 7B, or 8B. In KSR mode, lower case input and output characters -are automatically converted to upper case, and the high order bit is -forced to one on input. In 7B mode, input and output characters are -masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either interface changes both. The default mode is KSR. +The Teletype interfaces (TTI, TTO) can be set to one of four modes, +KSR, 7P, 7B, or 8B: + + mode input characters output characters + + KSR lower case converted lower case converted + to upper case, to upper case, + high-order bit set high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default mode is KSR. The Teletype input (TTI) polls the console keyboard for input. It implements these registers: diff --git a/GRI/gri_stddev.c b/GRI/gri_stddev.c index 6d6e5cb4..a6c07474 100644 --- a/GRI/gri_stddev.c +++ b/GRI/gri_stddev.c @@ -29,6 +29,7 @@ hsp S42-006 high speed punch rtc real time clock + 22-Nov-05 RMS Revised for new terminal processing routines 29-Dec-03 RMS Added support for console backpressure 25-Apr-03 RMS Revised for extended file support 22-Dec-02 RMS Added break support @@ -38,11 +39,6 @@ #include "gri_defs.h" #include -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) - uint32 hsr_stopioe = 1, hsp_stopioe = 1; extern uint16 M[]; @@ -69,7 +65,7 @@ int32 rtc_tps = 1000; tti_mod TTI modifiers list */ -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }; +UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_KSR, 0), KBD_POLL_WAIT }; REG tti_reg[] = { { ORDATA (BUF, tti_unit.buf, 8) }, @@ -77,14 +73,14 @@ REG tti_reg[] = { { FLDATA (IENB, ISR, INT_V_TTI) }, { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (UC, tti_unit.flags, UNIT_V_KSR), REG_HRO }, { NULL } }; MTAB tti_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, + { TT_MODE, TT_MODE_7P, "7b", NULL, NULL }, { 0 } }; @@ -102,7 +98,7 @@ DEVICE tti_dev = { tto_reg TTO register list */ -UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }; +UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_KSR, 0), SERIAL_OUT_WAIT }; REG tto_reg[] = { { ORDATA (BUF, tto_unit.buf, 8) }, @@ -114,9 +110,10 @@ REG tto_reg[] = { }; MTAB tto_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, + { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode }, { 0 } }; @@ -243,17 +240,12 @@ t_stat tti_svc (UNIT *uptr) { int32 c; -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ +sim_activate (uptr, uptr->wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */ -else if (tti_unit.flags & UNIT_KSR) { /* KSR? */ - c = c & 0177; /* force 7b */ - if (islower (c)) c = toupper (c); /* cvt to UC */ - tti_unit.buf = c | 0200; /* add TTY bit */ - } -else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); +if (c & SCPE_BREAK) uptr->buf = 0; /* break? */ +else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR); dev_done = dev_done | INT_TTI; /* set ready */ -tti_unit.pos = tti_unit.pos + 1; +uptr->pos = uptr->pos + 1; return SCPE_OK; } @@ -262,17 +254,15 @@ t_stat tto_svc (UNIT *uptr) int32 c; t_stat r; -if (tto_unit.flags & UNIT_KSR) { /* KSR? */ - c = tto_unit.buf & 0177; /* force 7b */ - if (islower (c)) c = toupper (c); /* cvt to UC */ - } -else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ +c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags)); +if (c >= 0) { + if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } } dev_done = dev_done | INT_TTO; /* set ready */ -tto_unit.pos = tto_unit.pos + 1; +uptr->pos = uptr->pos + 1; return SCPE_OK; } @@ -296,8 +286,8 @@ return SCPE_OK; t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { -tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -tto_unit.flags = (tto_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; +tti_unit.flags = (tti_unit.flags & ~TT_MODE) | val; +tto_unit.flags = (tto_unit.flags & ~TT_MODE) | val; return SCPE_OK; } diff --git a/H316/h316_doc.txt b/H316/h316_doc.txt index 604be750..a2c397ea 100644 --- a/H316/h316_doc.txt +++ b/H316/h316_doc.txt @@ -1,14 +1,14 @@ To: Users From: Bob Supnik Subj: H316 Simulator Usage -Date: 15-Nov-2004 +Date: 01-Dec-2005 COPYRIGHT NOTICE The following copyright notice applies to both the SIMH source and binary: - Original code published in 1993-2004, written by Robert M Supnik - Copyright (c) 1993-2004, Robert M Supnik + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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"), @@ -273,14 +273,24 @@ The console Teletype (TTY) consists of four separate units: TTY2 paper tape reader TTY3 paper tape punch -The keyboard and printer (TTY0, TTY1) can be set to one of three modes: -KSR, 7B, or 8B. In KSR mode, lower case input and output characters -are automatically converted to upper case, and the high order bit is -forced to one on input. In 7B mode, input and output characters are -masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either unit changes both. The default mode is KSR. The -Teletype keyboard reads from the console keyboard, and the printer -prites to the simulator console window. +The keyboard and printer (TTY0, TTY1) can be set to one of four modes, +KSR, 7P, 7B, or 8B: + + mode input characters output characters + + KSR lower case converted lower case converted + to upper case, to upper case, + high-order bit set high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default mode is KSR. The Teletype keyboard reads from the console +keyboard, and the printer writes to the simulator console window. The paper tape reader (TTY2) can bet set to operate in binary, ASCII, or Unix ASCII mode: diff --git a/H316/h316_stddev.c b/H316/h316_stddev.c index f675aaf6..9e3cf547 100644 --- a/H316/h316_stddev.c +++ b/H316/h316_stddev.c @@ -28,6 +28,7 @@ tty 316/516-33 teleprinter clk/options 316/516-12 real time clocks/internal options + 22-Nov-05 RMS Revised for new terminal processing routines 05-Feb-05 RMS Fixed bug in OCP '0001 (found by Philipp Hachtmann) 31-Jan-05 RMS Fixed bug in TTY print (found by Philipp Hachtmann) 01-Dec-04 RMS Fixed problem in SKS '104 (reported by Philipp Hachtmann) @@ -66,21 +67,8 @@ #include "h316_defs.h" #include -#define CHAR_FLAG(c) (1u << (c)) - -#define BEL_FLAG CHAR_FLAG('\a') -#define LF_FLAG CHAR_FLAG('\n') -#define CR_FLAG CHAR_FLAG('\r') -#define HT_FLAG CHAR_FLAG('\t') - -#define CNTL_SET (BEL_FLAG | HT_FLAG | LF_FLAG | CR_FLAG) - -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_V_ASC (UNIT_V_UF + 2) /* ASCII */ -#define UNIT_V_UASC (UNIT_V_UF + 3) /* Unix ASCII */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) +#define UNIT_V_ASC (TTUF_V_UF + 0) /* ASCII */ +#define UNIT_V_UASC (TTUF_V_UF + 1) /* Unix ASCII */ #define UNIT_ASC (1 << UNIT_V_ASC) #define UNIT_UASC (1 << UNIT_V_UASC) #define STA u3 /* state bits */ @@ -229,8 +217,8 @@ DEVICE ptp_dev = { DIB tty_dib = { TTY, IOBUS, 1, &ttyio }; UNIT tty_unit[] = { - { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }, + { UDATA (&tti_svc, TT_MODE_KSR, 0), KBD_POLL_WAIT }, + { UDATA (&tto_svc, TT_MODE_KSR, 0), SERIAL_OUT_WAIT }, { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) }, { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } }; @@ -256,9 +244,10 @@ REG tty_reg[] = { }; MTAB tty_mod[] = { - { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, UNIT_KSR, "KSR", "KSR", &ttio_set_mode }, - { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, 0 , "7b" , "7B" , &ttio_set_mode }, - { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, UNIT_8B , "8b" , "8B" , &ttio_set_mode }, + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &ttio_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &ttio_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &ttio_set_mode }, + { TT_MODE, TT_MODE_7P, "7p", "7P", &ttio_set_mode }, { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE, NULL, "BINARY", &ttrp_set_mode }, { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC, "ASCII", "ASCII", @@ -611,11 +600,7 @@ sim_activate (uptr, uptr->wait); /* continue poll */ if ((c = sim_poll_kbd ()) >= SCPE_KFLAG) { /* character? */ out = c & 0177; /* mask echo to 7b */ if (c & SCPE_BREAK) c = 0; /* break? */ - else if (uptr->flags & UNIT_KSR) { /* KSR? */ - if (islower (out)) out = toupper (out); /* cvt to UC */ - c = out | 0200; /* add TTY bit */ - } - else if (!(uptr->flags & UNIT_8B)) c = out; /* 7b? */ + else c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR); uptr->pos = uptr->pos + 1; } else if (c != SCPE_OK) return c; /* error? */ @@ -702,18 +687,10 @@ t_stat tto_write (int32 c) { UNIT *tuptr = &tty_unit[TTO]; -if (tuptr->flags & UNIT_8B) c = c & 0377; /* 8b? */ -else { - c = c & 0177; /* 7b, KSR: mask */ - if (c) return SCPE_OK; /* supress NUL */ - if (tuptr->flags & UNIT_KSR) { /* KSR? */ - if ((c < 040) && /* not in ctrl set? */ - !(CNTL_SET & CHAR_FLAG (c))) return SCPE_OK; - if (islower (c)) c = toupper (c); /* cvt to UC */ - } - } +c = sim_tt_outcvt (c, TT_GET_MODE (tuptr->flags)); tuptr->pos = tuptr->pos + 1; -return sim_putchar_s (c); +if (c >= 0) return sim_putchar_s (c); +else return SCPE_OK; } /* Output to punch */ @@ -766,8 +743,9 @@ return SCPE_OK; t_stat ttio_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { if (uptr->flags & UNIT_ATTABLE) return SCPE_NOFNC; /* not TTR, TTP */ -tty_unit[TTI].flags = (tty_unit[TTI].flags & ~(UNIT_KSR | UNIT_8B)) | val; -tty_unit[TTO].flags = (tty_unit[TTO].flags & ~(UNIT_KSR | UNIT_8B)) | val; +tty_unit[TTO].flags = (tty_unit[TTO].flags & ~TT_MODE) | val; +if (val == TT_MODE_7P) val = TT_MODE_7B; +tty_unit[TTI].flags = (tty_unit[TTI].flags & ~TT_MODE) | val; return SCPE_OK; } diff --git a/HP2100/hp2100_cpu.c b/HP2100/hp2100_cpu.c index d28530e2..5695b5d6 100644 --- a/HP2100/hp2100_cpu.c +++ b/HP2100/hp2100_cpu.c @@ -27,6 +27,7 @@ MP 12892B memory protect DMA0,DMA1 12895A/12897B direct memory access/dual channel port controller + 26-Dec-05 JDB Improved reporting in dev_conflict 22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 21-Jan-05 JDB Reorganized CPU option flags 15-Jan-05 RMS Split out EAU and MAC instructions @@ -2051,29 +2052,47 @@ return; t_bool dev_conflict (void) { -DEVICE *dptr, *cdptr; -DIB *dibp, *chkp; -uint32 i, j, dno; +DEVICE *dptr; +DIB *dibp; +uint32 i, j, k; +t_bool is_conflict = FALSE; +uint32 conflicts[I_DEVMASK + 1] = { 0 }; -for (i = 0; cdptr = sim_devices[i]; i++) { - chkp = (DIB *) cdptr->ctxt; - if (chkp && !(cdptr->flags & DEV_DIS)) { - dno = chkp->devno; - for (j = 0; dptr = sim_devices[j]; j++) { - dibp = (DIB *) dptr->ctxt; - if (dibp && !(dptr->flags & DEV_DIS) && - (chkp != dibp) && (dno == dibp->devno)) { - printf ("%s device number conflict, devno = %d\n", - sim_dname (dptr), dno); - if (sim_log) fprintf (sim_log, - "%s device number conflict, devno = %d\n", - sim_dname (dptr), dno); - return TRUE; +for (i = 0; dptr = sim_devices[i]; i++) { + dibp = (DIB *) dptr->ctxt; + if (dibp && !(dptr->flags & DEV_DIS)) + if (++conflicts[dibp->devno] > 1) + is_conflict = TRUE; + } + +if (is_conflict) { + sim_ttcmd(); + for (i = 0; i <= I_DEVMASK; i++) { + if (conflicts[i] > 1) { + k = conflicts[i]; + printf ("Select code %o conflict:", i); + if (sim_log) fprintf (sim_log, "Select code %o conflict:", i); + for (j = 0; dptr = sim_devices[j]; j++) { + dibp = (DIB *) dptr->ctxt; + if (dibp && !(dptr->flags & DEV_DIS) && (i == dibp->devno)) { + if (k < conflicts[i]) { + printf (" and"); + if (sim_log) fputs (" and", sim_log); + } + printf (" %s", sim_dname (dptr)); + if (sim_log) fprintf (sim_log, " %s", sim_dname (dptr)); + k = k - 1; + if (k == 0) { + putchar ('\n'); + if (sim_log) fputc ('\n', sim_log); + break; + } + } } } } } -return FALSE; +return is_conflict; } /* Configuration validation diff --git a/HP2100/hp2100_doc.txt b/HP2100/hp2100_doc.txt index 75e2aef5..59b89f62 100644 --- a/HP2100/hp2100_doc.txt +++ b/HP2100/hp2100_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: HP2100 Simulator Usage -Date: 01-Jul-2005 +Date: 01-Dec-2005 COPYRIGHT NOTICE @@ -442,13 +442,22 @@ The console teleprinter has three units: keyboard (unit 0), printer (unit 1), and punch (unit 2). The keyboard reads from the console keyboard; the printer writes to the simulator console window. The punch writes to a disk file. The keyboard and printer units (TTY0, TTY1) can -be set to one of three modes: UC, 7B, or 8B. In UC mode, lower case -input and output characters are automatically converted to upper case. -In 7B mode, input and output characters are masked to 7 bits. In 8B -mode, characters are not modified. In UC and 7B mode, output of control -characters other than BEL, BS, HT, LF, and CR is suppressed; in 8B mode, -output of all characters is permitted. Changing the mode of either the -keyboard or the printer changes both. The default mode is UC. +be set to one of four modes: UC, 7P, 7B, or 8B: + + mode input characters output characters + + UC lower case converted lower case converted + to upper case, to upper case, + high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default mode is UC. Some HP software systems expect the console to transmit line-feed automatically following carriage-return. This feature is enabled with: @@ -664,14 +673,26 @@ the port to be used: where port is a decimal number between 1 and 65535 that is not being used for other TCP/IP activities. -Each line (each unit of MUXL) can be set to one of three modes: UC, 7B, -or 8B. In UC mode, lower case input and output characters are converted -automatically to upper case. In 7B mode, input and output characters -are masked to 7 bits. In 8B mode, characters are not modified. The -default mode is UC. In addition, each line supports the DATASET option. -DATASET, when set, enables modem control. The default settings are UC -mode and DATASET disabled. Finally, each line supports output logging. -The SET MUXLn LOG command enables logging on a line: +Each line (each unit of MUXL) can be set to one of four modes: UC, 7P, 7B, +or 8B: + + mode input characters output characters + + UC lower case converted lower case converted + to upper case, to upper case, + high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +In addition, each line supports the DATASET option. DATASET, when set, +enables modem control. The default settings are UC mode and DATASET disabled. +Finally, each line supports output logging. The SET MUXLn LOG command enables +logging on a line: SET MUXLn LOG=filename log output of line n to filename diff --git a/HP2100/hp2100_dp.c b/HP2100/hp2100_dp.c index 816aa3c4..66384165 100644 --- a/HP2100/hp2100_dp.c +++ b/HP2100/hp2100_dp.c @@ -205,7 +205,6 @@ extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern int32 sim_switches; -extern UNIT cpu_unit; int32 dp_ctype = 1; /* ctrl type */ int32 dpc_busy = 0; /* cch unit */ diff --git a/HP2100/hp2100_dq.c b/HP2100/hp2100_dq.c index a0b23ddc..dce7361a 100644 --- a/HP2100/hp2100_dq.c +++ b/HP2100/hp2100_dq.c @@ -141,8 +141,6 @@ extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; -extern int32 sim_switches; -extern UNIT cpu_unit; int32 dqc_busy = 0; /* cch xfer */ int32 dqc_cnt = 0; /* check count */ diff --git a/HP2100/hp2100_ds.c b/HP2100/hp2100_ds.c index a769b0ba..10dfabc3 100644 --- a/HP2100/hp2100_ds.c +++ b/HP2100/hp2100_ds.c @@ -342,7 +342,6 @@ static struct drvtyp drv_tab[] = { extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern int32 sim_switches; -extern UNIT cpu_unit; uint32 ds_fifo[DS_FIFO_SIZE] = { 0 }; /* fifo */ uint32 ds_fifo_ip = 0; /* insertion ptr */ diff --git a/HP2100/hp2100_ms.c b/HP2100/hp2100_ms.c index 540ce04f..f6ada819 100644 --- a/HP2100/hp2100_ms.c +++ b/HP2100/hp2100_ms.c @@ -141,7 +141,6 @@ extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern int32 sim_switches; -extern UNIT cpu_unit; extern FILE *sim_deb; int32 ms_ctype = 0; /* ctrl type */ diff --git a/HP2100/hp2100_mux.c b/HP2100/hp2100_mux.c index 78b07e43..3573f910 100644 --- a/HP2100/hp2100_mux.c +++ b/HP2100/hp2100_mux.c @@ -25,6 +25,7 @@ mux,muxl,muxc 12920A terminal multiplexor + 22-Nov-05 RMS Revised for new terminal processing routines 29-Jun-05 RMS Added SET MUXLn DISCONNECT 07-Oct-04 JDB Allow enable/disable from any device 26-Apr-04 RMS Fixed SFS x,C and SFC x,C @@ -56,11 +57,7 @@ #define MUX_LINES 16 /* user lines */ #define MUX_ILINES 5 /* diag rcv only */ -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ -#define UNIT_V_MDM (UNIT_V_UF + 2) /* modem control */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) +#define UNIT_V_MDM (TTUF_V_UF + 0) /* modem control */ #define UNIT_MDM (1 << UNIT_V_MDM) #define MUXU_INIT_POLL 8000 #define MUXL_WAIT 500 @@ -259,29 +256,30 @@ DEVICE muxu_dev = { */ UNIT muxl_unit[] = { - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }, - { UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT } + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT }, + { UDATA (&muxo_svc, TT_MODE_UC, 0), MUXL_WAIT } }; MTAB muxl_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", NULL }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", NULL }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_UC, "UC", "UC", NULL }, + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, { UNIT_MDM, 0, "no dataset", "NODATASET", NULL }, { UNIT_MDM, UNIT_MDM, "dataset", "DATASET", NULL }, { MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT", @@ -552,11 +550,7 @@ for (ln = 0; ln < MUX_LINES; ln++) { /* loop thru lines */ } else { /* normal */ if (mux_rchp[ln]) mux_sta[ln] = mux_sta[ln] | LIU_LOST; - if (muxl_unit[ln].flags & UNIT_UC) { /* cvt to UC? */ - c = c & 0177; - if (islower (c)) c = toupper (c); - } - else c = c & ((muxl_unit[ln].flags & UNIT_8B)? 0377: 0177); + c = sim_tt_inpcvt (c, TT_GET_MODE (muxl_unit[ln].flags)); if (mux_rpar[ln] & OTL_ECHO) { /* echo? */ TMLN *lp = &mux_ldsc[ln]; /* get line */ tmxr_putc_ln (lp, c); /* output char */ @@ -586,18 +580,17 @@ if (mux_ldsc[ln].conn) { /* connected? */ if ((mux_xbuf[ln] & OTL_SYNC) == 0) { /* start bit 0? */ TMLN *lp = &mux_ldsc[ln]; /* get line */ c = mux_xbuf[ln]; /* get char */ - if (muxl_unit[ln].flags & UNIT_UC) { /* cvt to UC? */ - c = c & 0177; - if (islower (c)) c = toupper (c); - } - else c = c & ((muxl_unit[ln].flags & UNIT_8B)? 0377: 0177); + c = sim_tt_outcvt (c, TT_GET_MODE (muxl_unit[ln].flags)); if (mux_xpar[ln] & OTL_DIAG) /* xmt diag? */ mux_diag (mux_xbuf[ln]); /* before munge */ mux_xdon[ln] = 1; /* set done */ - if (!(muxl_unit[ln].flags & UNIT_8B) && /* not transparent? */ - (c != 0x7f) && (c != 0x13) && /* not del, ^S? */ - (c != 0x11) && (c != 0x5)) /* not ^Q, ^E? */ - tmxr_putc_ln (lp, c); /* output char */ + +/* In (default) UC or (new) 7P, all these chars are suppressed automatically */ +/* if ((TT_GET_MODE (muxl_unit[ln].flags) != TT_MODE_8B) && +/* (c != 0x7f) && (c != 0x13) && /* not del, ^S? */ +/* (c != 0x11) && (c != 0x5)) /* not ^Q, ^E? */ + if (c >= 0) /* valid? */ + tmxr_putc_ln (lp, c); /* output char */ tmxr_poll_tx (&mux_desc); /* poll xmt */ } } diff --git a/HP2100/hp2100_stddev.c b/HP2100/hp2100_stddev.c index b133bedc..a1e5fe90 100644 --- a/HP2100/hp2100_stddev.c +++ b/HP2100/hp2100_stddev.c @@ -28,6 +28,7 @@ tty 12531C buffered teleprinter interface clk 12539C time base generator + 22-Nov-05 RMS Revised for new terminal processing routines 13-Sep-04 JDB Added paper tape loop mode, DIAG/READER modifiers to PTR Added PV_LEFT to PTR TRLLIM register Modified CLK to permit disable @@ -96,12 +97,8 @@ #define FULL_SET 0xFFFFFFFF #define CNTL_SET (BEL_FLAG | BS_FLAG | HT_FLAG | LF_FLAG | CR_FLAG) -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ -#define UNIT_V_DIAG (UNIT_V_UF + 2) /* diag mode */ -#define UNIT_V_AUTOLF (UNIT_V_UF + 3) /* auto linefeed */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) +#define UNIT_V_DIAG (TTUF_V_UF + 0) /* diag mode */ +#define UNIT_V_AUTOLF (TTUF_V_UF + 1) /* auto linefeed */ #define UNIT_DIAG (1 << UNIT_V_DIAG) #define UNIT_AUTOLF (1 << UNIT_V_AUTOLF) @@ -117,7 +114,6 @@ extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; -extern UNIT cpu_unit; int32 ptr_stopioe = 0; /* stop on error */ int32 ptr_trlcnt = 0; /* trailer counter */ @@ -157,6 +153,7 @@ t_stat tti_svc (UNIT *uptr); t_stat tto_svc (UNIT *uptr); t_stat tty_reset (DEVICE *dptr); t_stat tty_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat tty_set_alf (UNIT *uptr, int32 val, char *cptr, void *desc); int32 clkio (int32 inst, int32 IR, int32 dat); t_stat clk_svc (UNIT *uptr); t_stat clk_reset (DEVICE *dptr); @@ -268,9 +265,9 @@ DEVICE ptp_dev = { DIB tty_dib = { TTY, 0, 0, 0, 0, 0, &ttyio }; UNIT tty_unit[] = { - { UDATA (&tti_svc, UNIT_UC, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&tto_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_8B, 0), SERIAL_OUT_WAIT } + { UDATA (&tti_svc, TT_MODE_UC, 0), KBD_POLL_WAIT }, + { UDATA (&tto_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }, + { UDATA (&tto_svc, UNIT_SEQ+UNIT_ATTABLE+TT_MODE_8B, 0), SERIAL_OUT_WAIT } }; REG tty_reg[] = { @@ -296,16 +293,12 @@ REG tty_reg[] = { }; MTAB tty_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &tty_set_opt, - NULL, ((void *) (UNIT_UC + UNIT_8B)) }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", &tty_set_opt, - NULL, ((void *) (UNIT_UC + UNIT_8B)) }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &tty_set_opt, - NULL, ((void *) (UNIT_UC + UNIT_8B)) }, - { UNIT_AUTOLF, UNIT_AUTOLF, "autolf", "AUTOLF", &tty_set_opt, - NULL, ((void *) UNIT_AUTOLF) }, - { UNIT_AUTOLF, 0 , NULL, "NOAUTOLF", &tty_set_opt, - NULL, ((void *) UNIT_AUTOLF) }, + { TT_MODE, TT_MODE_UC, "UC", "UC", &tty_set_opt }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_opt }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_opt }, + { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_opt }, + { UNIT_AUTOLF, UNIT_AUTOLF, "autolf", "AUTOLF", &tty_set_alf }, + { UNIT_AUTOLF, 0 , NULL, "NOAUTOLF", &tty_set_alf }, { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &tty_dev }, { 0 } @@ -699,7 +692,7 @@ t_stat tti_svc (UNIT *uptr) int32 c, dev; dev = tty_dib.devno; /* get device no */ -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */ +sim_activate (uptr, uptr->wait); /* continue poll */ tty_shin = 0377; /* assume inactive */ if (tty_lf) { /* auto lf pending? */ c = 012; /* force lf */ @@ -708,16 +701,12 @@ if (tty_lf) { /* auto lf pending? */ else { if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ if (c & SCPE_BREAK) c = 0; /* break? */ - else if (tty_unit[TTI].flags & UNIT_UC) { /* UC only? */ - c = c & 0177; - if (islower (c)) c = toupper (c); - } - else c = c & ((tty_unit[TTI].flags & UNIT_8B)? 0377: 0177); + else c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags)); tty_lf = ((c & 0177) == 015) && (uptr->flags & UNIT_AUTOLF); } if (tty_mode & TM_KBD) { /* keyboard enabled? */ tty_buf = c; /* put char in buf */ - tty_unit[TTI].pos = tty_unit[TTI].pos + 1; + uptr->pos = uptr->pos + 1; setFSR (dev); /* set flag */ if (c) { tto_out (c); /* echo? */ @@ -750,12 +739,8 @@ t_stat tto_out (int32 c) t_stat r; if (tty_mode & TM_PRI) { /* printing? */ - if (tty_unit[TTO].flags & UNIT_UC) { /* UC only? */ - c = c & 0177; - if (islower (c)) c = toupper (c); - } - else c = c & ((tty_unit[TTO].flags & UNIT_8B)? 0377: 0177); - if ((c > 31) || (CHAR_FLAG (c) & tty_cntlprt)) { /* normal, ctrl? */ + c = sim_tt_outcvt (c, TT_GET_MODE (tty_unit[TTO].flags)); + if (c >= 0) { /* valid? */ if (r = sim_putchar_s (c)) return r; /* output char */ tty_unit[TTO].pos = tty_unit[TTO].pos + 1; } @@ -796,13 +781,19 @@ return SCPE_OK; t_stat tty_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc) { int32 u = uptr - tty_dev.units; -int32 mask = (int32) desc; -if (u > 1) return SCPE_NOFNC; -tty_unit[TTI].flags = (tty_unit[TTI].flags & ~mask) | val; -tty_unit[TTO].flags = (tty_unit[TTO].flags & ~mask) | val; -if (val == UNIT_8B) tty_cntlprt = FULL_SET; -else tty_cntlprt = tty_cntlset; +if (u > TTO) return SCPE_NOFNC; +tty_unit[TTO].flags = (tty_unit[TTO].flags & ~TT_MODE) | val; +if (val == TT_MODE_7P) val = TT_MODE_7B; +tty_unit[TTI].flags = (tty_unit[TTI].flags & ~TT_MODE) | val; +return SCPE_OK; +} + +t_stat tty_set_alf (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 u = uptr - tty_dev.units; + +if (u != TTI) return SCPE_NOFNC; return SCPE_OK; } diff --git a/I1401/i1401_cpu.c b/I1401/i1401_cpu.c index 05f6b1cf..16ede910 100644 --- a/I1401/i1401_cpu.c +++ b/I1401/i1401_cpu.c @@ -24,7 +24,7 @@ in this Software without prior written authorization from Robert M Supnik. 22-Sep-05 RMS Fixed declarations (from Sterling Garwood) - 01-Sep-05 RMS Removed error stops in MCE + 01-Sep-05 RMS Removed error stops in MCE 16-Aug-05 RMS Fixed C++ declaration and cast problems 02-Jun-05 RMS Fixed SSB-SSG clearing on RESET (reported by Ralph Reinke) diff --git a/I1401/i1401_doc.txt b/I1401/i1401_doc.txt index 8078d01a..0951979a 100644 --- a/I1401/i1401_doc.txt +++ b/I1401/i1401_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: IBM 1401 Simulator Usage -Date: 01-Sep-05 +Date: 01-Nov-05 COPYRIGHT NOTICE @@ -182,6 +182,16 @@ This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands: The maximum length for the history is 65536 entries. +The original character encoding used by the 1401 simulator was revised to be +compatible with the coding used by Paul Pierce's 709X and 1401 simulators. +The user can select between the original (old) and compatible (new) encodings, +as follows: + + SET CPU OLDCONVERSIONS use original character encoding + SET CPU NEWCONVERSIONS use compatible character encoding + +NEWCONVERSIONS is the default. + 2.2 1402 Card Reader/Punch (CDR, CDP, STKR) The IBM 1402 card/reader punch is simulated as three independent devices: @@ -322,7 +332,6 @@ and Fortran (1403 H chain) character sets for output: The business character set is the default. - The inquiry terminal registers are: name size comments diff --git a/I1401/i1401_mt.c b/I1401/i1401_mt.c index 63ddfe59..410580d3 100644 --- a/I1401/i1401_mt.c +++ b/I1401/i1401_mt.c @@ -273,7 +273,7 @@ switch (mod) { if (M[BS] != (BCD_GRPMRK + WM)) { /* not GM+WM at end? */ if (flag == MD_WM) M[BS] = BCD_GRPMRK; /* LCA: clear WM */ else M[BS] = (M[BS] & WM) | BCD_GRPMRK; /* MCW: save WM */ - } + } if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, " to %d, stopped by EOR\n", BS); BS++; /* adv BS */ diff --git a/Interdata/id_doc.txt b/Interdata/id_doc.txt index dafbd71f..55f72efc 100644 --- a/Interdata/id_doc.txt +++ b/Interdata/id_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: Interdata 16b/32b Simulator Usage -Date: 01-Jul-2005 +Date: 01-Dec-2005 COPYRIGHT NOTICE @@ -373,12 +373,24 @@ Error handling is as follows: The Teletype keyboard (TT0) reads from the console keyboard; the Teletype printer (TT1) writes to the simulator console window. -The Teletype units (TT0, TT1) can be set to one of three modes: -KSR, 7B, or 8B. In KSR mode, lower case input and output characters -are automatically converted to upper case, and the high order bit is -forced to one on input. In 7B mode, input and output characters are -masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either unit changes both. The default mode is KSR. +The Teletype units (TT0, TT1) can be set to one of four modes, +KSR, 7P, 7B, or 8B: + + mode input characters output characters + + KSR lower case converted lower case converted + to upper case, to upper case, + high-order bit set high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +Changing the mode of either unit changes both. The default mode +is KSR. The Teletype has a BREAK key, which is not present on today's keyboards. To simulate pressing the break key, stop the simulator @@ -435,12 +447,24 @@ Otherwise, a device number conflict occurs. The PASLA keyboard (TTP0) reads from the console keyboard; the PALSA printer (TTP1) writes to the simulator console window. -The PASLA units (TTP0, TTP1) can be set to one of three modes: -UC, 7B, or 8B. In UC mode, lower case input and output characters -are automatically converted to upper case. In 7B mode, input and -output characters are masked to 7 bits. In 8B mode, characters -are not modified. Changing the mode of either unit changes both. -The default mode is 7B. +The PASLA units (TTP0, TTP1) can be set to one of four modes, +UC, 7P, 7B, or 8B: + + mode input characters output characters + + UC lower case converted lower case converted + to upper case, to upper case, + high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +Changing the mode of either unit changes both. The default mode +is 7B. To simulate pressing the break key, stop the simulator and use the command: @@ -619,14 +643,26 @@ user-specified port. The ATTACH command specifies the port to be used: where port is a decimal number between 1 and 65535 that is not being used for other TCP/IP activities. -Each line (each unit of PASL) can be set to one of three modes: UC, 7B, -or 8B. In UC mode, lower case input and output characters are converted -automatically to upper case. In 7B mode, input and output characters are -masked to 7 bits. In 8B mode, characters are not modified. The default -mode is UC. Each line (each unit of PASL) can also be set for modem -control with the command SET PASLn DATASET. The defaults are 7b mode -and DATASET disabled. Finally, each line supports output logging. -The SET PASLn LOG command enables logging on a line: +Each line (each unit of PASL) can be set to one of four modes, UC, 7P, +7B, or 8B: + + mode input characters output characters + + UC lower case converted lower case converted + to upper case, to upper case, + high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +Each line (each unit of PASL) can also be set for modem control with +the command SET PASLn DATASET. The defaults are 7b mode and DATASET +disabled. Finally, each line supports output logging. The SET +PASLn LOG command enables logging on a line: SET PASLn LOG=filename log output of line n to filename diff --git a/Interdata/id_pas.c b/Interdata/id_pas.c index 739c1769..6b73c33c 100644 --- a/Interdata/id_pas.c +++ b/Interdata/id_pas.c @@ -25,6 +25,7 @@ pas Programmable asynchronous line adapter(s) + 22-Nov-05 RMS Revised for new terminal processing routines 29-Jun-05 RMS Added SET PASLn DISCONNECT 21-Jun-05 RMS Fixed bug in SHOW CONN/STATS 05-Jan-04 RMS Revised for tmxr library changes @@ -45,11 +46,7 @@ #define PAS_LINES 32 -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ -#define UNIT_V_MDM (UNIT_V_UF + 2) /* modem control */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) +#define UNIT_V_MDM (TTUF_V_UF + 0) /* modem control */ #define UNIT_MDM (1 << UNIT_V_MDM) #define PAS_INIT_POLL 8000 @@ -214,9 +211,10 @@ UNIT pasl_unit[] = { }; MTAB pasl_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", NULL }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", NULL }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_UC, "UC", "UC", NULL }, + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, { UNIT_MDM, 0, "no dataset", "NODATASET", NULL }, { UNIT_MDM, UNIT_MDM, "dataset", "DATASET", NULL }, { MTAB_XTD|MTAB_VDV, 0, NULL, "DISCONNECT", @@ -341,18 +339,15 @@ for (ln = 0; ln < PAS_ENAB; ln++) { /* loop thru lines */ } else { /* normal */ out = c & 0x7F; /* echo is 7b */ - if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */ - c = c & 0xFF; - else { /* UC or 7b */ - if ((pasl_unit[ln].flags & UNIT_UC) && islower (out)) - out = toupper (out); /* cvt to UC */ - c = pas_par (pas_cmd[ln], out); /* apply parity */ - } + c = sim_tt_inpcvt (c, TT_GET_MODE (pasl_unit[ln].flags)); + if (TT_GET_MODE (pasl_unit[ln].flags) != TT_MODE_8B) + c = pas_par (pas_cmd[ln], c); /* apply parity */ pas_rbuf[ln] = c; /* save char */ pas_rchp[ln] = 1; /* char pending */ if ((pas_cmd[ln] & CMD_ECHO) && pas_ldsc[ln].xmte) { TMLN *lp = &pas_ldsc[ln]; /* get line */ - tmxr_putc_ln (lp, out); /* output char */ + out = sim_tt_outcvt (out, TT_GET_MODE (pasl_unit[ln].flags)); + if (out >= 0) tmxr_putc_ln (lp, out); /* output char */ tmxr_poll_tx (&pas_desc); /* poll xmt */ } } /* end else normal */ @@ -376,14 +371,12 @@ uint32 ln = uptr - pasl_unit; /* line # */ if (pas_ldsc[ln].conn) { /* connected? */ if (pas_ldsc[ln].xmte) { /* xmt enabled? */ TMLN *lp = &pas_ldsc[ln]; /* get line */ - if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */ + if (TT_GET_MODE (pasl_unit[ln].flags) == TT_MODE_8B) c = pas_par (pas_cmd[ln], pas_xbuf[ln]); /* apply parity */ - else { /* UC or 7b */ - c = pas_xbuf[ln] & 0x7F; /* mask char */ - if ((pasl_unit[ln].flags & UNIT_UC) && islower (c)) - c = toupper (c); /* cvt to UC */ + else c = sim_tt_outcvt (pas_xbuf[ln], TT_GET_MODE (pasl_unit[ln].flags)); + if (c >= 0) { + tmxr_putc_ln (lp, c); /* output char */ } - tmxr_putc_ln (lp, c); /* output char */ tmxr_poll_tx (&pas_desc); /* poll xmt */ } else { /* buf full */ diff --git a/Interdata/id_tt.c b/Interdata/id_tt.c index 8dbda083..08583542 100644 --- a/Interdata/id_tt.c +++ b/Interdata/id_tt.c @@ -25,6 +25,7 @@ tt console + 22-Nov-05 RMS Revised for new terminal processing routines 29-Dec-03 RMS Added support for console backpressure 25-Apr-03 RMS Revised for extended file support 11-Jan-03 RMS Added TTP support @@ -34,11 +35,6 @@ #include "id_defs.h" #include -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) - /* Device definitions */ #define TTI 0 @@ -78,8 +74,8 @@ t_stat tt_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc); DIB tt_dib = { d_TT, -1, v_TT, NULL, &tt, NULL }; UNIT tt_unit[] = { - { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT } + { UDATA (&tti_svc, TT_MODE_KSR, 0), KBD_POLL_WAIT }, + { UDATA (&tto_svc, TT_MODE_KSR, 0), SERIAL_OUT_WAIT } }; REG tt_reg[] = { @@ -101,9 +97,10 @@ REG tt_reg[] = { }; MTAB tt_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tt_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tt_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tt_set_mode }, + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tt_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tt_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tt_set_mode }, + { TT_MODE, TT_MODE_7P, "7p", "7P", &tt_set_mode }, { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED", &tt_set_enbdis, NULL, NULL }, { MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED", @@ -192,15 +189,14 @@ if (temp & SCPE_BREAK) { /* break? */ tt_sta = tt_sta | STA_BRK; /* set status */ uptr->buf = 0; /* no character */ } -else if (uptr->flags & UNIT_KSR) { /* KSR mode? */ - if (islower (out)) out = toupper (out); /* cvt to UC */ - uptr->buf = out | 0x80; /* set high bit */ - } -else uptr->buf = temp & ((tt_unit[TTI].flags & UNIT_8B)? 0xFF: 0x7F); +else uptr->buf = sim_tt_inpcvt (temp, TT_GET_MODE (uptr->flags) | TTUF_KSR); uptr->pos = uptr->pos + 1; /* incr count */ if (!tt_fdpx) { /* half duplex? */ - if (out) sim_putchar (out); /* write char */ - tt_unit[TTO].pos = tt_unit[TTO].pos + 1; + out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags)); + if (out >= 0) { /* valid echo? */ + sim_putchar (out); /* write char */ + tt_unit[TTO].pos = tt_unit[TTO].pos + 1; + } } return SCPE_OK; } @@ -210,13 +206,8 @@ t_stat tto_svc (UNIT *uptr) int32 ch; t_stat r; -if (uptr->flags & UNIT_KSR) { /* KSR mode? */ - ch = uptr->buf & 0x7F; /* mask to 7b */ - if (islower (ch)) ch = toupper (ch); /* cvt to UC */ - } -else ch = uptr->buf & ((tt_unit[TTO].flags & UNIT_8B)? 0xFF: 0x7F); -if ((uptr->flags & UNIT_8B) || /* KSR or 7b? */ - ((ch != 0) && (ch != 0x7F))) { /* supr NULL, DEL */ +ch = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags)); +if (ch >= 0) { if ((r = sim_putchar_s (ch)) != SCPE_OK) { /* output; error? */ sim_activate (uptr, uptr->wait); /* try again */ return ((r == SCPE_STALL)? SCPE_OK: r); @@ -250,8 +241,9 @@ return SCPE_OK; t_stat tt_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { -tt_unit[TTI].flags = (tt_unit[TTI].flags & ~(UNIT_KSR | UNIT_8B)) | val; -tt_unit[TTO].flags = (tt_unit[TTO].flags & ~(UNIT_KSR | UNIT_8B)) | val; +tt_unit[TTO].flags = (tt_unit[TTO].flags & ~TT_MODE) | val; +if (val == TT_MODE_7P) val = TT_MODE_7B; +tt_unit[TTI].flags = (tt_unit[TTI].flags & ~TT_MODE) | val; return SCPE_OK; } diff --git a/Interdata/id_ttp.c b/Interdata/id_ttp.c index 6b9c9d3c..ecd68130 100644 --- a/Interdata/id_ttp.c +++ b/Interdata/id_ttp.c @@ -25,6 +25,7 @@ ttp console (on PAS) + 22-Nov-05 RMS Revised for new terminal processing routines 29-Dec-03 RMS Added support for console backpressure 25-Apr-03 RMS Revised for extended file support */ @@ -32,11 +33,6 @@ #include "id_defs.h" #include -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) - #define TTI 0 #define TTO 1 @@ -103,9 +99,10 @@ REG ttp_reg[] = { }; MTAB ttp_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &ttp_set_mode }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", &ttp_set_mode }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &ttp_set_mode }, + { TT_MODE, TT_MODE_UC, "UC", "UC", &ttp_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &ttp_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &ttp_set_mode }, + { TT_MODE, TT_MODE_7P, "7p", "7P", &ttp_set_mode }, { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED", &ttp_set_enbdis, NULL, NULL }, { MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED", @@ -188,18 +185,17 @@ if (c & SCPE_BREAK) { /* break? */ ttp_sta = ttp_sta | STA_FR; /* framing error */ uptr->buf = 0; /* no character */ } -else { c = c & 0xFF; /* char is 8b */ +else { out = c & 0x7F; /* echo is 7b */ - if (!(uptr->flags & UNIT_8B)) { /* not 8b? */ - if ((uptr->flags & UNIT_UC) && islower (out)) - out = toupper (out); /* cvt to UC */ - c = pas_par (ttp_cmd, out); /* apply parity */ - } + c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags)); + if (TT_GET_MODE (uptr->flags) != TT_MODE_8B) /* not 8b mode? */ + c = pas_par (ttp_cmd, c); /* apply parity */ uptr->buf = c; /* save char */ uptr->pos = uptr->pos + 1; /* incr count */ ttp_kchp = 1; /* char pending */ if (ttp_cmd & CMD_ECHO) { - sim_putchar (out); + out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags)); + if (c >= 0) sim_putchar (out); ttp_unit[TTO].pos = ttp_unit[TTO].pos + 1; } } @@ -211,15 +207,10 @@ t_stat ttpo_svc (UNIT *uptr) int32 c; t_stat r; -if (uptr->flags & UNIT_8B) /* 8b? */ +if (TT_GET_MODE (uptr->flags) == TT_MODE_8B) /* 8b? */ c = pas_par (ttp_cmd, uptr->buf); /* apply parity */ -else { - c = uptr->buf & 0x7F; /* mask char */ - if ((uptr->flags & UNIT_UC) && islower (c)) - c = toupper (c); /* cvt to UC */ - } -if ((uptr->flags & UNIT_8B) || /* UC or 7b? */ - ((c != 0) && (c != 0x7F))){ /* supr NULL, DEL */ +else c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags)); +if (c >= 0) { if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ sim_activate (uptr, uptr->wait); /* try again */ return ((r == SCPE_STALL)? SCPE_OK: r); @@ -253,8 +244,9 @@ return SCPE_OK; t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { -ttp_unit[TTI].flags = (ttp_unit[TTI].flags & ~(UNIT_UC | UNIT_8B)) | val; -ttp_unit[TTO].flags = (ttp_unit[TTO].flags & ~(UNIT_UC | UNIT_8B)) | val; +ttp_unit[TTO].flags = (ttp_unit[TTO].flags & ~TT_MODE) | val; +if (val == TT_MODE_7P) val = TT_MODE_7B; +ttp_unit[TTI].flags = (ttp_unit[TTI].flags & ~TT_MODE) | val; return SCPE_OK; } diff --git a/PDP10/pdp10_doc.txt b/PDP10/pdp10_doc.txt index 7b2e9ddb..559c5a49 100644 --- a/PDP10/pdp10_doc.txt +++ b/PDP10/pdp10_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: PDP-10 Simulator Usage -Date: 01-Jul-2005 +Date: 01-Dec-2005 COPYRIGHT NOTICE @@ -338,12 +338,17 @@ are supported. The number of lines can be changed with the command The line count must be a multiple of 8, with a maximum of 32. -The DZ11 can support 8-bit input and output of characters. 8-bit -output is incompatible with TOPS-20 and is off by default. The command +The DZ11 supports three character processing modes, 7P, 7B, and 8B: - SET DZ 8B + mode input characters output characters -allows output characters to be 8 bits. + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default is 7B, for compatability with TOPS-20. The DZ11 supports logging on a per-line basis. The command diff --git a/PDP10/pdp10_rp.c b/PDP10/pdp10_rp.c index 344668fc..40763dde 100644 --- a/PDP10/pdp10_rp.c +++ b/PDP10/pdp10_rp.c @@ -25,6 +25,7 @@ rp RH/RP/RM moving head disks + 12-Nov-05 RMS Fixed DCLR not to clear drive address 07-Jul-05 RMS Removed extraneous externs 18-Mar-05 RMS Added attached test to detach routine 20-Sep-04 RMS Fixed bugs in replicated state, RP vs RM accuracy @@ -765,8 +766,11 @@ dc = rpdc[drv]; /* assume seek, sch */ switch (fnc) { /* case on function */ case FNC_DCLR: /* drive clear */ - rpda[drv] = 0; /* clear disk addr */ rper1[drv] = rper2[drv] = rper3[drv] = 0; /* clear errors */ + rpec2[drv] = 0; /* clear EC2 */ + if (drv_tab[dtype].ctrl == MBA_RM_CTRL) /* RM? */ + rpmr[drv] = 0; /* clear maint */ + else rpec1[drv] = 0; /* RP, clear EC1 */ case FNC_NOP: /* no operation */ case FNC_RELEASE: /* port release */ return; diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h index 294b90fd..98bb87f2 100644 --- a/PDP11/pdp11_defs.h +++ b/PDP11/pdp11_defs.h @@ -780,6 +780,7 @@ int32 mba_get_csr (uint32 mbus); void mba_upd_ata (uint32 mbus, uint32 val); void mba_set_exc (uint32 mbus); void mba_set_don (uint32 mbus); +void mba_set_enbdis (uint32 mb, t_bool dis); t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc); #endif diff --git a/PDP11/pdp11_doc.txt b/PDP11/pdp11_doc.txt index 1fc8dae5..2605a126 100644 --- a/PDP11/pdp11_doc.txt +++ b/PDP11/pdp11_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: PDP-11 Simulator Usage -Date: 01-Jul-2005 +Date: 01-Dec-2005 COPYRIGHT NOTICE @@ -486,10 +486,18 @@ Error handling is as follows: 2.3.3 DL11 Terminal Input (TTI) -The terminal interfaces (TTI, TTO) can be set to one of two modes: -7B or 8B. In 7B mode, input and output characters are masked to 7 -bits. In 8B mode, characters are not modified. Changing the mode -of either interface changes both. The default mode is 8B. +The terminal interfaces (TTI, TTO) can be set to one of three modes, +7P, 7B or 8B: + + mode input characters output characters + + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default mode is 8B. The terminal input (TTI) polls the console keyboard for input. It implements these registers: @@ -1310,12 +1318,17 @@ are supported. The number of lines can be changed with the command The line count must be a multiple of 8, with a maximum of 32. -The DZ11 supports 8-bit input and output of characters. 8-bit output -may be incompatible with certain operating systems. The command +The DZ11 supports three character processing modes, 7P, 7B, and 8B: - SET DZ 7B + mode input characters output characters -forces output characters (only) to be masked to 7 bits. + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default is 8B. The DZ11 supports logging on a per-line basis. The command diff --git a/PDP11/pdp11_dz.c b/PDP11/pdp11_dz.c index 865e4fca..355e9364 100644 --- a/PDP11/pdp11_dz.c +++ b/PDP11/pdp11_dz.c @@ -25,6 +25,7 @@ dz DZ11 terminal multiplexor + 22-Nov-05 RMS Revised for new terminal processing routines 07-Jul-05 RMS Removed extraneous externs 15-Jun-05 RMS Revised for new autoconfigure interface 04-Apr-04 RMS Added per-line logging @@ -61,12 +62,12 @@ extern int32 int_req; #elif defined (VM_VAX) /* VAX version */ #include "vax_defs.h" -#define DZ_8B_DFLT UNIT_8B +#define DZ_8B_DFLT TT_MODE_8B extern int32 int_req[IPL_HLVL]; #else /* PDP-11 version */ #include "pdp11_defs.h" -#define DZ_8B_DFLT UNIT_8B +#define DZ_8B_DFLT TT_MODE_8B extern int32 int_req[IPL_HLVL]; #endif @@ -80,9 +81,6 @@ extern int32 int_req[IPL_HLVL]; #define DZ_LINES 8 #endif -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8b output */ -#define UNIT_8B (1 << UNIT_V_8B) - #define DZ_MNOMASK (DZ_MUXES - 1) /* mask for mux no */ #define DZ_LNOMASK (DZ_LINES - 1) /* mask for lineno */ #define DZ_LMASK ((1 << DZ_LINES) - 1) /* mask of lines */ @@ -217,8 +215,9 @@ REG dz_reg[] = { }; MTAB dz_mod[] = { - { UNIT_8B, 0, "7b", "7B", NULL }, - { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", &tmxr_dscln, NULL, &dz_desc }, { UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &dz_summ }, @@ -295,7 +294,7 @@ return SCPE_OK; t_stat dz_wr (int32 data, int32 PA, int32 access) { int32 dz = ((PA - dz_dib.ba) >> 3) & DZ_MNOMASK; /* get mux num */ -int32 i, line; +int32 i, c, line; TMLN *lp; switch ((PA >> 1) & 03) { /* case on PA<2:1> */ @@ -364,8 +363,8 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ if (dz_csr[dz] & CSR_MSE) { /* enabled? */ line = (dz * DZ_LINES) + CSR_GETTL (dz_csr[dz]); lp = &dz_ldsc[line]; /* get line desc */ - tmxr_putc_ln (lp, dz_tdr[dz] & /* store char */ - ((dz_unit.flags & UNIT_8B)? 0377: 0177)); + c = sim_tt_outcvt (dz_tdr[dz], TT_GET_MODE (dz_unit.flags)); + if (c >= 0) tmxr_putc_ln (lp, c); /* store char */ tmxr_poll_tx (&dz_desc); /* poll output */ dz_update_xmti (); /* update int */ } diff --git a/PDP11/pdp11_hk.c b/PDP11/pdp11_hk.c index e612be20..bc55d8cc 100644 --- a/PDP11/pdp11_hk.c +++ b/PDP11/pdp11_hk.c @@ -25,6 +25,8 @@ hk RK611/RK06/RK07 disk + 17-Nov-05 RMS Removed unused variable + 13-Nov-05 RMS Fixed overlapped seek interaction with NOP, DCLR, PACK 16-Aug-05 RMS Fixed C++ declaration and cast problems 07-Jul-05 RMS Removed extraneous externs 18-Mar-05 RMS Added attached test to detach routine @@ -126,7 +128,7 @@ extern uint16 *M; #define CS1_DI 0040000 /* drive intr */ #define CS1_ERR 0100000 /* error */ #define CS1_CCLR 0100000 /* ctrl clear */ -#define CS1_RW (CS1_DT|CS1_UAE|CS1_IE|CS1_SPA|CS1_FNC|CS1_GO) +#define CS1_RW (CS1_DT|CS1_UAE|CS1_IE|CS1_SPA|CS1_FNC) #define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) #define GET_UAE(x) (((x) >> CS1_V_UAE) & CS1_M_UAE) #define PUT_UAE(x,n) (((x) & ~ CS1_UAE) | (((n) << CS1_V_UAE) & CS1_UAE)) @@ -329,10 +331,10 @@ int32 hkmr2 = 0; int32 hkmr3 = 0; int32 hkdc = 0; /* cylinder */ int32 hkspr = 0; /* spare */ -int32 hk_stopioe = 1; /* stop on error */ int32 hk_cwait = 5; /* command time */ int32 hk_swait = 10; /* seek time */ int32 hk_rwait = 10; /* rotate time */ +int32 hk_min2wait = 300; /* min time to 2nd int */ int16 hkdb[3] = { 0 }; /* data buffer silo */ int16 hk_off[HK_NUMDR] = { 0 }; /* saved offset */ int16 hk_dif[HK_NUMDR] = { 0 }; /* cylinder diff */ @@ -409,8 +411,10 @@ REG hk_reg[] = { { FLDATA (ERR, hkcs1, CSR_V_ERR) }, { FLDATA (DONE, hkcs1, CSR_V_DONE) }, { FLDATA (IE, hkcs1, CSR_V_IE) }, + { DRDATA (CTIME, hk_cwait, 24), REG_NZ + PV_LEFT }, { DRDATA (STIME, hk_swait, 24), REG_NZ + PV_LEFT }, { DRDATA (RTIME, hk_rwait, 24), REG_NZ + PV_LEFT }, + { DRDATA (MIN2TIME, hk_min2wait, 24), REG_NZ + PV_LEFT + REG_HRO }, { URDATA (FNC, hk_unit[0].FNC, DEV_RDX, 5, 0, HK_NUMDR, REG_HRO) }, { URDATA (CYL, hk_unit[0].CYL, DEV_RDX, 10, 0, @@ -419,7 +423,6 @@ REG hk_reg[] = { { BRDATA (CYLDIF, hk_dif, DEV_RDX, 16, HK_NUMDR), REG_HRO }, { URDATA (CAPAC, hk_unit[0].capac, 10, T_ADDR_W, 0, HK_NUMDR, PV_LEFT | REG_HRO) }, - { FLDATA (STOP_IOE, hk_stopioe, 0) }, { GRDATA (DEVADDR, hk_dib.ba, DEV_RDX, 32, 0), REG_HRO }, { GRDATA (DEVVEC, hk_dib.vec, DEV_RDX, 16, 0), REG_HRO }, { NULL } @@ -587,10 +590,8 @@ switch (j) { /* decode PA<4:1> */ else CLR_INT (HK); /* no, clr intr */ hkcs1 = (hkcs1 & ~CS1_RW) | (data & CS1_RW); /* merge data */ if (SC02C) hkspr = (hkspr & ~CS1_M_UAE) | GET_UAE (hkcs1); - if (hkcs1 & CS1_GO) { /* go? */ - if (hkcs1 & CS1_ERR) hkcs1 = hkcs1 & ~CS1_GO; - else hk_go (drv); - } + if ((data & CS1_GO) && !(hkcs1 & CS1_ERR)) /* go? */ + hk_go (drv); break; case 001: /* HKWC */ @@ -640,7 +641,7 @@ update_hkcs (0, drv); /* update status */ return SCPE_OK; } -/* Initiate operation - unit not busy, function set */ +/* Initiate operation - go set, not previously set */ void hk_go (int32 drv) { @@ -662,7 +663,7 @@ static int32 fnc_cyl[16] = { fnc = GET_FNC (hkcs1); if (DEBUG_PRS (hk_dev)) fprintf (sim_deb, - ">>HK%d: fnc=%o, ds=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", + ">>HK%d go: fnc=%o, ds=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", drv, fnc, hkds[drv], hkdc, hkda, hkba, hkwc); uptr = hk_dev.units + drv; /* get unit */ if (fnc != FNC_NOP) hkmr = hkmr & ~MR_MS; /* !nop, clr msg sel */ @@ -680,34 +681,40 @@ if (fnc_nxf[fnc] && ((hkds[drv] & DS_VV) == 0)) { /* need vol valid? */ hk_cmderr (ER_NXF, drv); /* non exec func */ return; } -if (fnc_att[fnc] && ((uptr->flags & UNIT_ATT) == 0)) { /* need attached? */ +if (fnc_att[fnc] && !(uptr->flags & UNIT_ATT)) { /* need attached? */ hk_cmderr (ER_UNS, drv); /* unsafe */ return; } -if (fnc_rdy[fnc] && sim_is_active (uptr)) { /* need inactive? */ - hkcs1 = (hkcs1 | CS1_DONE) & ~CS1_GO; /* ignore if busy */ - return; - } +if (fnc_rdy[fnc] && sim_is_active (uptr)) return; /* need inactive? */ if (fnc_cyl[fnc] && /* need valid cyl */ ((GET_CY (hkdc) >= HK_CYL (uptr)) || /* bad cylinder */ (GET_SF (hkda) >= HK_NUMSF) || /* bad surface */ (GET_SC (hkda) >= HK_NUMSC))) { /* or bad sector? */ - hk_cmderr (ER_IAE, drv); /* illegal addr */ + hk_cmderr (ER_IAE, drv); /* illegal addr */ return; } -hkcs1 = hkcs1 & ~CS1_DONE; /* clear done */ -hkds[drv] = hkds[drv] & ~DS_ATA; /* clear attention */ -uptr->FNC = fnc; /* save function */ +hkcs1 = (hkcs1 | CS1_GO) & ~CS1_DONE; /* set go, clear done */ switch (fnc) { /* case on function */ +/* Instantaneous functions (unit may be busy, can't schedule thread) */ + + case FNC_DCLR: /* drive clear */ + hkds[drv] &= ~DS_ATA; /* clr ATA */ + hker[drv] = 0; /* clear errors */ + case FNC_NOP: /* no operation */ + update_hkcs (CS1_DONE, drv); /* done */ + break; + case FNC_PACK: /* pack acknowledge */ + hkds[drv] = hkds[drv] | DS_VV; /* set volume valid */ + update_hkcs (CS1_DONE, drv); /* done */ + break; + /* "Fast functions" finish in less than 15 usec */ - case FNC_NOP: /* no operation */ - case FNC_DCLR: /* drive clear */ case FNC_START: /* start spindle */ case FNC_UNLOAD: /* unload */ - case FNC_PACK: /* pack acknowledge */ + uptr->FNC = fnc; /* save function */ sim_activate (uptr, hk_cwait); /* schedule */ return; @@ -718,6 +725,7 @@ switch (fnc) { /* case on function */ case FNC_RECAL: /* recalibrate */ case FNC_SEEK: /* seek */ hkds[drv] = hkds[drv] | DS_PIP; /* set positioning */ + uptr->FNC = fnc; /* save function */ sim_activate (uptr, hk_cwait); /* schedule */ return; @@ -732,6 +740,7 @@ switch (fnc) { /* case on function */ hk_dif[drv] = hkdc - uptr->CYL; /* cyl diff */ t = abs (hk_dif[drv]); /* |cyl diff| */ sim_activate (uptr, hk_rwait + (hk_swait * t)); /* Schedule */ + uptr->FNC = fnc; /* save function */ uptr->CYL = hkdc; /* update cyl */ return; @@ -751,32 +760,21 @@ return; t_stat hk_svc (UNIT *uptr) { -int32 i, t, dc, drv, fnc, err; +int32 i, t, dc, fnc, err; int32 wc, awc, da; -uint32 ba; +uint32 drv, ba; uint16 comp; -drv = (int32) (uptr - hk_dev.units); /* get drv number */ +drv = (uint32) (uptr - hk_dev.units); /* get drv number */ fnc = uptr->FNC & CS1_M_FNC; /* get function */ switch (fnc) { /* case on function */ -/* Fast commands and other NOPs - start spindle only provides one interrupt +/* Fast commands - start spindle only provides one interrupt because ATTACH implicitly spins up the drive */ - case FNC_DCLR: /* drive clear */ - hker[drv] = 0; /* clear errors */ - update_hkcs (CS1_DONE, drv); /* done */ - break; - - case FNC_PACK: /* pack acknowledge */ - hkds[drv] = hkds[drv] | DS_VV; /* set volume valid */ - update_hkcs (CS1_DONE, drv); /* done */ - break; - case FNC_UNLOAD: /* unload */ hk_detach (uptr); /* detach unit */ case FNC_START: /* start spindle */ - case FNC_NOP: /* select */ update_hkcs (CS1_DONE, drv); /* done */ break; @@ -791,7 +789,7 @@ switch (fnc) { /* case on function */ else { uptr->FNC = uptr->FNC | FNC_2ND; /* second state */ hk_off[drv] = hkof & AS_OF; /* save offset */ - sim_activate (uptr, hk_swait * 10); /* wait for compl */ + sim_activate (uptr, hk_min2wait); /* wait for compl */ update_hkcs (CS1_DONE, drv); /* done */ } break; @@ -807,10 +805,10 @@ switch (fnc) { /* case on function */ hk_off[drv] = 0; /* clr offset */ dc = (fnc == FNC_SEEK)? hkdc: 0; /* get cyl */ hk_dif[drv] = dc - uptr->CYL; /* cyl diff */ - t = abs (hk_dif[drv]); /* |cyl diff| */ - if (t == 0) t = 1; /* min time */ + t = abs (hk_dif[drv]) * hk_swait; /* |cyl diff| */ + if (t < hk_min2wait) t = hk_min2wait; /* min time */ uptr->CYL = dc; /* save cyl */ - sim_activate (uptr, hk_swait * t); /* schedule */ + sim_activate (uptr, t); /* schedule */ update_hkcs (CS1_DONE, drv); /* done */ } break; @@ -839,6 +837,7 @@ switch (fnc) { /* case on function */ if ((da + wc) > HK_SIZE (uptr)) { /* disk overrun? */ hker[drv] = hker[drv] | ER_AOE; /* set err */ + hkds[drv] = hkds[drv] | DS_ATA; /* set attn */ wc = HK_SIZE (uptr) - da; /* trim xfer */ if (da >= HK_SIZE (uptr)) { /* none left? */ update_hkcs (CS1_DONE, drv); /* then done */ @@ -923,11 +922,15 @@ switch (fnc) { /* case on function */ clearerr (uptr->fileref); return SCPE_IOERR; } + case FNC_WRITEH: /* write headers stub */ update_hkcs (CS1_DONE, drv); /* set done */ break; } /* end case func */ +if (DEBUG_PRS (hk_dev)) fprintf (sim_deb, + ">>HK%d done: fnc=%o, cs1 = %o, cs2 = %o, ds=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", + drv, fnc, hkcs1, hkcs2, hkds[drv], hkdc, hkda, hkba, hkwc); return SCPE_OK; } @@ -954,7 +957,7 @@ else CLR_INT (HK); hkcs1 = (hkcs1 & (CS1_DT|CS1_UAE|CS1_DONE|CS1_IE|CS1_SPA|CS1_FNC|CS1_GO)) | flag; for (i = 0; i < HK_NUMDR; i++) { /* if ATA, set DI */ if (hkds[i] & DS_ATA) hkcs1 = hkcs1 | CS1_DI; - } + } if (hker[drv] | (hkcs1 & (CS1_PAR | CS1_CTO)) | /* if err, set ERR */ (hkcs2 & CS2_ERR)) hkcs1 = hkcs1 | CS1_ERR; return; @@ -991,7 +994,6 @@ void hk_cmderr (int32 err, int32 drv) { hker[drv] = hker[drv] | err; /* set error */ hkds[drv] = hkds[drv] | DS_ATA; /* set attn */ -hkcs1 = hkcs1 & ~CS1_GO; /* clear go */ update_hkcs (CS1_DONE, drv); /* set done */ return; } @@ -1135,7 +1137,7 @@ t_stat r; uptr->capac = HK_SIZE (uptr); r = attach_unit (uptr, cptr); /* attach unit */ if (r != SCPE_OK) return r; /* error? */ -drv = (int32) (uptr - hk_dev.units); /* get drv number */ +drv = (uint32) (uptr - hk_dev.units); /* get drv number */ hkds[drv] = DS_ATA | DS_RDY | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); hker[drv] = 0; /* upd drv status */ hk_off[drv] = 0; @@ -1143,12 +1145,13 @@ hk_dif[drv] = 0; uptr->CYL = 0; update_hkcs (CS1_DI, drv); /* upd ctlr status */ -if ((p = sim_fsize (uptr->fileref)) == 0) { /* new disk image? */ +p = sim_fsize (uptr->fileref); /* get file size */ +if (p == 0) { /* new disk image? */ if (uptr->flags & UNIT_RO) return SCPE_OK; return pdp11_bad_block (uptr, HK_NUMSC, HK_NUMWD); } if ((uptr->flags & UNIT_AUTO) == 0) return SCPE_OK; /* autosize? */ -if (p > (RK06_SIZE * sizeof (int16))) { +if (p > (RK06_SIZE * sizeof (uint16))) { uptr->flags = uptr->flags | UNIT_RK07; uptr->capac = RK07_SIZE; } @@ -1163,16 +1166,16 @@ return SCPE_OK; t_stat hk_detach (UNIT *uptr) { -int32 drv; +uint32 drv; if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */ -drv = (int32) (uptr - hk_dev.units); /* get drv number */ +drv = (uint32) (uptr - hk_dev.units); /* get drv number */ hkds[drv] = (hkds[drv] & ~(DS_RDY | DS_WRL | DS_VV | DS_OF)) | DS_ATA; if (sim_is_active (uptr)) { /* unit active? */ sim_cancel (uptr); /* cancel operation */ hker[drv] = hker[drv] | ER_OPI; /* set drive error */ - if ((uptr->FNC & CS1_M_FNC) >= FNC_XFER) /* data transfer? */ - hkcs1 = hkcs1 | CS1_DONE | CS1_ERR; /* set done, err */ + if ((uptr->FNC & FNC_2ND) == 0) /* expecting done? */ + update_hkcs (CS1_DONE, drv); /* set done */ } update_hkcs (CS1_DI, drv); /* request intr */ return detach_unit (uptr); diff --git a/PDP11/pdp11_rh.c b/PDP11/pdp11_rh.c index 14d94a26..cda0bc8b 100644 --- a/PDP11/pdp11_rh.c +++ b/PDP11/pdp11_rh.c @@ -25,6 +25,7 @@ rha, rhb RH11/RH70 Massbus adapter + 21-Nov-05 RMS Added enable/disable routine 07-Jul-05 RMS Removed extraneous externs WARNING: The interupt logic of the RH11/RH70 is unusual and must be @@ -177,11 +178,6 @@ DEVICE mba0_dev, mba1_dev; extern uint32 Map_Addr (uint32 ba); -/* Maps */ - -static MBACTX *ctxmap[MBA_NUM] = { &massbus[0], &massbus[1] }; -static DEVICE *devmap[MBA_NUM] = { &mba0_dev, &mba1_dev }; - /* Massbus register dispatches */ static t_stat (*mbregR[MBA_NUM])(int32 *dat, int32 ad, int32 md); @@ -237,14 +233,6 @@ MTAB mba0_mod[] = { { 0 } }; -DEVICE mba0_dev = { - "RHA", &mba0_unit, mba0_reg, mba0_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &mba_reset, - NULL, NULL, NULL, - &mba0_dib, DEV_DEBUG | DEV_DISABLE | DEV_UBUS | DEV_QBUS - }; - DIB mba1_dib = { IOBA_TU, IOLN_TU, &mba_rd, &mba_wr, 1, IVCL (TU), VEC_TU, { &mba1_inta } @@ -278,12 +266,21 @@ MTAB mba1_mod[] = { { 0 } }; -DEVICE mba1_dev = { +DEVICE mba_dev[] = { + { + "RHA", &mba0_unit, mba0_reg, mba0_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &mba_reset, + NULL, NULL, NULL, + &mba0_dib, DEV_DEBUG | DEV_DISABLE | DEV_UBUS | DEV_QBUS + }, + { "RHB", &mba1_unit, mba1_reg, mba1_mod, 1, 0, 0, 0, 0, 0, NULL, NULL, &mba_reset, NULL, NULL, NULL, &mba1_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS + } }; /* Read Massbus adapter register */ @@ -292,12 +289,10 @@ t_stat mba_rd (int32 *val, int32 pa, int32 mode) { int32 ofs, dat, mb, drv; t_stat r; -MBACTX *mbp; mb = mba_map_pa (pa, &ofs); /* get mb number */ if ((mb < 0) || (ofs < 0)) return SCPE_NXM; /* valid? */ -mbp = ctxmap[mb]; /* get context */ -drv = GET_UNIT (mbp->cs2); /* get drive */ +drv = GET_UNIT (massbus[mb].cs2); /* get drive */ mba_upd_cs1 (0, 0, mb); /* update CS1 */ if (ofs & EXT) { /* external? */ @@ -314,31 +309,32 @@ switch (ofs) { /* case on reg */ if (!mbregR[mb]) return SCPE_NXM; /* nx device? */ r = mbregR[mb] (&dat, ofs, drv); /* get dev cs1 */ if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ - *val = mbp->cs1 | dat; + *val = massbus[mb].cs1 | dat; break; case WC_OF: /* WC */ - *val = mbp->wc; + *val = massbus[mb].wc; break; case BA_OF: /* BA */ - *val = mbp->ba & ~BA_MBZ; + *val = massbus[mb].ba & ~BA_MBZ; break; case CS2_OF: /* CS2 */ - *val = mbp->cs2 = (mbp->cs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; + *val = massbus[mb].cs2 = (massbus[mb].cs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; break; case DB_OF: /* DB */ - *val = mbp->db; + *val = massbus[mb].db; break; case BAE_OF: /* BAE */ - *val = mbp->bae = mbp->bae & ~AE_MBZ; + *val = massbus[mb].bae = massbus[mb].bae & ~AE_MBZ; break; case CS3_OF: /* CS3 */ - *val = mbp->cs3 = (mbp->cs3 & ~(CS1_IE | CS3_MBZ)) | (mbp->cs1 & CS1_IE); + *val = massbus[mb].cs3 = (massbus[mb].cs3 & ~(CS1_IE | CS3_MBZ)) | + (massbus[mb].cs1 & CS1_IE); break; default: /* huh? */ @@ -353,12 +349,10 @@ t_stat mba_wr (int32 val, int32 pa, int32 access) int32 ofs, cs1f, drv, mb; t_stat r; t_bool cs1dt; -MBACTX *mbp; mb = mba_map_pa (pa, &ofs); /* get mb number */ if ((mb < 0) || (ofs < 0)) return SCPE_NXM; /* valid? */ -mbp = ctxmap[mb]; /* get context */ -drv = GET_UNIT (mbp->cs2); /* get drive */ +drv = GET_UNIT (massbus[mb].cs2); /* get drive */ if (ofs & EXT) { /* external? */ if (!mbregW[mb]) return SCPE_NXM; /* device there? */ @@ -378,81 +372,84 @@ switch (ofs) { /* case on reg */ if (!mbregW[mb]) return SCPE_NXM; /* device exist? */ if ((access == WRITEB) && (pa & 1)) val = val << 8; if (val & CS1_TRE) { /* error clear? */ - mbp->cs1 = mbp->cs1 & ~CS1_TRE; /* clr CS1 */ - mbp->cs2 = mbp->cs2 & ~CS2_ERR; /* clr CS2<15:8> */ - mbp->cs3 = mbp->cs3 & ~CS3_ERR; /* clr CS3<15:11> */ + massbus[mb].cs1 &= ~CS1_TRE; /* clr CS1 */ + massbus[mb].cs2 &= ~CS2_ERR; /* clr CS2<15:8> */ + massbus[mb].cs3 &= ~CS3_ERR; /* clr CS3<15:11> */ } if ((access == WRITE) || (pa & 1)) { /* hi byte write? */ - if (mbp->cs1 & CS1_DONE) /* done set? */ - mbp->cs1 = (mbp->cs1 & ~CS1_UAE) | (val & CS1_UAE); + if (massbus[mb].cs1 & CS1_DONE) /* done set? */ + massbus[mb].cs1 = (massbus[mb].cs1 & ~CS1_UAE) | (val & CS1_UAE); } if ((access == WRITE) || !(pa & 1)) { /* lo byte write? */ if ((val & CS1_DONE) && (val & CS1_IE)) /* to DONE+IE? */ - mbp->iff = 1; /* set CSTB INTR */ - mbp->cs1 = (mbp->cs1 & ~CS1_IE) | (val & CS1_IE); + massbus[mb].iff = 1; /* set CSTB INTR */ + massbus[mb].cs1 = (massbus[mb].cs1 & ~CS1_IE) | (val & CS1_IE); cs1dt = (val & CS1_GO) && (GET_FNC (val) >= FNC_XFER); - if (cs1dt && ((mbp->cs1 & CS1_DONE) == 0)) /* dt, done clr? */ + if (cs1dt && ((massbus[mb].cs1 & CS1_DONE) == 0)) /* dt, done clr? */ mba_set_cs2 (CS2_PGE, mb); /* prgm error */ else { r = mbregW[mb] (val & 077, ofs, drv); /* write dev CS1 */ if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */ else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ else if (cs1dt && (r == SCPE_OK)) { /* xfer, no err? */ - mbp->cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE); - mbp->cs2 &= ~CS2_ERR; /* clear errors */ - mbp->cs3 &= ~(CS3_ERR | CS3_DBL); + massbus[mb].cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE); + massbus[mb].cs2 &= ~CS2_ERR; /* clear errors */ + massbus[mb].cs3 &= ~(CS3_ERR | CS3_DBL); } } } - mbp->cs3 = (mbp->cs3 & ~CS1_IE) | /* update CS3 */ - (mbp->cs1 & CS1_IE); - mbp->bae = (mbp->bae & ~CS1_M_UAE) | /* update BAE */ - ((mbp->cs1 >> CS1_V_UAE) & CS1_M_UAE); + massbus[mb].cs3 = (massbus[mb].cs3 & ~CS1_IE) | /* update CS3 */ + (massbus[mb].cs1 & CS1_IE); + massbus[mb].bae = (massbus[mb].bae & ~CS1_M_UAE) | /* update BAE */ + ((massbus[mb].cs1 >> CS1_V_UAE) & CS1_M_UAE); break; case WC_OF: /* WC */ if (access == WRITEB) val = (pa & 1)? - (mbp->wc & 0377) | (val << 8): (mbp->wc & ~0377) | val; - mbp->wc = val; + (massbus[mb].wc & 0377) | (val << 8): + (massbus[mb].wc & ~0377) | val; + massbus[mb].wc = val; break; case BA_OF: /* BA */ if (access == WRITEB) val = (pa & 1)? - (mbp->ba & 0377) | (val << 8): (mbp->ba & ~0377) | val; - mbp->ba = val & ~BA_MBZ; + (massbus[mb].ba & 0377) | (val << 8): + (massbus[mb].ba & ~0377) | val; + massbus[mb].ba = val & ~BA_MBZ; break; case CS2_OF: /* CS2 */ if ((access == WRITEB) && (pa & 1)) val = val << 8; - if (val & CS2_CLR) mba_reset (devmap[mb]); /* init? */ + if (val & CS2_CLR) mba_reset (&mba_dev[mb]); /* init? */ else { - if ((val & ~mbp->cs2) & (CS2_PE | CS2_MXF)) + if ((val & ~massbus[mb].cs2) & (CS2_PE | CS2_MXF)) cs1f = CS1_SC; /* diagn intr */ - if (access == WRITEB) val = (mbp->cs2 & /* merge val */ + if (access == WRITEB) val = (massbus[mb].cs2 & /* merge val */ ((pa & 1)? 0377: 0177400)) | val; - mbp->cs2 = (mbp->cs2 & ~CS2_RW) | + massbus[mb].cs2 = (massbus[mb].cs2 & ~CS2_RW) | (val & CS2_RW) | CS2_IR | CS2_OR; } break; case DB_OF: /* DB */ if (access == WRITEB) val = (pa & 1)? - (mbp->db & 0377) | (val << 8): (mbp->db & ~0377) | val; - mbp->db = val; + (massbus[mb].db & 0377) | (val << 8): + (massbus[mb].db & ~0377) | val; + massbus[mb].db = val; break; case BAE_OF: /* BAE */ if ((access == WRITEB) && (pa & 1)) break; - mbp->bae = val & ~AE_MBZ; - mbp->cs1 = (mbp->cs1 & ~CS1_UAE) | /* update CS1 */ - ((mbp->bae << CS1_V_UAE) & CS1_UAE); + massbus[mb].bae = val & ~AE_MBZ; + massbus[mb].cs1 = (massbus[mb].cs1 & ~CS1_UAE) | /* update CS1 */ + ((massbus[mb].bae << CS1_V_UAE) & CS1_UAE); break; case CS3_OF: /* CS3 */ if ((access == WRITEB) && (pa & 1)) break; - mbp->cs3 = (mbp->cs3 & ~CS3_RW) | (val & CS3_RW); - mbp->cs1 = (mbp->cs1 & ~CS1_IE) | /* update CS1 */ - (mbp->cs3 & CS1_IE); + massbus[mb].cs3 = (massbus[mb].cs3 & ~CS3_RW) | (val & CS3_RW); + massbus[mb].cs1 = (massbus[mb].cs1 & ~CS1_IE) | /* update CS1 */ + (massbus[mb].cs3 & CS1_IE); break; default: @@ -474,15 +471,13 @@ return SCPE_OK; int32 mba_rdbufW (uint32 mb, int32 bc, uint16 *buf) { -MBACTX *mbp; int32 i, j, ba, mbc, pbc; uint32 pa; bc = bc & ~1; /* bc even */ if (mb >= MBA_NUM) return 0; /* valid MBA? */ -mbp = ctxmap[mb]; /* get context */ -ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */ -mbc = (0200000 - mbp->wc) << 1; /* MB byte count */ +ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */ +mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */ if (bc > mbc) bc = mbc; /* use smaller */ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ @@ -495,31 +490,29 @@ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ for (j = 0; j < pbc; j = j + 2) { /* loop by words */ *buf++ = M[pa >> 1]; /* fetch word */ - if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */ + if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */ ba = ba + 2; /* incr ba, pa */ pa = pa + 2; } } } -mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */ -mbp->ba = ba & DMASK; /* update ba */ -mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ -mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */ - ((mbp->bae << CS1_V_UAE) & CS1_UAE); +massbus[mb].wc = (massbus[mb].wc + (bc >> 1)) & DMASK; /* update wc */ +massbus[mb].ba = ba & DMASK; /* update ba */ +massbus[mb].bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ +massbus[mb].cs1 = (massbus[mb].cs1 & ~ CS1_UAE) | /* update CS1 */ + ((massbus[mb].bae << CS1_V_UAE) & CS1_UAE); return i; } int32 mba_wrbufW (uint32 mb, int32 bc, uint16 *buf) { -MBACTX *mbp; int32 i, j, ba, mbc, pbc; uint32 pa; bc = bc & ~1; /* bc even */ if (mb >= MBA_NUM) return 0; /* valid MBA? */ -mbp = ctxmap[mb]; /* get context */ -ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */ -mbc = (0200000 - mbp->wc) << 1; /* MB byte count */ +ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */ +mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */ if (bc > mbc) bc = mbc; /* use smaller */ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ @@ -532,31 +525,29 @@ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ for (j = 0; j < pbc; j = j + 2) { /* loop by words */ M[pa >> 1] = *buf++; /* put word */ - if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */ + if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */ ba = ba + 2; /* incr ba, pa */ pa = pa + 2; } } } -mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */ -mbp->ba = ba & DMASK; /* update ba */ -mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ -mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */ - ((mbp->bae << CS1_V_UAE) & CS1_UAE); +massbus[mb].wc = (massbus[mb].wc + (bc >> 1)) & DMASK; /* update wc */ +massbus[mb].ba = ba & DMASK; /* update ba */ +massbus[mb].bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ +massbus[mb].cs1 = (massbus[mb].cs1 & ~ CS1_UAE) | /* update CS1 */ + ((massbus[mb].bae << CS1_V_UAE) & CS1_UAE); return i; } int32 mba_chbufW (uint32 mb, int32 bc, uint16 *buf) { -MBACTX *mbp; int32 i, j, ba, mbc, pbc; uint32 pa; bc = bc & ~1; /* bc even */ if (mb >= MBA_NUM) return 0; /* valid MBA? */ -mbp = ctxmap[mb]; /* get context */ -ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */ -mbc = (0200000 - mbp->wc) << 1; /* MB byte count */ +ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */ +mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */ if (bc > mbc) bc = mbc; /* use smaller */ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ @@ -568,24 +559,24 @@ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ for (j = 0; j < pbc; j = j + 2) { /* loop by words */ - mbp->db = *buf++; /* get dev word */ - if (M[pa >> 1] != mbp->db) { /* miscompare? */ + massbus[mb].db = *buf++; /* get dev word */ + if (M[pa >> 1] != massbus[mb].db) { /* miscompare? */ mba_set_cs2 (CS2_WCE, mb); /* set error */ - mbp->cs3 = mbp->cs3 | /* set even/odd */ + massbus[mb].cs3 = massbus[mb].cs3 | /* set even/odd */ ((pa & 1)? CS3_WCO: CS3_WCE); break; } - if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */ + if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */ ba = ba + 2; /* incr ba, pa */ pa = pa + 2; } } } -mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */ -mbp->ba = ba & DMASK; /* update ba */ -mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ -mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */ - ((mbp->bae << CS1_V_UAE) & CS1_UAE); +massbus[mb].wc = (massbus[mb].wc + (bc >> 1)) & DMASK; /* update wc */ +massbus[mb].ba = ba & DMASK; /* update ba */ +massbus[mb].bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */ +massbus[mb].cs1 = (massbus[mb].cs1 & ~ CS1_UAE) | /* update CS1 */ + ((massbus[mb].bae << CS1_V_UAE) & CS1_UAE); return i; } @@ -612,63 +603,51 @@ return; int32 mba_get_bc (uint32 mb) { -MBACTX *mbp; - if (mb >= MBA_NUM) return 0; -mbp = ctxmap[mb]; -return ((0200000 - mbp->wc) << 1); +return ((0200000 - massbus[mb].wc) << 1); } int32 mba_get_csr (uint32 mb) { -DEVICE *dptr; DIB *dibp; if (mb >= MBA_NUM) return 0; -dptr = devmap[mb]; -dibp = (DIB *) dptr->ctxt; +dibp = (DIB *) mba_dev[mb].ctxt; return dibp->ba; } void mba_set_int (uint32 mb) { -DEVICE *dptr; DIB *dibp; if (mb >= MBA_NUM) return; -dptr = devmap[mb]; -dibp = (DIB *) dptr->ctxt; +dibp = (DIB *) mba_dev[mb].ctxt; int_req[dibp->vloc >> 5] |= (1 << (dibp->vloc & 037)); return; } void mba_clr_int (uint32 mb) { -DEVICE *dptr; DIB *dibp; if (mb >= MBA_NUM) return; -dptr = devmap[mb]; -dibp = (DIB *) dptr->ctxt; +dibp = (DIB *) mba_dev[mb].ctxt; int_req[dibp->vloc >> 5] &= ~(1 << (dibp->vloc & 037)); return; } void mba_upd_cs1 (uint32 set, uint32 clr, uint32 mb) { -MBACTX *mbp; - if (mb >= MBA_NUM) return; -mbp = ctxmap[mb]; -if ((set & ~mbp->cs1) & CS1_DONE) /* DONE 0 to 1? */ - mbp->iff = (mbp->cs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ -mbp->cs1 = (mbp->cs1 & ~(clr | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | set; -if (mbp->cs2 & CS2_ERR) mbp->cs1 = mbp->cs1 | CS1_TRE | CS1_SC; -else if (mbp->cs1 & CS1_TRE) mbp->cs1 = mbp->cs1 | CS1_SC; -if (mbp->iff || - ((mbp->cs1 & CS1_SC) && - (mbp->cs1 & CS1_DONE) && - (mbp->cs1 & CS1_IE))) +if ((set & ~massbus[mb].cs1) & CS1_DONE) /* DONE 0 to 1? */ + massbus[mb].iff = (massbus[mb].cs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */ +massbus[mb].cs1 = (massbus[mb].cs1 & ~(clr | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | set; +if (massbus[mb].cs2 & CS2_ERR) massbus[mb].cs1 = massbus[mb].cs1 | CS1_TRE | CS1_SC; +else if (massbus[mb].cs1 & CS1_TRE) massbus[mb].cs1 = massbus[mb].cs1 | CS1_SC; +if (massbus[mb].iff || + ((massbus[mb].cs1 & CS1_SC) && + (massbus[mb].cs1 & CS1_DONE) && + (massbus[mb].cs1 & CS1_IE))) mba_set_int (mb); else mba_clr_int (mb); return; @@ -676,11 +655,8 @@ return; void mba_set_cs2 (uint32 flag, uint32 mb) { -MBACTX *mbp; - if (mb >= MBA_NUM) return; -mbp = ctxmap[mb]; -mbp->cs2 = mbp->cs2 | flag; +massbus[mb].cs2 = massbus[mb].cs2 | flag; mba_upd_cs1 (0, 0, mb); return; } @@ -708,12 +684,10 @@ return mba1_dib.vec; /* acknowledge */ uint32 mba_map_pa (int32 pa, int32 *ofs) { int32 i, uo, ba, lnt; -DEVICE *dptr; DIB *dibp; for (i = 0; i < MBA_NUM; i++) { /* loop thru ctrls */ - dptr = devmap[i]; /* get device */ - dibp = (DIB *) dptr->ctxt; /* get DIB */ + dibp = (DIB *) mba_dev[i].ctxt; /* get DIB */ ba = dibp->ba; lnt = dibp->lnt; if ((pa >= ba) && /* in range? */ @@ -738,27 +712,33 @@ return -1; t_stat mba_reset (DEVICE *dptr) { -int32 mb; -MBACTX *mbp; +uint32 mb; -for (mb = 0; mb < MBA_NUM; mb++) { - mbp = ctxmap[mb]; - if (dptr == devmap[mb]) break; - } +mb = dptr - mba_dev; if (mb >= MBA_NUM) return SCPE_NOFNC; -mbp->cs1 = CS1_DONE; -mbp->wc = 0; -mbp->ba = 0; -mbp->cs2 = 0; -mbp->db = 0; -mbp->bae= 0; -mbp->cs3 = 0; -mbp->iff = 0; +massbus[mb].cs1 = CS1_DONE; +massbus[mb].wc = 0; +massbus[mb].ba = 0; +massbus[mb].cs2 = 0; +massbus[mb].db = 0; +massbus[mb].bae= 0; +massbus[mb].cs3 = 0; +massbus[mb].iff = 0; mba_clr_int (mb); if (mbabort[mb]) mbabort[mb] (); return SCPE_OK; } +/* Enable/disable Massbus adapter */ + +void mba_set_enbdis (uint32 mb, t_bool dis) +{ +if (mb >= MBA_NUM) return; /* valid MBA? */ +if (dis) mba_dev[mb].flags |= DEV_DIS; +else mba_dev[mb].flags &= ~DEV_DIS; +return; +} + /* Show Massbus adapter number */ t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc) diff --git a/PDP11/pdp11_rp.c b/PDP11/pdp11_rp.c index f84f7252..11ec7b44 100644 --- a/PDP11/pdp11_rp.c +++ b/PDP11/pdp11_rp.c @@ -25,6 +25,8 @@ rp RH/RP/RM moving head disks + 21-Nov-05 RMS Enable/disable device also enables/disables Massbus adapter + 12-Nov-05 RMS Fixed DriveClear, does not clear disk address 16-Aug-05 RMS Fixed C++ declaration and cast problems 18-Mar-05 RMS Added attached test to detach routine 12-Sep-04 RMS Cloned from pdp11_rp.c @@ -673,8 +675,11 @@ if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */ switch (fnc) { /* case on function */ case FNC_DCLR: /* drive clear */ - rpda[drv] = 0; /* clear disk addr */ rper1[drv] = rper2[drv] = rper3[drv] = 0; /* clear errors */ + rpec2[drv] = 0; /* clear EC2 */ + if (drv_tab[dtype].ctrl == RM_CTRL) /* RM? */ + rpmr[drv] = 0; /* clear maint */ + else rpec1[drv] = 0; /* RP, clear EC1 */ case FNC_NOP: /* no operation */ case FNC_RELEASE: /* port release */ return SCPE_OK; @@ -918,6 +923,7 @@ t_stat rp_reset (DEVICE *dptr) int32 i; UNIT *uptr; +mba_set_enbdis (MBA_RP, rp_dev.flags & DEV_DIS); for (i = 0; i < RP_NUMDR; i++) { uptr = rp_dev.units + i; sim_cancel (uptr); diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c index 4caea234..0fb35d35 100644 --- a/PDP11/pdp11_rq.c +++ b/PDP11/pdp11_rq.c @@ -26,6 +26,7 @@ rq RQDX3 disk controller + 31-Oct-05 RMS Fixed address width for large files 16-Aug-05 RMS Fixed C++ declaration and cast problems 22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn) 17-Jan-05 RMS Added more RA and RD disks @@ -768,7 +769,7 @@ MTAB rq_mod[] = { DEVICE rq_dev = { "RQ", rq_unit, rq_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16, + RQ_NUMDR + 2, DEV_RDX, T_ADDR_W, 2, DEV_RDX, 16, NULL, NULL, &rq_reset, &rq_boot, &rq_attach, &rq_detach, &rq_dib, DEV_FLTA | DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_DEBUG @@ -837,7 +838,7 @@ REG rqb_reg[] = { DEVICE rqb_dev = { "RQB", rqb_unit, rqb_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16, + RQ_NUMDR + 2, DEV_RDX, T_ADDR_W, 2, DEV_RDX, 16, NULL, NULL, &rq_reset, &rq_boot, &rq_attach, &rq_detach, &rqb_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG @@ -906,7 +907,7 @@ REG rqc_reg[] = { DEVICE rqc_dev = { "RQC", rqc_unit, rqc_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16, + RQ_NUMDR + 2, DEV_RDX, T_ADDR_W, 2, DEV_RDX, 16, NULL, NULL, &rq_reset, &rq_boot, &rq_attach, &rq_detach, &rqc_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG @@ -975,7 +976,7 @@ REG rqd_reg[] = { DEVICE rqd_dev = { "RQD", rqd_unit, rqd_reg, rq_mod, - RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16, + RQ_NUMDR + 2, DEV_RDX, T_ADDR_W, 2, DEV_RDX, 16, NULL, NULL, &rq_reset, &rq_boot, &rq_attach, &rq_detach, &rqd_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG @@ -1213,7 +1214,7 @@ if ((pkt == 0) && cp->pip) { /* polling? */ } /* end if pip */ if (cp->rspq) { /* resp q? */ pkt = rq_deqh (cp, &cp->rspq); /* get top of q */ - if (!rq_putpkt (cp, pkt, FALSE)) return SCPE_OK; /* send to hst */ + if (!rq_putpkt (cp, pkt, FALSE)) return SCPE_OK; /* send to host */ } /* end if resp q */ if (pkt) sim_activate (uptr, rq_qtime); /* more to do? */ return SCPE_OK; /* done */ @@ -1605,7 +1606,7 @@ if ((uptr->flags & UNIT_ONL) == 0) /* not online? */ return ST_AVL; /* only avail */ if ((cmd != OP_ACC) && (cmd != OP_ERS) && /* 'real' xfer */ (cp->pak[pkt].d[RW_BAL] & 1)) /* odd address? */ - return (ST_HST | SB_HST_OA); /* host buf odd */ + return (ST_HST | SB_HST_OA); /* host buf odd */ if (bc & 1) return (ST_HST | SB_HST_OC); /* odd byte cnt? */ if (bc & 0xF0000000) return (ST_CMD | I_BCNT); /* 'reasonable' bc? */ /* if (lbn & 0xF0000000) return (ST_CMD | I_LBN); /* 'reasonable' lbn? */ diff --git a/PDP11/pdp11_stddev.c b/PDP11/pdp11_stddev.c index e1fe1c73..b082b271 100644 --- a/PDP11/pdp11_stddev.c +++ b/PDP11/pdp11_stddev.c @@ -26,6 +26,7 @@ tti,tto DL11 terminal input/output clk KW11L (and other) line frequency clock + 22-Nov-05 RMS Revised for new terminal processing routines 22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 07-Jul-05 RMS Removed extraneous externs 11-Oct-04 RMS Added clock model dependencies @@ -63,9 +64,6 @@ #define CLKCSR_RW (CSR_IE) #define CLK_DELAY 8000 -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_8B (1 << UNIT_V_8B) - extern int32 int_req[IPL_HLVL]; extern uint32 cpu_type; @@ -123,8 +121,9 @@ REG tti_reg[] = { }; MTAB tti_mod[] = { - { UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, + { TT_MODE, TT_MODE_7P, "7b", NULL, NULL }, { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, NULL, &show_addr, NULL }, { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, @@ -167,8 +166,9 @@ REG tto_reg[] = { }; MTAB tto_mod[] = { - { UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, + { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode }, { MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, NULL, &show_addr, NULL }, { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, @@ -278,11 +278,11 @@ t_stat tti_svc (UNIT *uptr) { int32 c; -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ +sim_activate (uptr, uptr->wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */ -else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); -tti_unit.pos = tti_unit.pos + 1; +if (c & SCPE_BREAK) uptr->buf = 0; /* break? */ +else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags)); +uptr->pos = uptr->pos + 1; tti_csr = tti_csr | CSR_DONE; if (tti_csr & CSR_IE) SET_INT (TTI); return SCPE_OK; @@ -347,14 +347,16 @@ t_stat tto_svc (UNIT *uptr) int32 c; t_stat r; -c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ +c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags)); +if (c >= 0) { + if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } } tto_csr = tto_csr | CSR_DONE; if (tto_csr & CSR_IE) SET_INT (TTO); -tto_unit.pos = tto_unit.pos + 1; +uptr->pos = uptr->pos + 1; return SCPE_OK; } @@ -371,8 +373,8 @@ return SCPE_OK; t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { -tti_unit.flags = (tti_unit.flags & ~UNIT_8B) | val; -tto_unit.flags = (tto_unit.flags & ~UNIT_8B) | val; +tti_unit.flags = (tti_unit.flags & ~TT_MODE) | val; +tto_unit.flags = (tto_unit.flags & ~TT_MODE) | val; return SCPE_OK; } diff --git a/PDP11/pdp11_sys.c b/PDP11/pdp11_sys.c index 2cfb9456..2cdf4d49 100644 --- a/PDP11/pdp11_sys.c +++ b/PDP11/pdp11_sys.c @@ -63,7 +63,7 @@ extern DEVICE vh_dev; extern DEVICE rk_dev, rl_dev; extern DEVICE hk_dev; extern DEVICE rx_dev, ry_dev; -extern DEVICE mba0_dev, mba1_dev; +extern DEVICE mba_dev[]; extern DEVICE rp_dev, tu_dev; extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; extern DEVICE dt_dev; @@ -95,8 +95,8 @@ int32 sim_emax = 4; DEVICE *sim_devices[] = { &cpu_dev, &sys_dev, - &mba0_dev, - &mba1_dev, + &mba_dev[0], + &mba_dev[1], &ptr_dev, &ptp_dev, &tti_dev, diff --git a/PDP11/pdp11_tm.c b/PDP11/pdp11_tm.c index aee5802d..d238a632 100644 --- a/PDP11/pdp11_tm.c +++ b/PDP11/pdp11_tm.c @@ -25,6 +25,7 @@ tm TM11/TU10 magtape + 31-Oct-05 RMS Fixed address width for large files 16-Aug-05 RMS Fixed C++ declaration and cast problems 07-Jul-05 RMS Removed extraneous externs 18-Mar-05 RMS Added attached test to detach routine @@ -238,7 +239,7 @@ MTAB tm_mod[] = { DEVICE tm_dev = { "TM", tm_unit, tm_reg, tm_mod, - TM_NUMDR, 10, 31, 1, 8, 8, + TM_NUMDR, 10, T_ADDR_W, 1, 8, 8, NULL, NULL, &tm_reset, &tm_boot, &tm_attach, &tm_detach, &tm_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 | DEV_DEBUG diff --git a/PDP11/pdp11_tq.c b/PDP11/pdp11_tq.c index a2970790..eca04718 100644 --- a/PDP11/pdp11_tq.c +++ b/PDP11/pdp11_tq.c @@ -25,6 +25,7 @@ tq TQK50 tape controller + 31-Oct-05 RMS Fixed address width for large files 16-Aug-05 RMS Fixed C++ declaration and cast problems 22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn) 30-Sep-04 RMS Revised Unibus interface @@ -454,7 +455,7 @@ MTAB tq_mod[] = { DEVICE tq_dev = { "TQ", tq_unit, tq_reg, tq_mod, - TQ_NUMDR + 2, 10, 31, 1, DEV_RDX, 8, + TQ_NUMDR + 2, 10, T_ADDR_W, 1, DEV_RDX, 8, NULL, NULL, &tq_reset, &tq_boot, &tq_attach, &tq_detach, &tq_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_DEBUG @@ -651,7 +652,7 @@ if ((pkt == 0) && tq_pip) { /* polling? */ } /* end if pip */ if (tq_rspq) { /* resp q? */ pkt = tq_deqh (&tq_rspq); /* get top of q */ - if (!tq_putpkt (pkt, FALSE)) return SCPE_OK; /* send to hst */ + if (!tq_putpkt (pkt, FALSE)) return SCPE_OK; /* send to host */ } /* end if resp q */ if (pkt) sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); /* more to do? */ return SCPE_OK; /* done */ diff --git a/PDP11/pdp11_ts.c b/PDP11/pdp11_ts.c index a17ed4c6..2b9f779f 100644 --- a/PDP11/pdp11_ts.c +++ b/PDP11/pdp11_ts.c @@ -25,6 +25,7 @@ ts TS11/TSV05 magtape + 31-Oct-05 RMS Fixed address width for large files 16-Aug-05 RMS Fixed C++ declaration and cast problems 07-Jul-05 RMS Removed extraneous externs 18-Mar-05 RMS Added attached test to detach routine @@ -354,7 +355,7 @@ MTAB ts_mod[] = { DEVICE ts_dev = { "TS", &ts_unit, ts_reg, ts_mod, - 1, 10, 31, 1, DEV_RDX, 8, + 1, 10, T_ADDR_W, 1, DEV_RDX, 8, NULL, NULL, &ts_reset, &ts_boot, &ts_attach, &ts_detach, &ts_dib, DEV_DISABLE | TS_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG diff --git a/PDP11/pdp11_tu.c b/PDP11/pdp11_tu.c index 72ba8ced..9d92e9d2 100644 --- a/PDP11/pdp11_tu.c +++ b/PDP11/pdp11_tu.c @@ -25,6 +25,8 @@ tu TM02/TM03 magtape + 12-Nov-05 RMS Changed default formatter to TM03 (for VMS) + 31-Oct-05 RMS Fixed address width for large files 16-Aug-05 RMS Fixed C++ declaration and cast problems 31-Mar-05 RMS Fixed inaccuracies in error reporting 18-Mar-05 RMS Added attached test to detach routine @@ -290,10 +292,15 @@ REG tu_reg[] = { MTAB tu_mod[] = { { MTAB_XTD|MTAB_VDV, 0, "MASSBUS", "MASSBUS", NULL, &mba_show_num }, +#if defined (VM_PDP11) { MTAB_XTD|MTAB_VDV, 0, "FORMATTER", "TM02", &tu_set_fmtr, &tu_show_fmtr }, { MTAB_XTD|MTAB_VDV, 1, NULL, "TM03", &tu_set_fmtr, NULL }, +#else + { MTAB_XTD|MTAB_VDV, 0, "FORMATTER", NULL, + NULL, &tu_show_fmtr }, +#endif { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, { UNIT_TYPE, UNIT_TE16, "TE16", "TE16", NULL }, @@ -306,10 +313,10 @@ MTAB tu_mod[] = { DEVICE tu_dev = { "TU", tu_unit, tu_reg, tu_mod, - TU_NUMDR, 10, 31, 1, DEV_RDX, 8, + TU_NUMDR, 10, T_ADDR_W, 1, DEV_RDX, 8, NULL, NULL, &tu_reset, &tu_boot, &tu_attach, &tu_detach, - &tu_dib, DEV_MBUS | DEV_UBUS | DEV_QBUS | DEV_DEBUG | DEV_DISABLE | DEV_DIS_INIT + &tu_dib, DEV_MBUS|DEV_UBUS|DEV_QBUS|DEV_DEBUG|DEV_DISABLE|DEV_DIS_INIT|DEV_TM03 }; /* Massbus register read */ @@ -846,6 +853,7 @@ t_stat tu_reset (DEVICE *dptr) int32 u; UNIT *uptr; +mba_set_enbdis (MBA_TU, tu_dev.flags & DEV_DIS); tucs1 = 0; tufc = 0; tuer = 0; diff --git a/PDP11/pdp11_vh.c b/PDP11/pdp11_vh.c index c62eb510..fa7f6dab 100644 --- a/PDP11/pdp11_vh.c +++ b/PDP11/pdp11_vh.c @@ -24,28 +24,28 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the Author. - vh DHQ11 asynch multiplexor for SIMH + vh DHQ11 asynch multiplexor for SIMH - 07-Jul-05 RMS Removed extraneous externs - 15-Jun-05 RMS Revised for new autoconfigure interface - Fixed bug in vector display routine - 12-Jun-04 RMS Repair MS2SIMH macro to avoid divide by 0 bug - 08-Jun-04 JAD Repair vh_dev initialization; remove unused - variables, cast to avoid conversion confusion - 07-Jun-04 JAD Complete function prototypes of forward declarations. - Repair broken prototypes of vh_rd() and vh_wr() - Explicitly size integer declarations - 4-Jun-04 JAD Preliminary code: If operating in a PDP-11 Unibus - environment, force DHU mode - 29-May-04 JAD Make certain RX.TIMER is within allowable range - 25-May-04 JAD All time-based operations are scaled by tmxr_poll units - 23-May-04 JAD Change to fifo_get() and dq_tx_report() to avoid - gratuitous stack manipulation - 20-May-04 JAD Made modem control and auto-hangup unit flags - 19-May-04 JAD Fix problem with modem status where the line number - was not being included - 12-May-04 JAD Revised for updated tmxr interfaces - 28-Jan-04 JAD Original creation and testing + 07-Jul-05 RMS Removed extraneous externs + 15-Jun-05 RMS Revised for new autoconfigure interface + Fixed bug in vector display routine + 12-Jun-04 RMS Repair MS2SIMH macro to avoid divide by 0 bug + 08-Jun-04 JAD Repair vh_dev initialization; remove unused + variables, cast to avoid conversion confusion + 07-Jun-04 JAD Complete function prototypes of forward declarations. + Repair broken prototypes of vh_rd() and vh_wr() + Explicitly size integer declarations + 4-Jun-04 JAD Preliminary code: If operating in a PDP-11 Unibus + environment, force DHU mode + 29-May-04 JAD Make certain RX.TIMER is within allowable range + 25-May-04 JAD All time-based operations are scaled by tmxr_poll units + 23-May-04 JAD Change to fifo_get() and dq_tx_report() to avoid + gratuitous stack manipulation + 20-May-04 JAD Made modem control and auto-hangup unit flags + 19-May-04 JAD Fix problem with modem status where the line number + was not being included + 12-May-04 JAD Revised for updated tmxr interfaces + 28-Jan-04 JAD Original creation and testing I/O Page Registers diff --git a/PDP11/pdp11_xq.c b/PDP11/pdp11_xq.c index 439f1dbe..16ea2620 100644 --- a/PDP11/pdp11_xq.c +++ b/PDP11/pdp11_xq.c @@ -1,7 +1,7 @@ /* pdp11_xq.c: DEQNA/DELQA ethernet controller simulator ------------------------------------------------------------------------------ - Copyright (c) 2002-2005, David T. Hittner + Copyright (c) 2002-2006, David T. Hittner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -66,6 +66,7 @@ Modification history: + 07-Jan-06 RMS Fixed unaligned access bugs (found by Doug Carman) 07-Sep-05 DTH Removed unused variable 16-Aug-05 RMS Fixed C++ declaration and cast problems 01-Dec-04 DTH Added runtime attach prompt @@ -274,16 +275,18 @@ UNIT xqa_unit[] = { }; REG xqa_reg[] = { - { GRDATA ( SA0, xqa.addr[0], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA1, xqa.addr[1], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA2, xqa.addr[2], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA3, xqa.addr[3], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA4, xqa.addr[4], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( SA5, xqa.addr[5], XQ_RDX, 16, 0), REG_RO}, - { GRDATA ( RBDL, xqa.rbdl, XQ_RDX, 32, 0) }, - { GRDATA ( XBDL, xqa.xbdl, XQ_RDX, 32, 0) }, - { GRDATA ( VAR, xqa.var, XQ_RDX, 16, 0) }, - { GRDATA ( CSR, xqa.csr, XQ_RDX, 16, 0) }, + { GRDATA ( SA0, xqa.addr[0], XQ_RDX, 8, 0), REG_RO|REG_FIT}, + { GRDATA ( SA1, xqa.addr[1], XQ_RDX, 8, 0), REG_RO|REG_FIT}, + { GRDATA ( SA2, xqa.addr[2], XQ_RDX, 8, 0), REG_RO|REG_FIT}, + { GRDATA ( SA3, xqa.addr[3], XQ_RDX, 8, 0), REG_RO|REG_FIT}, + { GRDATA ( SA4, xqa.addr[4], XQ_RDX, 8, 0), REG_RO|REG_FIT}, + { GRDATA ( SA5, xqa.addr[5], XQ_RDX, 8, 0), REG_RO|REG_FIT}, + { GRDATA ( RBDL, xqa.rbdl[0], XQ_RDX, 16, 0), REG_FIT }, + { GRDATA ( RBDH, xqa.rbdl[1], XQ_RDX, 16, 0), REG_FIT }, + { GRDATA ( XBDL, xqa.xbdl[0], XQ_RDX, 16, 0), REG_FIT }, + { GRDATA ( XBDH, xqa.xbdl[1], XQ_RDX, 16, 0), REG_FIT }, + { GRDATA ( VAR, xqa.var, XQ_RDX, 16, 0), REG_FIT }, + { GRDATA ( CSR, xqa.csr, XQ_RDX, 16, 0), REG_FIT }, { FLDATA ( INT, xqa.irq, 0) }, { GRDATA ( SETUP_PRM, xqa.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO}, { GRDATA ( SETUP_MLT, xqa.setup.multicast, XQ_RDX, 32, 0), REG_HRO}, diff --git a/PDP11/pdp11_xu.c b/PDP11/pdp11_xu.c index ab53514a..2eb96e0a 100644 --- a/PDP11/pdp11_xu.c +++ b/PDP11/pdp11_xu.c @@ -40,6 +40,11 @@ Testing performed: 1) Receives/Transmits single packet under custom RSX driver 2) Passes RSTS 10.1 controller diagnostics during boot + 3) VMS 7.2 on VAX780 summary: + LAT - Runs properly both in and out + DECNET - Starts without error, but will not do anything + TCP/IP - Starts with errors, will ping in/out but nothing else + Clustering - Not tested Known issues: 1) Transmit/Receive rings have not been thoroughly tested, @@ -52,6 +57,8 @@ Modification history: + 08-Dec-05 DTH Implemented ancilliary functions 022/023/024/025 + 18-Nov-05 DTH Corrected time between system ID packets 07-Sep-05 DTH Corrected runt packet processing (found by Tim Chapman), Removed unused variable 16-Aug-05 RMS Fixed C++ declaration and cast problems @@ -76,7 +83,7 @@ #include "pdp11_xu.h" -extern int32 tmr_poll, clk_tps; +extern int32 tmr_poll, clk_tps, cpu_astop; extern FILE *sim_log; t_stat xu_rd(int32* data, int32 PA, int32 access); @@ -101,6 +108,8 @@ void xub_write_callback(int status); void xu_setint (CTLR* xu); void xu_clrint (CTLR* xu); void xu_process_receive(CTLR* xu); +void xu_dump_rxring(CTLR* xu); +void xu_dump_txring(CTLR* xu); DIB xua_dib = { IOBA_XU, IOLN_XU, &xu_rd, &xu_wr, 1, IVCL (XU), VEC_XU, {&xu_int} }; @@ -144,6 +153,7 @@ DEBTAB xu_debug[] = { {"TRACE", DBG_TRC}, {"WARN", DBG_WRN}, {"REG", DBG_REG}, + {"PACKET", DBG_PCK}, {"ETH", DBG_ETH}, {0} }; @@ -463,7 +473,7 @@ t_stat xu_svc(UNIT* uptr) if (--xu->var->idtmr <= 0) { if ((xu->var->mode & MODE_DMNT) == 0) /* if maint msg is not disabled */ status = xu_system_id(xu, mop_multicast, 0); /* then send ID packet */ - xu->var->idtmr = XU_ID_TIMER_VAL; /* reset timer */ + xu->var->idtmr = XU_ID_TIMER_VAL * one_second; /* reset timer */ } /* has one second timer expired? if so, update stats and reset timer */ @@ -517,11 +527,17 @@ t_stat xu_sw_reset (CTLR* xu) sim_debug(DBG_TRC, xu->dev, "xu_sw_reset()\n"); /* Clear the registers. */ - xu->var->pcsr0 = 0; + xu->var->pcsr0 = PCSR0_DNI | PCSR0_INTR; xu->var->pcsr1 = STATE_READY; switch (xu->var->type) { - case XU_T_DELUA: xu->var->pcsr1 |= TYPE_DELUA; break; - case XU_T_DEUNA: xu->var->pcsr1 |= TYPE_DEUNA; break; + case XU_T_DELUA: + xu->var->pcsr1 |= TYPE_DELUA; + break; + case XU_T_DEUNA: + xu->var->pcsr1 |= TYPE_DEUNA; + if (!xu->var->etherface) /* if not attached, set transceiver powerfail */ + xu->var->pcsr1 |= PCSR1_XPWR; + break; } xu->var->pcsr2 = 0; xu->var->pcsr3 = 0; @@ -554,6 +570,9 @@ t_stat xu_sw_reset (CTLR* xu) sim_activate(&xu->unit[0], one_second/XU_SERVICE_INTERVAL); } + /* clear load_server address */ + memset(xu->var->load_server, 0, sizeof(ETH_MAC)); + return SCPE_OK; } @@ -563,6 +582,7 @@ t_stat xu_reset(DEVICE* dptr) t_stat status; CTLR* xu = xu_dev2ctlr(dptr); + sim_debug(DBG_TRC, xu->dev, "xu_reset()\n"); /* init read queue (first time only) */ status = ethq_init (&xu->var->ReadQ, XU_QUE_MAX); if (status != SCPE_OK) @@ -574,15 +594,19 @@ t_stat xu_reset(DEVICE* dptr) return SCPE_OK; } + /* Perform one of the defined ancillary functions. */ int32 xu_command(CTLR* xu) { uint32 udbb; int fnc, mtlen; - uint16 value; + uint16 value, pltlen; t_stat status, rstatus, wstatus, wstatus2, wstatus3; struct xu_stats* stats = &xu->var->stats; uint16* udb = xu->var->udb; + uint16* mac_w = (uint16*) xu->var->mac; + static const ETH_MAC zeros = {0,0,0,0,0,0}; + static const ETH_MAC mcast_load_server = {0xAB, 0x00, 0x00, 0x01, 0x00, 0x00}; static char* command[] = { "NO-OP", "Start Microaddress", @@ -610,11 +634,12 @@ int32 xu_command(CTLR* xu) /* Grab the PCB from the host. */ rstatus = Map_ReadW(xu->var->pcbb, 8, xu->var->pcb); - if (rstatus != SCPE_OK) + if (rstatus != 0) return PCSR0_PCEI + 1; /* High 8 bits are defined as MBZ. */ - if (xu->var->pcb[0] & 0177400) return PCSR0_PCEI; + if (xu->var->pcb[0] & 0177400) + return PCSR0_PCEI; /* Decode the function to be performed. */ fnc = xu->var->pcb[0] & 0377; @@ -625,28 +650,31 @@ int32 xu_command(CTLR* xu) break; case FC_RDPA: /* read default physical address */ - wstatus = Map_WriteW(xu->var->pcbb + 2, 6, (uint16*)xu->var->mac); - if (wstatus != SCPE_OK) + wstatus = Map_WriteB(xu->var->pcbb + 2, 6, xu->var->mac); + if (wstatus) return PCSR0_PCEI + 1; break; case FC_RPA: /* read current physical address */ - wstatus = Map_WriteW(xu->var->pcbb + 2, 6, (uint16*)&xu->var->setup.macs[0]); - if (wstatus != SCPE_OK) + wstatus = Map_WriteB(xu->var->pcbb + 2, 6, (uint8*)&xu->var->setup.macs[0]); + if (wstatus) return PCSR0_PCEI + 1; break; case FC_WPA: /* write current physical address */ - rstatus = Map_ReadW(xu->var->pcbb + 2, 6, (uint16*)&xu->var->setup.macs[0]); - if (xu->var->pcb[1] & 1) return PCSR0_PCEI; + rstatus = Map_ReadB(xu->var->pcbb + 2, 6, (uint8*)&xu->var->setup.macs[0]); + if (xu->var->pcb[1] & 1) + return PCSR0_PCEI; break; case FC_WMAL: /* write multicast address list */ mtlen = (xu->var->pcb[2] & 0xFF00) >> 8; - if (mtlen > 10) return PCSR0_PCEI; +sim_debug(DBG_TRC, xu->dev, "FC_WAL: mtlen=%d\n", mtlen); + if (mtlen > 10) + return PCSR0_PCEI; udbb = xu->var->pcb[1] | ((xu->var->pcb[2] & 03) << 16); - rstatus = Map_ReadW(udbb, mtlen * 6, (uint16*) &xu->var->setup.macs[1]); - if (rstatus == SCPE_OK) { + rstatus = Map_ReadB(udbb, mtlen * 6, (uint8*) &xu->var->setup.macs[1]); + if (rstatus == 0) { xu->var->setup.mac_count = mtlen + 1; status = eth_filter (xu->var->etherface, xu->var->setup.mac_count, xu->var->setup.macs, xu->var->setup.multicast, @@ -669,7 +697,7 @@ int32 xu_command(CTLR* xu) /* Write UDB to host memory. */ udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16); wstatus = Map_WriteW(udbb, 12, xu->var->pcb); - if (wstatus != SCPE_OK) + if (wstatus != 0) return PCSR0_PCEI+1; break; @@ -682,7 +710,7 @@ int32 xu_command(CTLR* xu) /* Read UDB into local memory. */ udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16); rstatus = Map_ReadW(udbb, 12, xu->var->udb); - if (rstatus != SCPE_OK) + if (rstatus) return PCSR0_PCEI+1; if ((xu->var->udb[0] & 1) || (xu->var->udb[1] & 0374) || @@ -699,6 +727,9 @@ int32 xu_command(CTLR* xu) xu->var->rrlen = xu->var->udb[5]; xu->var->rxnext = 0; xu->var->txnext = 0; +xu_dump_rxring(xu); +xu_dump_txring(xu); +/*cpu_astop=1;*/ break; case FC_RDCTR: /* read counters */ @@ -745,7 +776,7 @@ int32 xu_command(CTLR* xu) /* transfer udb to host */ udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16); wstatus = Map_WriteW(udbb, 68, xu->var->udb); - if (wstatus != SCPE_OK) { + if (wstatus) { xu->var->pcsr0 |= PCSR0_PCEI; } @@ -757,13 +788,14 @@ int32 xu_command(CTLR* xu) case FC_RMODE: /* read mode register */ value = xu->var->mode; wstatus = Map_WriteW(xu->var->pcbb+2, 2, &value); - if (wstatus != SCPE_OK) + if (wstatus) return PCSR0_PCEI + 1; break; case FC_WMODE: /* write mode register */ value = xu->var->mode; xu->var->mode = xu->var->pcb[1]; +sim_debug(DBG_TRC, xu->dev, "FC_WMODE: mode=%04x\n", xu->var->mode); /* set promiscuous and multicast flags */ xu->var->setup.promiscuous = (xu->var->mode & MODE_PROM) ? 1 : 0; @@ -784,13 +816,79 @@ int32 xu_command(CTLR* xu) wstatus2 = Map_WriteW(xu->var->pcbb+4, 2, &value); value = 32; wstatus3 = Map_WriteW(xu->var->pcbb+6, 2, &value); - if ((wstatus != SCPE_OK) || (wstatus2 != SCPE_OK) || (wstatus3 != SCPE_OK)) + if (wstatus + wstatus2 + wstatus3) return PCSR0_PCEI + 1; if (fnc == FC_RCSTAT) xu->var->stat &= 0377; /* clear high byte */ break; + case FC_RSID: /* read system id parameters */ + /* prepare udb for transfer */ + memset(xu->var->udb, 0, sizeof(xu->var->udb)); + + udb[11] = 0x260; /* type */ + udb[12] = 28/* + parameter size */; /* ccount */ + udb[13] = 7; /* code */ + udb[14] = 0; /* recnum */ + /* mop information */ + udb[15] = 1; /* mvtype */ + udb[16] = 0x0303; /* mvver + mvlen */ + udb[17] = 0; /* mvueco + mveco */ + /* function information */ + udb[18] = 2; /* ftype */ + udb[19] = 0x0502; /* fval1 + flen */ + udb[20] = 0x0700; /* hatype<07:00> + fval2 */ + udb[21] = 0x0600; /* halen + hatype<15:08> */ + /* built-in MAC address */ + udb[21] = mac_w[0]; /* HA<15:00> */ + udb[22] = mac_w[1]; /* HA<31:16> */ + udb[23] = mac_w[2]; /* HA<47:32> */ + udb[24] = 0x64; /* dtype */ + udb[25] = (11 << 8) + 1; /* dvalue + dlen */ + + /* transfer udb to host */ + udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16); + wstatus = Map_WriteW(udbb, 52, xu->var->udb); + if (wstatus) + xu->var->pcsr0 |= PCSR0_PCEI; + break; + + case FC_WSID: /* write system id parameters */ + /* get udb base */ + udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16); + /* get udb length */ + pltlen = xu->var->pcb[3]; + + /* transfer udb from host */ + rstatus = Map_ReadW(udbb, pltlen * 2, xu->var->udb); + if (rstatus) + return PCSR0_PCEI + 1; + + /* decode and store system ID fields , if we ever need to. + for right now, just return "success" */ + + break; + + case FC_RLSA: /* read load server address */ + if (memcmp(xu->var->load_server, zeros, sizeof(ETH_MAC))) { + /* not set, use default multicast load address */ + wstatus = Map_WriteB(xu->var->pcbb + 2, 6, (uint8*) mcast_load_server); + } else { + /* is set, use load_server */ + wstatus = Map_WriteB(xu->var->pcbb + 2, 6, xu->var->load_server); + } + if (wstatus) + return PCSR0_PCEI + 1; + break; + + + case FC_WLSA: /* write load server address */ + rstatus = Map_ReadB(xu->var->pcbb + 2, 6, xu->var->load_server); + if (rstatus) + return PCSR0_PCEI + 1; + break; + default: /* Unknown (unimplemented) command. */ printf("%s: unknown ancilliary command 0%o requested !\n", xu->dev->name, fnc); return PCSR0_PCEI; @@ -813,6 +911,8 @@ void xu_process_receive(CTLR* xu) sim_debug(DBG_TRC, xu->dev, "xu_process_receive(), buffers: %d\n", xu->var->rrlen); +/* xu_dump_rxring(xu); /* debug receive ring */ + /* process only when in the running state, and host buffers are available */ if ((state != STATE_RUNNING) || no_buffers) return; @@ -839,7 +939,7 @@ void xu_process_receive(CTLR* xu) /* if buffer not owned by controller, exit [at end of ring] */ if (!(xu->var->rxhdr[2] & RXR_OWN)) { /* tell the host there are no more buffers */ - xu->var->pcsr0 |= PCSR0_RCBI; + /* xu->var->pcsr0 |= PCSR0_RCBI; */ /* I don't think this is correct 08-dec-2005 dth */ break; } @@ -881,7 +981,7 @@ void xu_process_receive(CTLR* xu) } /* figure out chained packet size */ - wlen = item->packet.len - item->packet.used; + wlen = item->packet.crc_len - item->packet.used; if (wlen > slen) wlen = slen; @@ -899,7 +999,7 @@ void xu_process_receive(CTLR* xu) off += wlen; /* Is this the end-of-frame? */ - if (item->packet.used == item->packet.len) { + if (item->packet.used == item->packet.crc_len) { /* mark end-of-frame */ xu->var->rxhdr[2] |= RXR_ENF; @@ -918,9 +1018,14 @@ void xu_process_receive(CTLR* xu) * size is only 1514, not 1518, I doubt the CRC is actually * transferred in normal mode. Maybe CRC is transferred * and used in Loopback mode.. -- DTH + * + * The VMS XEDRIVER indicates that CRC is transferred as + * part of the packet, and is included in the MLEN count. -- DTH */ xu->var->rxhdr[3] &= ~RXR_MLEN; - xu->var->rxhdr[3] |= (item->packet.len + 4/*CRC*/); + xu->var->rxhdr[3] |= (item->packet.crc_len); + if (xu->var->mode & MODE_DRDC) /* data chaining disabled */ + xu->var->rxhdr[3] |= RXR_NCHN; /* update stats */ upd_stat32(&xu->var->stats.frecv, 1); @@ -967,6 +1072,8 @@ void xu_process_receive(CTLR* xu) /* set or clear interrupt, depending on what happened */ xu_setclrint(xu, 0); +xu_dump_rxring(xu); /* debug receive ring */ + } void xu_process_transmit(CTLR* xu) @@ -976,6 +1083,7 @@ void xu_process_transmit(CTLR* xu) t_stat rstatus, wstatus; sim_debug(DBG_TRC, xu->dev, "xu_process_transmit()\n"); +/* xu_dump_txring(xu); /* debug receive ring */ for (;;) { @@ -1125,13 +1233,10 @@ void xu_port_command (CTLR* xu) }; sim_debug(DBG_TRC, xu->dev, "xu_port_command(), Command = %s [0%o]\n", commands[command], command); - switch (command) { - case CMD_NOOP: /* NO-OP */ - /* NOOP does NOT set DNI */ - break; - - case CMD_GETPCBB: /* GET PCB-BASE */ - xu->var->pcbb = (xu->var->pcsr3 << 16) | xu->var->pcsr2; + switch (command) { /* cases in order of most used to least used */ + case CMD_PDMD: /* POLLING DEMAND */ + /* process transmit buffers, receive buffers are done in the service timer */ + xu_process_transmit(xu); xu->var->pcsr0 |= PCSR0_DNI; break; @@ -1140,6 +1245,11 @@ void xu_port_command (CTLR* xu) xu->var->pcsr0 |= PCSR0_DNI; break; + case CMD_GETPCBB: /* GET PCB-BASE */ + xu->var->pcbb = (xu->var->pcsr3 << 16) | xu->var->pcsr2; + xu->var->pcsr0 |= PCSR0_DNI; + break; + case CMD_SELFTEST: /* SELFTEST */ xu_sw_reset(xu); xu->var->pcsr0 |= PCSR0_DNI; @@ -1159,21 +1269,6 @@ void xu_port_command (CTLR* xu) xu->var->pcsr0 |= PCSR0_PCEI; break; - case CMD_BOOT: /* BOOT */ - /* not implemented */ - msg = "%s: BOOT command not implemented!\n"; - printf (msg, xu->dev->name); - if (sim_log) fprintf(sim_log, msg, xu->dev->name); - - xu->var->pcsr0 |= PCSR0_PCEI; - break; - - case CMD_PDMD: /* POLLING DEMAND */ - /* process transmit buffers, receive buffers are done in the service timer */ - xu_process_transmit(xu); - xu->var->pcsr0 |= PCSR0_DNI; - break; - case CMD_HALT: /* HALT */ if ((state == STATE_READY) || (state == STATE_RUNNING)) { sim_cancel (&xu->unit[0]); /* cancel service timer */ @@ -1193,6 +1288,19 @@ void xu_port_command (CTLR* xu) xu->var->pcsr0 |= PCSR0_PCEI; break; + case CMD_BOOT: /* BOOT */ + /* not implemented */ + msg = "%s: BOOT command not implemented!\n"; + printf (msg, xu->dev->name); + if (sim_log) fprintf(sim_log, msg, xu->dev->name); + + xu->var->pcsr0 |= PCSR0_PCEI; + break; + + case CMD_NOOP: /* NO-OP */ + /* NOOP does NOT set DNI */ + break; + case CMD_RSV06: /* RESERVED */ case CMD_RSV07: /* RESERVED */ case CMD_RSV11: /* RESERVED */ @@ -1200,8 +1308,9 @@ void xu_port_command (CTLR* xu) case CMD_RSV13: /* RESERVED */ case CMD_RSV14: /* RESERVED */ case CMD_RSV15: /* RESERVED */ + /* all reserved commands act as a no-op but set DNI */ xu->var->pcsr0 |= PCSR0_DNI; - break; /* all reserved commands act as a no-op but set DNI */ + break; } /* switch */ /* set interrupt if needed */ @@ -1213,10 +1322,6 @@ t_stat xu_rd(int32 *data, int32 PA, int32 access) CTLR* xu = xu_pa2ctlr(PA); int reg = (PA >> 1) & 03; - sim_debug(DBG_TRC, xu->dev, "xu_rd(), PCSR%d\n", reg); - if (PA & 1) - sim_debug(DBG_WRN, xu->dev, "xu_rd(), Unexpected Odd address access of PCSR%d\n", reg); - switch (reg) { case 00: *data = xu->var->pcsr0; @@ -1231,6 +1336,9 @@ t_stat xu_rd(int32 *data, int32 PA, int32 access) *data = xu->var->pcsr3; break; } + sim_debug(DBG_TRC, xu->dev, "xu_rd(), PCSR%d, data=%04x\n", reg, *data); + if (PA & 1) + sim_debug(DBG_WRN, xu->dev, "xu_rd(), Unexpected Odd address access of PCSR%d\n", reg); return SCPE_OK; } @@ -1238,10 +1346,27 @@ t_stat xu_wr(int32 data, int32 PA, int32 access) { CTLR* xu = xu_pa2ctlr(PA); int reg = (PA >> 1) & 03; + char desc[10]; - sim_debug(DBG_TRC, xu->dev, "xu_wr(), PCSR%d\n", reg); + switch (access) { + case WRITE : + strcpy(desc, "Word"); + break; + case WRITEB: + if (PA & 1) { + strcpy(desc, "ByteHi"); + } else { + strcpy(desc, "ByteLo"); + } + break; + default : + strcpy(desc, "Unknown"); + break; + } + sim_debug(DBG_TRC, xu->dev, "xu_wr(), PCSR%d, data=%08x, PA=%08x, access=%d[%s]\n", reg, data, PA, access, desc); switch (reg) { case 00: + /* Clear write-one-to-clear interrupt bits */ if (access == WRITEB) { data &= 0377; if (PA & 1) { @@ -1252,20 +1377,27 @@ t_stat xu_wr(int32 data, int32 PA, int32 access) xu_setclrint(xu, 0); /* Bail out early to avoid PCMD crap. */ - break; + return SCPE_OK; } + } else { /* access == WRITE [Word] */ + uint16 mask = data & 0xFF00; /* only interested in high byte */ + xu->var->pcsr0 &= ~mask; /* clear write-one-to-clear bits */ } /* RESET function requested? */ if (data & PCSR0_RSET) { xu_sw_reset(xu); - xu->var->pcsr0 |= PCSR0_DNI; xu_setclrint(xu, 0); - return SCPE_OK; + return SCPE_OK; /* nothing else to do on reset */ } - /* Nope. Handle the INTE interlock thingie. */ + /* Handle the INTE interlock; if INTE changes state, no commands can occur */ if ((xu->var->pcsr0 ^ data) & PCSR0_INTE) { xu->var->pcsr0 ^= PCSR0_INTE; xu->var->pcsr0 |= PCSR0_DNI; + if (xu->var->pcsr0 & PCSR0_INTE) { + sim_debug(DBG_TRC, xu->dev, "xu_wr(), Interrupts Enabled\n"); + } else { + sim_debug(DBG_TRC, xu->dev, "xu_wr(), Interrupts Disabled\n"); + } } else { /* Normal write, no interlock. */ xu->var->pcsr0 &= ~PCSR0_PCMD; @@ -1316,6 +1448,7 @@ t_stat xu_attach(UNIT* uptr, char* cptr) } uptr->filename = tptr; uptr->flags |= UNIT_ATT; + eth_setcrc(xu->var->etherface, 1); /* enable CRC */ /* reset the device with the new attach info */ xu_reset(xu->dev); @@ -1377,3 +1510,39 @@ int32 xu_int (void) } return 0; /* no interrupt request active */ } + +/*============================================================================== +/ debugging routines +/=============================================================================*/ + +void xu_dump_rxring (CTLR* xu) +{ + int i; + int rrlen = xu->var->rrlen; + printf ("receive ring[%s]: base address: %08x headers: %d, header size: %d, current: %d\n", xu->dev->name, xu->var->rdrb, xu->var->rrlen, xu->var->relen, xu->var->rxnext); + for (i=0; ivar->rdrb + (xu->var->relen * 2) * i; + t_stat rstatus = Map_ReadW (ba, 8, rxhdr); /* get rxring entry[i] */ + int own = (rxhdr[2] & RXR_OWN) >> 15; + int len = rxhdr[0]; + uint32 addr = rxhdr[1] + ((rxhdr[2] & 3) << 16); + printf (" header[%d]: own:%d, len:%d, address:%08x data:{%04x,%04x,%04x,%04x}\n", i, own, len, addr, rxhdr[0], rxhdr[1], rxhdr[2], rxhdr[3]); + } +} + +void xu_dump_txring (CTLR* xu) +{ + int i; + int trlen = xu->var->trlen; + printf ("transmit ring[%s]: base address: %08x headers: %d, header size: %d, current: %d\n", xu->dev->name, xu->var->tdrb, xu->var->trlen, xu->var->telen, xu->var->txnext); + for (i=0; ivar->tdrb + (xu->var->telen * 2) * i; + t_stat tstatus = Map_ReadW (ba, 8, txhdr); /* get rxring entry[i] */ + int own = (txhdr[2] & RXR_OWN) >> 15; + int len = txhdr[0]; + uint32 addr = txhdr[1] + ((txhdr[2] & 3) << 16); + printf (" header[%d]: own:%d, len:%d, address:%08x data:{%04x,%04x,%04x,%04x}\n", i, own, len, addr, txhdr[0], txhdr[1], txhdr[2], txhdr[3]); + } +} diff --git a/PDP11/pdp11_xu.h b/PDP11/pdp11_xu.h index 973b07e6..43f1c998 100644 --- a/PDP11/pdp11_xu.h +++ b/PDP11/pdp11_xu.h @@ -28,6 +28,7 @@ Modification history: + 08-Dec-05 DTH Added load_server, increased UDBSIZE for system ID parameters 07-Jul-05 RMS Removed extraneous externs 05-Jan-04 DTH Added network statistics 31-Dec-03 DTH Added reserved states @@ -68,7 +69,7 @@ extern int32 int_req[IPL_HLVL]; #define XU_FILTER_MAX 11 /* mac + 10 multicast addrs */ #define XU_SERVICE_INTERVAL 100 /* times per second */ #define XU_ID_TIMER_VAL 540 /* 9 min * 60 sec */ -#define UDBSIZE 100 /* max size of UDB (in words) */ +#define UDBSIZE 200 /* max size of UDB (in words) */ enum xu_type {XU_T_DEUNA, XU_T_DELUA}; @@ -124,6 +125,7 @@ struct xu_device { ETH_PACK read_buffer; ETH_PACK write_buffer; ETH_QUE ReadQ; + ETH_MAC load_server; /* load server address */ int idtmr; /* countdown for ID Timer */ int sectmr; /* countup for one second timer */ struct xu_setup setup; @@ -298,6 +300,7 @@ typedef struct xu_controller CTLR; #define DBG_TRC 0x0001 /* trace routine calls */ #define DBG_REG 0x0002 /* trace read/write registers */ #define DBG_WRN 0x0004 /* display warnings */ +#define DBG_PCK 0x0080 /* display packets */ #define DBG_ETH 0x8000 /* debug ethernet device */ #endif /* _PDP11_XU_H */ diff --git a/PDP18B/pdp18b_doc.txt b/PDP18B/pdp18b_doc.txt index f9c5c124..fa7170d4 100644 --- a/PDP18B/pdp18b_doc.txt +++ b/PDP18B/pdp18b_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: 18b PDP Simulator Usage -Date: 01-Jul-2005 +Date: 01-Dec-2005 COPYRIGHT NOTICE @@ -395,12 +395,22 @@ Error handling is as follows: 2.3.3 Terminal Input (TTI) On the PDP-7, PDP-9, and PDP-15, the terminal interfaces (TTI, TTO) -can be set to one of three modes: KSR, 7B, or 8B. In KSR mode, lower -case input and output characters are automatically converted to upper -case, the high order bit is forced to one on input, and printing of -ALTmode characters is supressed. In 7B mode, input and output characters -are masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either interface changes both. The default mode is KSR. +can be set to one of four modes, KSR, 7P, 7B, or 8B: + + mode input characters output characters + + KSR lower case converted lower case converted + to upper case, to upper case, + high-order bit set high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default mode is KSR. On the PDP-9 and PDP-15, the console terminal operates, by default, with local echo. For backward compatibility, the terminal input can @@ -549,11 +559,23 @@ with the command: The default is one additional terminal. -The additional terminals can be set to one of three modes: UC, 7B, or -8B. In KSR mode, lower case input and output characters are converted -automatically to upper case. In 7B mode, input and output characters -are masked to 7 bits. In 8B mode, characters are not modified. The -default mode is KSR. Finally, each line supports output logging. +The additional terminals can be set to one of four modes, KSR, 7P, 7B, +or 8B: + + mode input characters output characters + + KSR lower case converted lower case converted + to upper case, to upper case, + high-order bit set high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default mode is KSR. Finally, each line supports output logging. The SET TTOXn LOG command enables logging on a line: SET TTOXn LOG=filename log output of line n to filename diff --git a/PDP18B/pdp18b_stddev.c b/PDP18B/pdp18b_stddev.c index 098c4831..9f0f33bb 100644 --- a/PDP18B/pdp18b_stddev.c +++ b/PDP18B/pdp18b_stddev.c @@ -29,6 +29,7 @@ tto teleprinter clk clock + 22-Nov-05 RMS Revised for new terminal processing routines 28-May-04 RMS Removed SET TTI CTRL-C 16-Feb-04 RMS Fixed bug in hardware read-in mode bootstrap 14-Jan-04 RMS Revised IO device call interface @@ -271,19 +272,15 @@ static const int32 tti_trans[128] = { #endif #define TTI_MASK ((1 << TTI_WIDTH) - 1) -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_V_HDX (UNIT_V_UF + 2) /* half duplex */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) +#define UNIT_V_HDX (TTUF_V_UF + 0) /* half duplex */ #define UNIT_HDX (1 << UNIT_V_HDX) DIB tti_dib = { DEV_TTI, 1, &tti_iors, { &tti } }; #if defined (PDP4) || defined (PDP7) -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }; +UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_KSR, 0), KBD_POLL_WAIT }; #else -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR+UNIT_HDX, 0), KBD_POLL_WAIT }; +UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_KSR+UNIT_HDX, 0), KBD_POLL_WAIT }; #endif REG tti_reg[] = { @@ -300,9 +297,10 @@ REG tti_reg[] = { MTAB tti_mod[] = { #if !defined (KSR28) - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, + { TT_MODE, TT_MODE_7P, "7b", NULL, NULL }, { UNIT_HDX, 0 , "full duplex", "FDX", NULL }, { UNIT_HDX, UNIT_HDX, "half duplex", "HDX", NULL }, #endif @@ -349,7 +347,7 @@ static const char tto_trans[64] = { DIB tto_dib = { DEV_TTO, 1, &tto_iors, { &tto } }; -UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), 1000 }; +UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_KSR, 0), 1000 }; REG tto_reg[] = { { ORDATA (BUF, tto_unit.buf, TTO_WIDTH) }, @@ -365,9 +363,10 @@ REG tto_reg[] = { MTAB tto_mod[] = { #if !defined (KSR28) - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, + { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode }, #endif { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno }, { 0 } @@ -917,14 +916,9 @@ sim_activate (uptr, uptr->wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ out = c & 0177; /* mask echo to 7b */ if (c & SCPE_BREAK) c = 0; /* break? */ -else if (uptr->flags & UNIT_KSR) { /* KSR? */ - if (islower (out)) out = toupper (out); /* convert to UC */ - c = out | 0200; /* set TTY bit */ - } -else c = c & ((uptr->flags & UNIT_8B)? 0377: 0177); /* no, 7b/8b */ +else c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR); if ((uptr->flags & UNIT_HDX) && out && /* half duplex and */ - (!(tto_unit.flags & UNIT_KSR) || /* 7b/8b or */ - ((out >= 007) && (out <= 0137)))) { /* in range? */ + ((out = sim_tt_outcvt (out, TT_GET_MODE (uptr->flags))) >= 0)) { sim_putchar (out); /* echo */ tto_unit.pos = tto_unit.pos + 1; } @@ -985,12 +979,9 @@ else { c = tto_trans[uptr->buf + tto_state]; /* translate */ #else -c = uptr->buf & 0177; /* assume 7b or KSR */ -if (!(uptr->flags & UNIT_KSR) || /* 7b/8b or */ - ((c >= 007) && (c <= 0137))) { /* in range? */ - if ((uptr->flags & UNIT_KSR) && islower (c)) /* KSR? */ - c = toupper (c); - else if (tto_unit.flags & UNIT_8B) c = uptr->buf; +c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags)); +if (c >= 0) { + #endif if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ @@ -1025,7 +1016,7 @@ return SCPE_OK; t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { -tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -tto_unit.flags = (tto_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; +tti_unit.flags = (tti_unit.flags & ~TT_MODE) | val; +tto_unit.flags = (tto_unit.flags & ~TT_MODE) | val; return SCPE_OK; } diff --git a/PDP18B/pdp18b_tt1.c b/PDP18B/pdp18b_tt1.c index 8a85a56d..0df221c5 100644 --- a/PDP18B/pdp18b_tt1.c +++ b/PDP18B/pdp18b_tt1.c @@ -25,6 +25,7 @@ ttix,ttox LT15/LT19 terminal input/output + 22-Nov-05 RMS Revised for new terminal processing routines 29-Jun-05 RMS Added SET TTOXn DISCONNECT 21-Jun-05 RMS Fixed bug in SHOW CONN/STATS 14-Jan-04 RMS Cloned from pdp8_ttx.c @@ -48,11 +49,6 @@ #define TTX_MAXL 1 #endif -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) - uint32 ttix_done = 0; /* input flags */ uint32 ttox_done = 0; /* output flags */ uint8 ttix_buf[TTX_MAXL] = { 0 }; /* input buffers */ @@ -142,22 +138,22 @@ DEVICE tti1_dev = { */ UNIT ttox_unit[] = { - { UDATA (&ttox_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT } + { UDATA (&ttox_svc, TT_MODE_KSR, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT } }; REG ttox_reg[] = { @@ -170,9 +166,10 @@ REG ttox_reg[] = { }; MTAB ttox_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", NULL }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , NULL }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , NULL }, + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", NULL }, + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, { MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &ttx_desc }, { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", @@ -222,12 +219,7 @@ for (ln = 0; ln < TTX_MAXL; ln++) { /* loop thru lines */ if (ttx_ldsc[ln].conn) { /* connected? */ if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */ if (temp & SCPE_BREAK) c = 0; /* break? */ - else if (ttox_unit[ln].flags & UNIT_KSR) { /* KSR? */ - c = temp & 0177; - if (islower (c)) c = toupper (c); - c = c | 0200; - } - else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); + else c = sim_tt_inpcvt (temp, TT_GET_MODE (ttox_unit[ln].flags)); ttix_buf[ln] = c; ttix_set_done (ln); } @@ -288,12 +280,7 @@ int32 c, ln = uptr - ttox_unit; /* line # */ if (ttx_ldsc[ln].conn) { /* connected? */ if (ttx_ldsc[ln].xmte) { /* tx enabled? */ TMLN *lp = &ttx_ldsc[ln]; /* get line */ - if (ttox_unit[ln].flags & UNIT_KSR) { /* KSR mode? */ - c = ttox_buf[ln] & 0177; /* get char */ - if (islower (c)) c = toupper (c); - if ((c < 007) || (c > 0137)) c = -1; - } - else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); + c = sim_tt_outcvt (ttox_buf[ln], TT_GET_MODE (ttox_unit[ln].flags)); if (c >= 0) tmxr_putc_ln (lp, c); /* output char */ tmxr_poll_tx (&ttx_desc); /* poll xmt */ } diff --git a/PDP8/pdp8_df.c b/PDP8/pdp8_df.c index 6dac834d..b6491d56 100644 --- a/PDP8/pdp8_df.c +++ b/PDP8/pdp8_df.c @@ -1,6 +1,6 @@ /* pdp8_df.c: DF32 fixed head disk simulator - Copyright (c) 1993-2005, Robert M Supnik + Copyright (c) 1993-2006, 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"), @@ -25,6 +25,7 @@ df DF32 fixed head disk + 07-Jan-06 RMS Fixed unaligned register access bug (found by Doug Carman) 04-Jan-04 RMS Changed sim_fsize calling sequence 26-Oct-03 RMS Cleaned up buffer copy code 26-Jul-03 RMS Fixed bug in set size routine @@ -133,8 +134,8 @@ UNIT df_unit = { REG df_reg[] = { { ORDATA (STA, df_sta, 12) }, { ORDATA (DA, df_da, 12) }, - { ORDATA (WC, M[DF_WC], 12) }, - { ORDATA (MA, M[DF_MA], 12) }, + { ORDATA (WC, M[DF_WC], 12), REG_FIT }, + { ORDATA (MA, M[DF_MA], 12), REG_FIT }, { FLDATA (DONE, df_done, 0) }, { FLDATA (INT, int_req, INT_V_DF) }, { ORDATA (WLS, df_wlk, 8) }, diff --git a/PDP8/pdp8_doc.txt b/PDP8/pdp8_doc.txt index 80219dd0..4e3ac263 100644 --- a/PDP8/pdp8_doc.txt +++ b/PDP8/pdp8_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: PDP-8 Simulator Usage -Date: 01-Jul-2005 +Date: 01-Dec-2005 COPYRIGHT NOTICE @@ -287,12 +287,23 @@ Error handling is as follows: 2.3.3 KL8E Terminal Input (TTI) -The terminal interfaces (TTI, TTO) can be set to one of three modes: -KSR, 7B, or 8B. In KSR mode, lower case input and output characters -are automatically converted to upper case, and the high order bit is -forced to one on input. In 7B mode, input and output characters are -masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either interface changes both. The default mode is KSR. +The terminal interfaces (TTI, TTO) can be set to one of four modes, +KSR, 7B, 7B, or 8B: + + mode input characters output characters + + KSR lower case converted lower case converted + to upper case, to upper case, + high-order bit set high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default mode is KSR. The terminal input (TTI) polls the console keyboard for input. It implements these registers: @@ -381,11 +392,24 @@ command specifies the port to be used: where port is a decimal number between 1 and 65535 that is not being used for other TCP/IP activities. -The additional terminals can be set to one of three modes: UC, 7B, or -8B. In UC mode, lower case input and output characters are converted -automatically to upper case. In 7B mode, input and output characters -are masked to 7 bits. In 8B mode, characters are not modified. The -default mode is UC. Finally, each line supports output logging. +The additional terminals can be set to one of four modes: UC, 7P, 7B, +or 8B. + + mode input characters output characters + + UC lower case converted lower case converted + to upper case, to upper case, + high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + + +The default mode is UC. Finally, each line supports output logging. The SET TTOXn LOG command enables logging on a line: SET TTOXn LOG=filename log output of line n to filename diff --git a/PDP8/pdp8_dt.c b/PDP8/pdp8_dt.c index 1fd97610..35293a34 100644 --- a/PDP8/pdp8_dt.c +++ b/PDP8/pdp8_dt.c @@ -1,6 +1,6 @@ /* pdp8_dt.c: PDP-8 DECtape simulator - Copyright (c) 1993-2005, Robert M Supnik + Copyright (c) 1993-2006, 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"), @@ -25,6 +25,7 @@ dt TC08/TU56 DECtape + 07-Jan-06 RMS Fixed unaligned register access bug (found by Doug Carman) 16-Aug-05 RMS Fixed C++ declaration and cast problems 25-Jan-04 RMS Revised for device debug support 09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR @@ -329,10 +330,10 @@ REG dt_reg[] = { { FLDATA (ENB, dtsa, DTA_V_ENB) }, { FLDATA (DTF, dtsb, DTB_V_DTF) }, { FLDATA (ERF, dtsb, DTB_V_ERF) }, - { ORDATA (WC, M[DT_WC], 18) }, - { ORDATA (CA, M[DT_CA], 18) }, - { DRDATA (LTIME, dt_ltime, 31), REG_NZ | PV_LEFT }, - { DRDATA (DCTIME, dt_dctime, 31), REG_NZ | PV_LEFT }, + { ORDATA (WC, M[DT_WC], 12), REG_FIT }, + { ORDATA (CA, M[DT_CA], 12), REG_FIT }, + { DRDATA (LTIME, dt_ltime, 24), REG_NZ | PV_LEFT }, + { DRDATA (DCTIME, dt_dctime, 24), REG_NZ | PV_LEFT }, { ORDATA (SUBSTATE, dt_substate, 2) }, { DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN }, { URDATA (POS, dt_unit[0].pos, 10, T_ADDR_W, 0, diff --git a/PDP8/pdp8_rf.c b/PDP8/pdp8_rf.c index ffaeaeef..1308d8ae 100644 --- a/PDP8/pdp8_rf.c +++ b/PDP8/pdp8_rf.c @@ -1,6 +1,6 @@ /* pdp8_rf.c: RF08 fixed head disk simulator - Copyright (c) 1993-2005, Robert M Supnik + Copyright (c) 1993-2006, 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"), @@ -25,6 +25,7 @@ rf RF08 fixed head disk + 07-Jan-06 RMS Fixed unaligned register access bug (found by Doug Carman) 04-Jan-04 RMS Changed sim_fsize calling sequence 26-Oct-03 RMS Cleaned up buffer copy code 26-Jul-03 RMS Fixed bug in set size routine @@ -145,8 +146,8 @@ UNIT pcell_unit = { UDATA (&pcell_svc, 0, 0) }; REG rf_reg[] = { { ORDATA (STA, rf_sta, 12) }, { ORDATA (DA, rf_da, 20) }, - { ORDATA (WC, M[RF_WC], 12) }, - { ORDATA (MA, M[RF_MA], 12) }, + { ORDATA (WC, M[RF_WC], 12), REG_FIT }, + { ORDATA (MA, M[RF_MA], 12), REG_FIT }, { FLDATA (DONE, rf_done, 0) }, { FLDATA (INT, int_req, INT_V_RF) }, { ORDATA (WLK, rf_wlk, 32) }, diff --git a/PDP8/pdp8_rl.c b/PDP8/pdp8_rl.c index 56b5f398..ac2376c0 100644 --- a/PDP8/pdp8_rl.c +++ b/PDP8/pdp8_rl.c @@ -1,4 +1,4 @@ - /* pdp8_rl.c: RL8A cartridge disk simulator +/* pdp8_rl.c: RL8A cartridge disk simulator Copyright (c) 1993-2005, Robert M Supnik @@ -25,6 +25,7 @@ rl RL8A cartridge disk + 25-Oct-05 RMS Fixed IOT 61 decode bug (found by David Gesswein) 16-Aug-05 RMS Fixed C++ declaration and cast problems 04-Jan-04 RMS Changed attach routine to use sim_fsize 25-Apr-03 RMS Revised for extended file support @@ -334,12 +335,12 @@ switch (IR & 07) { /* case IR<9:11> */ return 0; /* clear AC */ } -int32 rl61 (int32 pulse, int32 AC) +int32 rl61 (int32 IR, int32 AC) { int32 dat; UNIT *uptr; -switch (pulse) { /* case IR<9:11> */ +switch (IR & 07) { /* case IR<9:11> */ case 0: /* RRER */ uptr = rl_dev.units + GET_DRIVE (rlcsb); /* select unit */ diff --git a/PDP8/pdp8_tt.c b/PDP8/pdp8_tt.c index 1c6ab891..30a3f69d 100644 --- a/PDP8/pdp8_tt.c +++ b/PDP8/pdp8_tt.c @@ -25,6 +25,7 @@ tti,tto KL8E terminal input/output + 22-Nov-05 RMS Revised for new terminal processing routines 28-May-04 RMS Removed SET TTI CTRL-C 29-Dec-03 RMS Added console output backpressure support 25-Apr-03 RMS Revised for extended file support @@ -39,11 +40,6 @@ #include "pdp8_defs.h" #include -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_KSR (1 << UNIT_V_KSR) - extern int32 int_req, int_enable, dev_done, stop_inst; int32 tti (int32 IR, int32 AC); @@ -64,7 +60,7 @@ t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); DIB tti_dib = { DEV_TTI, 1, { &tti } }; -UNIT tti_unit = { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }; +UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_KSR, 0), KBD_POLL_WAIT }; REG tti_reg[] = { { ORDATA (BUF, tti_unit.buf, 8) }, @@ -73,14 +69,14 @@ REG tti_reg[] = { { FLDATA (INT, int_req, INT_V_TTI) }, { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, - { FLDATA (UC, tti_unit.flags, UNIT_V_KSR), REG_HRO }, { NULL } }; MTAB tti_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, + { TT_MODE, TT_MODE_7P, "7b", NULL, NULL }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev, NULL }, { 0 } }; @@ -102,7 +98,7 @@ DEVICE tti_dev = { DIB tto_dib = { DEV_TTO, 1, { &tto } }; -UNIT tto_unit = { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }; +UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_KSR, 0), SERIAL_OUT_WAIT }; REG tto_reg[] = { { ORDATA (BUF, tto_unit.buf, 8) }, @@ -115,9 +111,10 @@ REG tto_reg[] = { }; MTAB tto_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, + { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode }, { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev }, { 0 } }; @@ -173,16 +170,11 @@ t_stat tti_svc (UNIT *uptr) { int32 c; -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ +sim_activate (uptr, uptr->wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */ -else if (tti_unit.flags & UNIT_KSR) { /* KSR? */ - c = c & 0177; - if (islower (c)) c = toupper (c); - tti_unit.buf = c | 0200; /* add TTY bit */ - } -else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); -tti_unit.pos = tti_unit.pos + 1; +if (c & SCPE_BREAK) uptr->buf = 0; /* break? */ +else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR); +uptr->pos = uptr->pos + 1; dev_done = dev_done | INT_TTI; /* set done */ int_req = INT_UPDATE; /* update interrupts */ return SCPE_OK; @@ -242,18 +234,16 @@ t_stat tto_svc (UNIT *uptr) int32 c; t_stat r; -if (tto_unit.flags & UNIT_KSR) { /* UC only? */ - c = tto_unit.buf & 0177; - if (islower (c)) c = toupper (c); - } -else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output char; error? */ - sim_activate (uptr, uptr->wait); /* try again */ - return ((r == SCPE_STALL)? SCPE_OK: r); /* if !stall, report */ +c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags)); +if (c >= 0) { + if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output char; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* if !stall, report */ + } } dev_done = dev_done | INT_TTO; /* set done */ int_req = INT_UPDATE; /* update interrupts */ -tto_unit.pos = tto_unit.pos + 1; +uptr->pos = uptr->pos + 1; return SCPE_OK; } @@ -271,7 +261,7 @@ return SCPE_OK; t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { -tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; -tto_unit.flags = (tto_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val; +tti_unit.flags = (tti_unit.flags & ~TT_MODE) | val; +tto_unit.flags = (tto_unit.flags & ~TT_MODE) | val; return SCPE_OK; } diff --git a/PDP8/pdp8_ttx.c b/PDP8/pdp8_ttx.c index e5e1a944..5faefcd2 100644 --- a/PDP8/pdp8_ttx.c +++ b/PDP8/pdp8_ttx.c @@ -25,6 +25,7 @@ ttix,ttox PT08/KL8JA terminal input/output + 22-Nov-05 RMS Revised for new terminal processing routines 29-Jun-05 RMS Added SET TTOXn DISCONNECT Fixed bug in SET LOG/NOLOG 21-Jun-05 RMS Fixed bug in SHOW CONN/STATS @@ -53,11 +54,6 @@ #define TTX_LINES 4 #define TTX_MASK (TTX_LINES - 1) -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ -#define UNIT_V_UC (UNIT_V_UF + 1) /* upper case */ -#define UNIT_8B (1 << UNIT_V_8B) -#define UNIT_UC (1 << UNIT_V_UC) - #define TTX_GETLN(x) (((x) >> 4) & TTX_MASK) extern int32 int_req, int_enable, dev_done, stop_inst; @@ -134,10 +130,10 @@ DEVICE ttix_dev = { */ UNIT ttox_unit[] = { - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }, - { UDATA (&ttox_svc, UNIT_UC, 0), SERIAL_OUT_WAIT } + { UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }, + { UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT } }; REG ttox_reg[] = { @@ -151,9 +147,10 @@ REG ttox_reg[] = { }; MTAB ttox_mod[] = { - { UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", NULL }, - { UNIT_UC+UNIT_8B, 0 , "7b", "7B", NULL }, - { UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_UC, "UC", "UC", NULL }, + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, { MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &ttx_desc }, { MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG", @@ -232,11 +229,7 @@ for (ln = 0; ln < TTX_LINES; ln++) { /* loop thru lines */ if (ttx_ldsc[ln].conn) { /* connected? */ if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */ if (temp & SCPE_BREAK) c = 0; /* break? */ - else if (ttox_unit[ln].flags & UNIT_UC) { /* UC? */ - c = temp & 0177; - if (islower (c)) c = toupper (c); - } - else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); + else c = sim_tt_inpcvt (temp, TT_GET_MODE (ttox_unit[ln].flags)); ttix_buf[ln] = c; dev_done = dev_done | (INT_TTI1 << ln); int_req = INT_UPDATE; @@ -321,12 +314,8 @@ int32 c, ln = uptr - ttox_unit; /* line # */ if (ttx_ldsc[ln].conn) { /* connected? */ if (ttx_ldsc[ln].xmte) { /* tx enabled? */ TMLN *lp = &ttx_ldsc[ln]; /* get line */ - if (ttox_unit[ln].flags & UNIT_UC) { /* UC mode? */ - c = ttox_buf[ln] & 0177; /* get char */ - if (islower (c)) c = toupper (c); - } - else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177); - tmxr_putc_ln (lp, c); /* output char */ + c = sim_tt_outcvt (ttox_buf[ln], TT_GET_MODE (ttox_unit[ln].flags)); + if (c >= 0) tmxr_putc_ln (lp, c); /* output char */ tmxr_poll_tx (&ttx_desc); /* poll xmt */ } else { diff --git a/VAX/ka655.bin b/VAX/ka655.bin deleted file mode 100644 index 1edd8b931e10cc59037aab5a07569afb2b5acf1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131072 zcmd?Sdwf*Y)i=J+%$Z~ohLD*Fm;jOkf}#aIgQ#c`a^+GXoH;X-3tGyM3}H-2XfB8? z0mMteQYLA^wrM*9f=EcT;H9=gp9ZjfKw3T6fUPtde8fuM>Y)}d4TAk}_7uh9 zwt5`GhuPK`1E7G|W9-yeB@(lt1i_NYQdtgTTIA=~GNw2)wa6>k6iC$~pMweI6XnZm zV*6N%bWQ9fAY6g=T84?X#9^YX&NR@@iDsE5i!Ixw?L{ryCkD0c@^;0uik*^_)2WIZ z%$y#gIL=v3aL*!e!z#Q5VVVNdQ>NPX9$STr02j_A%1xF(o)vxJ9GrXlZ zwMcntmb56Ur+gWYE5{Y+wJ41lrzwjL>269o<@B~k)~VgfL!YP@qWU`*<8l209-col ztL+W0_FU=Tid}*dJ6pKwD=o2?5mQ@Yhw$>Z#9qa#v?cZiUga&ZxA0on5_=b~`%X<* z^Va4GZ?QZ3hQ%%*0j>29ycSu^w;;SFOtZ*$OzH93z+PNHpL6soUkLi%sf?{wZ2KM4 z7pvMf(dSHQe^`;fH|4zg*=prwhppG!8}U+&WAo5Afg z*j5(12EY;iWa&4ta#qD!*u(6H>;?8QvkOjPq;O5_22qrpm*kg(R)s@4U+alw1Ft8R z!k_7QPNKe!pFNg=m=>7~^07=jJb#GG2W9ygLH-8wyd0N*C(GZHzbnPGjdl?*q_lkhxSGu0eMv9>024Iof*Qd2($G@ z9yXF&ksOUZg~HWnj4Jn}*!!di_>(XrdzB@K7Kh;~vK3zc2JmiuXnyHLz7+ z%MT5gk1zC$h|BL*$VV1>hQ{UZx#Zt1^oVhJ(!KJp7Ji^uJr}<8d~&HbvdKUj1vK5B z!kcmp${K=rZ|qa5yFO|W*tO`NPXW6<%4x&wS&sIV+KX#^k_3^S5Cx8 zqHgPvOhsn~u=kwTW>FGFdE4`K?VF4tH5I9*IYBJVs%X4_cu%K#Q;$R#nLwMoHm)gZ zJ8wH*RR0w){cXM~S7zrlzUQ}pgrylz`}ir@Ku`%VEU*G!XtU(w6(&+>&;PrC~i zLh*fQv2g0lHQ__MB}RS8>Kb{@GSsNt?g&famDm!qKm^WIwC*)`FxI2$qR2B8cgAtW zF($2z0}LDGI%hR=3=~aJ`(^t(51QoG;iuC%=5eH^QU%Os4wE`oZ#lY-wc3w9 z#9A|su4k>n(TAD*X~tRQJ~_yGO668|R=H>Ikf+5}_EM!oRI24QNV)U*2otMaH*13O zJVwu_Q{0x5il(g5O4qc5o^mjfPwcLV>Yv@m*cx>3pUaGWESCQA31mB??M%_SM6cK< zbcr`(yy%O^%ao&dTY*FrfEfj*@-FKVt=$%)jk=YAh)s*E3s=Wu*W!uV$|ga8pV>Z8GNSr-%(OzJ zae4huB}3W_5B^u=ne!!gLN+HZuN|NLo-Yt&h8ShG$5Ea!v$)B6d&Jl*DbCjP?FCzyuP zm7H{gS{}GPsk|CF2d*F~WW7yE>MK)~Xx`C2R(^R&(TQeBW6oH(+S^9_Cd>I(qgdOC zB{{uF$aEg@c-U)=6d9IKY>mt(^r#*xB^zMZx7MS@I}8bWHZ4fJ@*-xoO=@duUdIj8 z%>zAt!bsg^*8*6FjTn`xjZpU5ccr6T$9~U5rKsbET^TQXx)uK+CGcj)=~=-|MAq zap#AJROL-Y+pOB!ZDGyAm4S$7X`7Mijp>+_fXp?EW3Tsq>ACHq$s_uK1H5K@1?Y2M zdeSfQ9t8O4(Z@wKVe$@QMhpoY^^1coo+HWPRkmhB3YJ|C4Pd)6_eN&3U86B-?#k`i zCCU4~kU#mt&@)WH+CV&YjJq8#sQ*JgQh$rS^?JrQk#Pe=3X+M`ej)GWL@-;0vEqhi z9B6npu>bFD^NRjzi7QnuU>_*|vT2#Vy^&e>C{M0eKJi_^imNpT_4+E7{(3>a_KO~c zcR5URZ3Nu2%h5vun3c@?-V5^i3rT>QP#QhDSyc8!tbL2!sokRTvAy);sD45<<^vlh zz$$B&sJ@^qNd-@Rx%TLKF?KX4_6lo{E_kjBjU)?7jq+*vtkQT0)z5AZ-iRG&q5?6?9f z_vEO)8)Li~%WV^gAdtKqcEncjMNvPGrjGb)x#+n&j()a(JoNq6cpJbiIa$4_(DC%O zNADLg_YY%*@__;-TL{ThD71QyE)t27%j&7b1ZN=`$97$%*BVq_(H42-_s3vTdP1Sf z-N^BV2%NZ^YKz{w#&d!7_?+2q7eYOhwrv*BB;ZmG{5Jcz)c0O1(vEHtp^S?~YtGnS z?(^x5*s;#&wXZ$eK-?WeZO{8``&7*GymRg&9KQc-I&p4{;DtUqm1x%6ai)yZTF% zu-+`8mIcWY zU5=b|JTtRI;EO$qsCBF^BR%QNA;zgRmGQZZ20#r@wpsrPg)%A@p$^(V`5KQ(O4BQ z|J{n(Evj3ew7TAk>ggb*IK}9bR^{cu;05w|@SOPF@ZvKtR@cjkW6X+VG4^Im1dMxBFMosg+fju<3o%;{&w4eJ z^K!;;kueBnFw~2Y>5wCBEBK+MJH-L!oM2Am%muWkChoKkVA z@d%>keQF~7ZaeMpFEh(i6SwS~)U(sEW#>&NeC{kw-RaOriA$7LW#>(NUcPEcRDbFH z0l(82M^t|r@uwyp5%6cQ{_f~1tQuk?$T!LqEFSG_Fe~5Utax4NR5^HYdQ|b0Lp?Rr zhlv9^p1D@Syn^+uUGF^(_f_gAzH^$ah=)Y=ltVeJsNPknUatY@H6|d0sCcQsem(1R z)r`2H|2ho6vAZX-+S6ynR?RuiSn6qsOI(e`78haZ`J>~ z)3z$juVC#+Y$)P?nQl_gM)rm7A}%+RPAF>5gC9KUXoh1BKWJk@@oq=i=&<)uMy`mA zb;zc%`C22RFyS)g?)TUsW_c%BnLoo`5$1iMFfs;zv7zO|fc`cz$Phqw&_Qx@Yux`# zRb*^`3?z%WLsYjAaoV&Xy;2dpMN#m~aMWnEl&V52+kMDS;&o%PI4$(avwp`J6 zh~Dmp)Q@wO|30qnz{;YV3)<)Wi{?WgCdA7qpcBOGe4Aq{7OpXdpbaikycGDvX`b90 zA@kB3!T8T2F%cUb%xY(8%*kM2d$}*snbI36;Mv9=+%W9HU4uOX{kPQ^8Zu(~etM_G z^xxne(;vh0ixmC((Tuf4N+YFicW(r`f}HPCjzxDMr#F(yi-n#bV<}}=^?#3o4TA%D ze+G#y<12+`dreTB*OHdU<343oB<}TgtyfkFigG4XvHVK;#Cz^)(y;YjxsCW;aK^V0 z@8$s*pj{NeUK~s-Z^hoouZMu&VZB0c(e*yk>oSd5P> z)+zUP(PZW9aOxP7-7_!f&w*k6sUog2C))%Va@XtBy~WtEhcIIUa1}5OMf(*7M|!ZqPMSloI-ML;?+Vk|cLXcaV(j|_WXd+*McovAM=l$EMKHBy8 zL)lbg^dA0aj&U`;omo(mAHmka(z<(LY&HQ5#`ldJk`JK0op!A=t8-F!r@b@le5Z6Q z3BNDB=0$7=X-enBSf`_xQ?u$5(l|ANaI^Ixwi@Lh%%&*sbY^1@2DRwU)3flZL&3Eu z<$}H+jiLV+v1b%Ckr(t#QbF=Jc_Hm+NZ%og@3c^3J1BI*M`clkmIAbCrz44h=g^;M z;IN%k+f<{KhJ0Uo%k7C%$efruSY`s|MJOC`=r}hG4@clSyC={lL{{ ztx3^3?TQm3nW#7|uoIi_<*ExjG_z69E-|LhMiZf)d3aGhAHkLv%1PE=-IfpxIFIRN z27+QD_)G+oE%}?+FzTF0QxR1=*2a8Pdq0>69QUa?nTG|x@=5^nG3=B2UJC>SLl`PL z`cKgLxh#w%npgZNkz|OZQ-Vyy5#0e_cR)o0ALas~RY2rf(gmyjb1bX&Pmk(LegM70 zrtRB$A6iVs<|<&gbgd^B{ksFwt)$ZEh(7L znH#^-?|!)mH<))yUC0rE+wJiWtJ^z7=TfYMZGr$NWev zJr+2&m6aV=OI^0(zB2d7K6lN??u8Xl9SmvZ(41G@=gWB?LeBfVV`&wgSuMa#SOm-K zZ(qEipIpq?>+DPCp$mG}#A4*yWX0`#zF#C3g=&hO=5^Qv^r3^Ue;9N8CtxPY0Q`$A$C^Wyx^{?e zP5ZIOv2e5MuV8dc5Rg+{*&@3Cr1Z8u$HusYC9aM#l%agFuSMNk=;`s)yD>n zmG3id@CX~ghvB2yFk=}@AQ-G@y_z!TDB8q}r+vDjbbIqUvH^D!a}7T%AneuXIUSn^ zM&8GKqFjC`sz0;X;BP4SlbL`$6I+fms=sI^f9k@DY*sv~zicL)p@iGwa7a6%s0Nl? z9bzkdmGj%Y5?r+2Nv?nGw_&J7()Dm(zJY@TV_r#Dugy6md%L~rwNB)?-fves9PX6k z^mIk_29x$i(0sym@H@Fl#s#C=y^ z?vnzRIIaxSt2+|_T8c0FWXhWMCv9*oOyZbU{d#1)=|dW}9iB{4oshstljsm+VJ>g) zqx~%G$S~R|#HM~!|6Lo}^&?fCJzr?2a3I++|?#*WaR+u<8#x z(Gts|b?cQMTqoVWqqv+jp9 zs_t|{Rg@2%quxZK-DT^cJh;E&@wL5P4A?2)hrH4>fy3b>418*<$DR?7oaF~EZ|YBj#_U?YN2D8jL~$_SR8iQoqY0$Rm>g6 zD&~%_oRAN{+H_m|2cLc%8lpt?r%2P3UoV zu{<`5&0{K~GTu7iV9ptM3eIVGTAWkxv^poD1b)`aIqnoY;BbyUCEz*Ylm*YsQ&v3F zjWbvXF)ag37|fh@qEyfKS)@y3GaqBdzwPEb5g<U~hh9-T>79H1z3Zv`{|}e0dOr z9hK@5J?q&i2vSqHxI9ffYe=G|o+?;ZI$n0b;i(wNqLXW$xu%B*Su=Rn&~pbInKmwI z&m^XsL1gFlXAcwjK_|~prkg=zlLe;(i2PwQkF|;Nvw{s%PIv;2@k4B2^00s{V6^V5 zJb_#o(1cMq!KKQ>N%@T_beDLt%khc&4@jTuh~dak{BVOP0ey@`!Mc;yvBTLob_+XY zS5Kw+jt6{WMmwcb>FTK=6v-XtbQ{hS%CR_8NNl5pw~LpQwUt_OY+7}>^Ty+4=n!n( z7@iq7y)lwy9k~Ku|MNwS9D&%|JA>Mnr)Xmp&neaiRhR_lPdScUSqz;#=M`}PD_4L6 z^qe;ZXS)>rX`IsF2z$8TCh<-umK!CPS35`bmUD-iWZ`bd*PAcGoyN<0kkJ_47cZ|^ zl~z%4#9yIRpg%Zx2T9c`;DL2ul&3R+6)G35?@eEKh0hSE@3;yl@IScBBdSeIXTw+) zP9u$Bt&4-soV|EtX?P54!6O}ymTmU!cBndc5JA><<+P}bKb@gSI1D@bbgnWKoWpS7 z+@@V}4mrXP+VKeW-2`8D?%hGN{=YBzwAf`If^))&GI;+s*dYzS`?!}{NX|_|AReE| zM!Ad>DR&&D&#pCTT14IIzggATW^#cyfXRsu-QO6)t0_DQ_ zN{xqk&q0h_SE!gD(oBuVyX+Tg^(`OAJW_P*(W2y<(dh z`O@vcGwx2o^OEbjRd!W}nTx--KJ&SvD*!?jMBN4T;f#R$Zm<8~GoK5}hb|Q39vajC zgNO)v5r~|8=5tDZ=JS!i2A`MW?%VPDGVZz$j*X)@p2k>0C_8cJu3PM{T}+P<6^nie z3v=gW4xX0;-b~<@B=DsM`0D`g_Xiw81m#7T+lkjNnL8b?*BLtGY^M32Ie*APBF0>P zfQ@TG7ZnpkR2wz5=qGScV#?+<-Orq_gLo=APxpf^3P1nM#os~+4x_!jB0tYZZLjtm za74Q7EOj+Y{By!xhT)yGz?fg7n;gy4Pk~xj<{Ca>e(LjhoV#|w+&?V9w^>q|1HF&^ z#Orlhr+B^XK*A9D7?9M1UKNe?kWuBoVev|tTAm(8Cim20_9#DXY4_uxW-6eRHs9jh zls4ZsVU(>KuAp;K{TzW#*=E5c%6m<))px+r>x=2P8YDM@q-UXpw0}%uxIft?UZ{P2 zRQy$L@w)79cA@2AnCT#i4`cXbB6!f77X)YL5r*svh>Y7Z0F#ykbHacbLom890CNVj z@dTY0444a8czcc|!5mD2*=oR?B$%g@V1AJV^MC>K9Kk#+kg(*9LQCnI7C)TO6vaj- zK#XF+_(lL~evC_{Nd)I55v()_28rMlq1~d$cM84!n64V>b18i!&Ee&-NfgriDG)3P z?6l}Z&%GI;I&?c1q5T(53@Y+JV8s)X{WDfB25W>iv>z?QL_39vpQnov7tbf5{d^GG zhbY@9?IVP!w4H?3Ovl#b)$AvJ|3MYf(ErvC_g52cHNnm2T>06Q1l-|%xNZ~9PjC}B z8$Z8ycB}?lpK4f3iUZwmjZ>LZf&D&`q=Q##ByONm)H#t^lmMl1K(2=m` zulWPc9BkG41Hb^V;7`0?ta80{qST$%9#SSMPhnE0l`7(XdEeq-)*UU2)s~?DMb&)+ zHZ1!TeYTe|>v~CPf7ILO)$cT7-Zo4{954A_Qe7ur^t)4>X+7j}g9i?dJmqEC2A-#j zhej{b7A;I1b02*_-1Y%-1Pgi_ENUw&IAHIEk9Z+;@W<#F$Gwx`MDQwNRR1xx=04>h z+*4Rk9<;EL&M5~)oIcZAkmKw2p%-^YAYI(4_{#|_7v3ZnEfoD(=GhfTDG4X(GcZ-K zTE|uFv0An9ICd;xc5qzvW)E$ZfPpPeNs+r*Pry@$qwS_^^#NcRjDCP3U>svQ*4Wg^ zzlj{c7Q`ns!c`9!Ald#ol&BgAFChs4W8;egL(^G*X~SCg*o@-#*c4eIkV}_5UtH?( zV*0Z|frvK<-qUHudG-w!@7aKLgXo3$YmvtffAuOc{oci}komeFFIX~iTmH#PO&zfH z8K}e023!Of00bEOCFO3W8P)_MBX1IH2Nga7tkEJ^eV{WuC;&ii6u6HRYYo1MGKPlo z1|VZ#fUEQ#qGr*9l%PfEFsQO+@dnG{E!!+xwpq7q6MMF$k$;vhFu)l$5iVDni(>0q zemzd1{>-SJWnrvSit5AZJsy@Bn$TH=jcj_?M)fh^s&isgA3^U)#tx-&jt#Xg-h+cd zi^-d7+n;W5;oFMMpqwA?5ZiZHaK3+sO?krm{m4b{4$I5wCs2OI`|^(j*9bZ1eeA}u z@BPS{qm#!I2Pj`ox5*C)@T(xO-?2(m)Kzu`YNf79GhXS&Ybbx2r9CcGLe;GDOK0Q< z*lBB}{o`K-xPil)!1tkfg@Cz-%UxL350ih%a2d-k zw_a*>Db5G_+oK96SV!!yZG(HA9MuM&neB0eoT$aHHYF7v6eSCpVx@CYn=;Hb zW|L5PnpMIF5rCGcoQn(X>%Hzg@ZmhyrdVCskj9oB;+7rOEjuhHcBEmudPmx#-a1>` z4pGd`Zr@?`K8~hnRnRPEt5~1dA@WL`!d;|PY*5)w@#|yORx5(z%(S<>*TLkmp7NfG zo`vn-hkI}W_6g2d%UN5^WS8xTz5L|8uUgC7YHo66X`2=vu^@h8VRp)E3l}2KDfcXV z6)T4t*=0Q#{l4}#+ zyPR#+lzU-Sm3zDG_sJhzIz3Fe>6c1GSQl}wo6K%!Gua&G#lMAYFyRC{#5aq33dR~cZn-qD|m!AD`7-;zig6Fw7&h^TV2%e6(2E+MX!Lu!{r7LoS z;Q4V}E@YmzxLhH4z7L<9f@P3JaSqcknMwz+69?B6Cqs?p@fJ@wE`Q77sRXnICopB7 z#ZwlS=UY5p6j_F)p`d^7JxuqMQk`KLh#_j21Q*0?T$>trKg@Qp-yv?iwNh+>!$KZl z7?-e!ldCP*2tDkpz!F5RLYOjRJaeH}{)UmckTPeRnd@0gg(Axqt<)>ul$3vik?*YJ zg!Nnh@WnfFI_3BHP4YIx0?tCp2knn=?3Cwm>SyT?s`CaSeL^78uT!>(_(z2OhbuT> zHvzUvw1qDh3AlFlJw?vEc;5FJr3JjQjGebl*m5kzW@DM>{Y!8wvDKwm)Ll4c{ zOPWqWZBuEF|GP?QsoGjlxdyADQrEwF0zIWYWl6G>Ah&V&n}~lm<2{Z4lh_RWD`L(` zhy4o!&g=0kb4uVZaM)i_<{W`|sWX$Orc(-XN}bH)ua&jRidN>8zsK4!It0G>#Lrnr zm7CeiVAj@WEq9$3$}>*0@^l~p+bb_*HYB-_lyTZRkX(qPIMd-(g*7R|abB~2_fb&W zBPH%mgo>W@h;93vc@Wtp?u3ehZ8=yyoyqsEYib7a&Nwy{E!>9#{Fg zYRvW8Ohta?0tn#@Yo7iQ)`N=t3nIqjZ}a#ME)f2*Q^4E0#O2V2D)M(Okj^(z29~I} zKj=kg_QLC?c+v9^pm_{>tu^ZV>Lbfo$HMoG12V+xjf`i>HPA1?1b%X=QZUEB{Sl zx3WC^%g4X=J*n!>^nyKhSjTM&-ZtA4ds5r>q}p?=8!Y$RY!F%sPRuoy!}7HqWZ=+s zZQC9jCU?2R>1|~rhpw{k5%vhJ2LaQe1bpMJjjU%=`3Rb~4KA05m2WX1y7x;=5o1;Rksb%=D#Kr_t@a>Q?r& z1@j)-t)eQtF_d3`Jv}T&ce_6~FM%hRj_hRoQri-dd`! z)zYyNqkLbgV)dM0?MtxVe4SRz&m4QNXtu9DigMojMynN+B!klTapwuKvC5w#43l;8 zKdxe}wvLr;$`ZH5x%{O1iSN-X$S@&C!ZU z_8$>z#X{px{OyQU;+>em>0dm=SmOF_|03m$&*E{+b~zo|B5cjmzgr3kh*3^dd17%} z=Hl$kR$*~JN(?Bm*bQojjF#QJ_~EcOOv#5DeVoj<7t?Xlx{u8DEhV)|IZ zOV$0rYvVbVoV%m3-2hQ~S6ulorVk^8A^LSdc-gw&x*z+}I80$AX7EJY1^r3HU;oRc z<7hzasy~8G1J@(|*a?1;3+J=DS)`7o9Dr--fcdYIc{*9-S$kxibqIS32SJ{K3B`T} zzY1)4*p`Lc$>${JU79WPe;wXSVdvniD1&EbT3jcu5Z7n1-E~G*zR4V@!}Ori}BTm7L{Lp zZ}Ic1?=7YL>U&E$zxv*?kY9aoxsRW{!!=Oais-G=>fru-N#G533XX#A$T~#oV7vZ= zSbKqf4a!wlMJ}nT6E4Z;49I=RJFlLL>A#{lPMjj%%L(`L!g@Iay?jRr9!SXi3!A>0 z1HDhh#!m9*ANccEc*b;?83HQfK%6(uZ!fPyFRxcj|D^#mg#*3Kv0vlQ|KK!!PuZgG zMs|-HgP(B*v6rG-knpjne#q@0w_iikr3P8LTbdwGD^HUerkX*Ceht%-V^Y3iMj0V_ z29Rz`25Y!8IVQ~-gfwLU>GmYB22X+oUasUDgmmiw(j9}45-bc&hZ_Jq;TNb2ty&SP zYzkFLp;eWk6;0v#I%%>rae_Rh{6>kTDZz%|@=#N#!6XF4G^NleRq9W}0(G95W=IBL zB%r&}=*eX@@IW4RH2BYM#|xv8h@X-2RnLiEl`)WRXLj>vq}lCb#tOpNF}#pzMJOT{ ze|6ub+!^`#f<;6QF@WE=apSV=Gw_ec2j^xu1xtq0nPJa#W*E@<<3B)soa7&AKUHwyz@i%P6BU>~_&2j2#PdqCL~$8asCEO#A^9>B&)q zlcU$?u;eIafXPvZ%aI%fwbkiqX*1K((jFu(@FPXR54w_qa%Unq41Y6`gL0FjppzU$ zLCI0zl8VufngUfxjsiD13fw`_!O}pD#*V#i!i^rI`k*`pA^MT1K{+`J%E?jSCPz`w zpePO(pz3$xZw*M{w`i>A#v3PG$0?&z7{wR`W!lB$C>NuVz+3!QFqsssWcm5%NA%-_ z2eCN3ld8YSgZ3RmLPsw|6$sTV2rZl( zrGk=jiE?r@5g#K-=pC2U=&~p;ZQx*Qo)1? zF1vlas*)*S4A$70;q;F6l_LM^CX5JvcBmKqD1aXlc@&RvS!=V#B_cFvtW79v zf8uBdCNJi1Z6eVBwvXm)<>g6`o&}bI=RkD)XPRldBi*R-44w<&0Nh~_403A`nU7ga^SUsaChNA?sSxKcVT|M3B1-QShN^Cf^t6nnYk1UE&_<5NTA2r zHF-`%%?k1gKqE4Za;b3em#8t%;2@Mi%}q5>7n7KbVX!Kk1;YaB{mi$4xL6CHg9 z{t9NAxDXS5CXYYE< znU-oxbB;B*;ylp9sA7J8WgswjZi46h{KDe7-e4lig^EamXM|t~@H1;fS^0ClGx8`t zlX9sXqo5i2kjp>|l7<;Sj!TIAXNV3#48>VlS%$V#&RqNghLRdKm85IpnkLo&CPm^( zXw+yrH#m4q=fHvmZHU&D@_2L%^#uAExM<%}KmyzZ#yCKdoZDYb&U1n?=L%f*1DiDh2fR{d6;K%-y>nIp=_n85 zf%?u!^k3NdnI!q5X^C90hu@+^lv+5^zDVN@Y_=~&(WFUj!BIUoOQsI5Sn?3NIc_g_XJnS7ff|;eQkopRG}54qpg|9SGpBODEwHPf|`C=Ac+8C`@HRFR~ z^cgvvL5agZMqiGL(PDJa?Kb0b9*&nJ-*6j#(mWNTZRThACq{mMxBky`fgNI&o)|5J zd-!^{Cq~QK9=?|D;fv)S&dI<*f3g4TUv7MMMp5(S=f%BZrDwR1R5RZ`Y{`k5gu5q| z@Lv5lgc^ms(CX*TkYjR_5&173i5ZcTh{)Gj(Sm9GOLu=rhWrhWY%?Icc!b~D;)lR{ zchKFJV!i}lh|gVdANpk1u>Nws3k2tUfPsP6UM01wbk88IeI8mn?4`<)Lwd&{%THjN z+L21iTL9%J<$a!%m+CXR_j&-`0w5e1MvHsRsvlP;yN67wd>*>Rzc|-ltO(F#q4fIr zw)-|2~-hyaNs1u3OYv%!H?M~&Hh3uba? z%)0Z+htaxn@Lo>$PL_73EHcR&S3MvUd@)7HwH^1;S!EO&)iH-<%8dMNmy~mh&Ck@e zZWH*Y>qwA-)skXKw~AIKX4ovYp|-RXdupoPkv1&dHe^Ur`;O2r{u0Ws^unF>n*y!_ z@4gFH7ibt?C5-7^lx)$DA(=?Wcss`QpBu?9n902srve!yk~4v!1^ihVqi z#v@!L=@%v%mR88ZjRIYvJ90t zsqh~84UD%2(Qm*vV1zF0Mf3B5K0x_4dE@ViapRmhESJ|gqCJQ`<1TT?pSROD*+|92 zZkx9)c&+OUK*jx$#jqp16C85lY)!>hG_T9S8Aw4Jdxl#cLJEcl#Wn10eeZw91SqJvc-ea^U5dh50Zz2U7}O*A#&ljIpCLOBMut zGIK3K_IBC9PI<*}sb;;Qzti4|$8owVS-wjd$#*dhur2}&E~@xj{KQ~XFF_oK z6ao{|LLGL`*-L0MB6Zjx_2FNk^P9cNq(*U4!+{zD4DP4kxMGXS<F#5vozEpqg~LPv*V65Q)kR=%Ej@b0 z-T;^4%dha>B#2bw-at%$in@qZp9MBsHmk(uHJDmzH!9*0Urmp%MJ04nXt_3yni0ye zZ*Ua1Q8W5Pj7abpv#e=2l0BJW?u)x?*yL|f`mxXc{;<+HX;7MWS-hpwkpPFrKSrep z`j6i>YzBtCt@%Rf*XJ{7e$~zUt@TrZP@bb&I z16tBy&cBm~qu%_xg)Z|$gaIu;UnOyZi}n=d_qI~Bd|7+-nnR^! zxa+U^aWCcX3+P^oUH`Bbh64LXR_p=dOnDg{i#eTJy+UV}YQ-IX6JJKHrtea&QiM`{ zgjlVt8leQ_wK&g7-@sgzRf;>#2bI7Yl!(!lDBz0tMMc$A6tbHaV$(OEknV}NEzS2K z@lCtm@(e+*r;O6_Zhu90W*JWZ=Yc@(I^5*ZD%NP_pm2}_iux=7o`A)&%J))@#Z{5> zxa=BhqFtd?DW%>X{~PO6x8sDGZ8_;*C8(L+sDj4?e3%0+GXa|k&^Rd(>% zf8slPIN)DH-*v!A3A_U+<;P|zXJMah1oIqe0!vJ<6W{;zCBFW-KVp~o9zMc`?ZNBl!*t1a z^8&Bp18qKj9nYtX$(mk>>v;SyIVAj3oX+z*bF@I2ycxkpet~Xzw{dwc;FS1vy<7Qp zJ)d`slZfD!IFTqlr1+e;$cLMCcOO*zmtCy$A1|wLN$BTMeI{qyqW>25lP<}zb^No< zr?IFy>GM?M>x1}ue77ZF-s7|35RcX7xjlZ__k0{jG2!PQ_qf{ke9VzR?h^3v+G$+X z*tD-ywb6rGyZ>W5qrjo_cP6Q0kz6qzujv$%zl+^}UlpH?;P-f=zkC!%0xg9PkK<@m zG3r`}-uJUVqiKD(z51NFVShot4_W#G3$DO?9qH}zpFWkRAka4A6vi84;v|nn!n&>e zyD~T+VD&V{2Qi9a$%eHieNGzZu~QAkaM-B-0|bu?{KJrZmRIr@+Qf8b^%ii1nEoQ> zCYT)Fj`V-?tH|nm{Y#v&NYpyT8Vpf5!C`zMMWF8!(8;4iBH!zMhhMP4oqY*cop=hy z(MK?k124Dq!+eB3eHqMR17^s;;?uT;*Ky#>3HY#M9tL{j1(DM+l1ZA_X}Ccfd(QVxnbnrghtW=hgoO*}V*0 zGE)fx==NnVR%1m!5ue?`w?0enx~uvn(LGFCRC-YG?h7a1WP%+&-R=2a2X~+MDyo$j;2`(jlWwCIJO+f z*1ARqw607#i(lSb4heJ-o>Fnw*otLag6$iWH!E-g^e5x6dOTUNb(MQb+bzpnIVa28 z4rF&_WtVH^Pl+#tUU{;-A;`DIgSE912X2%aLXDw@l_B_$xGxe9Y>M}9 zeOs+euv#tFulg}z?IlbqENjoP6lSfyWEU7L4r79io)-SJ@~6n3wv@GfOtjhY%);{$ z)^2GJ04pt>aMSFBWlLcnt;2KOM}m-=^3X?_0>YQ_1Y7F1k3cwe-A9r$C0z$(Du3Gf z)5dXA_%oG1?fhxbOy^;oiEIisG==M`rJ{f$@rpOxeDlpi=?sCdseZ+Zt7ob6N@NSSQuj)jlXSHm^YAHxc7S zKHpraDzq|O8EPCmG(DXu4fWMH8nK+}-n1-apc+z1&RQA_*M_PLSrymOISOB~f09%< zuQ*?wB>CnnD4QhBDW0cHl8VdcBBQ=R@&@MmsRVz0y|g@7_n@>i9ICBqBpwqf-);`p zhLPMrsfG2+0ahh}|KRc^;p*o4=F5_s>uT!iAE*PYH-Sjd&2l*ecBCd}%m--g;G_X;skt#EEqPE1CJSv4{RBk6+^$wu0w`El z54eWQh(Sx1qN--kYzi)^<-9L#uB`>J{&u{fNm>$;s=|!~kX%U+MMbHM1ZOZNsBXSl zT}k3~L?*R9{U-CDsUk)sDObYzmfPz&Ac9PFB~UGwrKp@u7HOb4^yGTUZ`G<`WW$P6MCs^hY_O!$<;buPgJC0ylaO6u~q zBS_NKt6&UDYFt+TfK=Js&_JfMGP#M23XrA`Lbys~MMD_KP1GHmLaUk#MCu$@fgO~z z!sw9$z0p9W?lcJQDv_%CI%vvO2&DI)e@e8Y*@jmkGLR%oP4&_pM)89iY5*oVbjR(o zj1ygiM8Byf=0Kw+0}l#M@kkTVW;HjG;g~W-n%D&E$E_*L5U#mjl!m7JgRq$;IK(wm z!p^xc35gcGr{XJAO)sX6K!_Sp%%%{v zh&YBqBw&mx!%`DJg!&`HQmwhehQXI(VGfu$zcgnaj2q5;Ii$HT_85v0vmsVgFppv$ zL|p^XDTulUqPHTNf+&bcb4z?g33qfQUts~^QZ6SnN6Ie+f)lZOz$%a6oRLIl-HOW#Z$sY5f#~gsjv9!f_1U#% zR4txMz+(oY1e`k%CEz?nOBVP7g>#CEOIbc*c;{o(nO(vP`txSZomb2X5v737uLcVJ zxKH7b3i6A?&+XaN{SZD;)Lf8 z;FjdiFJ|AMcwpA7Vs%03EOrlKg?@D&B#n=BaQ^0&*}qL>%4k_GC5`S{pJqTVG7ii&Yt0g6%Ln>9aQQHy6YKcZ@}AB+bm zqZBd$XK)696`J_@OW0V-z+6u)p2fzQ;llYvxQ67A^5+-KmMC%uWt8{=v!r}=HoJ|o z)Y;O4(qeTMyN>6TN=38%Y%0RuK>j>4%ae$fEGW&Nhbt8(Ndm#?9urnA_DYmJ9trdO z^KkdV;3yyRzaC-aN&W>3qFbvl|n^iut&QL^^wqZ$A4P zLQwVMB7F1=%~rw{6iW|>> z*e2$Hru~3978T;XPH?OUHa3P=hA^G24F&m7_>kb3AFNy!t_w+(%R-ekfLkv(NdE_> z1rOuP^z{#5NT$gR03Hz>syQFN1=f2dW<1p)%tz`Pn;M!cY3dB1M+HY=b7NEea^NLq z&zFHbHb6(JUlD4+qy~uJOG-5dJeqTnaYXJ0!I58yIa#B$GF)HF=jlk@C^-B;Z!{7l z8tfBun#XxoWk^~Ps;dGaK!0Cw6f}f_H7n{d@*uuRa5UFpW z#}%n}B6ZIdsrg9lydt##sa;p3QeS!Iiqs;cK6^zfHTy5GNS%e$y@F#d&Htf?Qd1bc z0BQS@B>kM=C|=%dDr_SyxB&2caw6taScEl`*1wR1_+nD{S4rWQlES}E3jZc4{Blxw ze^U5BQuwz?;r}3wt!u2uWE*N5g6RM=zZ*zwqE5FwOsxM9M#yucRD=W=5orp7q2{K> z%4O0-Gf<2Eeap#4$fO|@u3Uy$i*#!el&^Bx1EKJDD0%9QQgK~%ZMYH0fx0jqR=)>b zx2k?Q<=%E>E*7j!p~hPZgLT2GAi>-Yn8p>sf7QcYNq5{R%>tu;4`PZraR6poaxwu_ zhHfbc)mDeU-Aq#|>CWVQUvs#zk&->~jnZ8B48mBaAciWJgsMUfRJlgPQSXxa1`>e> zl~b^qY_4wp2j!qrzUKPnVFXbF-^vgKh0ZTc^xS+iQtqOQr`CD(K{8TO855oSBH7Sz`_Ersm|=f7Z9(@+gs1Q=$E zz@tPG>*=Mz=2|S#fN3tSrDefJEZIVJQX{S<&>EMs5M$Q-m8dOW+nCF6qO*-zi}<1( zliTeif~JNCNnUlKrU&X9YB*(#LctX`Lz=dE_0{1@ET$(@y+2qU!eR+EZEk2p;TZ0M z4b>rX`Viqq@a@@PU7aagn;NP*yFA#?5Uj>(vRSIVj1XbqYxusakR{nt_6BA%L<@aK z6P)Gp-pFjlt5($3!|BAO3epMI!pjGX*ES1%1S|f*ta4e~iqV6b8wM}9q~&Lq*M|+| zh%y^>o3n&FP>&Ts5Ic(&pp`J%38sY@jhVm@O1N=FeI2zhEq)+tg9;b5t+=r<7*3+r z2nHI?Him-DBxe1zwWRiLT~iS^S5m$g9{=PGIiO9A>r zIJBhE?B@@J8>*!0P;Ia(#7lpKS!RWn!8J#$JbHETx==GvxMc}(MShG~NY6vdd1KVR z*Syr!Z;PSd!6g8%TviL?V3e|vSq$?5RUmhM5v)A(JItqjHa-_-q%$H8>%J;V0f!A`)qixNqV5U0n#u^3f5I4 zb&0`Hj9E%y3NKbKp=r%*0uC7pZs8FwV$ROWdeY)*=^|V(u-&2^li34O46%oezDKme=n8ev*HCqHcuBZ6Y)C#O;jj!s(WC+Hcr%#H zQ%-+>FxWypp=yKrL<*UiJ_*{wn`1CJUUnFh?n=yZspJ?l;S+`i92xCkr1N%2DQT`p zAL7c+dlT_DU{+w;G2fu+NK=SZUYJ`~Rr@}C)aKY``gE3uYN^CWm@q4JKMy|2gxMH! zX~g^r;Ku-554y1V4G9xsbR=pJBDaAFNnIhhw6V6ismbUi8<}8^nKhp`G(sc7H8n6G z&9&ibL+B=E7y^S;htX)n*vTa>%xSKH?=V!`7-}4(?2SuJ-lI$?0#EplQ%#tk5SRs{ z)fm-6b;~eGY6{m%!6s@BR8m^nU`kymrd(jtUk#ky=ob%yans5RbFhM|=_i6&No_v_ zZxTUi_tsDTjB7^z%3n73dou4;lBnuf$^iqu*4&0LI+UI|zi z4mCe87~!#gC=!1or-|~L!%fwpmGz+pK2O-dQmI>DHCSKUR9_!9=P#+I0g|Zy^7%m+ zqFN47)rRk{F&ZRw!3r*@CBTRJ@}}S{VswNBTo!6Zb^E&j8jaAREOj=YtZJZbDO}fzM%1{+1 zef=^uM3s;%q&@_O6vl9H2QWlFWR}qn9%VxoEa!ZpyI%?T7#m_Luc7bILcWJ1tvFMC zh7T4S*bqbW`?G3lgS4dCn8<*9Nwq@vOToI8@4+1K2~Rt+NgEToP7Fz52@|5a%aq+P z)loKNE=)IOgQiI##cq<8ehTfYTOMqp(YCR_k2hg7M!gf_#^wMoG{%Pb!?m^5@6j5f z8sjz52sIeu9zva=iOU*AU4>-Lrrsu$n@lCPR+t^N0wSV>(7x z=tYtQn%BjppVw=;F0d}xQYB0>TmrN&(22j*StZ*<`aXw<;EnHiDe+UW>J*Cx2 zlAhWJ^mGtYNy=YyKUGtzJ0m4baT83kX^Yb^S7``UoAZu=i8)E-5tfGOIA*eglOJVi zG|#LI^ZEDR|BKIL2hGjXidSKlV&-sZH^SaE(878!sSPM0yc~(NsRQ}*#@NWxu-Qr; zFwA9*NeYpw!yiqQxoeWQemh}f?iV(u>WRrNSMfBOTwx>|n4OsHU}Ey`{>ge;(kz>R z6C{kn5*EW;JH%Krcw$oi;mT0h93hjlxyGlJ)UOQo&ru-9q!NM>27;zAMq55F$1G*w zH*`WHwxlK6h`xD36`PE|NmA+j0_-3nj+VJ6|MsaeJ#RCfw_&dYhYJ|}&v59EK1o9V zKOFo7i&eCxq}u7?HT}|uIEH2nGs0JUUY3vlwXbn$=xVTL+E>HS|JLFE=@+-I0SNtF z@x$RLqY_u-^e50A9P_u95)%=;*G@#7ZaNj3e>m^Nzc6qu-nc0X-#Ekfr|7K4Y-xg8 zDg6(_8qPpe`ATR+*qaV7zLL*SC#VJ-zVdd~EG7 z>{{Vy82*OikAB(4i%I62$gaa5@s<25=7$6f7sr53(^@BSPyj1P+I&MRU?T zL`Hf(`b>2ltw-QtVuojgw&|141q`GP91AGno6LhZ^bNSiyRZR1*)!$ln;KD^0mrvO zJ+xgp<+j@y24$2|t@MPKuzh#1aYkh(NY*pW~(qIrveDWMEt*yrZGI2r`rmF)R z#UXwg1Dye74Z{}Yn~#Z-!Nnw_VDvTi-R-!(^JF}}bVod%`&2xB4u9X@@cJM1k8~*E zFs3sdO23Y=Ir;OjExA}=B@1xud9j6I8xC(PD^Mt1M4a9>ruqtS-ZF*FD^d#m*He;TLDCJZXl|(@u&#-0{({oNTM@dE70y>EwD%_FE6gt`MCfbGr%=f9!XyrN z8$y#g+-*YUuWzO_f1!~1ms@x!P+0QAM`V&#S;-HpJdjqI_lLWuP@!e>@_)GdRvs!4 z*rurjPsQIx#FSefVqLd$cITlocknd)Kk~F`thi{dUn$II+MR5EzQ1q|+HTWbY~KH7 z@7?30s;<8AeP+%ilMp0xCWLU!0Eq;RG82LZ8zpxV4RGenCF7NZa7ij4B;0Hz4k}jL z%1jhmpA-zV`jq1Z@F`k>ssS%mta1Vgw&6(%^-^ziQZ-(|dB1C)Gsy(|ywB(N`Tg;} zpU?XQ)|_?L*_XA~-e>K-*Is*{1*L@ifO)QyOWhB?R!GU+P*YvCJ$yAQE-k64dT{qO zL@NgN@*F1nJe9>Y4`!)2W2~&KBJaVhr*PI7u$iEhkiwgZT2v)$6Ik%)-zsKK5s!;MRL|tJ|-`yzP_R@OZ8J) z6=f)Q00l#_GuUf4@zz{P=*=AUR@vEWxA2BtN$5h3daF)7tJab@%JNP<`&1prW`eee z#KCFx93$Fd5(lR(;TX}Dk~lbR8OLV6^sL%I{FIfv@vPd&v6>Ulsz2md^@(R+zm+hh ztU813UQTF9+4T?ZUO`w*849zKuNZ-@Q z;A3hmk zrNy3dVE2WIX+l~_T0nL`$mW$Um`9|CkeV0BJzJ@)glr@E5%LSPl2Sr`$;!%0OVDf| z=CxC8WxM~4V>Qr>ZIt*8B_O``D;=!~XFaf;DGRWWo)X?cRfa@%Kf)yk?B#Y{awTY; zJ4s$Oc~uWSxr<{nLHjkyi_?C?F`_+6^5V3|I7YO8CwXz&Z#hP^-6StgQ#nSo$4OqC z_5{a>_9V%R)1KlO(e`l3K|?&bmrD-Vefx-MLY^kc0onZ@TyjME9a8fGxo1B~j*w?a za)dlfk|X5zB)J-az5E=pBYOxvKwJRD<5B~5zeZ9cq?4ouL_N->Mx+x+%?o667fFqf zZju@yCrN6AyiHOAa{r%EyqZ!Ve_`lE20t{>xy`_@mW+$ z!4;iH+nP(7znEjB(M!&wZE;#D$B0&T9&L-$$~i`~it}h&oHmzZr1>j(%B1Rpw>|O93$FNDj26NhT6jxw0gs>hVU7)udHD{zHycr&S%jl`y5U z+EMlRazaZgC$rrv2&<`_QuX*s!m2B?<~?{D6%qXXbQKkmkkwQ~;<$+y5!k)WRK&`Z z@@LoZB37nU?pe!=SUI8U@pY6|2qUG-q_J3=rt*8j3EE1+3LwlhCKGcr1H z4%azz=D=wY4o?pHyBwxW*fg5?IdULRrSs(IHy;CaMsr3JfaY0r07fbxp60-P5g-VN zJ#YXm0tAgK%^52Im>a;WjlpG&!6yxyD*=?pjeuJKivUXjjezBV+W?A_DK4huF=ZxG z@|iM=DOWJ%N~RPrWi}qsV;3uyS%r+DFO!kioN?QW7C5)d3)gS2z3o@qSKayI_TZLx zwuc|d-?4MgsvY}YShb_$t>5m@`hL6P^gsG`^ncg4BNR&9(cT`|v3Kw2M_zn!^drZP zUH!;k|9bT!k;sxqqR}OfaFKX!fl%@S?8fZon^|@<%gJt@&MxD>^m8en4_`Q)twN-x zMT}q8>zC#FWwm~}jTPy!i*&)4+(Mb~REy&98j$l1avWX_a)CjP!zm&vktcvFMW9>b zst066#+8k+r&u#5;9M66oet-4;G~nAvg_GRx8Mi=>2eb)-^w0*k^-KsZ zVy55*oRWSU6N77+CAgR+1e;l6a0Rml7d0gX*Eb~xmp6?Fu5L;R!WApHwCSSY;-*o- zWlgEUh9+B((s8=-X6Dbj;>v>A#U-U>U2aiB`vqMDvX|CYp*CCMG#s5>r^ziZE7$u_BBW@gb8LRy@NVl1wX}n?W-p zj2U5Ydhs|j=w{J5$82%TFeenXm=Q)q7!hGagb@)&L>LiaM1&C$Mno73!dMW-f-n|@ zu^@~E&nV0Ig?7EtoBKGp+#gLgXBtM4C;s^p? z5u;ogLkeQZY#otZPL3e)CLO~Op|L!gVtF*h@@UfY7@6Fp=YhbnJep#8G#PooZ#9-Q z3GyjG+@BT3leC9L$BlHv$<0?ea!M8~@Xk{IKB!-syo{l}}8`AUB`;3!%2dlACTc`e1X95MX7>R8U63H@HKt%l;B2o${quHYW z<^Sw^+*{vzE*fp1V2hRx;^sw5mk-{ExLG!MXTe?FGVA+@wHmQRavZZ39*9PNM0X8X z_p(+%xOd~u3J<(xYq53@oUx=>v6Es_O0pPO(g+@ciBk|W5evMu)G1z#8!*MM#1Ka~ zGaSZ8tRs>;h4}M{+JV%EMFyV0R{%R z(~-D~ZkB9-YsAVW;(iLV0!u>TAAy;%$w=%W5^dHI&k{yX2qJ@Z-?Db)59?NlcA$E( zE+!&hx)KQ$n#I}l42K4<5vze&NnYfX%I}1FaUqBa@B(Y9ZxEXZZ(6cyN!=Q8GjL&p z_%JTwQaFK#PY_0HLE;O*l41+%s4iYFLHwGUoaogsRO7hIN=;J7^Q@%xbbKa1*ipyx ztyIrCKFf+TZVdbieju7ozmlJorsD;CwM55fTj|Xs+>GOut<)-v8yEW3!J9nm$f28= z){BO2@~tpD$KuQyjAN=>H5kRTbk$%CQ}e392&Pr_dZ{sjO*V2- z#fz*{;wft=%+%o&gvlC4S%j3c<0)_pY_ifa6y?rKx&j*(nyfV18DwY$R)MXT#0P4w zTZdM0sXmVjM4~-)u3=T;8X%q$}m#nI*?L_#j9^}S<{A58bQez77Z!6 ztP_Tjkdg~L>2ga%M^N9)SsF%gfumuBJn%D&FcaJiBjkgbVT4)WWfyG4X4bs7F8bSA;fZX#2#0o6#7>p*y^Km_hQUYFWGjofq_7 z?3Vg6G-Ts;^`aF}ehgDPYW5b~E?Ggh`dhGiQR8iN$AUq;Ab3@Qj>DRyAYyQ2$^a%d z92$kG&%+jG>G%~6Z4crnk>)~lC=*L!4>N2~>^I@Nqo*0>u^rg4$&eO07CQb6H&Cip zT4T2I1!hnYgH$Fj4y`gByBB=1-bF&7&e&CZTx!%@LwcfJpLI2Omt$Q3a^P_gW>D+ zz4kg+oTEkXn}qKeN*K@9U_^&wJvN7-Jk7Vm85?`u>LH`s!5y4h>iMQK+OIP**$)?* z#g3tE`w$SNF{8vWqsB3#+A+iJm;rMx-_TjLV7~EmE{Kj9e#Z>iF=L)V^LWeUs~j`t z6D)ue08geySuh`gvB4~sRji7PjLOR81s?2!zOitKhih(j6dLBWYw!TB*K1b{AvfQw zr(GT>o`+qX7skACFscy__QCH38Voa(k)EgrryrD7UYKTF@KtqiEo)jy?5x24 z-)yPj#oynIlz6KiYPv=?^J(AwjhrWgLfeO{=K2()n6xV&1{|2M%8f}U&atRlMQ)Bx zM-C1Y$j^6Ts~Wou_Mm?i2!{wzpetg5N?;H|M6&h5o9AEuPUEC7ht)s3@D~$XSY!KDGwLHZJh3ywkZS5bfDQ_k+MVx8OE9 zi3h#T_Y>nu)3BG0;2BIGtipH~$HU;0k;w+9C5>w^H0H^d8v7VM^>7oeZ*UZ211^8y z#(dl{&j{s#!xHgOf^x`4IdJHWLFGZKW-P$ol)CyQJod0hMy|1^I)nP5HvF(4EMg2} znnYfJy$)QA{Foe~%)D(n`ey32Q-zh(Yp0r;W>L4DD#DX;l}O#XWqs3aE0>8h`xO?6 zH1QSIi-~kuF4BlZSS`}*c0}BsY>{Sp!ZO%;acLB3LMN=_-?b1{i8PZHR)`pKVAQ{A zkw|knVXa6LI5UPkB2C=P=*vYKdx&)Eibw+x!)`&t5D}X?ZWS>WVIrMLA<_&jk!lPl z=!i5hF)v=bN~B5Ih!u5wGZSsNL}=J9agvn-{q;4xHNh5zyn_h%U;I%qt8p?~60Yyz zx&uHGcpull1AzWN@F(EFWD6h(FcM$`j0TJaOax2@WCNxHE(5p#vjDRJR|ARwWq?XR zHNXw<0j>w!45$Mv0W<fLVaqfU5z;fO0?;U>?8?@Byv|+zhA#ECDnERsdE5)&gz^Yy@lqYzF)r zU^fKFzdIj4$oGsndYqsH7I@=F>Ew-h-3ARPOiMCsMt+pF_lWhLp zWSi1E!ZyD*#ddA)NLxkkMYfXOQMPM(Q*BrE+H6Q1n6Fj)ULmqgT2_Evn!z}P{1$ej; zJQRS3+2G+S@bClhPzWBb1`pSOhdE;+i-`wjy909A06DCI99BUN%OQsb$YC+$PzyQS z1UUpC2QTCxLk`uDLnY);200W#4uz0I0pySmIXEGQT*x5@a>#-l9FW5V$RPuANP`?w zA%_&m!3sHuy_xs`ai|E|X62a3+jQb34u$?dDw9EOs=y7O1BykNC7ETJ6`3MbE&ZcE zfu)ju#x>2jW*FBAV=0!!Qk^MUQ>B1}4@{Y?!!e;)aRAiT6zmPkead&WXDx?wk1BL{lQ>yUa9-|LXYv*Wb9f0_M(w zz{akk>rk6W`hu42ibLdHM z66HhkN17}+LC{m7(yD(HaIeJ*LjHjQXV`X{TE?yr*kos|6pBa@}~m*3cP&8 z6P|K9H#vw^a;ZY&mtZ14b!wp#H{e!34Q;BEhBUE9F5C<~a?uzk_9zcGLyz)k%oBSw z6E{PTX7X{6rCRp8Tzo8Kxh`-mP#O;~!g) z8a_=CX;fqJdi>5=eAr@90{%RgIDx08AX<$``wbGx2rm&cDRddndooAoQOZ*}T3+og z21@yryXO;1`IUP()f_bIkHw%_e`pDs=}{KNRorEPnLrWuy0YR~PN0aZC}kYQlAPi$ z&6@?Ph+SKBn&D+M$;G`TC@SjyP6qRY;sD1B2*0j|r3VO-J#2*IhqHTRVJs8JgLVBbTFDz4A&M8kE=jGc=_uu1H2>nKi2g&7iF8 z7jVujEsfx}xOh?xgTv{F>#;A&H6OoD=jw&uu0d$VX90u2ofX#ph09ygu0gnQn1UwIT z1@I=I8_)}Q4{#PR05}h@9L5|3Fd8rskPWyDFbi-spd2s{-~-$YSOQo9SPR$)*bI08 zunn*S@EG7Jz%zj70j~hw1at#>0q+6M0tNu*0XU%CF%mEuK;{1*_#YYkzuE@6T5RLP zd&KtNC8jz0_J}PVd&HG(Vhi`0X|uMtz7iN~OKEZS(>1ll^#NVeT3n~;n$hC=GhHXN zxHMe*_E=lm94)Rt#qg{ad~gZRb6Q;c=$hN&+D%tyi)$xc^IKdrc55qWafRu=u*G#B zT|-4JF1T;Bh00o7Ffg`-DqCC_ueXJ&TeOueeS1>&h^}P`ldh{;Tx00Ero}ait{Ylhm=Lvv?r3pE zDZgNg>r1-c)8dNI^}ZI@-|71E7S~_t8g6mDP1mh0u48n4xW)BHx^8cAy-3%cEw10w z_0bmBUb^mXas8IAPqw()>AJ7Q^-H?$Z*hg_`do|aCv^Qoi|bChcC@(G)Ai*R*KKrt zt;MyBu77HAEu^c4^3$~o<)`bPQGUAqC(2LP(y7r^|bp0IV zr|VZJKV8qY*cg|zb&sfjL?TcL7 zf^pbA?37KV6w~@5OEB1U_qc7_)U}c&tgcblhSjy|nl^Q<$DY#ZG1(J4J!X8Y!Q#AS zgl$HvN01VnA2C!yYv?-<@F{}pB}S}v$#;i#dgRP$Qqop6QBzaFQfH=|IVLRQwkUE% z7#}~8%&u+Bx!QtC2#3B=*Y`zAzlcV?+ZIc+Z5L;+q!YW=!qz{u_K@rFI%bzUa4en! z#|y5>Udh_`zTGRNM@mvKbgE*m3U<=l>bb`*cHd)r?yr&02cpr#i??_+ubPqfsLA(8 z`Qq1uEFy{?U%xM3Yz%wUWap2?qajGh)ad+M!u{$xb-gSx5@EzCHn!mVjpX#wlPPgY zwuYkWdZ`e%JdW6?sTtnaD0)$2U*t_xqMGuOc#C>R-lL*#tGa%xx-PwZF@krgDLh6| zqs2Bd8)x|NrH!kzm$P1VLi^scy{7cYMws|*DY-aRW970n4OeHc$1_L!-ha@uI(l|d zu71iZ*7)_OQ`+}_LQhNSDNlB7GgeIWWV4K9FQ$if-zPTlFA!wD0{p z#WzzB8-g^iUBs8iR@L(W5LWx%4=BVLtVh@`LI^qx69)n5@ozHne~F%s$kh)FygGXk z7+=@EH$oA2^N6(VeBly0sZD>n-iY{9dYX=8V~-c=JJ0n{8`}52OKB{oQ1)D$-v;kW zoQuL&@AM$I8zm^FAY*c|7=vXfJtu_1vY;-gAGPm&hf*4cV21?FEZasS(^XCI0LAh9 zG0spKMe1TB(+CzQy5-S1onpfHq?cr|rE^O{#<;g-n+5Axv5=orqOTyNt?Qs*%RrjT zv0Aop$%gtR+?QctOprSv$TJl9VG5jrfP6Kai?PuV)kb=hiZajwrSX{BfY`qGBZ_)6 zJs*Rp4UNkhC`?Qqx+s#2GG2jThlB{4w``M$qa}+M(ve-u>u%=(<@UWFQgRm|9GE8Q zV=0|Z2^|(pO*RDaJ}fX?T<~XGvTy}l%;MyKWBcCsD6zv7C=FFaVNlUA{;4V4(7yM5 z3bTX4n0d1fwD0|rNIxYKF*&#nyAU4t^it#)4X=ShBsv`MzbA5T``*teqT3+D8=uHd zgM5`ihHpNR^9}M;gA7l7A{Q9s6e17L9WMM7qR`0wBfQa+I~@9nTx3K%VUXe8PvkO# z{0D=K4FyE5G{}$XWZGUpJ74+h)ny z9Z1XSs+C2Tru_cTLAg>^@^Qq_;TX4HYK7#~zS=x3AN?&AMzpl&^ z`gY=jhz~_^**0@a+4VIjpE_0BieqT1Y$ZOi+`l9k;x>WfWJ#VKv!pPdk)( z%GSa=x%T!V(b2QTb}$pV_6*x;$~esyr=3pRX_|gE)zoN~tk9}WsKV+q!cNoZ)52mK zJxn<((L;;#8H+9NA@fd?J((g;p+FPQnD7%xGq;mFq;G>SM4nu}4j*)(%@PiMtFFg~ z^LC29uur``uHJSg`cZctUUwIx?!>OUZR1gI0n}Tk5Rfd|=DTgl+P!ygHw6M60pCDP zPuos2z6cj+r8K3uQlabSWwK2+I;PX+onj*IWlW7{z`xn~T)uM_bJ}O|{t6-i(_&&j zK7_4`mR6w#9qY+xtBI~}MO)1^v zHg>(f6Gv-vu^X4Z$S3IN)RgqU1exBYZBy6T=lAn4=q!IO>Y??^>9LK)&ei$OMTvv; zrJ+%_Xlmg4^hb<#%FB6%sbYG1`<(0RylEb<-g z{CehKrZf`b+30<@87)Qc0{to%h?saOgXK*srb+@5xa& zw1#Ri8cWkcJIyAh-jp6$hGAY0o6^G^eGyvFe<3%P$SJ9%e@m)mk7&}=J8rSq60=u& z(NUo9`GQ7C6U>nCrP(W|!V9f<@XIOmu?ccZi~Y%i&Uc7+oZ`KU457GbwDk?$ci~Cpos>orJ`=TMAvRqj&gT^8r#vMX zO&y-TNW~`@d~U0QG74{!@t@ewUgU7_M0ihoBZB`mG6~@hZ`$JB=WTg|+hCIA zlk^$Zff}=Ga@6(jQHYIwzjean)SNuRl$ttjyjilP2z`71;cnfeuC-e_M7M1~YbQ@` z`7ATZW-0ZoXqH7u#HW5OZMy{7a@J(x&zUr_ZI@Z@Ra5%-ht<@SXWDVRkwe>}rrO(AtTQ5)4x z{?b~=2D@oHxmS0#lS{RFQ|1?zzP%^*oI7h9wdY*O1chl&7}Nfbw-OxmD>{yt)SJ@2 zvG8}m(P%OBjin1;uEwVjHIqkEyhr`sqcvW8hUTr)>U>9Qe4RcozPu)QEXNgPz|+e= z`PtP~*X6MsnxlnY+zhiSzLx2QbTxH?+wOczP)_2bwP%#NuTCnT%APNd$jXK!r6tFE z>}TJ-!1|7D{?7Ljsd3-oEp$0J$8yMlYQ|?Lmz!)~9CTQE1Bb<10(j|}w%e-o?N0Hw z-6h*?t=ag9AF$NPm=hG6Y#(X6MQ>jjezbHoZ3A#-!H0P_-~8)6ff$%7Zh#o1^0Ski+NE6Ues@yB{end-fBrr-bcTp zhTlUe&L*bSC~bFny4>9!$$T)y@^Y&CZ4X#$oh^^G9&zGDa@*cLa;4mwDyNx`IQV@R zBF>JFn1IwMZn7TNi1xlSjkPWFA1ci8|5n(~4i;{$*w4D}LAJ%2v-vd!EzHT0IW?C9R$$dv@4!m+j9l)!@VFf^0vwt*Ol_J6){JAv-T+gl99? zb5VMJw;(SA1BWJc$%8|cw`S=>l}R8Q#MY6rWZ9}(ZJDTCXfyeLTC!R*#*(6JNq@21xoGhpA#VGRBG`SyNQB(sFs0N^;&1yhvCl`HpWTM#( z$|z9qd0#?Dh(HrfgeFmxNv3w%>w()u-0JGV9Z3`@K!Sh(CLYa%X#H-CF#`CkEwqaJ zOmaIp>8C~nGe_hNf{f2WyZ6<}kx@YVvFxq}Fe=3gb}*M6hT==dYD($CRrEcQwW}Cr zAjY4AO=eSquv4TttnXwrnqBv^zP;!1miFy^*B=(tb#3=znA3Kza>^}tx+hDft#YR# zOAWSnU~O23SAg_Tj%HP~137B0ElHZ+A*wk8N`If~bZepiz}GGn?boTBv|pzItbi22 z1VF~7CM3 zSQ!P^B0iv?^Gm$;MM^+aon7E4#3ieR(jX`|SAZS0TCJK(Y)9B6HCM4KlsPH^xKu$| z_X`t+My*ciXSjwf>bg!r&5~wD#-_7M13JUBrdO!aOj`^i) zNvaew#6FBh{mx@wNmptDLdd*T$byu^8wK*}QnXYL9_+_wZWYOfNP0%-IzQwkKa;6e z=NuYEd>O1420a^6Js3A_8c;sdg1cY`i~bc0$Kt_JXzk+}nYAEmH_iqclr_dm?~H-4 zF_5LV6O2*2)+J3%4lm#1p`cgI=~Qz0gI=_0oMes1FTcxD#(-3oDN&0hM1U)hyl+>wZor+o}U2Z%-%U?Y; z%Y(Y13@A*!5hghn#+IllYNac|Ld{24H&olsxJc>*Z=s3_u-WJ9s^bQKN!1J%?}0fW^9DH zo4S-(O{5L)QuJqov9_wyG5-uFsq6OFKT{h{R@ZG)r%Ox2Bh+;ed8;~IkggA>3}wf2 zktz@eF~cL(bz6TUAl^lKyvxI*hT=^Qrw+v%%#aeePqNq&T;`~&(|kr*ob)=CHi&A$ zYlfG?^QlkyTi6C+lFp{r0>bP>@_nlynjEcgY{gj>WPxg1)DXqGuG? z{;?rRmOK11Ldzv}yiW?2)OFQr^0IIm7+;3M$!Me5;nBFOHSWeBT_o)92o*tG-T~iZ zTA-v3O;bkGywwy=r<%~;+A-?7!OGCkPhwnOL$O)x)ADX!7*Glalq}|IXL9|c% zzHkPYA4_0(!+4@6Q32G&3T#&|S0w;yX5ho(vUbXB)wG2iT z!SzRB9skI)vnHUKea9IeYiS|c0_lMs&4eR~R__gm{(!}YdM%(jHD3egtGhvOBELE3 zJv-6t740K82tJ?me0TyXWvvjNh<;R0O%J||2iKEqr{ud1I7zF--X(pMrxtdp1xEc^ z3)|^kQVXN^}OJk|1Sw3jeOE4MOtVjN`+if?${n$B# z{{#xv*X7nWQ=(sYx=opRJmr%-ZAutQ4;IkMmoSVCPenP<0PQ2fSyZAjULq?)IxleT z9w*+@nX1za8Goo=a`7R0tDr<>WK>*BIVJVG!M~;y*XpX&{r7{3mS3nj9VU#mexXiB zM|BGuZ61fu6vno!U>60BftmA$-_tY3_&E*>7uBs@ z%<%0y9qGrpCD1N0OVG`*qEfG#zX1v=SAabR+CJo%kMYz=<%sM~`+7sN0&dkZ%$~_~ zl#2+|IrXdgDY}J|x}sAK`P5|j)D-#DRM|Dcv@V^SXM4mch>1vFM&PA2S#@r8Q`d89 zit0R*s5-Bpex}DgRS$E5!Z`FN6DaWSLhJ+8DW$@G?39wXxuqnS9No6(U4Id%&xxhd zPaQ>1h{m5rO83X5beuYko{&29^wzki`>6-$3HgSe&Wn4xg!%>Iq&4(7SnyNt0H!*C zUrU{X{>X>hA5fRj8tPD8l9M`x^oR%P^rT_YuAoaT>Iu=Ha|&_%P^d_Cq7k9P=vE6P zlg;c(7O2PQu}c`E7fAio1$3sVMbi7Eu^~b{>EZg#LE_O9I7$k*i(XkI9#`}&{}>YD zzmwubnuXGKQkp!?2T3Ik6=`G`YB45svy0|R=P~*wrRvBmKAWmnuo;Tl9m44yj&YaS zk~nH{jGICVvBxsSXcuY7ne-r<0XqBLXh>2XX+7P{_?eok=2KyRdA{F_28cN(w-2fL zL+yxOBRzENDNK<@8?$T>@XFnEk{Z+FXCYc{y!;p8PO1f`B(=zLQZ3|H8ml+3bwUO{ z&T6btImo*cBR`QX6s)Ex`ip~>&xDxc_&Bm32{sOy(k$KRILxlIjO*dP2-ZlMT83)VZED?WA)X#%Ts?QI6Qo3Xm0U+? z90UWHI>ApPxCr)e_|E#Q2PVKs1hZJ`5#DF|$GuPQl4~o|{Ay8bY^bS4Pc%SRicd7~ zL0pJ^N4h6S9W6_8WDY?4mW+Z8m=F3x44U|fLTD&9$N5BH-<(5*SmVh*9KvpM_C&)i zG0Q`wU<2&MTWp$|f6GQ0Gf%v6ohI2nw%?5Mk||>Zy=MI;+}VubHYz|<%b?OsY$3Zz z7>lpra=DZEE+hF-1(XR%@EzxxOqgz5XT=GhHLhH>7F#Wwo8mFFb47;_M_5T*M*|?k)1%teNL4C zM~@>QZ%Fa`!G>__(%u_2|BbssEWwXjq8YiGgGx~Ip9nzu1&}`G0rAp52+vF|{eoMx zEjLmHbjxNL-xN|YLocn6i<6ispB+J??-Hnpa8;%0gj){%sGKys znp1>n$w_yo=pJof5c<(8jPW1&?@6R*E^?*+q{g)}bpNvQsg&Z#1&@rz^H=dai$DJZwX`OxRXjY#AF6{7+ex3t*f~y9 z$+=KGJnZ(~j7B6hl5~0rkvKmOF;ePXYJPfT7v{%!OM=J+%^~0Z4j=y~lLB`>2mL#D z3U3PZ&}n~_6h0mtzyl2Sa^fFKDs=&P^`)Jp<~1u%q8!oh)YEp_C-ON$5`Qq4Mmo%@ zr>nm_l&S^(IC7_2uu3wYRGl43sN<7reutIU^-XM(DIGN~;|u8AjMRj|!3OqkraRcL zO%^k45x^hmH2O0;nTc?!Gh>Rmz5$=tSjaz1%GTpME*xFBwwX5+ye`Se3PQ^7H$iPT zZpYNyeHgC=Ok@H0TB!x3*evk2QVXb|Xe60nLw5uENVF0yfNAt0WQM_9GQQS;scGPY zXjGa_jiqn5)tw$GqxncaOnbPi@TlVayRo)PE0gBgbVMFwAE2)Iu_uh_ z2aGM`eQ@3^=L$IA)G;rdPxu#H^?ukSni^3=48N#-o*FM}d@)|l$MRRB$!_U4;|hCL zehM|%9$`F=U@H6BAF@1(>5&w#C1;0+Q+Bb3nH zwF@FB8fj)Qeo*&{X$viI)tnlybeNRG$%iu1O3dC8!rQXOh_^MM)Iq9yY$;48id_ z)*0Yybm&4R;|SbwP&mWCXpBKr2lE>?w0_e?B=a17_CW1-!Mhl!r5l6S4A`gM!JZK` zh778cp3xF1k(7Qjq9Ml~mVwcq4lq3B^DJ*ksP8d%ed* zePX^`qfhRBD|Y#NSawh7G@fU3#RoHr-9t_2!^M?-d!O~R-R+}Bq}{C?XUq7g4;~eo zLiScZ$|K9_)H5bkv{L&zJ#kt3fbaOHYOenX37rN5Ht_?vWNOO-r>3dS9ySdbLN3`@ z+{H<>&*D`W$LjIDcDPY3S+TGl2N2b>#Fz}gmIz?xqQNl~-HYZbvN7^Mk?)2Bs?QDS zpbS1Y%DImTB zc-ItwseLeF0~L(aI}dm@%?gq9EQ(-81i-syM9_m_j)?p-XugL)shI!j)nRt6{LVG^ zJJ$$?X~z;Y4r;@vvekSv-2$WO(!g4z$7j<>@uv2haBXGkIte-$D7W-=@Wn$ThB;Wm zUa`=8p_JOW3oeCq%NDL!OfRiDA=x~RnJ_z{Ki;-=6u(1_cWC8F;|arxlgtsW(?s-} z7|=Qo{gv7-Jf?j;zU))ka*r9mZoOesOYX!q~K+ z({I^G-UnXN=&uQZoLvl)cHeZgWV1mG1sSP9i;x?Y~&p($R`Jk*qh`V}Q^4w7AANBO6GyJ#>Gjlh zrRYno5D8?!2Vi9WZKHSdEK7tNZHQjW&YBeIUL=F2-WS0XA88;(JsG@=-F3W^;5M3R z@yYKG0yTj@|?sgwl+ynl<(bCwNaqhSE>Wd{YEEd_YwR#`5uuQT# zcY1tMdR!V^MjEe!y=H-|(fYgXj#UjBDK9a^+g-;C_;yFCQTre3Qif$3k-m#2B9dMg z@sV~}d8}Q7u|DFl@EW(Oxu!`8zff~s2frmv5{6ORx#E=bS^?|jlm(Z~ADJNy!3%+G zlj<>eI|#>!r zWknbim*#=aPSr^RQY!|Fhrb~;&jY}~!}Th3exa`O(Xy#=TVhY*)ce2e0EEU<*?Z2l z?K!6wotn1iTo_2P^Y>9SJW5GR4fLzI3252qi%}4Z_JXKZV;UT@d1SC`aFx!g8;t{| znlU8hL$~xu@!QcTaY`r4|2wxo&GVGXm(hV_hVKH7U=$L~WB6Fff%O(gLmG1+J^WS4 z+~`C@9c*nWpyhhi*#=uGAG+G5{Rc44J&lP9jdRET1>@XIsqlbPUndsSqR0qQcDK3( zsf2ov)1&08sP{ONBYCKKB7-w-S&jfmG@nR zjJlV$km%l59C;7i9l*?w#=3Elwjt8f2b{%`SMZ#oy^DQUpS$0(C4a6Knq3btS6P($ zA1Xt7lw74BZvvg+OD$ z+jLD8mq;Sw!iFO0nWr+>PO6F?wZMjgskxRxjN9FiEvF3LfXRFdd6f8k{a9{b!BW;E z%)J3F^`XOp`-kt7lfzg76^+mRzjxfX@8WLbih#AUQ7z%S~ z{&8tXDoj*rj$ohs#wb)W;ndO{naLb;0MpH~6@vcqU}%8(viq4$RI|@)GXCkByCX%- zrHA`WyG;9cnW)YScfo{GSci3u6gB@K)%m9F70f>_oC@YF`gVhYt4br&pVoN zaAkc1PoBHvx+(c4Mq5sFvEr-2Is3?{cj|H|#q)UOf&gzT zMn`!i0I=hXYIvv)(a`YRjh;jB@CiuWGj-cGZQG>(4tOFoe&bJ#km&RDNf?c{Zi1#9 z@O)xCqFUTo=kLOV4SiMJ#yamte;rj^r{a}dRA1EhL#;$lcu8^iNc3W4vZn!piCa;~VUD;9i_`yJS zY|nSH7WQdjzZS01!hybHJ3tV_nmMeQ!kQ57JN9!5;nu>67WQaiZ{M*WgWwBm{;*aP z)&gM~FLt^`X-}tOmQ-xylOFB#3Q{|-Mj@ENZXH&Q_=ptKH8I~t0l}0BR8?I*$epoN zKgObZ4Fq5=q`JaJ21VNxgoMa`h^M#}d|F+dwyA@O9dNE!J{^2Q6|8~m(}Esd?(Z?G zR^=l;Vn@_~8;k2u9&YkZ>JU8x%9oTPlID3(4bwdz^m>R)K1|<$bll^m+q$6U1?5Yw ztM!O=#2hsNBO&k@G$O@i$ETD*A613|mUz|?J;rgbM+^F>O^|1DK512|@Jl)8?-{8g z0O}ufyPXs)LK^O8?{QJ1KTBsHLWF7L2RY1(i6jdjOs&@436Hr-61Udwgn^3B0*c@{ zl+WeXPN!>w#-uDREjS+NVaP#TO68(~pMW05J_bqxwiS8<872ti@5g6eB$&Rv@9BFN z^%EqxpMWY@zjX7n5VFc9^WEm}MBUxM|Ma&#Y!NUHF(&Ia39T zCh|lqi9siO32PbCnZL1V%~~vklY(+!iIVLVve?T)HG5kqVjl|$oJUM#zA9#^WF0+6 z*L>>4(<7v1dKfnc_ORL9+iNHFqc&#Uc_6<>D8Rni5IdLYAPk!l1C~YOlGMyt@r*!x^5uw6$$;laR;1p@RNTP$+jmH9hJ(GU{M3V;4eKA)uPe9 zz3PQ&qCsN+OOE9<1}SD2Ho`(7A(I{~A|gI7q2mCiExECDeoyHftBqcm5ZBPT_CHX& z8=n_S9-*wXcnM3{(We!G1 zrSyax4jhh3!SI*|GsS|z=>mg&`7;D%aLh2IL>aPRBg7163~IPI2em z@71&L5{KZ;Z}2t|en(UQt~HkWy7U|BXrT>%i9EeJ%YpH)8i~frk7%ean|IsOrf5gO~Qo|6NI8W^nc- z@{-z&l9IWBN_vEs6yAgLsHC_SQAvw2ucn4WO+~=k%J3SdG8!)kuivktHCt6Ep4nY6 z`wg}#GF))huu%5g8&KH8s$26fjW0a*86yapAe{9AypPH24YMSyU&77+Y_>Gx1pN3U zvlAX0WJRE+P@YJ&mQKb1D$B^hT3bhD*a#D;-uUqFhS>BU6&r2f-L!ay405* znMnChMgH$FsgP#rJpa6Kwvm5M_+mWVngCmr^G^wS#?vm$xQ#Lv8R=kWW5TKImbR5N z%U&5?sTOx{q3N}*CE)OCp+OqA&fB*4yttWJb# z@eaxd1&e?$@wLJRJcZkU^ROndX34UqHMf%yOgWZrEV0>`LP&=O61D`*P)!G7_pKl&1p5aTQH1~(jrW( zkx5NPGDNj3&>E1XDaXCu0nhKqnSDS}H-ygB)O35L9lG9AbH{H+<<1oio-hP(u1PR> zqW=FlyBGgS^=XOjuzMZtgn+KwxKtr_ox2jGi}@&1(XGQ{`AE~Fn}$;c^LPe%ykj=< zAhnm8(2vz6QsMn*#gJ%fpfdnwVByaV9PtM_tbq-o^8u_`k}Vk{dbj3Ajve|l3aJSTF&D_sc)79l#MkNz)uP$JqvKMP zQ7sUp&rsthF$yB<=ucv5A{VTjF@X!bBmgFdFT)Ff0aFMc17b8I`zkYPAOB%|h|3Y8 zR-tAUo`LA!nlM3gqG2jBwraVkg)&LHAc3Q3ICEHBDm;1~qW{5!Y1d4W2qS?zf5WJw zIDSEVjrR{#?Ei27U^5y00}e-_LKpCvC+1+#zkI?OVdKuYp}5U4;jz4Z*XbhV60sj(tR3AC81R_k>8G@i!f!KY*NlIv1{#D)boBN<`?4nC9w zWy+H=+c{l|qhp^H-?-DOkiZ%s;?qkNDbfY%0bVg)!`)Kl~PPg#QdJ3d0`! ziplkm$>_r297MAy7fqpDn@naHuwFF%E&4*#Sajx>Jmy-&BapR;mqK;I6$Fz!c(EkF zXa&DGW0k2I^J{~3s4-eM!G8=@-OhVy6#WHvi0C^u#-vt~v5Oj+x9+5uTYd&;KtN$* zPwM1OuS~NE_epgA{m#$%$`TG&Lo^yCz?2x+$dry%jn`g)LtTO8U#_j;II`WaOpyl>{$rE+nF((AkmlO5<6UiX zxvR|?xY|f36}pT-5bSz!cF8t7v^CzR7}uG{j$?G50;34+qrHRMdrNMsYg+73=!=AW zAG1D!F*f&1q`@*?oFI8q%eqaa$k>G__jBt7cW$Glgs$hwjOKu2KfP&bn3~`xu5TFZ zEyzg8Eta5=ky6vGiZDE;B1X)(=oTz(r$;Vkxt3|EQc2)P;1bwVw zmJ;y_I^4FAF^WktVV2{rg&5mH&-1-dU9nB;NwICG$jjKi4hJ@{OqNsKCAL;$JK^zJ z+mRx}Z8kWZ2>02YDSG9^G{>NxkvFnIE%~|e6h|*nUv1%zpX6 z!Dhgl?FEq^D?^oCjO3?(SK6?o{?>(9VWJ6HQ*&%ZhRi*USnqS%ZEb3dg>-O3&IcpMSi!_zm6AK3VJ?U_! z4AjMj4gLZ_S{U60*u(K+Ypa2D2e zB0=kZLaRZZ(=^887l(dvvQ8X{HRVK#+irT>b99uu3yc5sj}Imfj_el{IE}j= zh#L2<+oRjC7H<40jt=Y%k#pj=LS%IoK5-GdSFo(}QZ$J2UFBJpgqSx#8p_GIc! zPG`!O+eTAgawb#GqORm@x(H9Dv0Q4gG@qefrQ3s^ZkJ$juF7^@V@}4G4xl3VA9)}S z;-H9Tcg!P^2FC(3-JqLHV}auQ6Jzd)b+|)u?R=^n_saQSw2GxcAcUR)2M`dC`5DjeTv6~*FDJdTNXnsQF z+nx<3kEg?fv8r-9Q?d4AuZo&)t2Lt2K(+`g@Ywxot3C>o0YG<`6fxR{LoS7mq+8S+ z=mM&hnlqWp5+S=~vVB5_NG^xGHaJBIhfD~O z35RXk9g1<0eM}@N4Nf}l0~0XgcMAt57&|}@n)-3h0aoXoKNk#ATukQ^QLIGd$9y&) zC*LyeIby=_*#ag_9!vKY-FL+K#Z>a?oOJ1-tU~n)h2s;Kk1|%5F6rm!9K-pu z_h8lm5soGBxShP;OD{EivNf*{mXyp?jI?!hl11~nZBO^J6j9ATB7XFI6@@D-XE)_sQxM3sropx<2$Btc;UcoQw^r^M)`DJ539*)3neM8#R;~ zdwI+D@v6i|IPM2QelwMtS`F*lR<)#`CBP@)%tXH7SVSLPawtP{c(gq!UU(~i=r#XB zEdgg_fBN(wI*1ZeCR%?YBw`z}O)bIbU%;6z`P!D1IEN{SwLu)}`-ffQt( zs_Xh6zi;NvFpMm-pn?mIJ5gfZs2F2N#4RzYN#1+2Fya!yeW{wIscD6PrcIir0r)DfUtPdlUE`J(} z5Bh@rwJ9Rxw@sTKaL@(lL%kjOX-D$rg70|LHFHkyEQE=pv2w_vO2?tf5sj6jIxuyw z?qDOh)ono64h|1OW;a+qVL?x8G=gXnff++&3RX29%Epyb62KTze_xcpqKQSz!a%$b z%_+^wI(_B5ldPhfQo)XzFi2(GjBzGcMfxRYLQr+jP^=k?l%Tkg~m)osis5=&Da_9C#G za=vxM>S*H2TkzROCz&Q-Q$5)lM~+m)jEf#yy_O6NIVC$ptoTWmeUhO%;J}Nbc10B# zcVWKXWhmkirr)J6g6c{Uw~H%c*%~tr+NFcU4>=M$j!G{eS(&Pd3cYBIsA(r6d=_!m zhmZkD#^@`E>hTrv(TE*QA~6I*)gkm1xMvEFMg3xk6QUx;z~FYk5M10a_B2h z_$z4bhrau$_q%8kpb;2PkZ8V9YV@Fh47pi(5F7#W5Q$pom7)xBWZx{S_D;>kMU2tHXTIFf`5M#W*F|T)2)O zcDlaO`We!>Pz52Bqp~?*DQe~g^l-$F<*z_sK8{KCzN5-`NBcp8U9d$%Ez;yIEf$wK zwBo`F@k>Z?@sfe1z%e%o{YTZhD;*dZLy%Drb|4+upk|saH6p_h0lPsmA$bpa>SEj& z^%6u65^Sq&qH|udwEeM8ch`F!PswBQCXWogm~3J9P~qIwS1U(Uj_3d*x7wL?MHRu^ zdND^!mFYrqS5f7(%Damy@2Z?ugi|Yb6~WB%R2q!VoNitI9M*W1v6n9qcR4%z$!x}< z?BFvYlEINIdK@ey;0GJx_ytWJ_-(YXApRw=?)bWAnDhMQh;)DdCE?DieP{#@Ctz|H zY`ki!6od@2!*k^FzQTOo*Ie^5w1Alj)UfFHb1P>RSIz?eY&}&uHza$JY-TO|rOH`2 z74cK1?Fm4-rIvA?k}`w$q*p%aA$Br~^L2Px6wS~W!yR(?v2q>;C1}rfiU=hjtn}cF z7nszBl|EZ0k(E%i_7MhTg9tI-!y1i2f;ms4VDvU1j-7we3$jUfgxr2rBu zH)pq+uwE51uGYDLdG29)=a3+*48n%Y)OR%E?yXF>#$oP=yvvp8wJR$#XriA?^y|-J z<ZlnhN*{)JmH-7*8daA+WA=zh+1?AO3wVCaQxDCp9VeZKI>0)`F1wo z%A;34?4;hC`Sg>^BkKxU3M7AXts{h8m%->s!XGc82kyE=z-(6D!RV+rk%~Umy#x#) z^#)}fqQQV3DBcZ}jR+F}sF5kXOiE!J365dXm=5A5*UG!}>AUor$`>VggxZ>$4LhCS z=YU+`8xU&OwpeJZ!GJIdvg@pxx+IOm!5VWF0`Qs3Apm3PKPTv%rZGyEPXQn+pcADf zw4N3!zH$B~h;2_@{s6{Ze(>_~iv*MzAxoQm;bQC*esSp-&JmH3z-gVh`0p#|K?Q3!8#Qr{2OvWSRf zkAiUMDg|voJ{}}k1ZmXKkfQ-d$VgRuACQY@64)-#BMZ~`JG={@ccNA+JDZhhs3QTI z7%oI$^>-OJI(7&3he~g6w_>{%<3wwK#~wqSV7-@SN$XUt&P_kIHMZ!a{=M0BM`>aV zce2j<+i+mG3WW2;&ds5f*iCKy%SCFd&ial)mp`06@l7IgUZ5VCGi%nPbI2GuEn_zE zZuTqQS#dE!KvrKk#%Br_I&bJ7Bek;NqAGbpNDAVMwXFwRXzsyAr$_Jn4WrU710gP| z6+HIXjzapvVlntDcvY7j+Tp3-8?tq_jl~swx^2w~ZPSNh>lt|Xd?ZIao^`f|wG^<& z5(-rH^$g~@dQ`qZ0WBR5r_DNyX+ss-D-V$XUV$nN)9bP5i99(uI%D~0rGJ>I} zF{dE}))zSWh9(l(Zf;LOg)ljyF|cFf+YjBFNMrWVGZ8MTJPs6Rb7j=?1pS}{5_$M+u^1&-5LV!{(Mq&=7^ixq$Y76&3}e0X z7f`X@hd##0Tp2=HO$;CFBR2GBE70fE!NiO_<*sSz(`U?_ zHG9r|_s@Oc!SBp_=;231Nrve{Z|3~0g^w=D&RM!_`HGdR*R0#{*yB%rf71_h^R$86 zkLEig0Oh>U4fz|j7pp``IN2d69m2aE!k;>vj|cxT%E;HDj2uE4`DTmgEN?Y=@hkkF?u;m)%PJ- zdfQzZDVY=@HkdE?KJl8I+16i66JKJ^Zpb#1<=jqVog+hUM z;TSD9pkRbo0?L^+CGK|$pXmt>TM3jVKHFidr$iXzG;^3m+p9FnBWXfIof3r67A>He zB}}9U8~g3jgGA9F)y9yE#%Sd8P!ZS&pamKxE|6}JHk6}>8E9<-g-9JOz5p=-UkF3r z>gdJLS9+YKJp?~fh;jOl9^sc?IzI_&T^&zdZAMo^Gn@K1)Ymn*VQNZZAGQzec=>bc z*;yMNe|-7UCs%J+&zuQgMmqJ>=fcwVYdwk{run#8`7L%9oet(3GHCIz1&fkarH)&F z$J+1SwsG>rr|x{>d(Nqwe{kntrj_4G zz4|^G$gEpwYo-pT^)=Q$Xi&S%`8=q7hX)VTgb>{tf)*rR-vSV?Ia&jz_cq|V1^QyG z&sU1ALq!*n*ieBY?6ZP2HhM@VTqC=*8oUlqc7EB5Cy(_w zpX!Sz8+wEdp94?AC~;Opi3x0=!Te>SCQZ3-_Ct@(+prQx#Yx_-d*g4Iy7~%Ku8H2U zuH>A}e;025J59<#M#Q2FX7T4R0@4;$9dLxO3Yi|vf3)mcc|3^iK|?1s9((CMLt zGp?QK++O?01}_QZy(DEJpX#GbG>uL-(l}d z?|gu7R_0)DJ;bAGWmKjR=SR4Oyx=3D#Z@W5Kxw6BBUBTke(K!JV7S){_(8ZES>W<3 z>UnQiDo_wwIv3zLhL(wF|0C^Z!$uHr1xBGE`@>5;+67$J)cTs z8Xx*hz;wJ2Gi}=usxzRpgY~I4);*G#tXW@bDzIMw5c)KO&^+?}vQC)&1e)WWT4i%< z>;+!XHrxH0`WL;hI@`2x6J3PAsNgtAGKO8!_FRF*k^B;{FHML{>s;1S(T$451)bY; zG}R*m3}~+lAAg~JY;B_Xy%9j$EDQNMn$!`OK_V#RM+*hpBoa2^g;osEO(R)TxaCRO z;q(HVwNt)AvZhFh7~8{inp##E^v)rG%r)$=^udmE&V2;^kUY6t5~{gtV3J^8-wXTb z5R)|e+PvdVL4_^o^#aKWAr5rc#T>v=@<2B@+!mVAo$ELfKHO#f&rlvV-3K5PUi<7u zu}%^@y;n&9Mr*_WLg*<3bcJMKF57|L08)4rq0QGDph?3#wiliE2Zcw$3FCwn4%TWw zr(NO#GpT%i6{xkH4kICqI6QCcS*80c1TD|;8ui@ZDj2qgKlMLQeBBT zqMeyVx!r6QUF`{G(G9!Rq6aj8rAWRKPKeNjBMe*#KOE>NVUEU~{l;lLCro3`J?D>* zyDns?iO53(S3cp$IpHX?;Bw#+P!tlB%{~l?KH28yyjCMUG!lV{Y?OrRqvg`*!MS+| zMFCKk3g1wA6^9*MuzH=@GAwgcr+7g#N^Ehp^6s;Ja%l5{L0nJP|ItPwT$xQPZLv6o zt!2t=I_p~}+#c&OUH(%n%J>+pdquc zgod-g{b#U|M`Rw$j1}6nkdB2cHYd|yo+<$*fvNc%W(xe#oYV;J7 zY#Py0>m9@%5Q8-a`CvxZS>GlascQCFD5E%JWELi$)5@?`3yEh#PgO)Zo0a=$EsM6H zVyIlYN0>~N%e!^u{-?T~w4NZ^3wZ_jM3UvD5uruhKwWRB8!6Y^P`6+GHBz_DpGE2h zlH07z>aAOP2ynmp40W@Ac1ys8>ox$*9Zs{b`%3_=$@&hFX;cjKIaDzaXjBZ8`MQez znaJ~v6$^$zRV#e@X}Dta(S(*UtH*tT!OUzUao*OJ+yG4kpdpXrij`ACv>zvJ(>216 z3jgw3;ov92?>-CR7IqqFw~WpV1%q`#Xj>8E+$afmchez9mcbzNlNm9d*g#ByT{Tkm z31LrY2(RRTacJBX=bwW#SqM|R1x07qS&ym`B>u>OiAVvB2~5c(63Sqb^JC4D<#9gK ztF=VnyHVtcu29Ap<}_nr$1+lZSFcq-J9*#K1$Q8}_kd#|lp$pGfV#S9BH$Xbajvv= z#OlGVLstw$8t8#hP%`>rknsCZr&5hvr#d}vQ;o0zYCRzQ?2`~w|3(`r;kGp^4)i+Z z47QCjv1uQ6qP>3;?(4#wJU1vET6KPwGaIiJfHq34ROxxC6McW<- z3X`wi+_r^5niE59`_5IgEgo&7M!|SOsK<=Lq^r&=ExlNyccNX6tHN)Y?WERe*SCwN z#DCOhhETgSZWevkr(OTu5@{D^)Bmwu+J~V&`}q~L>meBAMIWsT3JY6=(Vr0Ki(PZ! znJWh2hgU)~n>Ia!bpfE@qcsd#Wy3=otY8W4X4-KQTg1vK+9njR+WOzvo~E1$?i`b_ znXb#vXRow=);d6&R^;U?VB&NY=9GsKANuin_qAslwy+8mHYF8S+}PEuO)K<)eo@HI zpd}8vTj2~scBV*&1GYS2Sc*&z!s{SZIF|L@xfP}~3&&gD#tHmuJ1y6y7j4vQlgjZk zwj`Qt8nH&hCRi?Lepu3t^$$%Vn-Z`)1a-0>{W6FhX%LHMWgD=RW&s*dSKIMy604~rQ44i$f$Lm}{gidkC7!$xQg55JQk>5Lhc zJT>c$U}%^=+kSw+{YO zmi5_Cz%HQ=ie<3kfGu*Y`$9@5M0>S!#G1Q1K(1Tc!s^4p2u?cI2gM^u1{^NxfjSG$ zT7RSBT>DZtmU;^ty+B2`$8IVGQ|9gTTt4WnbR^HIhkaBq;*28QP>X?HhiwpT7545V zmf|=NR4l|n`eSY^&|m};S}qVLPlk@4%Tp)LfpBbVr~E5=#rhfc!Cuhz4nu_WkGK;GFwKjPE9X_3Q(h4b$I@qS>Ux>{{|VM+ipH3o^l^|J3O}b zPPw(y)pQu28NzyJ_IH}whohg|CC}1Pf}lO_I2tW~VKT}d+uyC#s5i!vWIcg#W{mC^ z8y}>FB|cyY+C77%X!m@UuHEY>3L?*u5GajVy%6p>wB?Y5Re46X+|CTLt9T$3T_VL# zEgs;qO`^CjD9)DhwMG1@gTv=I&;{j8i+H8E=0%*67wxej4+RBa-IiFtgiDXsk*hNz z`P`|-!;HZEpj@1TMnn~F@!5x4FQ8PP%We)eLWI^H*3&~Gt8s3{Mc=!W$+So&&Lgp; zje{*7SF;iu6x$P`Tyimvj&b{+Dwq{~&tx6Mvv|g8jI%+>2HuW%YYg6W$O2@# zQd15-GQAew%ET10UH9`~a3|VfX>Pw%412Z5MR4ev;sLYJBRrCky5JKLM|3m6hll&t+6jt6GVa`i@bkRQAO zh_v>DXTVvq5Q^DJO0Qv$yq8f&`p*48Z!CW;_AimxhY_t6xzltl_Gl#b0dFLh%!!6` z_G__Pxz2F8WPdXpo8SAb9Em00a^cvVNG!??If&I<(S>7YM`BTKIF@XehGWMd_9F*? zF?zl1yAc@C6ggajl5^Lj{qj!yb$gcj+(=}UzoM}{MB{PI7eYP)A z%ZO|Hn& zvqfzbh_mGNnk#5{ebh#Qg>vrW(~{A9(&+Uxf!`;498QM=k5F@dG>qp&$amH>(+Fw= z)w7yl>?VwCBsd8BaQ=NHYGPz`^hWt3Q6Znju(aD7wUwg!6h5)H@Q@>87;^0`JTsC_ z$eA%bF!pAX9*GKhF~$(-jT#<_3VAYyZQtG~;|+yR>McCv-gu|uTH$}$7H)aS#qrKj z*RuJqa8%gM@lKlP!a&&*i3-Cj^;*$Mxw&-qKP+Lub6P*=*h@0)aTAH05h%?-tx0h%bj5WlCEtyn>P>zCwHLQ!`N?N z#sogI9$%jQekpuRerY{ig z!C*~w-ZPtwXu`fy>co5ScadWnT&$m|OgU2tKhbOhn7GG-4+W&WH7iSs)4{33Afhp%&oZ<|1A=cm-2^~Z+cQQ)#iXzubkzN zUsvfCs`U5Ja1`#c8Mo)tj8;6o@*Z2v5m>F7^%Fppv;G2yq)La4#ozxLG~8--+#Z1_ zdC*3(c_^v~Ht&VI4bBxoNbH*1bx(zS$c~}LJiGx8?U$}{kPXuH8=iP__0r*t{Kex_ zD?W8j44#sTT?HW*t8braf8%>_EStT}t>t-+*KRF5e8$Qz!KAzha89-vTiLSvtb8lC zEWKx)>o<@QHO$Cy{%y8+{l>38EJ{QiR+3qScqwL+>L_ zXx2Z^mj+)d4cb<;#4pRaxz=yIfE?}!t2wP+ztTY**K`N4cjKz3pIE&#dmZZgRLJ_z zP34@Ra@L|8IznN1zA(QucykF$sf0V_Zl}+S`?$V!mB%+3ttEP9w6OzmvzJ(%G2=#<%j-rPu__{FGqt`d~e-4 z6ym(DkhiIj2YU;_kVYYT?iPjILxqfUJ-K0Hc$_#Q5Yh^H_z@H_e~#;>68=mjoX5wZ zW`s)6!8jWYtrqU))-*mJ47T(9uAt9q2dkkKgCj*xJ5omH+%`?~e|(VQ8qto?*^X%%8T=7BcJ81iypI^?(Xi9!TYdT} zeQJq(3c>}7Kb@T}=T9%EO#XVBAJD!HX^M5_-S(MkjLT|F8NKc{%nIeEFfG_XS?J+H zJ3{C+;LSjrshh^C<#0M7$gIxgaZV)f+&3glL_(av!eV6kFbn>c^Mj&=ky>&+bIuEr zJL-v7ofmox$6*Dva%xi22QY?OnUZff&TH?{$8d*qAm3me7b2w_vzIPUb>w6(UHiR_ zWTFs0b)H(i;d@W?p|2n+?-NmZ^~cv!yJqFhE9(t^V6|Kh&*F?ZSR~^ZEgoZJJZT%- z;a7^GeQwT0v91_Ak~E5|r`LLJGTkO~#kfTkbCYn3p2WRDfp2gg-1>RA`{;HbzTvqv zJQ~vQXkjoa!W_tF7RAnD5HH|RFET0OCgK)7k$Vfbn723yH?zdKaqH*iCO?bYWbO^R zy}`=L8TX%vph_XDKG$Bx!B|V2$;mxHw+FPiV+=`;aRP-1TF4_&czi_rns#{bUkiSi zg5k7F`&|ouh=L!wDR>?Q&$}u3I~4q#n}Q#t;0JFCo=d@VBf(S)5{r|dmAjv!?vF$P zP+BFmKFOe_WKe37Uukupji7$B>5ZF$N5d2fC%aj+Bq@?rk0yyX0XFYcd;Y882%pM1oS!hQi{b$iCBw|pbZ6M zq}(bPBjr}X7%8_3#z?tUFh=^0l!TTMP=%)Pz{)gIWW1Ra(U->1mx!e=jn}>;@{3mu z=RtnMpKHAndZifc733GOlzoK!Qf?r>bOZS{qJbd4#%M<5mjXe4sa%j>-0;)LuMw-F z8_2H~o1u|k$^_(>G6DIeOhA6&NSBDI5kLhor5keKj-efh$AE~0fF9s6{0k8kN(g#z zt6&U=TLoh{+$tFK;8wvH4z~)%aOe|E)$PR&5Ys+UECUrpbYwUnie70{X^jLi4Z%($ zrW)+7C#D22%t-`i%t>?uX+>c87lHyvD#;}+o{3<> zA}y9%f}4?1U(&_pXs=Y|f9-o%PdB3_MWNdy+<*ZSLpO{TGj)CFMkRnE#DysW3J#A0 zAR$sjWrQ-h3*P^b$<$CLchZnEo2G;^Nz*{9Wipv+48{YoG57$t-q(qgDunqI>(t>j zg<|XJRp9WcIp#L*4Z5XpI2U2=H|?n~l`{tdxKQBVaaI zDCsqB06|gFoSPDvxXJmrMR9M?&B)E6I6^M^g_@V8Lzil`A^%ZCKg}_Cz^`+z!Ep)K zYY!M4zr)plYr=O7j)}Mu<{2E5aK$}jaM*D5$CZfd@3^kwihkJOxEI$9T(fX#8Q$X0 zPeg;`Pq=1E2FGSx*OHK3vRM40@r%ffmL%sbakAlH#WN;O8a#5+xJY5x50 z_4jyIM?dhuhWJMw*=P~P1%rRMVA0UrMcLep8Bf?^bushi-OZ-mJ(i6ayKu_ZQwveeWGY{G;)hE2aC)Vf+Wk&Qt8GbT+*9)o({fqJK)-nXIN_Xy+J^zn<> zf<>3vhaZk)3rCJ+7%6c+!ZmLne<+8Jd=|AbHAyMZ@k~ zH2j&V!_Tq1&b2V1OeZjbh_Q5ge#K3)$#}BU#2sf=Mcyo_aT%aQ8HJ$25Y~ zq``NfPSdAQd@388+Q$C$r#pv@z4H(3=pQoJ!VId{-E2J4kDEqy`-Yu5^%;BpbqXKJ z#*Q4%#*LpexMI>7HvJ62n96ptqv)>%XzwEAJ#vb`777HrJJ_^4# zCa}9FjA!?Z&tT4sk!<3~N0X;KdVbiQ=h-t;*#dUgf<;VNbUPb=`{(SQ&quK_qpq;g zSH`i0V7;rSM}sHKf9XdA^wj-q;XvxVK? zum#_I#uk0{SN7(c)aPHZhK6&Dor|=S`gTh4h$#g3v24lMbL_3R^4Q`$!V{d_H5hHl z?MPtfz`0VD26>o;(ukQS3T%9$3MGAsnuiA4fR;uw;oHb)gwF2`Y7r#owA^M^vz@H4SC!}c}%0W z+?_OfR$BU?F|*U|8Jw0e2cOPNyLbAGTjX&gJhVJ=!g)-jJSI^dD<-EcU7nU^S+?>P zdHj?0SdDtDqI#?e=aB|@Y)lKmWBrY7dF+;Lp*+63E^WiIwUK%}PJR1?2Gb{R$m4sx zFan)uvL!g;*-Gh6b@;kIm}dK6y6vAc?I*_Q3pFE6DP{rngIdLF+D=kd$`2&FwwGK!(44%HMFG?Qj1+ zCjG$N?E!aVV5+~pvmT)fon|)sff@G;+Kkv3nAaE()qrolI$tiSXJyb7>d5fUvmf%@H9%Yn>O+GE|v{H#kSG@_U920Nb$G-g6^sQ zcCw}uSmtjprTaQ)?i!`Ts4{dtTDV-%Q?i%Otn+53Kj*_a2u`xjX;``37S~Y0m-Du$ zgB7N7lf7Tvpv+F+Iape?j;*hV^U7+4IZ~gxI;yVSpz0;7xxT`N(+Hes)isKTkv+=T z!pQ4#2`3FWA{@qBZ%|`z$bch5+C;uc3U~}f0gs3jFGAy#UDh+XF5r_JUA3+)Uqk-} zemOb^97#EhXhRcDo}bPfa3odTmT8S`kf2;ZuPJziA+X}Y8rc^0ye{B|yNcq%1N6e< zB_A)fvd!_LDd7GEE_<}UeFO3ptx^8=)$}mn$Yf_0QvDjAykNv953ypo@aVAnk7>uT zQf`&_ZbOl9vuw$!?v?-@f-sFqrpxA-Fr{s@vu&nYlDc13}Y<6ZMz0>a?lW&s}O_~tCaZRR77xF_Iw0EIm? z5f{eZ&e%^<60Iw-V}YL;UK z!X66cXCsMB2Et^7`6RHGj4fdnZnOho=doTEWi2e4BIx&kwuUxEXUsLtutd+SGtDxY zW?M{iQcU+%>F(cXnwtorpYcIA`%a@{-m~l>mjAFR{}D^Rn3ylUsFP>wT@&NnvuWKB zYc@L^6DLf-12&Lx7bZ+V7+!D3HFLv;CmpjPS6#Y%ngiuVcy+47|D!*SE#U$o#{L%N zq&jX9c#EK@_^8MaPrWbkQTk!=@x;4_ZObL7g@CY7Q`ubex>&+5X|CB>%KMd~yEE(P zKo}#RopkfR1>4Fcg~9pF${$SMzc~MLqap_V%0p2VNF5(tv7`x}Rtye%oL`wd?X45c zuVhbq>s|JjOzTJY;v~prlQmZ^RKR(kpmTe z1UsbMz-&1;km_!Y_HayH>_zG3#Z85cFQSBGfBVqeaVQWp=X-Qd@hj1+ebHDn$>8Di z{x?|<{Dkctk}K~WmFwP{8ZL6;PUZEU)7G8J$eu2}VzV|Y@Arr$N^Q>)zY^#vD^XvdQEKEG#N4c&CUJrMy$jROKh#?^rm$^2cu%s*AJK%=x*2Q8H2GcX%#W z4$R)9m*vK)nB$yWW%0j*qjRdfs&OA*;_z(tLX|9&lK*@w&Wv@+m#r3#gWWty)Sb$_ z5G8$M{X4}Xhrm3P&vVBz1M{q~UxrZ8pOGz}`m3N4%Sb}GN^20V|&qsyuiTJ!;7d8;WPjM z5ry&AX@2GDuFO_GAQ=40)~?L=ji_Wx+rhHSMhY=lyZ?6Sd}7HaDnwjg$n|! zRVBSEum;uh*yGf4-kZMMV>cA9a3l;+3qe4Hz>vm(11Gr9EKYR(ikmjdv%;QzT=c+J zm?@#HDbs$oxbT5pI$QH`PW0q@UByf9N*G_fRY)4s>AujA$t5Ig6;>#}?k-kpx=o2u zpYT0=!WSWl5S{mPr#-2eD;%aOSZ?xsqOVG2b(!8%-Ug2;;l<5?At{~}fg!np zA&R&ACB@xs>!%jZ0KHWn=!VrNWp+2FKS8;tTUDlYi(3U{Qn!>eu~>>uxV=P@N_ZKr zO$Tog#H8e6F*+fsM0CAwmY_nrqwul_+iR`q5_HO8syDrGu1RzrVYRaIw=RsetC@!a z%f4WVN=w&D`{36qO!laQN+X`*>k=|wTWMqp6!0yfk$%%S7sl&bfGGot3zq~|*yD=}m*Qs1 zHw0D{O+Z)2^&;4#SAi|rv0Do>6u#>n6GufY#vhFy!NXD-|NV>Z%P++2q_nSe_)6ar2X0m+WJ=D;qBr3(AH|_9}$ene0gvZL-^N zO94ZOo5^J7Pv}HLqfh1Lt65&*M_@z0N=IU`WWP=>-mm9upWHihjU=S$+QgB~ zr<5I+_o64`w3|5ICyAMXpVJB-{@rh0lPj%t!an&pf^0G)o_zciOij zIy3LIx9$M%t;_Uv8I|w$YZH@?WzJ7{yA^dvIL)+_qw?^8e_c^Z?L_#c1{yXg-Ip*U z9^l2gZHrZ<{nC0}dZ8&_1pT04aNUIp6A3D`KQpyA)kpSis)d#jF!*Q*hf_I79itC2-@Gk!_;QUlXOwxzva%G%EL8 z0+SxC(HeCd{7gy#w*hRq=q{;wl5+a+1sPPzOwDat3`SPdYAuVr_-FI#QJ?h12%pKyO%G@r09(=1DALe(6eRA_$v>Cn zV%RIP+3I(h;EJ|xmjw#(yAp5!TQuZKdFh3mQQR?bf!tj7jJ#uDmQ*)ivKm_Dqlr;p zOYn=viMePr%21Wb->kR4qylP~GN@<&>E9;rWZRKs;m1*J;+&%SHDB(>TwHTDw=lvH z)*LS}NheHh;U$cNPxevlTP<;-3F$Iw{$MpCB%|iF+?wq*B|Tt4Qd(Cbz zC(r#tUsFim^KPLAky3HZi)EZ`uF$}@iL+l;@`5F15JUrn|3{-?9^rPZor&ce#z^Iq}`zkN7u zdrRM>Z_xuwGLcj~Cc6B}3m3(fI4P=D+0-Lj_319yQY+PC&LyL2rMev^Syq)9U=nMU z={=>U52@#1OM&ixjQ^5>$?i~7#>XPdSW7N}C5a1^Yua8W$8Bup80DkH#K znfSb&Z(DTu!h=pW3bBBWQ8>V#7aKxjCeM#(*{^h7kaBnN%AdY1*`;&sFu7bsyY#Mu zg&!MS!{+X=xI}8cco3)Pw%GbN6zWZE{1%(LWJ@UN7MFEoQI6{ciwmn%m(5U;4E^-t z!cSc`XUQ<>d|7bZYmYmB%MQZNnaeH!gQC*6h&v$TE*_RMEbd^TZi&n8K3K@%_Kd1{ zzLn~@`cn2GtKY+%FEXT$*-_XbipS!#kJ59bT_!2VKch@19n=-r)}GH^m7A@^ed|~5 zxFFS{5IFM8E*Xk-f3YFQW(GTo+UHBwDaFw_s9ZnEnp$kkvAxt1t6b{7J&Z)3b_-AI zt-~;iTU>6~>ksa5aqc1@T3lwsFocB`sEc59Kc zxEp_b-CNadqG6cF!dmvzCKV&WNL`T$aWj#C--=9O3v_qz6~)=TRby?73VU`3X~MJ> z1y=129=Y?Cz$zR<2&`Uu_|ENHg(1vPWX9)Q_tx!O4MkD-duVHGykw{?)9vo5MP>Aq z@1d==x~)aJt+j>o+1A>qtwqMIs#4yywH7QJ0+%tZ-pU{7g<7EfuPrRbojx-1TMb9< zR3%YWp6`;1`faU6O995{l)@7%d#Q65dkrjcJiM*j%<$Z8Gc@gru^V1xTdn%q?5*T} zCfeOpmSBfP)vZ=uEwjKCwcP3cyv`!4MmIc6ZmvJU4vD!rId=U%k65<_uODuyf0ylm z-Mmisx!3C7W;SCJ0z$bOYLQ@Tt+*8qn;T3X+aIV1-u>FKGD>!APj9kgr7Tp`XNT`Z z3pN4kq!cL!urpwprL~h$)3k_Vdc>9KDe}m@hs02rQR<)Me;X&L>&kR4;eC(`GZGn> zhDp}pdksh8HdjsFTs3NQ)x5^}heX0`m%mIWAJe(|J4&{QC0isox-t%BW7$k5vn-Z_ ze|0eCD7g|oa!L%e#0SZgS{9t|oW=ZAlSRwIS}CxqK{5^IYfXVw{=gd1@__YSf7K|_ zBKQL-;^rlm6zfrc)ojt?v>x(TrHhtCYn8uho@g0v-9y#&)Xn$MgcgT$i8@;h4whm! zZb^C$x$c`zIqN~m0f{9zta4;xgUdIJuXjmUYhS{tE^W~ci?Np^=`E8dVntG$z-rxj zyChHEUeo&0ZR-zi3(QWi)dl9dKlez>AR2^C3q6%Okti6(Ar^U3V?Ez`e1>LDT!1rt;gWsWsTDX&9eIln?QL$VM z^dtA4a8#upQgSZ$O`?4lN!GM$ojn@V%%a?L*~*u2yVe0B%J|FS){nTXvE;;y+rZoF zdLMttFgjE? zh!y2l<5K+#j-{t?bn#+Im5B^F!ossGs#P&^k+>yA%+A5GsLr$)eajz7ZWIUXG~weH z3iCxUDGdAetP@v9c$+(xeI0aRH(VFl5l7rDe)%}IjbM^$(bXNVRwd5=XsV>ns9fkm zd$Q82OgLc3+;S2LnTlVob;3{04Z2{a8)cp zO)3_;Rg(t~F0nZyN3u9niwDR2Afl;oyLSw9yDf3)6>iZ#3tPFtV1EOQKykylp4t$3vCL;8cNm9hJ*WI>`sCg26lo7mU`hvNX|TRllK1N519FA2Hb!cwvN&w|TC;?1TPgTh(mi{0D9dLb zMa5R|Qswjt-uoMGJF4Vqbk|mxvUXUqvT7@IS6l@4W+Jk^@rx&B+S_S~5LmRPvtZ;b7kd1}wh-V`EI z{2Fy@x1slJmio%cg){NAUi~9mk1spLPeLCzZNul}yJFA1r}o^7Y8lmSRIp|O1s`1Z zi*b9dVL^=8=j9MUhCfJT$ zX1ngCerwD_hq{xJT4Zn!*ys?^DwhA6JE^^PYlZGYoP02p zUFnax-t1nh(AjU1(|O9NzHmD-P>PwdgVh%{(({j)vYpi@D7j22LYSMv9%IV$tWnw0 zW66XVDZR`hzFwF=$Vgtwl*fAd8&pwQ(<7|rR4ymIa#N^WIA&-01md7x?GvkZgQEsUejU*XG4&Vf4i6BMhd0MY&CUplmZ zh%)}GzyICu|J8E;UElc?7L?nRueu>#o)VN#%Oz3b<}ICKm%2?Za+LKmSWbhQ499`| z0ti@`q0xPCUDPmMts3HP@+8?_8C_;NQn--`PqV|gwTZ4`owB#vW`qy8HZj9e`pWP! zNMf0;ET+MySvpGORbLt8f@K!L0xTX04g;J^7L0!5=1Zu1NmB`L3X?WJz68G_C=3~nEZjUV%Yg~h>IJ%b++47fJh!T#r z^Zv3JsmYTV1w-KbOl4-(lPzq=80HKwDObCo6y{gjz6B7z=mHQv{Z@Wi`4pB+Fqo9) zuE`(FF8Gl`&w&q{)6I=Ud5-6(#EA>oWV5OnQBgD)vCv%gX&- zR1{h7%+IM^DbhEI$3g@-pG9aD$N^@s|KkXA%&YZQ7=uv3ptUG9LTnX3lf%?jR-WpC$i@j1oZRw8l+Tx&HkZe2E>D0- zX-puvZb59*Zy8Ey|KIr)4X=3~l)!;i!w4l87UyezruvjkK{ZSHJ`QE)zx*pEYaO?xh9F*x;?G!8xJ^ZDNx4H6O%iSL7fl(m~E`<26P~ zEmNuo)&@Z>_YE`-)PgS%1$__JZj$n^FpJ5|h=Tf03Wbyiy-3A#-IxtF_ z^W#qG>M6NX?C5lT;#YoZkT=5zj|3|tkR)LJ7||nRjrTWDjq0U0tUf!o>TvUojY|VuhZJ_1Tb>p(oFmnh%o#gYu@0bpaphlpBH=wfviC7Zss9)R&3peYoetmyyqEYV$$3i)X*`Sa+6YN7P539wCQn~$R z+byOEjoYW0Xf4<#RVN}F^L~?UcB^T>$y~?P)je^$rKxqwK3!=do`&EM z?tYWoJ`ld&V77-V6%pvRn(#CiPxBz6;aj8kn<&7CfQ5v3^s)pm%QSr9OX5TTwN8f} z3GYqdvwh@OmUU&pq^b`Rz781%=9YXqfGNqkHeAsl^Jtu6(Vd=nJ)mm2{pL!5&P`yt z#LYWK#J>#WX$ z<+{BwHrx4feoR9-#varH%T0UD_7Q&NKFEx?I@*4y+rv87>z(iRI0ppPy~c9BcCWeI z6etW{-ft3%_M64h2|$|xoUe}C=lGEA8&xOnv*4c4w!(s-sd!9BkbwK-QUW+Kh!Zzq z-=h{?bZznqk>=N#k-%9IgZb_M6LwRv-BJqh**_r#2-3+<{Jy~gkpD6mBrn~OA0{j9 zM{7d}e6{EQz`#G*9t@6$2+e|!p}10UeTcR5INWgt8h;rpNBpeLV9*=No>5*7Tx24Z zbOVFICHTwO3Fzt7!FQ1X=|^fI3}+g^_}k`vwX)t z=d~EjGt<9-`7dv#eM(BXX~ifdT+U9j|qPh_QW*q8KRa$s%xnCN_&Ph?s2H) ziQzX#pe8rT;(v1n0y_lhdZ$IrXlP zFNz7N;~g2}M&G_5+8lewh9B z`)c7OokeHu7OryBe7Dt9+0PsoZxd^{|=R`;;(Htq;}f&GYW)GgMX z)cssnYWSJnXDHXtVE424^#}1)>FXAdc<%{*jbX@~CuTQjsU(8F{_oJh5?k|Qj@ z8`8DEs`mGzwFrQMchj0A!;V0YB-Kf44SdWHp)hDUZy9g-;|Xp}3BpTe)U?T{s;h-t z!&_W%jpYiMHc6bkeP+O9nGb=Cu$B1(iLT?WwXP)Fn><|9$0wLe3Lh6Oa-(dut7~2A z5V>hhVsuI2M$vLFEG1fEO70M?lM$;&ls^FeN9J8p(G2Cvx6dBq<;0Hd%P6$uSt!a_ zVyu@8C4~!VugNEth|pYWK45|lLi@$P!e9gTeo7po^;}7;X!)eX3{SEpKk?Z)1L1=( z`)EsPTG?v!VH?C}*<0lM$uyry`Ng;PcZy?u zHl3w*`)bO;`l>LfXRA#_=Qeqvxe(j)VqyLo19jcCPJ?}*K5#rHt#$sfN66_xKOy1y z05ANe2QCx9Xs_9>^^H$_;Ql!?UqEl)(<6w%X+C4k=QWT6O=Vx|PO^6P5sdyiM}0eM zUgk`}iDDpkt=;RhM1gbflxT-p<+D#vJuac7M|iMDDC~jFLt##j@Z%mt{<;fZaD_YR@dO@? z!p0uqww?dowKWHL$r{rP&3ROvMgTlpd7Z!NZVn`R zFnl|OyL+bjEXwCy_S=t(7Hq04_Zl!P9PQAy|6FRGp={}rtgpi{NSDX*zPiF|Jq}{< zm-sQx_AdCL$rY6YSN+PXSEXFJAlF@x>n+Ij735|WG;SBhGcb@q?Ymp{+ffOyjq%whkd1qYN-PcJ4+pE=_owBTsq1*p(i)sKEP|= zq~V(aBrib90wgLZ9pxw0=mI&nz@1y*%`Ncd7G&iXEX-8~T*dLooX6LanJA*c!XrVU ziZua(&nK=C*02^n;G3$tJc978(9-R%dEYHuMUS~%!l`ay;J1MB?5kL1snS|uK{wvK zc+;yARI-(htCozj`Zdv?APe@1VGR=&26aMv&soD7Y(@rrme|kuH6J6dwSuGD`krdS zuAB1S713_Quxq=rq*H1)gaUt$z=WbDGnDtQ{33CU-Pj=FWQ4v*k0h-~;%W%EXDQp^ z6|mEF(V(vN2tVsC9_zCkihMt^UQj)2Z=^j%f%8Y0p;r5gzQ*%kK=Taf`e?k)hhdrN zR}DZ6X2_l){2=SD%sYj2rkZ7I3~tbg#(t-2!Gd+O>jRfHqh!`mlc&jLi!1hww@)ng z+-~DfxvjS~O2wWTHGdoyMYqF)jbH1fFRf#?%&0jCCmeF}kRQmRN5m-+``1;x>j-?l zz9)*Rcr+%o!v@yrbQQ0z7uC|qB6R(#ET^kXr>hdq9F6HRX4Epix*V!(<$cVDt<|sstC~9NK>PpJ~R0EtMNZQl~we6_3(fvs=u~m+Zq} zueBjCPfGeaT_$}9?9sqkuG?~Fk|9@CZdahgY_PnmDkBxyKH?a^7~8$ab#mV6*iF%j zUCG-NE$21nofe_3^ch#jFE)_+TOBrZMOU2+5I|A6MLaS$_P9%gs+>E~QqPGlcx#Y8 z3x^oecZ02p_0L)&S(5y-uzzf^rSCS0_9(nKB#WVBw?%^Gn`|k`1dj<&q?BZXDRMG} zMdLWitVbSt=#hu{Zd1d$=p;K-C`ZL<`k#JfQIu>yH!w$4>fbxcA1m|$Ad8!;TdF^9 ztX4^IkyyR2VVx-{TCH+atLLj#d$V%)dkdg8u1v)(>fl<=u4`NX)5gKflIOgqGLPxJ zY8C1>Hg}0UZJN9kmE6U-{2S%s!UapAWS+j%Hnc#uRs2AnCdx~JVYPbIm3iDHd6A|W zNjK*;tcyzGbE^{9pQ*l@TV=^RT@`bty7BZ;{I^h_Uv&x?b7M(K>S*%ayC^ za=q0jnydFgMYURuZ&nt(yGmWP&(w_Fi+wS*eDzh8ukKc#hePoasCdTYieBLg%dI}) zwd&y@J6Ei3JhT4vf-aq+AkTr=ytm-AjBRq$^ERPrl|41Lx=yzKZgX|Zq3ZKZt8Bk% z@+O=>sf~?tQ*~p)>r`VbJJ+L5?Rq{vCbudk>v&-zxXLUsDXW%S3%zAsfY<(--WXMt zARUv$q#5;E5-9*;9}}=_impn8Xh-aC!VWbMQMvie;N4^wH3T52gxz#rvTT2zCm@2_`0qN^l} ze%m&wx%vy)vhOetF_u50`foT`HDUGxazSn3-Og-3-f;}haAa!AftWv9s{eL)>ftEs zheK#@-nAo|%Ok~J*J%#J`LqF$8r|I{E`UAV^r50q%i}>P=Zkm8>TLI`yA!4K-40RR zJ;Ytk?~Zeqitc(*I$-MBrnF-#Wi%247=;|hEe4x#4`1s(-os&Nx*<*d#Jt-Gi^L+p z4Gm`qfsP4_36q8OjSCuJ4c`RG%mU!(LLk$M6ywpv^|?n)*k3gEAKf6vCpb`&d=L$K zoKym-d5_y-ju~-;qWTn+FRDMN5AX|o^#Rj@`PSsyEY<2Nn^E;uU$iDSh~|W7dVHz+ zl-*J{3QFzshn-fdFZ%5FTH~AcCELv@#(l|06RC2!`z+Nh>b}J4^R@eiRDXV)tNzTJ zUfq(JUj2D>cYXEw1=W|qmpY*;_!9={mhwx;@S(_J!FhqB3Erf(=JEvh4lJZHU)vJ{ zzb~2foVWV3+RW;fBCh%qwCs`NggY`cG-TO6vq8=TS%7#dU~v&WLRajZwf1!NXXuPB zgHm!8+SRID-R+;Xw)!%vZ?n|O)t{@b>hnkq{xe`fWkB_zQciG9#NXD~^2zN`ax^Wo zod*DYjaj)q*R%<)Wf<`rT^RK4X?MGp*^FAy#ABlGOy162+|G?a;KNti#KY>gEbHKs za)bMJ-)iPAH`<3LS<;sSt;%(t*On)oy^!gJ%+eAq^1^qS^@~&Pw>h_ecDd0NNz{~O zw;s$|YL6N8VI8JEmuJ{l);Du^>%8finJLEIx}%8zLn<{Us;T;-ZG_dNdaJ(#h`v?> zCSUz1ANo8HlVDcGfGK5EwK{h#^^0>*u&KJ+9`^yrMfGJ*^BYW8ec3>O52Nsz<)@*h zPf%NS<-B;7-^||QK;MaMnUZ2bCP9~TmsEE&9vuQQAm>&kxO121sf#^%dEU*-K3JB% zJg?PUW;7I)8xH8eBZCBfm!%);;Q(gwRCV{6oHI*Li&O%yd>11oQ+b&WZPCEO(cbPxIV6XPL*)9;aJ|^&Kf54TZE~hviwZ zgTXtF`mAJ4dJnDDxk=agS+U(@6s4yjJ}TMMEka8?9YHJ(JOC1QbhFLghIM=r^pUU~ z8lAhu`*xJK5zIjq?HC@(W>~I zDn0jqwRb`*u|a8{*N!cVjK-5N@=A1W!yB;$0=|E`t-VCl4r+f6$SXv4^ zyb~?o*KGN!J>vFX&04V^W^va3N6Ee++i<$tKrwQsc5%p#;jcd$9f!%-ict<# z9*N;fLF6jQl&HDKTNU(X(A--Q%vOXB6`^f!gs_V6rT#Aw)ONrowrlS5`mc_bRFRPJ zI$RIdaT2?CD_&BgNCN|S(>!uqJt(y~)BSyBdJi7+&rI^na?%~E%caQ3&4LK@)Z8oe z-zM#?HM*_&i_Wo>{EX$%ORBv~Y+IxewFkh$h4+c0#_q4|isK^A*0y}>(*j}s?0!{7xVbyvo0RPcvt(BS)b8F@zi49HIHfGkhMDMk zJ&u*YI5Ubdj?UziULCFCYueYXgqpI?M3xFV*_`a(unw%+GQ5!Y34O!<>SPmAM+N@x z&Sb*ht)^RZ5;=TkZ~8wvi79_OYHLo78jbM^jmGPD zLnl-}rP3Q&Lo6rcbFC_n)UP=Epypa2CZ zKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt t00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZK!N{3;3udauI~T< diff --git a/VAX/vax780_bugs.txt b/VAX/vax780_bugs.txt new file mode 100644 index 00000000..1692b6cd --- /dev/null +++ b/VAX/vax780_bugs.txt @@ -0,0 +1,17 @@ +1. RP: drive clear does not clear RPDA. +2. TU: default formatter must be TM03. +3. SBI: drive 'letter' is actually a 1-based number. +4. MBA: drive register reads return SR<31:16> as high word. +5. UBA: DMA addresses must be masked to Unibus width (18b). +6. HK: thread used multiple times if SEEK is followed by NOP or DCLR. +7. HK: only DCLR clears ATA. +8. MEM: MS780E size declaration off-by-1. +9. MEM: MS780E array start off by >> 4. +10. MEM: CSR-C register write logic incorrect. +11. CIS: CMPP3/CMPP4 using wrong arguments to ReadDstr. +12. CPU, OCTA: CVTfi with integer overflow not setting trap if PSW = 1. +13. STDDEV: read of ICR was missing the call parameter. + + + + diff --git a/VAX/vax780_defs.h b/VAX/vax780_defs.h new file mode 100644 index 00000000..66ea0142 --- /dev/null +++ b/VAX/vax780_defs.h @@ -0,0 +1,403 @@ +/* vax780_defs.h: VAX 780 model-specific definitions file + + Copyright (c) 2004-2005, 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 + ROBERT M SUPNIK 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 Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + This file covers the VAX 11/780, the first VAX. + + System memory map + + 0000 0000 - 1FFF FFFF main memory + + 2000 0000 - 2001 FFFF nexus register space + 2002 0000 - 200F FFFF reserved + 2010 0000 - 2013 FFFF Unibus address space, Unibus 0 + 2014 0000 - 2017 FFFF Unibus address space, Unibus 1 + 2018 0000 - 201B FFFF Unibus address space, Unibus 2 + 201C 0000 - 201F FFFF Unibus address space, Unibus 3 + 2020 0000 - 3FFF FFFF reserved +*/ + +#ifndef FULL_VAX +#define FULL_VAX 1 +#endif + +#ifndef _VAX_780_DEFS_H_ +#define _VAX_780_DEFS_H_ 1 + +/* Microcode constructs */ + +#define VAX780_SID (1 << 24) /* system ID */ +#define VAX780_ECO (7 << 19) /* ucode revision */ +#define VAX780_PLANT (0 << 12) /* plant (Salem NH) */ +#define VAX780_SN (1234) +#define CON_HLTPIN 0x0200 /* external CPU halt */ +#define CON_HLTINS 0x0600 /* HALT instruction */ +#define MCHK_RD_F 0x00 /* read fault */ +#define MCHK_RD_A 0xF4 /* read abort */ +#define MCHK_IBUF 0x0D /* read istream */ +#define VER_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 MCTL_NUM 2 /* number of mem ctrl */ +#define MBA_NUM 2 /* number of MBA's */ +#define TR_MCTL0 1 /* nexus assignments */ +#define TR_MCTL1 2 +#define TR_UBA 3 +#define TR_MBA0 8 +#define TR_MBA1 9 +#define NEXUS_HLVL (IPL_HMAX - IPL_HMIN + 1) +#define SCB_NEXUS 0x100 /* nexus intr base */ +#define SBI_FAULTS 0xFC000000 /* SBI fault flags */ + +/* Internal I/O interrupts - relative except for clock and console */ + +#define IPL_CLKINT 0x18 /* clock IPL */ +#define IPL_TTINT 0x14 /* console IPL */ + +#define IPL_MCTL0 (0x15 - IPL_HMIN) +#define IPL_MCTL1 (0x15 - IPL_HMIN) +#define IPL_UBA (0x15 - IPL_HMIN) +#define IPL_MBA0 (0x15 - IPL_HMIN) +#define IPL_MBA1 (0x15 - IPL_HMIN) + +/* Nexus interrupt macros */ + +#define SET_NEXUS_INT(dv) nexus_req[IPL_##dv] |= (1 << TR_##dv) +#define CLR_NEXUS_INT(dv) nexus_req[IPL_##dv] &= ~(1 << TR_##dv) + +/* Machine specific IPRs */ + +#define MT_ACCS 40 /* FPA control */ +#define MT_ACCR 41 /* FPA maint */ +#define MT_WCSA 44 /* WCS address */ +#define MT_WCSD 45 /* WCS data */ +#define MT_SBIFS 48 /* SBI fault status */ +#define MT_SBIS 49 /* SBI silo */ +#define MT_SBISC 50 /* SBI silo comparator */ +#define MT_SBIMT 51 /* SBI maint */ +#define MT_SBIER 52 /* SBI error */ +#define MT_SBITA 53 /* SBI timeout addr */ +#define MT_SBIQC 54 /* SBI timeout clear */ +#define MT_MBRK 60 /* microbreak */ + +/* Memory */ + +#define MAXMEMWIDTH 23 /* max mem, MS780C */ +#define MAXMEMSIZE (1 << MAXMEMWIDTH) +#define MAXMEMWIDTH_X 27 /* max mem, MS780E */ +#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) + +/* Unibus I/O registers */ + +#define UBADDRWIDTH 18 /* Unibus addr width */ +#define UBADDRSIZE (1u << UBADDRWIDTH) /* Unibus addr length */ +#define UBADDRMASK (UBADDRSIZE - 1) /* Unibus addr mask */ +#define IOPAGEAWIDTH 13 /* IO addr width */ +#define IOPAGESIZE (1u << IOPAGEAWIDTH) /* IO page length */ +#define IOPAGEMASK (IOPAGESIZE - 1) /* IO addr mask */ +#define UBADDRBASE 0x20100000 /* Unibus addr base */ +#define IOPAGEBASE 0x2013E000 /* IO page base */ +#define ADDR_IS_IO(x) ((((uint32) (x)) >= UBADDRBASE) && \ + (((uint32) (x)) < (UBADDRBASE + UBADDRSIZE))) +#define ADDR_IS_IOP(x) (((uint32) (x)) >= IOPAGEBASE) + +/* Nexus register space */ + +#define REGAWIDTH 17 /* REG addr width */ +#define REG_V_NEXUS 13 /* nexus number */ +#define REG_M_NEXUS 0xF +#define REG_V_OFS 2 /* register number */ +#define REG_M_OFS 0x7FF +#define REGSIZE (1u << REGAWIDTH) /* REG length */ +#define REGBASE 0x20000000 /* REG addr base */ +#define ADDR_IS_REG(x) ((((uint32) (x)) >= REGBASE) && \ + (((uint32) (x)) < (REGBASE + REGSIZE))) +#define NEXUS_GETNEX(x) (((x) >> REG_V_NEXUS) & REG_M_NEXUS) +#define NEXUS_GETOFS(x) (((x) >> REG_V_OFS) & REG_M_OFS) + +/* ROM address space in memory controllers */ + +#define ROMAWIDTH 12 /* ROM addr width */ +#define ROMSIZE (1u << ROMAWIDTH) /* ROM size */ +#define ROM0BASE (REGBASE + (TR_MCTL0 << REG_V_NEXUS) + 0x1000) +#define ROM1BASE (REGBASE + (TR_MCTL1 << REG_V_NEXUS) + 0x1000) +#define ADDR_IS_ROM0(x) ((((uint32) (x)) >= ROM0BASE) && \ + (((uint32) (x)) < (ROM0BASE + ROMSIZE))) +#define ADDR_IS_ROM1(x) ((((uint32) (x)) >= ROM1BASE) && \ + (((uint32) (x)) < (ROM1BASE + ROMSIZE))) +#define ADDR_IS_ROM(x) (ADDR_IS_ROM0 (x) || ADDR_IS_ROM1 (x)) + +/* Other address spaces */ + +#define ADDR_IS_CDG(x) (0) +#define ADDR_IS_NVR(x) (0) + +/* Unibus I/O modes */ + +#define READ 0 /* PDP-11 compatibility */ +#define WRITE (L_WORD) +#define WRITEB (L_BYTE) + +/* Common CSI flags */ + +#define CSR_V_GO 0 /* go */ +#define CSR_V_IE 6 /* interrupt enable */ +#define CSR_V_DONE 7 /* done */ +#define CSR_V_BUSY 11 /* busy */ +#define CSR_V_ERR 15 /* error */ +#define CSR_GO (1u << CSR_V_GO) +#define CSR_IE (1u << CSR_V_IE) +#define CSR_DONE (1u << CSR_V_DONE) +#define CSR_BUSY (1u << CSR_V_BUSY) +#define CSR_ERR (1u << CSR_V_ERR) + +/* Timers */ + +#define TMR_CLK 0 /* 100Hz clock */ + +/* I/O system definitions */ + +#define DZ_MUXES 4 /* max # of DZV muxes */ +#define DZ_LINES 8 /* lines per DZV mux */ +#define VH_MUXES 4 /* max # of DHQ muxes */ +#define MT_MAXFR (1 << 16) /* magtape max rec */ + +#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ +#define DEV_V_MBUS (DEV_V_UF + 1) /* Massbus */ +#define DEV_V_NEXUS (DEV_V_UF + 2) /* Nexus */ +#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */ +#define DEV_V_FFUF (DEV_V_UF + 4) /* first free flag */ +#define DEV_UBUS (1u << DEV_V_UBUS) +#define DEV_MBUS (1u << DEV_V_MBUS) +#define DEV_NEXUS (1u << DEV_V_NEXUS) +#define DEV_FLTA (1u << DEV_V_FLTA) +#define DEV_QBUS (0) +#define DEV_Q18 (0) + +#define UNIBUS TRUE /* Unibus only */ + +#define DEV_RDX 16 /* default device radix */ + +/* Device information block + + For Massbus devices, + ba = Massbus number + lnt = Massbus ctrl type + ack[0] = abort routine + + For Nexus devices, + ba = Nexus number + lnt = number of consecutive nexi */ + +#define VEC_DEVMAX 4 /* max device vec */ + +typedef struct { + uint32 ba; /* base addr */ + uint32 lnt; /* length */ + t_stat (*rd)(int32 *dat, int32 ad, int32 md); + t_stat (*wr)(int32 dat, int32 ad, int32 md); + int32 vnum; /* vectors: number */ + int32 vloc; /* locator */ + int32 vec; /* value */ + int32 (*ack[VEC_DEVMAX])(void); /* ack routine */ + } DIB; + +/* Unibus I/O page layout - XUB,RQB,RQC,RQD float based on number of DZ's + Massbus devices (RP, TU) do not appear in the Unibus IO page */ + +#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */ +#define IOLN_DZ 010 +#define IOBA_XUB (IOPAGEBASE + 000330 + (020 * (DZ_MUXES / 2))) +#define IOLN_XUB 010 +#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2))) +#define IOLN_RQB 004 +#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB) +#define IOLN_RQC 004 +#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC) +#define IOLN_RQD 004 +#define IOBA_RQ (IOPAGEBASE + 012150) /* UDA50 */ +#define IOLN_RQ 004 +#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */ +#define IOLN_TS 004 +#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */ +#define IOLN_RL 012 +#define IOBA_XQ (IOPAGEBASE + 014440) /* DEQNA/DELQA */ +#define IOLN_XQ 020 +#define IOBA_XQB (IOPAGEBASE + 014460) /* 2nd DEQNA/DELQA */ +#define IOLN_XQB 020 +#define IOBA_TQ (IOPAGEBASE + 014500) /* TMSCP */ +#define IOLN_TQ 004 +#define IOBA_XU (IOPAGEBASE + 014510) /* DEUNA/DELUA */ +#define IOLN_XU 010 +#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */ +#define IOLN_RX 004 +#define IOBA_RY (IOPAGEBASE + 017170) /* RXV21 */ +#define IOLN_RY 004 +#define IOBA_QDSS (IOPAGEBASE + 017400) /* QDSS */ +#define IOLN_QDSS 002 +#define IOBA_HK (IOPAGEBASE + 017440) /* RK611 */ +#define IOLN_HK 040 +#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */ +#define IOLN_LPT 004 +#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */ +#define IOLN_PTR 004 +#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */ +#define IOLN_PTP 004 + +/* Interrupt assignments; within each level, priority is right to left */ + +#define INT_V_DZRX 0 /* BR5 */ +#define INT_V_DZTX 1 +#define INT_V_HK 2 +#define INT_V_RL 3 +#define INT_V_RQ 4 +#define INT_V_TQ 5 +#define INT_V_TS 6 +#define INT_V_RY 7 +#define INT_V_XU 8 + +#define INT_V_LPT 0 /* BR4 */ +#define INT_V_PTR 1 +#define INT_V_PTP 2 + +#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_PTR (1u << INT_V_PTR) +#define INT_PTP (1u << INT_V_PTP) +#define INT_LPT (1u << INT_V_LPT) + +#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_PTR (0x14 - IPL_HMIN) +#define IPL_PTP (0x14 - IPL_HMIN) +#define IPL_LPT (0x14 - IPL_HMIN) + +/* Device vectors */ + +#define VEC_Q 0000 +#define VEC_PTR 0070 +#define VEC_PTP 0074 +#define VEC_XQ 0120 +#define VEC_XU 0120 +#define VEC_RQ 0154 +#define VEC_RL 0160 +#define VEC_LPT 0200 +#define VEC_HK 0210 +#define VEC_TS 0224 +#define VEC_TQ 0260 +#define VEC_RX 0264 +#define VEC_RY 0264 +#define VEC_DZRX 0300 +#define VEC_DZTX 0304 + +/* Interrupt macros */ + +#define IVCL(dv) ((IPL_##dv * 32) + INT_V_##dv) +#define NVCL(dv) ((IPL_##dv * 32) + TR_##dv) +#define IREQ(dv) int_req[IPL_##dv] +#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv) +#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv) +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ + +/* Logging */ + +#define LOG_CPU_I 0x1 /* intexc */ +#define LOG_CPU_R 0x2 /* REI */ +#define LOG_CPU_P 0x4 /* context */ + +/* Massbus definitions */ + +#define MBA_RP (TR_MBA0 - TR_MBA0) /* MBA for RP */ +#define MBA_TU (TR_MBA1 - TR_MBA0) /* MBA for TU */ +#define MBA_RMASK 0x1F /* max 32 reg */ +#define MBE_NXD 1 /* nx drive */ +#define MBE_NXR 2 /* nx reg */ +#define MBE_GOE 3 /* err on GO */ + +/* Boot definitions */ + +#define BOOT_MB 0 /* device codes */ +#define BOOT_HK 1 /* for VMB */ +#define BOOT_RL 2 +#define BOOT_UDA 17 +#define BOOT_TK 18 + +/* Function prototypes for I/O */ + +int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf); +int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf); +int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf); +int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf); + +t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat auto_config (char *name, int32 num); + +int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf); +int32 mba_wrbufW (uint32 mbus, int32 bc, uint16 *buf); +int32 mba_chbufW (uint32 mbus, int32 bc, uint16 *buf); +int32 mba_get_bc (uint32 mbus); +void mba_upd_ata (uint32 mbus, uint32 val); +void mba_set_exc (uint32 mbus); +void mba_set_don (uint32 mbus); +void mba_set_enbdis (uint32 mbus, t_bool dis); +t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc); + +t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc); + +void sbi_set_errcnf (void); + +#endif diff --git a/VAX/vax780_doc.txt b/VAX/vax780_doc.txt new file mode 100644 index 00000000..b3abbd31 --- /dev/null +++ b/VAX/vax780_doc.txt @@ -0,0 +1,1093 @@ +To: Users +From: Bob Supnik +Subj: VAX780 Simulator Usage +Date: 01-Dec-2005 + + COPYRIGHT NOTICE + +The following copyright notice applies to both the SIMH source and binary: + + Original code published in 1993-2005, written by Robert M Supnik + Copyright (c) 1993-2005, 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 + ROBERT M SUPNIK 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 Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + +This memorandum documents the VAX simulator. + + +1. Simulator Files + +To compile the VAX780, you must define VM_VAX, VAX780, and USE_INT64 as part of +the compilation command line. To enable extended file support (files greater +than 2GB), you must define USE_ADDR64 as part of the command line as well. + +sim/ scp.h + sim_console.h + sim_defs.h + sim_ether.h + sim_fio.h + sim_rev.h + sim_sock.h + sim_tape.h + sim_timer.h + sim_tmxr.h + scp.c + sim_console.c + sim_ether.c + sim_fio.c + sim_sock.c + sim_tape.c + sim_timer.c + sim_tmxr.c + +sim/vax/ vax_defs.h + vax780_defs.h + vax_cis.c + vax_cmode.c + vax_cpu.c + vax_cpu1.c + vax_fpa.c + vax_mmu.c + vax_octa.c + vax_sys.c + vax_syscm.c + vax780_mba.c + vax780_mem.c + vax780_sbi.c + vax780_stddev.c + vax780_syslist.c + vax780_uba.c + +sim/pdp11/ pdp11_mscp.h + pdp11_uqssp.h + pdp11_xu.h + pdp11_dz.c + pdp11_hk.c + pdp11_lp.c + pdp11_rl.c + pdp11_rp.c + pdp11_rq.c + pdp11_ry.c + pdp11_tq.c + pdp11_ts.c + pdp11_tu.c + pdp11_xu.c + +Additional files are: + +sim/vax/ vmb780.bin standard boot code + +2. VAX780 Features + +The VAX simulator is configured as follows: + +device simulates +name(s) + +CPU VAX-11/780 CPU +TLB translation buffer +SBI system bus controller +MCTL0,MTCL1 memory controllers, MS780C with 4MB memory each, or + MS780E with 8MB-64MB each +UBA DW780 Unibus adapter +MBA0,MBA1 RH780 Massbus adapters +TODR time-of-day clock +TMR interval timer +TTI,TTO console terminal +RX console floppy +DZ DZ11 8-line terminal multiplexor (up to 4) +LPT LP11 line printer +RP RP04/RP05/RP06/RM03/RM05/RP07/RM80 Massbus disks, up to eight +HK RK611/RK06(7) cartridge disk controller with eight drives +RL RL11/RL01(2) cartridge disk controller with four drives +RQ UDA50 MSCP controller with four drives +RQB second UDA50 MSCP controller with four drives +RQC third UDA50 MSCP controller with four drives +RQD fourth UDA50 MSCP controller with four drives +RY RX211 floppy disk controller with two drives +TS TS11 magnetic tape controller with one drive +TQ TUK50 TMSCP magnetic tape controller with four drives +TU TM02/TM03 tape formatter with eight drives +XU DEUNA/DELUA Ethernet controller +XUB second DEUNA/DELUA Ethernet controller + +The DZ, LPT, RP, RL, RQ, RQB, RQC, RQD, RY, TS, TQ, TU, XU, and XUB +devices can be set DISABLED. RQB, RQC, RQD, and XUB are disabled by +default. + +The VAX780 simulator implements several unique stop conditions: + + - change mode to interrupt stack + - illegal vector (bits<1:0> = 2 or 3) + - unexpected exception during interrupt or exception + - process PTE in P0 or P1 space instead of system space + - unknown IPL + - infinite loop (BRB/W to self at IPL 1F) + +The VAX780 supports a simple binary format consisting of a stream of +binary bytes without origin or checksum, for loading memory. + +2.1 CPU and System Devices + +2.1.1 CPU + +CPU options include the size of main memory and the treatment of the +HALT instruction. + + SET CPU 8M set memory size = 8MB + SET CPU 16M set memory size = 16MB + SET CPU 32M set memory size = 32MB + SET CPU 48M set memory size = 48MB + SET CPU 64M set memory size = 64MB + SET CPU 128M set memory size = 128MB + +The CPU implements a show command to display the I/O address map: + + SHOW CPU IOSPACE show I/O space address map + +The CPU also implements a command to display a virtual to physical address +translation: + + SHOW CPU VIRTUAL=n show translation for address n + +Notes on memory size: + +- The first version of the VAX-11/780 used MS780C controllers, which + supported 1-4MB of memory per controller. This is the only memory + controller recognized by VMS V1. +- MS780E controllers supported 4MB-64MB per controller. +- The controller type is set automatically based on memory size. + +Initial memory size is 8MB. + +Memory can be loaded with a binary byte stream using the LOAD command. +The LOAD command recognizes three switches: + + -o origin argument follows file name + -r load ROM in memory controller 0 + -s load ROM in memory controller 1 + +These switches are recognized when examining or depositing in CPU memory +(or any other byte oriented device): + + -b examine/deposit bytes + -w examine/deposit words + -l examine/deposit longwords + -d data radix is decimal + -o data radix is octal + -h data radix is hexadecimal + +These switches are recognized when examining or depositing in CPU memory +only: + + -m examine (only) VAX instructions + -p examine/deposit PDP-11 (compatibility mode) + instructions + -r examine (only) RADIX50 encoded data + -v interpret address as virtual, current mode + +CPU registers include the visible state of the processor as well as the +control registers for the interrupt system. + + name size comments + + PC 32 program counter + R0..R14 32 R0..R14 + AP 32 alias for R12 + FP 32 alias for R13 + SP 32 alias for R14 + PSL 32 processor status longword + CC 4 condition codes, PSL<3:0> + KSP 32 kernel stack pointer + ESP 32 executive stack pointer + SSP 32 supervisor stack pointer + USP 32 user stack pointer + IS 32 interrupt stack pointer + SCBB 32 system control block base + PCBB 32 process controll block base + P0BR 32 P0 base register + P0LR 22 P0 length register + P1BR 32 P1 base register + P1LR 22 P1 length register + SBR 32 system base register + SLR 22 system length register + SISR 16 software interrupt summary register + ASTLVL 4 AST level register + MAPEN 1 memory management enable flag + TRPIRQ 8 trap/interrupt pending + CRDERR 1 correctible read data error flag + MEMERR 1 memory error flag + PCQ[0:63] 32 PC prior to last PC change or interrupt; + most recent PC change first + WRU 8 interrupt character + +The CPU can maintain a history of the most recently executed instructions. +This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands: + + SET CPU HISTORY clear history buffer + SET CPU HISTORY=0 disable history + SET CPU HISTORY=n enable history, length = n + SHOW CPU HISTORY print CPU history + SHOW CPU HISTORY=n print first n entries of CPU history + +The maximum length for the history is 65536 entries. + +2.1.2 Translation Buffer (TLB) + +The translation buffer consists of two units, representing the system +and user translation buffers, respectively. It has no registers. Each +translation buffer entry consists of two 32b words, as follows: + + word n tag + word n+1 cached PTE + +An invalid entry is indicated by a tag of FFFFFFFF. + +2.1.3 SBI Controller (SBI) + +The SBI was the VAX-11/780 system bus. The simulated SBI implements +these registers: + + name size comments + + NREQ14 16 Nexus IPL14 interrupt requests + NREQ15 16 Nexus IPL15 interrupt requests + NREQ16 16 Nexus IPL16 interrupt requests + NREQ17 16 Nexus IPL17 interrupt requests + WCSA 16 writeable control store address + WCSD 32 writeable control store data + MBRK 13 microbreak register + SBIFS 32 SBI fault status + SBISC 32 SBI silo compare + SBIMT 32 SBI maintenance register + SBIER 32 SBI error status + SBITMO 32 SBI timeout address + +2.1.4 Memory Controllers (MCTL0, MCTL1) + +The memory controllers implement the registers for the MS780C (non- +extended memory) or MS780E (extended memory). Each controller implements +these registers: + + name size comments + + CRA 32 control register A + CRB 32 control register B + CRC 32 control register C + CRD 32 control register D (MS780E only) + ROM[0:1023] 32 bootstrap ROM + +ROM can be loaded from a file with the commands + + LOAD -R load MCTL0 ROM + LOAD -S load MCTL1 ROM + +2.1.5 Time-Of-Day Clock (TODR) + +The TODR tracks time since an arbitrary start in 1 usec intervals. It +has these registers: + + name size comments + + TODR 32 time-of-day register + TIME 24 delay between ticks + +The TODR register autocalibrates against real-world time. + +2.1.6 Interval Timer (TMR) + +The interval timer implements the VAX architectural timer, with 1 usec +intervals. It has these registers: + + name size comments + + ICCS 32 interval timer control and status + ICR 32 interval count register + NICR 32 next interval count register + INT 1 interrupt request + +For standard VMS intervals (10msec = 100Hz), the interval timer +autocalibrates against real-world time. + +2.1.7 Unibus Adapter (UBA) + +The Unibus adapter (UBA) simulates the DW780. It recognizes these options: + + SET UBA AUTOCONFIGURE enable autoconfiguration + SET UBA NOAUTOCONFIGURE disable autoconfiguration + +and this display command: + + SHOW UBA IOSPACE display IO address space assignments + +The UBA has these registers: + + name size comments + + IPL14 32 Unibus IPL14 interrupt requests + IPL15 32 Unibus IPL15 interrupt requests + IPL16 32 Unibus IPL16 interrupt requests + IPL17 32 Unibus IPL17 interrupt requests + CNFR 32 configuration register + CR 32 control register + SR 32 status register + DR 32 diagnostic register + INT 1 internal UBA interrupt request + NEXINT 1 UBA Nexus interrupt request + AIIP 1 adapter initialization in progress flag + UIIP 1 Unibus initialization in progress flag + FMER 32 failing memory address + FUBAR 32 failing UBA map register + BRSVR0 32 spare register 0 + BRSVR1 32 spare register 1 + BRSVR2 32 spare register 2 + BRSVR3 32 spare register 3 + BRRVR4 32 vector register, IPL 14 + BRRVR5 32 vector register, IPL 15 + BRRVR6 32 vector register, IPL 16 + BRRVR7 32 vector register, IPL 17 + DPR[0:15] 32 data path registers 0..15 + MAP[0:495] 32 map registers 0..495 + AITIME 24 adapter initialization time + UITIME 24 Unibus initialization time + +2.1.8 Massbus Adapters (MBA0, MBA1) + +The Massbus adapters (MBA0, MBA1) simulate RH780's. MBA0 is assigned +to the RP disk drives, MBA1 to the TU tape drives. Each MBA has +these registers: + + name size comments + + CNFR 32 configuration register + CR 32 control register + SR 32 status register + VA 17 virtual address register + BC 32 byte count register + DR 32 diagnostic register + SMR 32 selected map register + MAP[0:255] 32 map registers + NEXINT 1 MBA Nexus interrupt request + +2.2 I/O Device Addressing + +Unibus I/O space is not large enough to allow all possible devices to be +configured simultaneously at fixed addresses. Instead, many devices have +floating addresses; that is, the assigned device address depends on the +presense of other devices in the configuration: + + DZ11 all instances have floating addresses + RL11 first instance has fixed address, rest floating + RX11/RX211 first instance has fixed address, rest floating + DEUNA/DELUA first instance has fixed address, rest floating + MSCP disk first instance has fixed address, rest floating + TMSCP tape first instance has fixed address, rest floating + +To maintain addressing consistency as the configuration changes, the +simulator implements DEC's standard I/O address and vector autoconfiguration +algorithms for devices DZ, VH, RL, RY, XUn, RQn, and TQ. This allows the +user to enable or disable devices without needing to manage I/O addresses +and vectors. + +In addition to autoconfiguration, most devices support the SET ADDRESS +command, which allows the I/O page address of the device to be changed, +and the SET VECTOR command, which allows the vector of the device to be +changed. Explicitly setting the I/O address of a device which normally +uses autoconfiguration DISABLES autoconfiguration for that device and for +the entire system. As a consequence, the user may have to manually configure +all other autoconfigured devices, because the autoconfiguration algorithm +no longer recognizes the explicitly configured device. A device can be +reset to autoconfigure with the SET AUTOCONFIGURE command. Auto- +configuration can be restored for the entire system with the SET UBA +AUTOCONFIGURE command. + +The current I/O addresses can be displayed with the SHOW UBA IOSPACE command. +Addresses that have set by autoconfiguration are marked with an asterisk (*). + +All devices support the SHOW ADDRESS and SHOW VECTOR commands, which display +the device address and vector, respectively. + +2.3 Programmed I/O Devices + +2.3.1 Console Input (TTI) + +The console interfaces (TTI, TTO) can be set to one of three modes, +7P, 7B or 8B: + + mode input characters output characters + + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default mode is 8B. + +The console input (TTI) polls the console keyboard for input. It +implements these registers: + + name size comments + + BUF 8 last data item processed + CSR 16 control/status register + INT 1 interrupt pending flag + ERR 1 error flag (CSR<15>) + DONE 1 device done flag (CSR<7>) + IE 1 interrupt enable flag (CSR<6>) + POS 32 number of characters input + TIME 24 keyboard polling interval + +2.3.2 Console Output (TTO) + +The console output (TTO) writes to the simulator console window. It +implements these registers: + + name size comments + + BUF 8 last data item processed + CSR 16 control/status register + INT 1 interrupt pending flag + ERR 1 error flag (CSR<15>) + DONE 1 device done flag (CSR<7>) + IE 1 interrupt enable flag (CSR<6>) + POS 32 number of characters input + TIME 24 time from I/O initiation to interrupt + +2.3.3 RX01 Console Floppy Disk (RX) + +RX01 options include the ability to set units write enabled or write +locked: + + SET RXn LOCKED set unit n write locked + SET RXn WRITEENABLED set unit n write enabled + +The RX01 implements these registers: + + name size comments + + FNC 8 function select + ES 8 error status + ECODE 8 error code + TA 8 track address + SA 8 sector address + STATE 4 protocol state + BPTR 7 data buffer pointer + CTIME 24 command initiation delay + STIME 24 seek time delay, per track + XTIME 24 transfer time delay, per byte + STOP_IOE 1 stop on I/O error + DBUF[0:127] 8 data buffer + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 disk not ready + +RX01 data files are buffered in memory; therefore, end of file and OS +I/O errors cannot occur. + +2.3.4 Line Printer (LPT) + +The line printer (LPT) writes data to a disk file. The POS register +specifies the number of the next data item to be written. Thus, +by changing POS, the user can backspace or advance the printer. + +The line printer implements these registers: + + name size comments + + BUF 8 last data item processed + CSR 16 control/status register + INT 1 interrupt pending flag + ERR 1 error flag (CSR<15>) + DONE 1 device done flag (CSR<7>) + IE 1 interrupt enable flag (CSR<6>) + POS 32 position in the output file + TIME 24 time from I/O initiation to interrupt + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 out of paper + + OS I/O error x report error and stop + +2.4 Disks + +All VAX-11/780 disks support a special form of the boot command, with +the following syntax: + + BOOT {/R5:} + +For example, + + BOOT HK0/R5:1 + +The optional switch, /R5, specifies that R5 is to be loaded with the +specified value prior to booting. If the switch is omitted, R5 is loaded +with 0. + +2.4.1 RM02/03/05/80, RP04/05/06/07 Disk Pack Drives (RP) + +The RP controller implements the Massbus family of large disk drives. +RP options include the ability to set units write enabled or write +locked, to set the drive type to one of six disk types, or autosize, +and to write a DEC standard 044 compliant bad block table on the last +track: + + SET RPn LOCKED set unit n write locked + SET RPn WRITEENABLED set unit n write enabled + SET RPn RM03 set type to RM03 + SET RPn RM05 set type to RM05 + SET RPn RM80 set type to RM80 + SET RPn RP04 set type to RP04 + SET RPn RP06 set type to RP06 + SET RPn RP07 set type to RP07 + SET RPn AUTOSIZE set type based on file size at attach + SET RPn BADBLOCK write bad block table on last track + +The type options can be used only when a unit is not attached to a file. +The bad block option can be used only when a unit is attached to a file. +Units can be set ENABLED or DISABLED. The RP controller supports the +BOOT command. + +The RP controller implements the registers listed below. Registers +suffixed with [0:7] are replicated per drive. + + name size comments + + CS1[0:7] 16 current operation + DA[0:7] 16 desired surface, sector + DS[0:7] 16 drive status + ER1[0:7] 16 drive errors + OF[0:7] 16 offset + DC[0:7] 16 desired cylinder + ER2[0:7] 16 error status 2 + ER3[0:7] 16 error status 3 + EC1[0:7] 16 ECC syndrome 1 + EC2[0:7] 16 ECC syndrome 2 + MR[0:7] 16 maintenance register + MR2[0:7] 16 maintenance register 2 (RM only) + HR[0:7] 16 holding register (RM only) + STIME 24 seek time, per cylinder + RTIME 24 rotational delay + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 disk not ready + + end of file x assume rest of disk is zero + + OS I/O error x report error and stop + +2.4.2 RL11/RL01/RL02 Cartridge Disk (RL) + +RL11 options include the ability to set units write enabled or write locked, +to set the drive size to RL01, RL02, or autosize, and to write a DEC standard +044 compliant bad block table on the last track: + + SET RLn LOCKED set unit n write locked + SET RLn WRITEENABLED set unit n write enabled + SET RLn RL01 set size to RL01 + SET RLn RL02 set size to RL02 + SET RLn AUTOSIZE set size based on file size at attach + SET RLn BADBLOCK write bad block table on last track + +The size options can be used only when a unit is not attached to a file. The +bad block option can be used only when a unit is attached to a file. Units +can also be set ENABLED or DISABLED. + +The RL11 implements these registers: + + name size comments + + RLCS 16 control/status + RLDA 16 disk address + RLBA 16 memory address + RLBAE 6 memory address extension (not used) + RLMP..RLMP2 16 multipurpose register queue + INT 1 interrupt pending flag + ERR 1 error flag (CSR<15>) + DONE 1 device done flag (CSR<7>) + IE 1 interrupt enable flag (CSR<6>) + STIME 24 seek time, per cylinder + RTIME 24 rotational delay + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 disk not ready + + end of file x assume rest of disk is zero + + OS I/O error x report error and stop + +2.4.3 RK611/RK06/RK07 Cartridge Disk (HK) + +RK611 options include the ability to set units write enabled or write +locked, to set the drive size to RK06, RK07, or autosize, and to write +a DEC standard 044 compliant bad block table on the last track: + + SET HKn LOCKED set unit n write locked + SET HKn WRITEENABLED set unit n write enabled + SET HKn RK06 set size to RK06 + SET HKn RK07 set size to RK07 + SET HKn AUTOSIZE set size based on file size at attach + SET HKn BADBLOCK write bad block table on last track + +The size options can be used only when a unit is not attached to a file. +The bad block option can be used only when a unit is attached to a file. +Units can be set ENABLED or DISABLED. The RK611 supports the BOOT command. + +The RK611 implements these registers: + + name size comments + + HKCS1 16 control/status 1 + HKWC 16 word count + HKBA 16 bus address + HKDA 16 desired surface, sector + HKCS2 16 control/status 2 + HKDS[0:7] 16 drive status, drives 0-7 + HKER[0:7] 16 drive errors, drives 0-7 + HKDB[0:2] 16 data buffer silo + HKDC 16 desired cylinder + HKOF 8 offset + HKMR 16 maintenance register + HKSPR 16 spare register + INT 1 interrupt pending flag + ERR 1 error flag (CSR<15>) + DONE 1 device done flag (CSR1<7>) + IE 1 interrupt enable flag (CSR1<6>) + STIME 24 seek time, per cylinder + RTIME 24 rotational delay + STOP_IOE 1 stop on I/O error + +Error handling is as follows: + + error STOP_IOE processed as + + not attached 1 report error and stop + 0 disk not ready + + end of file x assume rest of disk is zero + + OS I/O error x report error and stop + +2.4.4 UDA50 MSCP Disk Controllers (RQ, RQB, RQC, RQD) + +The simulator implements four MSCP disk controllers, RQ, RQB, RQC, RQD. +Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates +an UDA50 MSCP disk controller. RQ options include the ability to set +units write enabled or write locked, and to set the drive type to one +of many disk types: + + SET RQn LOCKED set unit n write locked + SET RQn WRITEENABLED set unit n write enabled + SET RQn RX50 set type to RX50 + SET RQn RX33 set type to RX33 + SET RQn RD51 set type to RD51 + SET RQn RD52 set type to RD52 + SET RQn RD53 set type to RD53 + SET RQn RD54 set type to RD54 + SET RQn RD31 set type to RD31 + SET RQn RA81 set type to RA81 + SET RQn RA82 set type to RA82 + set RQn RA71 set type to RA71 + SET RQn RA72 set type to RA72 + SET RQn RA90 set type to RA90 + SET RQn RA92 set type to RA92 + SET RQn RAUSER{=n} set type to RA81 with n MB's + SET -L RQn RAUSER{=n} set type to RA81 with n LBN's + +The type options can be used only when a unit is not attached to a file. +RAUSER is a "user specified" disk; the user can specify the size of the +disk in either MB (1000000 bytes) or logical block numbers (LBN's, 512 +bytes each). The minimum size is 5MB; the maximum size is 2GB without +extended addressing, 1000GB with extended addressing. + +Units can also be set ENABLED or DISABLED. + +Each RQ controller implements the following special SHOW commands: + + SHOW RQn TYPE show drive type + SHOW RQ RINGS show command and response rings + SHOW RQ FREEQ show packet free queue + SHOW RQ RESPQ show packet response queue + SHOW RQ UNITQ show unit queues + SHOW RQ ALL show all ring and queue state + SHOW RQn UNITQ show unit queues for unit n + +Each RQ controller implements these registers: + + name size comments + + SA 16 status/address register + S1DAT 16 step 1 init host data + CQBA 22 command queue base address + CQLNT 8 command queue length + CQIDX 8 command queue index + RQBA 22 request queue base address + RQLNT 8 request queue length + RQIDX 8 request queue index + FREE 5 head of free packet list + RESP 5 head of response packet list + PBSY 5 number of busy packets + CFLGS 16 controller flags + CSTA 4 controller state + PERR 9 port error number + CRED 5 host credits + HAT 17 host available timer + HTMO 17 host timeout value + CPKT[0:3] 5 current packet, units 0-3 + PKTQ[0:3] 5 packet queue, units 0-3 + UFLG[0:3] 16 unit flags, units 0-3 + INT 1 interrupt request + ITIME 1 response time for initialization steps + (except for step 4) + QTIME 24 response time for 'immediate' packets + XTIME 24 response time for data transfers + PKTS[33*32] 16 packet buffers, 33W each, + 32 entries + +While VMS is not timing sensitive, most of the BSD-derived operating systems +(NetBSD, OpenBSD, etc) are. The QTIME and XTIME parameters are set to +values that allow these operating systems to run correctly. + +Error handling is as follows: + + error processed as + + not attached disk not ready + + end of file assume rest of disk is zero + + OS I/O error report error and stop + +2.5 Tapes + +2.5.1 TM02/TM03/TE16/TU45/TU77 Magtapes (TU) + +The TU controller implementes the Massbus family of 800/1600bpi tape +drives. TU options include the ability to select the formatter type +(TM02 or TM03), to set the drive type to one of three drives (TE16, +TU45, or TU77), and to set the drives write enabled or write locked. + + SET TU TM02 set controller type to TM02 + SET TU TM03 set controller type to TM03 + set TUn TE16 set drive type to TE16 + SET TUn TU45 set drive type to TU45 + SET TUn TU77 set drive type to TU77 + SET TUn LOCKED set unit write locked + SET TUn WRITEENABLED set unit write enabled + +Units can be set ENABLED or DISABLED. + +The TU controller implements the following registers: + + name size comments + + CS1 6 current operation + FC 16 frame count + FS 16 formatter status + ER 16 formatter errors + CC 16 check character + MR 16 maintenance register + TC 16 tape control register + TIME 24 operation execution time + STOP_IOE 1 stop of I/O error + +Error handling is as follows: + + error processed as + + not attached tape not ready; if STOP_IOE, stop + + end of file bad tape + + OS I/O error parity error; if STOP_IOE, stop + +2.5.2 TS11 Magnetic Tape (TS) + +TS options include the ability to set the drive write enabled or write +locked. + + SET TS LOCKED set unit write locked + SET TS WRITEENABLED set unit write enabled + +The TS controller implements these registers: + + name size comments + + TSSR 16 status register + TSBA 16 bus address register + TSDBX 16 data buffer extension register (not used) + CHDR 16 command packet header + CADL 16 command packet low address or count + CADH 16 command packet high address + CLNT 16 command packet length + MHDR 16 message packet header + MRFC 16 message packet residual frame count + MXS0 16 message packet extended status 0 + MXS1 16 message packet extended status 1 + MXS2 16 message packet extended status 2 + MXS3 16 message packet extended status 3 + MXS4 16 message packet extended status 4 + WADL 16 write char packet low address + WADH 16 write char packet high address + WLNT 16 write char packet length + WOPT 16 write char packet options + WXOPT 16 write char packet extended options + ATTN 1 attention message pending + BOOT 1 boot request pending + OWNC 1 if set, tape owns command buffer + OWNM 1 if set, tape owns message buffer + TIME 24 delay + POS 32 position + +Error handling is as follows: + + error processed as + + not attached tape not ready + + end of file (read or space) end of physical tape + (write) ignored + + OS I/O error fatal tape error + +2.5.3 TUK50 TMSCP Disk Controller (TQ) + +The TQ controller simulates the TUK50 TMSCP disk controller. TQ options +include the ability to set units write enabled or write locked, and to +specify the controller type and tape length: + + SET TQn LOCKED set unit n write locked + SET TQn WRITEENABLED set unit n write enabled + SET TQ TK50 set controller type to TK50 + SET TQ TK70 set controller type to TK70 + SET TQ TU81 set controller type to TU81 + SET TQ TKUSER{=n} set controller type to TK50 with + tape capacity of n MB + +User-specified capacity must be between 50 and 2000 MB. + +The TQ controller implements the following special SHOW commands: + + SHOW TQ TYPE show controller type + SHOW TQ RINGS show command and response rings + SHOW TQ FREEQ show packet free queue + SHOW TQ RESPQ show packet response queue + SHOW TQ UNITQ show unit queues + SHOW TQ ALL show all ring and queue state + SHOW TQn UNITQ show unit queues for unit n + +The TQ controller implements these registers: + + name size comments + + SA 16 status/address register + S1DAT 16 step 1 init host data + CQBA 22 command queue base address + CQLNT 8 command queue length + CQIDX 8 command queue index + RQBA 22 request queue base address + RQLNT 8 request queue length + RQIDX 8 request queue index + FREE 5 head of free packet list + RESP 5 head of response packet list + PBSY 5 number of busy packets + CFLGS 16 controller flags + CSTA 4 controller state + PERR 9 port error number + CRED 5 host credits + HAT 17 host available timer + HTMO 17 host timeout value + CPKT[0:3] 5 current packet, units 0-3 + PKTQ[0:3] 5 packet queue, units 0-3 + UFLG[0:3] 16 unit flags, units 0-3 + POS[0:3] 32 tape position, units 0-3 + OBJP[0:3] 32 object position, units 0-3 + INT 1 interrupt request + ITIME 1 response time for initialization steps + (except for step 4) + QTIME 24 response time for 'immediate' packets + XTIME 24 response time for data transfers + PKTS[33*32] 16 packet buffers, 33W each, + 32 entries + +Error handling is as follows: + + error processed as + + not attached tape not ready + + end of file end of medium + + OS I/O error report error and stop + +2.6 Communications Devices + +2.6.1 DZ11 Terminal Multiplexor (DZ) + +The DZ11 is an 8-line terminal multiplexor. Up to 4 DZ11's (32 lines) +are supported. The number of lines can be changed with the command + + SET DZ LINES=n set line count to n + +The line count must be a multiple of 8, with a maximum of 32. + +The DZ11 supports three character processing modes, 7P, 7B, and 8B: + + mode input characters output characters + + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default is 8B. + +The DZ11 supports logging on a per-line basis. The command + + SET DZ LOG=line=filename + +enables logging for the specified line to the indicated file. The +command + + SET DZ NOLOG=line + +disables logging for the specified line and closes any open log file. +Finally, the command + + SHOW DZ LOG + +displays logging information for all DZ lines. + +The terminal lines perform input and output through Telnet sessions +connected to a user-specified port. The ATTACH command specifies +the port to be used: + + ATTACH {-am} DZ set up listening port + +where port is a decimal number between 1 and 65535 that is not being used +for other TCP/IP activities. The optional switch -m turns on the DZ11's +modem controls; the optional switch -a turns on active disconnects +(disconnect session if computer clears Data Terminal Ready). Without +modem control, the DZ behaves as though terminals were directly connected; +disconnecting the Telnet session does not cause any operating system- +visible change in line status. + +Once the DZ is attached and the simulator is running, the DZ will listen +for connections on the specified port. It assumes that the incoming +connections are Telnet connections. The connection remains open until +disconnected by the simulated program, the Telnet client, a SET DZ +DISCONNECT command, or a DETACH DZ command. + +The SHOW DZ CONNECTIONS command displays the current connections to the DZ. +The SHOW DZ STATISTICS command displays statistics for active connections. +The SET DZ DISCONNECT=linenumber disconnects the specified line. + +The DZ11 implements these registers: + + name size comments + + CSR[0:3] 16 control/status register, boards 0-3 + RBUF[0:3] 16 receive buffer, boards 0-3 + LPR[0:3] 16 line parameter register, boards 0-3 + TCR[0:3] 16 transmission control register, boards 0-3 + MSR[0:3] 16 modem status register, boards 0-3 + TDR[0:3] 16 transmit data register, boards 0-3 + SAENB[0:3] 1 silo alarm enabled, boards 0-3 + RXINT 4 receive interrupts, boards 3..0 + TXINT 4 transmit interrupts, boards 3..0 + MDMTCL 1 modem control enabled + AUTODS 1 autodisconnect enabled + +The DZ11 does not support save and restore. All open connections are +lost when the simulator shuts down or the DZ is detached. + +2.7 Symbolic Display and Input + +The VAX780 simulator implements symbolic display and input. Display is +controlled by command line switches: + + -a,-c display as ASCII data + -m display instruction mnemonics + -p display compatibility mode mnemonics + -r display RADIX50 encoding + +Input parsing is controlled by the first character typed in or by command +line switches: + + ' or -a ASCII characters (determined by length) + " or -c ASCII string (maximum 60 characters) + -p compatibility mode instruction mnemonic + alphabetic instruction mnemonic + numeric octal number + +VAX instruction input uses standard VAX assembler syntax. Compatibility +mode instruction input uses standard PDP-11 assembler syntax. + +The syntax for VAX specifiers is as follows: + +syntax specifier displacement comments + +#s^n, #n 0n - short literal, integer only +[Rn] 4n - indexed, second specifier + follows +Rn 5n - PC illegal +(Rn) 6n - PC illegal +-(Rn) 7n - PC illegal +(Rn)+ 8n - +#i^n, #n 8F n immediate +@(Rn)+ 9n - +@#addr 9F addr absolute +{+/-}b^d(Rn) An {+/-}d byte displacement +b^d AF d - PC byte PC relative +@{+/-}b^d(Rn) Bn {+/-}d byte displacement deferred +@b^d BF d - PC byte PC relative deferred +{+/-}w^d(Rn) Cn {+/-}d word displacement +w^d CF d - PC word PC relative +@{+/-}w^d(Rn) Dn {+/-}d word displacement deferred +@w^d DF d - PC word PC relative deferred +{+/-}l^d(Rn) En {+/-}d long displacement +l^d EF d - PC long PC relative +@{+/-}l^d(Rn) Fn {+/-}d long displacement deferred +@l^d FF d - PC long PC relative deferred + +If no override is given for a literal (s^ or i^) or for a displacement or PC +relative addres (b^, w^, or l^), the simulator chooses the mode automatically. diff --git a/VAX/vax780_mba.c b/VAX/vax780_mba.c new file mode 100644 index 00000000..9a05a68d --- /dev/null +++ b/VAX/vax780_mba.c @@ -0,0 +1,770 @@ +/* vax780_mba.c: VAX 11/780 Massbus adapter + + Copyright (c) 2004-2005, 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 + ROBERT M SUPNIK 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 Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + mba0, mba1 RH780 Massbus adapter +*/ + +#include "vax_defs.h" + +/* Massbus */ + +#define MBA_NMAPR 256 /* number of map reg */ +#define MBA_V_RTYPE 10 /* nexus addr: reg type */ +#define MBA_M_RTYPE 0x3 +#define MBART_INT 0x0 /* internal */ +#define MBART_EXT 0x1 /* external */ +#define MBART_MAP 0x2 /* map */ +#define MBA_V_INTOFS 2 /* int reg: reg ofs */ +#define MBA_M_INTOFS 0xFF +#define MBA_V_DRV 7 /* ext reg: drive num */ +#define MBA_M_DRV 0x7 +#define MBA_V_DEVOFS 2 /* ext reg: reg ofs */ +#define MBA_M_DEVOFS 0x1F +#define MBA_RTYPE(x) (((x) >> MBA_V_RTYPE) & MBA_M_RTYPE) +#define MBA_INTOFS(x) (((x) >> MBA_V_INTOFS) & MBA_M_INTOFS) +#define MBA_EXTDRV(x) (((x) >> MBA_V_DRV) & MBA_M_DRV) +#define MBA_EXTOFS(x) (((x) >> MBA_V_DEVOFS) & MBA_M_DEVOFS) + +/* Massbus configuration register */ + +#define MBACNF_OF 0x0 +#define MBACNF_ADPDN 0x00800000 /* adap pdn - ni */ +#define MBACNF_ADPUP 0x00400000 /* adap pup - ni */ +#define MBACNF_CODE 0x00000020 +#define MBACNF_RD (SBI_FAULTS|MBACNF_W1C) +#define MBACNF_W1C 0x00C00000 + +/* Control register */ + +#define MBACR_OF 0x1 +#define MBACR_MNT 0x00000008 /* maint */ +#define MBACR_IE 0x00000004 /* int enable */ +#define MBACR_ABORT 0x00000002 /* abort */ +#define MBACR_INIT 0x00000001 +#define MBACR_RD 0x0000000E +#define MBACR_WR 0x0000000E + +/* Status register */ + +#define MBASR_OF 0x2 +#define MBASR_DTBUSY 0x80000000 /* DT busy RO */ +#define MBASR_NRCONF 0x40000000 /* no conf - ni W1C */ +#define MBASR_CRD 0x20000000 /* CRD - ni W1C */ +#define MBASR_CBH 0x00800000 /* CBHUNG - ni W1C */ +#define MBASR_PGE 0x00080000 /* prog err - W1C int */ +#define MBASR_NFD 0x00040000 /* nx drive - W1C int */ +#define MBASR_MCPE 0x00020000 /* ctl perr - ni W1C int */ +#define MBASR_ATA 0x00010000 /* attn - W1C int */ +#define MBASR_SPE 0x00004000 /* silo perr - ni W1C int */ +#define MBASR_DTCMP 0x00002000 /* xfr done - W1C int */ +#define MBASR_DTABT 0x00001000 /* abort - W1C int */ +#define MBASR_DLT 0x00000800 /* dat late - ni W1C abt */ +#define MBASR_WCEU 0x00000400 /* wrchk upper - W1C abt */ +#define MBASR_WCEL 0x00000200 /* wrchk lower - W1C abt */ +#define MBASR_MXF 0x00000100 /* miss xfr - ni W1C abt */ +#define MBASR_MBEXC 0x00000080 /* except - ni W1C abt */ +#define MBASR_MBDPE 0x00000040 /* dat perr - ni W1C abt */ +#define MBASR_MAPPE 0x00000020 /* map perr - ni W1C abt */ +#define MBASR_INVM 0x00000010 /* inv map - W1C abt */ +#define MBASR_ERCONF 0x00000008 /* err conf - ni W1C abt */ +#define MBASR_RDS 0x00000004 /* RDS - ni W1C abt */ +#define MBASR_ITMO 0x00000002 /* timeout - W1C abt */ +#define MBASR_RTMO 0x00000001 /* rd timeout - W1C abt */ +#define MBASR_RD 0xE08F7FFF +#define MBASR_W1C 0x608F7FFF +#define MBASR_ABORTS 0x00000FFF +#define MBASR_ERRORS 0x608E49FF +#define MBASR_INTR 0x000F7000 + +/* Virtual address register */ + +#define MBAVA_OF 0x3 +#define MBAVA_RD 0x0001FFFF +#define MBAVA_WR (MBAVA_RD) + +/* Byte count */ + +#define MBABC_OF 0x4 +#define MBABC_WR 0x0000FFFF +#define MBABC_V_MBC 16 /* MB count */ + +/* Diagnostic register */ + +#define MBADR_OF 0x5 +#define MBADR_RD 0xFFFFFFFF +#define MBADR_WR 0xFFC00000 + +/* Selected map entry - read only */ + +#define MBASMR_OF 0x6 +#define MBASMR_RD (MBAMAP_RD) + +/* Command register (SBI) - read only */ + +#define MBACMD_OF 0x7 + +/* External registers */ + +#define MBA_CS1 0x00 /* device CSR1 */ +#define MBA_CS1_WR 0x3F /* writeable bits */ +#define MBA_CS1_DT 0x28 /* >= for data xfr */ + +/* Map registers */ + +#define MBAMAP_VLD 0x80000000 /* valid */ +#define MBAMAP_PAG 0x001FFFFF +#define MBAMAP_RD (MBAMAP_VLD | MBAMAP_PAG) +#define MBAMAP_WR (MBAMAP_RD) + +/* Debug switches */ + +#define MBA_DEB_RRD 0x01 /* reg reads */ +#define MBA_DEB_RWR 0x02 /* reg writes */ +#define MBA_DEB_MRD 0x04 /* map reads */ +#define MBA_DEB_MWR 0x08 /* map writes */ +#define MBA_DEB_XFR 0x10 /* transfers */ +#define MBA_DEB_ERR 0x20 /* errors */ + +uint32 mba_cnf[MBA_NUM]; /* config reg */ +uint32 mba_cr[MBA_NUM]; /* control reg */ +uint32 mba_sr[MBA_NUM]; /* status reg */ +uint32 mba_va[MBA_NUM]; /* virt addr */ +uint32 mba_bc[MBA_NUM]; /* byte count */ +uint32 mba_dr[MBA_NUM]; /* diag reg */ +uint32 mba_smr[MBA_NUM]; /* sel map reg */ +uint32 mba_map[MBA_NUM][MBA_NMAPR]; /* map */ + +extern uint32 nexus_req[NEXUS_HLVL]; +extern UNIT cpu_unit; +extern FILE *sim_log; +extern FILE *sim_deb; +extern int32 sim_switches; + +t_stat mba_reset (DEVICE *dptr); +t_stat mba_rdreg (int32 *val, int32 pa, int32 mode); +t_stat mba_wrreg (int32 val, int32 pa, int32 lnt); +t_bool mba_map_addr (uint32 va, uint32 *ma, uint32 mb); +void mba_set_int (uint32 mb); +void mba_clr_int (uint32 mb); +void mba_upd_sr (uint32 set, uint32 clr, uint32 mb); +DIB mba0_dib, mba1_dib; + +extern int32 ReadB (uint32 pa); +extern int32 ReadW (uint32 pa); +extern int32 ReadL (uint32 pa); +extern void WriteB (uint32 pa, int32 val); +extern void WriteW (uint32 pa, int32 val); +extern void WriteL (uint32 pa, int32 val); + +/* Massbus register dispatches */ + +static t_stat (*mbregR[MBA_NUM])(int32 *dat, int32 ad, int32 md); +static t_stat (*mbregW[MBA_NUM])(int32 dat, int32 ad, int32 md); +static int32 (*mbabort[MBA_NUM])(void); + +/* Massbus adapter data structures + + mba_dev MBA device descriptors + mbax_unit MBA unit + mbax_reg MBA register list +*/ + +DIB mba0_dib = { TR_MBA0, 0, &mba_rdreg, &mba_wrreg, 0, NVCL (MBA0) }; + +UNIT mba0_unit = { UDATA (NULL, 0, 0) }; + +REG mba0_reg[] = { + { HRDATA (CNFR, mba_cnf[0], 32) }, + { HRDATA (CR, mba_cr[0], 4) }, + { HRDATA (SR, mba_sr[0], 32) }, + { HRDATA (VA, mba_va[0], 17) }, + { HRDATA (BC, mba_bc[0], 16) }, + { HRDATA (DR, mba_dr[0], 32) }, + { HRDATA (SMR, mba_dr[0], 32) }, + { BRDATA (MAP, mba_map[0], 16, 32, MBA_NMAPR) }, + { FLDATA (NEXINT, nexus_req[IPL_MBA0], TR_MBA0) }, + { NULL } + }; + +MTAB mba0_mod[] = { + { MTAB_XTD|MTAB_VDV, TR_MBA0, "NEXUS", NULL, + NULL, &show_nexus }, + { 0 } + }; + +DIB mba1_dib = { TR_MBA1, 0, &mba_rdreg, &mba_wrreg, 0, NVCL (MBA1) }; + +UNIT mba1_unit = { UDATA (NULL, 0, 0) }; + +MTAB mba1_mod[] = { + { MTAB_XTD|MTAB_VDV, TR_MBA1, "NEXUS", NULL, + NULL, &show_nexus }, + { 0 } + }; + +REG mba1_reg[] = { + { HRDATA (CNFR, mba_cnf[1], 32) }, + { HRDATA (CR, mba_cr[1], 4) }, + { HRDATA (SR, mba_sr[1], 32) }, + { HRDATA (VA, mba_va[1], 17) }, + { HRDATA (BC, mba_bc[1], 16) }, + { HRDATA (DR, mba_dr[1], 32) }, + { HRDATA (SMR, mba_dr[1], 32) }, + { BRDATA (MAP, mba_map[1], 16, 32, MBA_NMAPR) }, + { FLDATA (NEXINT, nexus_req[IPL_MBA1], TR_MBA1) }, + { NULL } + }; + +DEBTAB mba_deb[] = { + { "REGREAD", MBA_DEB_RRD }, + { "REGWRITE", MBA_DEB_RWR }, + { "MAPREAD", MBA_DEB_MRD }, + { "MAPWRITE", MBA_DEB_MWR }, + { "XFER", MBA_DEB_XFR }, + { "ERROR", MBA_DEB_ERR }, + { NULL, 0 } + }; + +DEVICE mba_dev[] = { + { + "MBA0", &mba0_unit, mba0_reg, mba0_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &mba_reset, + NULL, NULL, NULL, + &mba0_dib, DEV_NEXUS | DEV_DEBUG, 0, + mba_deb, 0, 0 + }, + { + "MBA1", &mba1_unit, mba1_reg, mba1_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &mba_reset, + NULL, NULL, NULL, + &mba1_dib, DEV_NEXUS | DEV_DEBUG, 0, + mba_deb, 0, 0 + } + }; + +/* Read Massbus adapter register */ + +t_stat mba_rdreg (int32 *val, int32 pa, int32 lnt) +{ +int32 mb, ofs, drv, rtype; +uint32 t; +t_stat r; + +mb = NEXUS_GETNEX (pa) - TR_MBA0; /* get MBA */ +if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? */ + printf (">>MBA%d: invalid adapter read mask, pa = %X, lnt = %d\r\n", mb, pa, lnt); + sbi_set_errcnf (); /* err confirmation */ + return SCPE_OK; + } +if (mb >= MBA_NUM) return SCPE_NXM; /* valid? */ +rtype = MBA_RTYPE (pa); /* get reg type */ + +switch (rtype) { /* case on type */ + + case MBART_INT: /* internal */ + ofs = MBA_INTOFS (pa); /* check range */ + switch (ofs) { + + case MBACNF_OF: /* CNF */ + *val = (mba_cnf[mb] & MBACNF_RD) | MBACNF_CODE; + break; + + case MBACR_OF: /* CR */ + *val = mba_cr[mb] & MBACR_RD; + break; + + case MBASR_OF: /* SR */ + *val = mba_sr[mb] & MBASR_RD; + break; + + case MBAVA_OF: /* VA */ + *val = mba_va[mb] & MBAVA_RD; + break; + + case MBABC_OF: /* BC */ + t = mba_bc[mb] & MBABC_WR; + *val = (t << MBABC_V_MBC) | t; + break; + + case MBADR_OF: /* DR */ + *val = mba_dr[mb] & MBADR_RD; + break; + + case MBASMR_OF: /* SMR */ + *val = mba_smr[mb] & MBASMR_RD; + break; + + case MBACMD_OF: /* CMD */ + *val = 0; + break; + + default: + return SCPE_NXM; + } + if (DEBUG_PRI (mba_dev[mb], MBA_DEB_RRD)) + fprintf (sim_deb, ">>MBA%d: int reg %d read, value = %X\n", mb, ofs, *val); + break; + + case MBART_EXT: /* external */ + if (!mbregR[mb]) return SCPE_NXM; /* device there? */ + drv = MBA_EXTDRV (pa); /* get dev num */ + ofs = MBA_EXTOFS (pa); /* get reg offs */ + r = mbregR[mb] (val, ofs, drv); /* call device */ + if (r == MBE_NXD) mba_upd_sr (MBASR_NFD, 0, mb);/* nx drive? */ + else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ + *val |= (mba_sr[mb] & ~WMASK); /* upper 16b from SR */ + if (DEBUG_PRI (mba_dev[mb], MBA_DEB_RRD)) + fprintf (sim_deb, ">>MBA%d: drv %d ext reg %d read, value = %X\n", mb, drv, ofs, *val); + break; + + case MBART_MAP: /* map */ + ofs = MBA_INTOFS (pa); + *val = mba_map[mb][ofs] & MBAMAP_RD; + if (DEBUG_PRI (mba_dev[mb], MBA_DEB_MRD)) + fprintf (sim_deb, ">>MBA%d: map %d read, value = %X\n", mb, ofs, *val); + break; + + default: + return SCPE_NXM; + } + +return SCPE_OK; +} + +/* Write Massbus adapter register */ + +t_stat mba_wrreg (int32 val, int32 pa, int32 lnt) +{ +int32 mb, ofs, drv, rtype; +t_stat r; +t_bool cs1dt; + +mb = NEXUS_GETNEX (pa) - TR_MBA0; /* get MBA */ +if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? */ + printf (">>MBA%d: invalid adapter write mask, pa = %X, lnt = %d\r\n", mb, pa, lnt); + sbi_set_errcnf (); /* err confirmation */ + return SCPE_OK; + } +if (mb >= MBA_NUM) return SCPE_NXM; /* valid? */ +rtype = MBA_RTYPE (pa); /* get reg type */ + +switch (rtype) { /* case on type */ + + case MBART_INT: /* internal */ + ofs = MBA_INTOFS (pa); /* check range */ + switch (ofs) { + + case MBACNF_OF: /* CNF */ + mba_cnf[mb] &= ~(val & MBACNF_W1C); + break; + + case MBACR_OF: /* CR */ + if (val & MBACR_INIT) /* init? */ + mba_reset (&mba_dev[mb]); /* reset MBA */ + if ((val & MBACR_ABORT) && + (mba_sr[mb] & MBASR_DTBUSY)) { + if (mbabort[mb]) mbabort[mb] (); /* abort? */ + mba_upd_sr (MBASR_DTABT, 0, mb); + } + if ((val & MBACR_MNT) && + (mba_sr[mb] & MBASR_DTBUSY)) { + mba_upd_sr (MBASR_PGE, 0, mb); /* mnt & xfer? */ + val = val & ~MBACR_MNT; + } + if ((val & MBACR_IE) == 0) mba_clr_int (mb); + mba_cr[mb] = (mba_cr[mb] & ~MBACR_WR) | + (val & MBACR_WR); + break; + + case MBASR_OF: /* SR */ + mba_sr[mb] = mba_sr[mb] & ~(val & MBASR_W1C); + break; + + case MBAVA_OF: /* VA */ + if (mba_sr[mb] & MBASR_DTBUSY) /* err if xfr */ + mba_upd_sr (MBASR_PGE, 0, mb); + else mba_va[mb] = val & MBAVA_WR; + break; + + case MBABC_OF: /* BC */ + if (mba_sr[mb] & MBASR_DTBUSY) /* err if xfr */ + mba_upd_sr (MBASR_PGE, 0, mb); + else mba_bc[mb] = val & MBABC_WR; + break; + + case MBADR_OF: /* DR */ + mba_dr[mb] = (mba_dr[mb] & ~MBADR_WR) | + (val & MBADR_WR); + break; + + default: + return SCPE_NXM; + } + if (DEBUG_PRI (mba_dev[mb], MBA_DEB_RWR)) + fprintf (sim_deb, ">>MBA%d: int reg %d write, value = %X\n", mb, ofs, val); + break; + + case MBART_EXT: /* external */ + if (!mbregW[mb]) return SCPE_NXM; /* device there? */ + drv = MBA_EXTDRV (pa); /* get dev num */ + ofs = MBA_EXTOFS (pa); /* get reg offs */ + cs1dt = (ofs == MBA_CS1) && (val & CSR_GO) && /* starting xfr? */ + ((val & MBA_CS1_WR) >= MBA_CS1_DT); + if (cs1dt && (mba_sr[mb] & MBASR_DTBUSY)) { /* xfr while busy? */ + mba_upd_sr (MBASR_PGE, 0, mb); /* prog error */ + break; + } + r = mbregW[mb] (val & WMASK, ofs, drv); /* write dev reg */ + if (r == MBE_NXD) mba_upd_sr (MBASR_NFD, 0, mb);/* nx drive? */ + else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ + if (cs1dt && (r == SCPE_OK)) /* did dt start? */ + mba_sr[mb] = (mba_sr[mb] | MBASR_DTBUSY) & ~MBASR_W1C; + if (DEBUG_PRI (mba_dev[mb], MBA_DEB_RWR)) + fprintf (sim_deb, ">>MBA%d: drv %d ext reg %d write, value = %X\n", mb, drv, ofs, val); + break; + + case MBART_MAP: /* map */ + ofs = MBA_INTOFS (pa); + mba_map[mb][ofs] = val & MBAMAP_WR; + if (DEBUG_PRI (mba_dev[mb], MBA_DEB_MWR)) + fprintf (sim_deb, ">>MBA%d: map %d write, value = %X\n", mb, ofs, val); + break; + + default: + return SCPE_NXM; + } + +return SCPE_OK; +} + +/* Massbus I/O routine + + mb_rdbufW - fetch word buffer from memory + mb_wrbufW - store word buffer into memory + mb_chbufW - compare word buffer with memory + + Returns number of bytes successfully transferred/checked +*/ + +int32 mba_rdbufW (uint32 mb, int32 bc, uint16 *buf) +{ +int32 i, j, ba, mbc, pbc; +uint32 pa, dat; + +if (mb >= MBA_NUM) return 0; /* valid MBA? */ +ba = mba_va[mb]; /* get virt addr */ +mbc = (MBABC_WR + 1) - mba_bc[mb]; /* get Mbus bc */ +if (bc > mbc) bc = mbc; /* use smaller */ +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */ + if (!ADDR_IS_MEM (pa)) { /* NXM? */ + mba_upd_sr (MBASR_RTMO, 0, mb); + break; + } + pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */ + if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (DEBUG_PRI (mba_dev[mb], MBA_DEB_XFR)) + fprintf (sim_deb, ">>MBA%d: read, pa = %X, bc = %X\n", mb, pa, pbc); + if ((pa | pbc) & 1) { /* aligned word? */ + for (j = 0; j < pbc; pa++, j++) { /* no, bytes */ + if ((i + j) & 1) { /* odd byte? */ + *buf = (*buf & BMASK) | (ReadB (pa) << 8); + buf++; + } + else *buf = (*buf & ~BMASK) | ReadB (pa); + } + } + else if ((pa | pbc) & 3) { /* aligned LW? */ + for (j = 0; j < pbc; pa = pa + 2, j = j + 2) { /* no, words */ + *buf++ = ReadW (pa); /* get word */ + } + } + else { /* yes, do by LW */ + for (j = 0; j < pbc; pa = pa + 4, j = j + 4) { + dat = ReadL (pa); /* get lw */ + *buf++ = dat & WMASK; /* low 16b */ + *buf++ = (dat >> 16) & WMASK; /* high 16b */ + } + } + } +mba_bc[mb] = (mba_bc[mb] + i) & MBABC_WR; +mba_va[mb] = (mba_va[mb] + i) & MBAVA_WR; +return i; +} + +int32 mba_wrbufW (uint32 mb, int32 bc, uint16 *buf) +{ +int32 i, j, ba, mbc, pbc; +uint32 pa, dat; + +if (mb >= MBA_NUM) return 0; /* valid MBA? */ +ba = mba_va[mb]; /* get virt addr */ +mbc = (MBABC_WR + 1) - mba_bc[mb]; /* get Mbus bc */ +if (bc > mbc) bc = mbc; /* use smaller */ +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */ + if (!ADDR_IS_MEM (pa)) { /* NXM? */ + mba_upd_sr (MBASR_RTMO, 0, mb); + break; + } + pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */ + if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (DEBUG_PRI (mba_dev[mb], MBA_DEB_XFR)) + fprintf (sim_deb, ">>MBA%d: write, pa = %X, bc = %X\n", mb, pa, pbc); + if ((pa | pbc) & 1) { /* aligned word? */ + for (j = 0; j < pbc; pa++, j++) { /* no, bytes */ + if ((i + j) & 1) { + WriteB (pa, (*buf >> 8) & BMASK); + buf++; + } + else WriteB (pa, *buf & BMASK); + } + } + else if ((pa | pbc) & 3) { /* aligned LW? */ + for (j = 0; j < pbc; pa = pa + 2, j = j + 2) { /* no, words */ + WriteW (pa, *buf); /* write word */ + buf++; + } + } + else { /* yes, do by LW */ + for (j = 0; j < pbc; pa = pa + 4, j = j + 4) { + dat = (uint32) *buf++; /* get low 16b */ + dat = dat | (((uint32) *buf++) << 16); /* merge hi 16b */ + WriteL (pa, dat); /* store LW */ + } + } + } +mba_bc[mb] = (mba_bc[mb] + i) & MBABC_WR; +mba_va[mb] = (mba_va[mb] + i) & MBAVA_WR; +return i; +} + +int32 mba_chbufW (uint32 mb, int32 bc, uint16 *buf) +{ +int32 i, j, ba, mbc, pbc; +uint32 pa, dat, cmp; + +if (mb >= MBA_NUM) return 0; /* valid MBA? */ +ba = mba_va[mb]; /* get virt addr */ +mbc = (MBABC_WR + 1) - mba_bc[mb]; /* get Mbus bc */ +if (bc > mbc) bc = mbc; /* use smaller */ +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */ + if (!ADDR_IS_MEM (pa)) { /* NXM? */ + mba_upd_sr (MBASR_RTMO, 0, mb); + break; + } + pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */ + if (DEBUG_PRI (mba_dev[mb], MBA_DEB_XFR)) + fprintf (sim_deb, ">>MBA%d: check, pa = %X, bc = %X\n", mb, pa, pbc); + if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + for (j = 0; j < pbc; j++, pa++) { /* byte by byte */ + cmp = ReadB (pa); + if ((i + j) & 1) dat = (*buf++ >> 8) & BMASK; + else dat = *buf & BMASK; + if (cmp != dat) { + mba_upd_sr ((j & 1)? MBASR_WCEU: MBASR_WCEL, 0, mb); + break; + } /* end if */ + } /* end for j */ + } /* end for i */ +mba_bc[mb] = (mba_bc[mb] + i) & MBABC_WR; +mba_va[mb] = (mba_va[mb] + i) & MBAVA_WR; +return i; +} + +/* Map an address via the translation map */ + +t_bool mba_map_addr (uint32 va, uint32 *ma, uint32 mb) +{ +uint32 vblk = (va >> VA_V_VPN); /* map index */ +uint32 mmap = mba_map[mb][vblk]; /* get map */ + +mba_smr[mb] = mmap; /* save map reg */ +if (mmap & MBAMAP_VLD) { /* valid? */ + *ma = ((mmap & MBAMAP_PAG) << VA_V_VPN) + VA_GETOFF (va); + return 1; /* legit addr */ + } +mba_upd_sr (MBASR_INVM, 0, mb); /* invalid map */ +return 0; +} + +/* Device access, status, and interrupt routines */ + +void mba_set_don (uint32 mb) +{ +mba_upd_sr (MBASR_DTCMP, 0, mb); +return; +} + +void mba_upd_ata (uint32 mb, uint32 val) +{ +if (val) mba_upd_sr (MBASR_ATA, 0, mb); +else mba_upd_sr (0, MBASR_ATA, mb); +return; +} + +void mba_set_exc (uint32 mb) +{ +mba_upd_sr (MBASR_MBEXC, 0, mb); +if (DEBUG_PRI (mba_dev[mb], MBA_DEB_ERR)) + fprintf (sim_deb, ">>MBA%d: EXC write\n", mb); +return; +} + +int32 mba_get_bc (uint32 mb) +{ +if (mb >= MBA_NUM) return 0; +return (MBABC_WR + 1) - mba_bc[mb]; +} + +void mba_set_int (uint32 mb) +{ +DIB *dibp; + +if (mb >= MBA_NUM) return; +dibp = (DIB *) mba_dev[mb].ctxt; +if (dibp) + nexus_req[dibp->vloc >> 5] |= (1u << (dibp->vloc & 0x1F)); +return; +} + +void mba_clr_int (uint32 mb) +{ +DIB *dibp; + +if (mb >= MBA_NUM) return; +dibp = (DIB *) mba_dev[mb].ctxt; +if (dibp) + nexus_req[dibp->vloc >> 5] &= ~(1u << (dibp->vloc & 0x1F)); +return; +} + +void mba_upd_sr (uint32 set, uint32 clr, uint32 mb) +{ +if (mb >= MBA_NUM) return; +if (set & MBASR_ABORTS) set |= (MBASR_DTCMP|MBASR_DTABT); +if (set & (MBASR_DTCMP|MBASR_DTABT)) mba_sr[mb] &= ~MBASR_DTBUSY; +mba_sr[mb] = (mba_sr[mb] | set) & ~clr; +if ((set & MBASR_INTR) && (mba_cr[mb] & MBACR_IE)) + mba_set_int (mb); +if ((set & MBASR_ERRORS) && (DEBUG_PRI (mba_dev[mb], MBA_DEB_ERR))) + fprintf (sim_deb, ">>MBA%d: CS error = %X\n", mb, mba_sr[mb]); +return; +} + +/* Reset Massbus adapter */ + +t_stat mba_reset (DEVICE *dptr) +{ +int32 i, mb; +DIB *dibp; + +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +mb = dibp->ba - TR_MBA0; +if ((mb < 0) || (mb >= MBA_NUM)) return SCPE_IERR; +mba_cnf[mb] = 0; +mba_cr[mb] &= MBACR_MNT; +mba_sr[mb] = 0; +mba_bc[mb] = 0; +mba_va[mb] = 0; +mba_dr[mb] = 0; +mba_smr[mb] = 0; +if (sim_switches & SWMASK ('P')) { + for (i = 0; i < MBA_NMAPR; i++) mba_map[mb][i] = 0; + } +if (mbabort[mb]) mbabort[mb] (); /* reset device */ +return SCPE_OK; +} + +/* Show Massbus adapter number */ + +t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +DEVICE *dptr = find_dev_from_unit (uptr); +DIB *dibp; + +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +fprintf (st, "Massbus adapter %d", dibp->ba); +return SCPE_OK; +} + +/* Enable/disable Massbus adapter */ + +void mba_set_enbdis (uint32 mb, t_bool dis) +{ +if (mb >= MBA_NUM) return; /* valid MBA? */ +if (dis) mba_dev[mb].flags |= DEV_DIS; +else mba_dev[mb].flags &= ~DEV_DIS; +return; +} + +/* Init Mbus tables */ + +void init_mbus_tab (void) +{ +uint32 i; + +for (i = 0; i < MBA_NUM; i++) { + mbregR[i] = NULL; + mbregW[i] = NULL; + mbabort[i] = NULL; + } +return; +} + +/* Build dispatch tables */ + +t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp) +{ +uint32 idx; + +if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ +idx = dibp->ba; /* Mbus # */ +if (idx >= MBA_NUM) return SCPE_STOP; +if ((mbregR[idx] && dibp->rd && /* conflict? */ + (mbregR[idx] != dibp->rd)) || + (mbregW[idx] && dibp->wr && + (mbregW[idx] != dibp->wr)) || + (mbabort[idx] && dibp->ack[0] && + (mbabort[idx] != dibp->ack[0]))) { + printf ("Massbus %s assignment conflict at %d\n", + sim_dname (dptr), dibp->ba); + if (sim_log) fprintf (sim_log, + "Massbus %s assignment conflict at %d\n", + sim_dname (dptr), dibp->ba); + return SCPE_STOP; + } +if (dibp->rd) mbregR[idx] = dibp->rd; /* set rd dispatch */ +if (dibp->wr) mbregW[idx] = dibp->wr; /* set wr dispatch */ +if (dibp->ack[0]) mbabort[idx] = dibp->ack[0]; /* set abort dispatch */ +return SCPE_OK; +} + diff --git a/VAX/vax780_mem.c b/VAX/vax780_mem.c new file mode 100644 index 00000000..5e9b05cc --- /dev/null +++ b/VAX/vax780_mem.c @@ -0,0 +1,276 @@ +/* vax780_mem.c: VAX 11/780 memory controllers + + Copyright (c) 2004-2005, 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 + ROBERT M SUPNIK 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 Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + This module contains the VAX 11/780 system-specific registers and devices. + + mctl0, mctl1 MS780C/E memory controllers +*/ + +#include "vax_defs.h" + +/* Memory controller register A */ + +#define MCRA_OF 0x0 +#define MCRA_SUMM 0x00100000 /* err summ (MS780E) */ +#define MCRA_C_SIZE 0x00007E00 /* array size - fixed */ +#define MCRA_V_SIZE 9 +#define MCRA_ILVE 0x00000100 /* interleave wr enab */ +#define MCRA_TYPE 0x000000F8 /* type */ +#define MCRA_C_TYPE 0x00000010 /* 16k uninterleaved */ +#define MCRA_E_TYPE 0x0000006A /* 256k upper + lower */ +#define MCRA_ILV 0x00000007 /* interleave */ +#define MCRA_RD (0x00107FFF|SBI_FAULTS) +#define MCRA_WR 0x00000100 + +/* Memory controller register B */ + +#define MCRB_OF 0x1 +#define MCRB_FP 0xF0000000 /* file pointers */ +#define MCRB_V_SA 15 /* start addr */ +#define MCRB_M_SA 0x1FFF +#define MCRB_SA (MCRB_M_SA << MCRB_V_SA) +#define MCRB_SAE 0x00004000 /* start addr wr enab */ +#define MCRB_INIT 0x00003000 /* init state */ +#define MCRB_REF 0x00000400 /* refresh */ +#define MCRB_ECC 0x000003FF /* ECC for diags */ +#define MCRB_RD 0xFFFFF7FF +#define MCRB_WR 0x000043FF + +/* Memory controller register C,D */ + +#define MCRC_OF 0x2 +#define MCRD_OF 0x3 +#define MCRC_DCRD 0x40000000 /* disable CRD */ +#define MCRC_HER 0x20000000 /* high error rate */ +#define MCRC_ERL 0x10000000 /* log error */ +#define MCRC_C_ER 0x0FFFFFFF /* MS780C error */ +#define MCRC_E_PE1 0x00080000 /* MS780E par ctl 1 */ +#define MCRC_E_PE0 0x00040000 /* MS780E par ctl 0 */ +#define MCRC_E_CRD 0x00000200 /* MS780E CRD */ +#define MCRC_E_PEW 0x00000100 /* MS780E par err wr */ +#define MCRC_E_USEQ 0x00000080 /* MS780E seq err */ +#define MCRC_C_RD 0x7FFFFFFF +#define MCRC_E_RD 0x700C0380 +#define MCRC_WR 0x40000000 +#define MCRC_C_W1C 0x30000000 +#define MCRC_E_W1C 0x300C0380 + +#define MCRROM_OF 0x400 + +uint32 mcr_a[MCTL_NUM]; +uint32 mcr_b[MCTL_NUM]; +uint32 mcr_c[MCTL_NUM]; +uint32 mcr_d[MCTL_NUM]; +uint32 rom_lw[MCTL_NUM][ROMSIZE >> 2]; + +extern UNIT cpu_unit; + +t_stat mctl_reset (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 (CRA, mcr_a[0], 32) }, + { HRDATA (CRB, mcr_b[0], 32) }, + { HRDATA (CRC, mcr_c[0], 32) }, + { HRDATA (CRD, mcr_d[0], 32) }, + { BRDATA (ROM, rom_lw[0], 16, 32, ROMSIZE >> 2) }, + { NULL } + }; + +MTAB mctl0_mod[] = { + { MTAB_XTD|MTAB_VDV, TR_MCTL0, "NEXUS", NULL, + NULL, &show_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 (CRA, mcr_a[1], 32) }, + { HRDATA (CRB, mcr_b[1], 32) }, + { HRDATA (CRC, mcr_c[1], 32) }, + { HRDATA (CRD, mcr_d[1], 32) }, + { BRDATA (ROM, rom_lw[1], 16, 32, ROMSIZE >> 2) }, + { 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 + }, + { + "MCTL1", &mctl1_unit, mctl1_reg, mctl1_mod, + 1, 16, 16, 1, 16, 8, + NULL, NULL, &mctl_reset, + NULL, NULL, NULL, + &mctl1_dib, DEV_NEXUS + } + }; + +/* Memory controller register read */ + +t_stat mctl_rdreg (int32 *val, int32 pa, int32 lnt) +{ +int32 mctl, ofs; +t_bool extmem = MEMSIZE > MAXMEMSIZE; + +if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? */ + printf (">>MCTL: invalid adapter read mask, pa = %X, lnt = %d\r\n", pa, lnt); + sbi_set_errcnf (); /* err confirmation */ + return SCPE_OK; + } +mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */ +ofs = NEXUS_GETOFS (pa); /* get offset */ +if (ofs >= MCRROM_OF) { /* ROM? */ + *val = rom_lw[mctl][ofs - MCRROM_OF]; /* get lw */ + return SCPE_OK; + } +switch (ofs) { + + case MCRA_OF: /* CR A */ + *val = mcr_a[mctl] & MCRA_RD; + break; + + case MCRB_OF: /* CR B */ + *val = (mcr_b[mctl] & MCRB_RD) | MCRB_INIT; + break; + + case MCRC_OF: /* CR C */ + *val = mcr_c[mctl] & (extmem? MCRC_E_RD: MCRC_C_RD); + break; + + case MCRD_OF: /* CR D */ + if (!extmem) return SCPE_NXM; /* MS780E only */ + *val = mcr_d[mctl] & MCRC_E_RD; + 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, mask; +t_bool extmem = MEMSIZE > MAXMEMSIZE; + +if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? */ + printf (">>MCTL: invalid adapter write mask, pa = %X, lnt = %d\r\n", pa, lnt); + sbi_set_errcnf (); /* err confirmation */ + return SCPE_OK; + } +mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */ +ofs = NEXUS_GETOFS (pa); /* get offset */ +switch (ofs) { + + case MCRA_OF: /* CR A */ + mask = MCRA_WR | ((val & MCRA_ILVE)? MCRA_ILV: 0); + mcr_a[mctl] = (mcr_a[mctl] & ~mask) | (val & mask); + break; + + case MCRB_OF: /* CR B */ + mask = MCRB_WR | ((val & MCRB_SAE)? MCRB_SA: 0); + mcr_b[mctl] = (mcr_b[mctl] & ~mask) | (val & mask); + break; + + case MCRC_OF: /* CR C */ + mcr_c[mctl] = ((mcr_c[mctl] & ~MCRC_WR) | (val & MCRC_WR)) & + ~(val & (extmem? MCRC_E_W1C: MCRC_C_W1C)); + break; + + case MCRD_OF: /* CR D */ + if (!extmem) return SCPE_NXM; /* MS780E only */ + mcr_d[mctl] = ((mcr_d[mctl] & ~MCRC_WR) | (val & MCRC_WR)) & + ~(val & MCRC_E_W1C); + break; + + default: + return SCPE_NXM; + } + +return SCPE_OK; +} + +/* Used by CPU and loader */ + +void rom_wr_B (int32 pa, int32 val) +{ +uint32 mctl = NEXUS_GETNEX (pa) - TR_MCTL0; /* get mctl num */ +uint32 ofs = NEXUS_GETOFS (pa) - MCRROM_OF; /* get offset */ +int32 sc = (pa & 3) << 3; + +rom_lw[mctl][ofs] = ((val & 0xFF) << sc) | (rom_lw[mctl][ofs] & ~(0xFF << sc)); +return; +} + +/* MEMCTL reset */ + +t_stat mctl_reset (DEVICE *dptr) +{ +int32 i, amb; +t_bool extmem = MEMSIZE > MAXMEMSIZE; + +amb = (int32) (MEMSIZE / 2) >> 20; /* array size MB */ +for (i = 0; i < MCTL_NUM; i++) { /* init for MS780C */ + if (extmem) { /* extended memory? */ + mcr_a[i] = ((amb - 1) << MCRA_V_SIZE) | MCRA_E_TYPE; + mcr_b[i] = MCRB_INIT | ((i * amb) << (MCRB_V_SA + 4)); + } + else { + mcr_a[i] = MCRA_C_SIZE | MCRA_C_TYPE; + mcr_b[i] = MCRB_INIT | (i << 21); + } + mcr_c[i] = 0; + mcr_d[i] = 0; + } +return SCPE_OK; +} diff --git a/VAX/vax780_sbi.c b/VAX/vax780_sbi.c new file mode 100644 index 00000000..fb7b8351 --- /dev/null +++ b/VAX/vax780_sbi.c @@ -0,0 +1,745 @@ +/* vax780_sbi.c: VAX 11/780 SBI + + Copyright (c) 2004-2005, 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 + ROBERT M SUPNIK 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 Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + This module contains the VAX 11/780 system-specific registers and devices. + + sbi bus controller +*/ + +#include "vax_defs.h" + +/* 11/780 specific IPRs */ + +/* Writeable control store */ + +#define WCSA_RW 0xFFFF /* writeable */ +#define WCSA_ADDR 0x1FFF /* addr */ +#define WCSA_CTR 0x6000 /* counter */ +#define WCSA_CTR_INC 0x2000 /* increment */ +#define WCSA_CTR_MAX 0x6000 /* max value */ +#define WCSD_RD_VAL 0xFF /* fixed read val */ +#define WCSD_WR 0xFFFFFFFF /* write */ +#define MBRK_RW 0x1FFF /* microbreak */ + +/* System registers */ + +#define SBIFS_RD (0x031F0000|SBI_FAULTS) /* SBI faults */ +#define SBIFS_WR 0x03140000 +#define SBIFS_W1C 0x00080000 + +#define SBISC_RD 0xFFFF0000 /* SBI silo comp */ +#define SBISC_WR 0x7FFF0000 +#define SBISC_LOCK 0x80000000 /* lock */ + +#define SBIMT_RD 0xFFFFFF00 /* SBI maint */ +#define SBIMT_WR 0xFFFFF900 + +#define SBIER_CRDIE 0x00008000 /* SBI error, CRD IE */ +#define SBIER_CRD 0x00004000 /* CRD */ +#define SBIER_RDS 0x00002000 /* RDS */ +#define SBIER_TMO 0x00001000 /* timeout */ +#define SBIER_STA 0x00000C00 /* timeout status (0) */ +#define SBIER_CNF 0x00000100 /* error confirm */ +#define SBIER_IBRDS 0x00000080 +#define SBIER_IBTMO 0x00000040 +#define SBIER_IBSTA 0x00000030 +#define SBIER_IBCNF 0x00000008 +#define SBIER_MULT 0x00000004 /* multiple errors */ +#define SBIER_FREE 0x00000002 /* SBI free */ +#define SBIER_RD 0x0000FDFE +#define SBIER_WR 0x00008000 +#define SBIER_W1C 0x000070C0 +#define SBIER_TMOW1C (SBIER_TMO|SBIER_STA|SBIER_CNF|SBIER_MULT) +#define SBIER_IBTW1C (SBIER_IBTMO|SBIER_STA|SBIER_IBCNF) + +#define SBITMO_V_MODE 30 /* mode */ +#define SBITMO_VIRT 0x20000000 /* physical */ + +#define SBIQC_MBZ 0xC0000007 /* MBZ */ + +/* VAX-11/780 boot device definitions */ + +struct boot_dev { + char *name; + int32 code; + int32 let; + }; + +uint32 wcs_addr = 0; +uint32 wcs_data = 0; +uint32 wcs_mbrk = 0; +uint32 nexus_req[NEXUS_HLVL]; /* nexus int req */ +uint32 sbi_fs = 0; /* SBI fault status */ +uint32 sbi_sc = 0; /* SBI silo comparator */ +uint32 sbi_mt = 0; /* SBI maintenance */ +uint32 sbi_er = 0; /* SBI error status */ +uint32 sbi_tmo = 0; /* SBI timeout addr */ + +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[] = { + { "RP", BOOT_MB, 0 }, + { "HK", BOOT_HK, 0 }, + { "RL", BOOT_RL, 0 }, + { "RQ", BOOT_UDA, 1 << 24 }, + { "TQ", BOOT_TK, 1 << 24 }, + { NULL } + }; + +extern int32 R[16]; +extern int32 PSL; +extern int32 ASTLVL, SISR; +extern int32 mapen, pme, trpirq; +extern int32 in_ie; +extern int32 mchk_va, mchk_ref; +extern int32 crd_err, mem_err, hlt_pin; +extern int32 tmr_int, tti_int, tto_int; +extern jmp_buf save_env; +extern int32 p1; +extern int32 sim_switches; +extern DEVICE *sim_devices[]; +extern FILE *sim_log; +extern CTAB *sim_vm_cmd; + +t_stat sbi_reset (DEVICE *dptr); +void sbi_set_tmo (int32 pa); +t_stat vax780_boot (int32 flag, char *ptr); + +void uba_eval_int (void); +extern void Write (uint32 va, int32 val, int32 lnt, int32 acc); +extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei); +extern int32 iccs_rd (void); +extern int32 nicr_rd (void); +extern int32 icr_rd (t_bool interp); +extern int32 todr_rd (void); +extern int32 rxcs_rd (void); +extern int32 rxdb_rd (void); +extern int32 txcs_rd (void); +extern 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 init_mbus_tab (void); +extern void init_ubus_tab (void); +extern t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp); +extern t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp); +extern void WriteLP (uint32 pa, int32 val); + +/* SBI data structures + + sbi_dev SBI device descriptor + sbi_unit SBI unit + sbi_reg SBI register list +*/ + +UNIT sbi_unit = { UDATA (NULL, 0, 0) }; + +REG sbi_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, 16) }, + { HRDATA (WCSD, wcs_data, 32) }, + { HRDATA (MBRK, wcs_mbrk, 13) }, + { HRDATA (SBIFS, sbi_fs, 32) }, + { HRDATA (SBISC, sbi_sc, 32) }, + { HRDATA (SBIMT, sbi_mt, 32) }, + { HRDATA (SBIER, sbi_er, 32) }, + { HRDATA (SBITMO, sbi_tmo, 32) }, + { NULL } + }; + +DEVICE sbi_dev = { + "SBI", &sbi_unit, sbi_reg, NULL, + 1, 16, 16, 1, 16, 8, + NULL, NULL, &sbi_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +/* Special boot command, overrides regular boot */ + +CTAB vax780_cmd[] = { + { "BOOT", &vax780_boot, RU_BOOT, + "bo{ot} {/R5:flg} boot device\n" }, + { NULL } + }; + +/* The VAX 11/780 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 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) return IPL_HLTPIN; /* hlt pin int */ +if ((ipl < IPL_MEMERR) && mem_err) return IPL_MEMERR; /* mem err int */ +if ((ipl < IPL_CRDERR) && crd_err) return IPL_CRDERR; /* crd err int */ +if ((ipl < IPL_CLKINT) && tmr_int) return IPL_CLKINT; /* clock int */ +uba_eval_int (); /* update UBA */ +for (i = IPL_HMAX; i >= IPL_HMIN; i--) { /* chk hwre int */ + if (i <= ipl) return 0; /* at ipl? no int */ + if (nexus_req[i - IPL_HMIN]) return i; /* req != 0? int */ + } +if ((ipl < IPL_TTINT) && (tti_int || tto_int)) /* console int */ + return IPL_TTINT; +if (ipl >= IPL_SMAX) return 0; /* ipl >= sw max? */ +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) return i; /* req != 0? int */ + } +return 0; +} + +/* Return vector for highest priority hardware interrupt at IPL lvl */ + +int32 get_vector (int32 lvl) +{ +int32 i, l; + +if (lvl == IPL_MEMERR) { /* mem error? */ + mem_err = 0; + return SCB_MEMERR; + } +if (lvl == IPL_CRDERR) { /* CRD error? */ + crd_err = 0; + return SCB_CRDERR; + } +if (lvl == IPL_CLKINT) { /* clock? */ + tmr_int = 0; /* clear req */ + return SCB_INTTIM; /* return vector */ + } +if (lvl > IPL_HMAX) { /* error req lvl? */ + ABORT (STOP_UIPL); /* unknown intr */ + } +if ((lvl <= IPL_HMAX) && (lvl >= IPL_HMIN)) { /* nexus? */ + l = lvl - IPL_HMIN; + for (i = 0; nexus_req[l] && (i < NEXUS_NUM); i++) { + if ((nexus_req[l] >> i) & 1) { + nexus_req[l] = nexus_req[l] & ~(1u << i); + return SCB_NEXUS + (l << 6) + (i << 2); /* return vector */ + } + } + } +if (lvl == IPL_TTINT) { /* console? */ + if (tti_int) { /* input? */ + tti_int = 0; /* clear req */ + return SCB_TTI; /* return vector */ + } + if (tto_int) { /* output? */ + tto_int = 0; /* clear req */ + return SCB_TTO; /* return vector */ + } + } +return 0; +} + +/* Read 780-specific IPR's */ + +int32 ReadIPR (int32 rg) +{ +int32 val; + +switch (rg) { + + case MT_ICCS: /* ICCS */ + val = iccs_rd (); + break; + + case MT_NICR: /* NICR */ + val = nicr_rd (); + break; + + case MT_ICR: /* ICR */ + val = icr_rd (FALSE); + break; + + case MT_TODR: /* TODR */ + val = todr_rd (); + break; + + case MT_ACCS: /* ACCS (not impl) */ + val = 0; + break; + + case MT_WCSA: /* WCSA */ + val = wcs_addr & WCSA_RW; + break; + + case MT_WCSD: /* WCSD */ + val = WCSD_RD_VAL; + break; + + case MT_RXCS: /* RXCS */ + val = rxcs_rd (); + break; + + case MT_RXDB: /* RXDB */ + val = rxdb_rd (); + break; + + case MT_TXCS: /* TXCS */ + val = txcs_rd (); + break; + + case MT_SBIFS: /* SBIFS */ + val = sbi_fs & SBIFS_RD; + break; + + case MT_SBIS: /* SBIS */ + val = 0; + break; + + case MT_SBISC: /* SBISC */ + val = sbi_sc & SBISC_RD; + break; + + case MT_SBIMT: /* SBIMT */ + val = sbi_mt & SBIMT_RD; + break; + + case MT_SBIER: /* SBIER */ + val = sbi_er & SBIER_RD; + break; + + case MT_SBITA: /* SBITA */ + val = sbi_tmo; + break; + + case MT_MBRK: /* MBRK */ + val = wcs_mbrk & MBRK_RW; + break; + + case MT_SID: /* SID */ + val = VAX780_SID | VAX780_ECO | VAX780_PLANT | VAX780_SN; + break; + + default: + RSVD_OPND_FAULT; + } + +return val; +} + +/* Write 780-specific IPR's */ + +void WriteIPR (int32 rg, int32 val) +{ +switch (rg) { + + case MT_ICCS: /* ICCS */ + iccs_wr (val); + break; + + case MT_NICR: /* NICR */ + nicr_wr (val); + break; + + case MT_TODR: /* TODR */ + todr_wr (val); + break; + + case MT_WCSA: /* WCSA */ + wcs_addr = val & WCSA_RW; + break; + + case MT_WCSD: /* WCSD */ + wcs_data = val & WCSD_WR; + wcs_addr = (wcs_addr & ~WCSA_CTR) | + ((wcs_addr + WCSA_CTR_INC) & WCSA_CTR); + if ((wcs_addr & WCSA_CTR) == WCSA_CTR_MAX) + wcs_addr = (wcs_addr & ~WCSA_ADDR) | + ((wcs_addr + 1) & WCSA_ADDR); + break; + + case MT_RXCS: /* RXCS */ + rxcs_wr (val); + break; + + case MT_TXCS: /* TXCS */ + txcs_wr (val); + break; + + case MT_TXDB: /* TXDB */ + txdb_wr (val); + break; + + case MT_SBIFS: /* SBIFS */ + sbi_fs = (sbi_fs & ~SBIFS_WR) | (val & SBIFS_WR); + sbi_fs = sbi_fs & ~(val & SBIFS_W1C); + break; + + case MT_SBISC: /* SBISC */ + sbi_sc = (sbi_sc & ~(SBISC_LOCK|SBISC_WR)) | (val & SBISC_WR); + break; + + case MT_SBIMT: /* SBIMT */ + sbi_mt = (sbi_mt & ~SBIMT_WR) | (val & SBIMT_WR); + break; + + case MT_SBIER: /* SBIER */ + sbi_er = (sbi_er & ~SBIER_WR) | (val & SBIER_WR); + sbi_er = sbi_er & ~(val & SBIER_W1C); + if (val & SBIER_TMO) sbi_er = sbi_er & ~SBIER_TMOW1C; + if (val & SBIER_IBTMO) sbi_er = sbi_er & ~SBIER_IBTW1C; + if ((sbi_er & SBIER_CRDIE) && (sbi_er & SBIER_CRD)) + crd_err = 1; + else crd_err = 0; + break; + + case MT_SBIQC: /* SBIQC */ + if (val & SBIQC_MBZ) { RSVD_OPND_FAULT; } + WriteLP (val, 0); + WriteLP (val + 4, 0); + break; + + case MT_MBRK: /* MBRK */ + wcs_mbrk = val & MBRK_RW; + break; + + default: + RSVD_OPND_FAULT; + } + +return; +} + +/* ReadReg - read register space + + Inputs: + pa = physical address + lnt = length (BWLQ) + Output: + longword of data +*/ + +int32 ReadReg (int32 pa, int32 lnt) +{ +int32 nexus, val; + +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; + } + } +sbi_set_tmo (pa); /* timeout */ +MACH_CHECK (MCHK_RD_F); /* machine check */ +return 0; +} + +/* WriteReg - write register space + + Inputs: + pa = physical address + val = data to write, right justified in 32b longword + lnt = length (BWLQ) + Outputs: + none +*/ + +void WriteReg (int32 pa, int32 val, int32 lnt) +{ +int32 nexus; + +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; + } + } +sbi_set_tmo (pa); /* timeout */ +mem_err = 1; /* interrupt */ +eval_int (); +return; +} + +/* Set SBI timeout - machine checks only on reads */ + +void sbi_set_tmo (int32 pa) +{ +if ((sbi_er & SBIER_TMO) == 0) { /* not yet set? */ + sbi_tmo = pa >> 2; /* save addr */ + if (mchk_ref == REF_V) sbi_tmo |= SBITMO_VIRT | /* virt? add mode */ + (PSL_GETCUR (PSL) << SBITMO_V_MODE); + sbi_er |= SBIER_TMO; /* set tmo flag */ + } +else sbi_er |= SBIER_MULT; /* yes, multiple */ +return; +} + +/* Set SBI error confirmation - always machine checks */ + +void sbi_set_errcnf (void) +{ +if (sbi_er & SBIER_CNF) sbi_er |= SBIER_MULT; +else sbi_er |= SBIER_CNF; +MACH_CHECK (MCHK_RD_F); +return; +} + +/* 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 acc, err; + +err = (GET_TRAP (trpirq) << 4) | (pme << 3) | ASTLVL; /* error word */ +cc = intexc (SCB_MCHK, cc, 0, IE_SVE); /* take exception */ +acc = ACC_MASK (KERN); /* in kernel mode */ +in_ie = 1; +SP = SP - 44; /* push 11 words */ +Write (SP, 40, L_LONG, WA); /* # bytes */ +Write (SP + 4, p1, L_LONG, WA); /* mcheck type */ +Write (SP + 8, err, L_LONG, WA); /* CPU error status */ +Write (SP + 12, 0, L_LONG, WA); /* uPC */ +Write (SP + 16, mchk_va, L_LONG, WA); /* VA */ +Write (SP + 20, 0, L_LONG, WA); /* D register */ +Write (SP + 24, mapen, L_LONG, WA); /* TB status 1 */ +Write (SP + 28, 0, L_LONG, WA); /* TB status 2 */ +Write (SP + 32, sbi_tmo, L_LONG, WA); /* SBI timeout addr */ +Write (SP + 36, 0, L_LONG, WA); /* cache status */ +Write (SP + 40, sbi_er, L_LONG, WA); /* SBI error */ +in_ie = 0; +sbi_er = sbi_er & ~SBIER_TMOW1C; /* clr SBIER etc */ +return cc; +} + +/* Console entry */ + +int32 con_halt (int32 code, int32 cc) +{ +ABORT (STOP_HALT); +return cc; +} + +/* Special boot command - linked into SCP by initial reset + + Syntax: BOOT {/R5:val} + + Sets up R0-R5, calls SCP boot processor with effective BOOT CPU +*/ + +t_stat vax780_boot (int32 flag, char *ptr) +{ +char gbuf[CBUFSIZE]; +char *slptr, *regptr; +int32 i, r5v, unitno; +DEVICE *dptr; +UNIT *uptr; +DIB *dibp; +t_stat r; + +regptr = get_glyph (ptr, gbuf, 0); /* get glyph */ +if (slptr = strchr (gbuf, '/')) { /* found slash? */ + regptr = strchr (ptr, '/'); /* locate orig */ + *slptr = 0; /* zero in string */ + } +dptr = find_unit (gbuf, &uptr); /* find device */ +if ((dptr == NULL) || (uptr == NULL)) return SCPE_ARG; +dibp = (DIB *) dptr->ctxt; /* get DIB */ +if (dibp == NULL) return SCPE_ARG; +unitno = (int32) (uptr - dptr->units); +r5v = 0; +if ((strncmp (regptr, "/R5:", 4) == 0) || + (strncmp (regptr, "/R5=", 4) == 0) || + (strncmp (regptr, "/r5:", 4) == 0) || + (strncmp (regptr, "/r5=", 4) == 0)) { + r5v = (int32) get_uint (regptr + 4, 16, LMASK, &r); + if (r != SCPE_OK) return r; + } +else if (*regptr != 0) return SCPE_ARG; +for (i = 0; boot_tab[i].name != NULL; i++) { + if (strcmp (dptr->name, boot_tab[i].name) == 0) { + R[0] = boot_tab[i].code; + if (dptr->flags & DEV_MBUS) { + R[1] = dibp->ba + TR_MBA0; + R[2] = unitno; + } + else { + R[1] = TR_UBA; + R[2] = boot_tab[i].let | (dibp->ba & UBADDRMASK); + } + R[3] = unitno; + R[4] = 0; + R[5] = r5v; + return run_cmd (flag, "CPU"); + } + } +return SCPE_NOFNC; +} + +/* Bootstrap - finish up bootstrap process */ + +t_stat cpu_boot (int32 unitno, DEVICE *dptr) +{ +t_stat r; + +printf ("Loading boot code from vmb.exe\n"); +if (sim_log) fprintf (sim_log, + "Loading boot code from vmb.exe\n"); +r = load_cmd (0, "-O vmb.exe 200"); +if (r != SCPE_OK) return r; +SP = PC = 512; +return SCPE_OK; +} + +/* SBI reset */ + +t_stat sbi_reset (DEVICE *dptr) +{ +wcs_addr = 0; +wcs_data = 0; +wcs_mbrk = 0; +sbi_fs = 0; +sbi_sc = 0; +sbi_mt = 0; +sbi_er = 0; +sbi_tmo = 0; +sim_vm_cmd = vax780_cmd; +return SCPE_OK; +} + +/* Show nexus */ + +t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "nexus=%d", val); +return SCPE_OK; +} + +/* Init nexus tables */ + +void init_nexus_tab (void) +{ +uint32 i; + +for (i = 0; i < NEXUS_NUM; i++) { + nexusR[i] = NULL; + nexusW[i] = NULL; + } +return; +} + +/* Build nexus tables + + Inputs: + dptr = pointer to device + dibp = pointer to DIB + Outputs: + status +*/ + + +t_stat build_nexus_tab (DEVICE *dptr, DIB *dibp) +{ +uint32 idx; + +if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; +idx = dibp->ba; +if (idx >= NEXUS_NUM) return SCPE_IERR; +if ((nexusR[idx] && dibp->rd && /* conflict? */ + (nexusR[idx] != dibp->rd)) || + (nexusW[idx] && dibp->wr && + (nexusW[idx] != dibp->wr))) { + printf ("Nexus %s conflict at %d\n", sim_dname (dptr), dibp->ba); + if (sim_log) fprintf (sim_log, + "Nexus %s conflict at %d\n", sim_dname (dptr), dibp->ba); + return SCPE_STOP; + } +if (dibp->rd) nexusR[idx] = dibp->rd; /* set rd dispatch */ +if (dibp->wr) nexusW[idx] = dibp->wr; /* set wr dispatch */ +return SCPE_OK; +} + +/* Build dib_tab from device list */ + +t_stat build_dib_tab (void) +{ +uint32 i; +DEVICE *dptr; +DIB *dibp; +t_stat r; + +init_nexus_tab (); +init_ubus_tab (); +init_mbus_tab (); +for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */ + dibp = (DIB *) dptr->ctxt; /* get DIB */ + if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */ + if (dptr->flags & DEV_NEXUS) { /* Nexus? */ + if (r = build_nexus_tab (dptr, dibp)) /* add to dispatch table */ + return r; + } + else if (dptr->flags & DEV_MBUS) { /* Massbus? */ + if (r = build_mbus_tab (dptr, dibp)) + return r; + } + else { /* no, Unibus device */ + if (r = build_ubus_tab (dptr, dibp)) /* add to dispatch tab */ + return r; + } /* end else */ + } /* end if enabled */ + } /* end for */ +return SCPE_OK; +} diff --git a/VAX/vax780_stddev.c b/VAX/vax780_stddev.c new file mode 100644 index 00000000..88c2a3c6 --- /dev/null +++ b/VAX/vax780_stddev.c @@ -0,0 +1,931 @@ +/* vax780_stddev.c: VAX 11/780 standard I/O devices + + Copyright (c) 1998-2005, 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 + ROBERT M SUPNIK 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 Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + tti console input + tto console output + rx console floppy + todr TODR clock + tmr interval timer + + + 22-Nov-05 RMS Revised for new terminal processing routines + 10-Mar-05 RMS Fixed bug in timer schedule routine (from Mark Hittinger) + 08-Sep-04 RMS Cloned from vax_stddev.c, vax_sysdev.c, and pdp11_rx.c + + The console floppy protocol is based on the description in the 1982 VAX + Architecture Reference Manual: + + TXDB<11:8> = 0 -> normal console output + TXDB<11:8> = 1 -> data output to floppy + TXDB<11:8> = 3 -> read communications region + TXDB<11:8> = 9 -> command output to floppy + TXDB<11:8> = F -> flag output (e.g., reboot) + + RXDB<11:8> = 0 -> normal terminal input + RXDB<11:8> = 1 -> data input from floppy + RXDB<11:8> = 3 -> communications region data + RXDB<11:8> = 2 -> status input from floppy + RXDB<11:8> = 9 -> "command" input from floppy (protocol error) +*/ + +#include "vax_defs.h" +#include + +/* 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_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 TMR_NICR_STD ((~TMR_INC + 1) & LMASK) +#define CLK_DELAY 5000 /* 100 Hz */ +#define TMXR_MULT 2 /* 50 Hz */ + +/* Floppy definitions */ + +#define FL_NUMTR 77 /* tracks/disk */ +#define FL_M_TRACK 0377 +#define FL_NUMSC 26 /* sectors/track */ +#define FL_M_SECTOR 0177 +#define FL_NUMBY 128 /* bytes/sector */ +#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 FL_IDLE 0 /* idle state */ +#define FL_RWDS 1 /* rw, sect next */ +#define FL_RWDT 2 /* rw, track next */ +#define FL_READ 3 /* read */ +#define FL_READ1 4 +#define FL_WRITE 5 /* write */ +#define FL_WRITE1 6 +#define FL_FILL 7 /* fill buffer */ +#define FL_EMPTY 8 /* empty buffer */ +#define FL_READSTA 9 /* read status */ +#define FL_DONE 10 /* cmd done */ + +#define FL_V_FNC 0 /* floppy function */ +#define FL_M_FNC 0xFF +#define FL_FNCRD 0x0 /* read */ +#define FL_FNCWR 0x1 /* write */ +#define FL_FNCRS 0x2 /* read status */ +#define FL_FNCWD 0x3 /* write del data */ +#define FL_FNCCA 0x4 /* cancel */ +#define FL_CDATA 0x100 /* returned data */ +#define FL_CDONE 0x200 /* completion code */ +#define FL_STACRC 0x001 /* status bits */ +#define FL_STAPAR 0x002 +#define FL_STAINC 0x004 +#define FL_STADDA 0x040 +#define FL_STAERR 0x080 +#define FL_CPROT 0x905 /* protocol error */ +#define FL_GETFNC(x) (((x) >> FL_V_FNC) & FL_M_FNC) + +#define TRACK u3 /* current track */ +#define CALC_DA(t,s) (((t) * FL_NUMSC) + ((s) - 1)) * FL_NUMBY + +int32 tti_csr = 0; /* control/status */ +int32 tti_buf = 0; /* buffer */ +int32 tti_int = 0; /* interrupt */ +int32 tto_csr = 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_sav = 0; /* timer save */ +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 */ +int32 todr_reg = 0; /* TODR register */ + +int32 fl_fnc = 0; /* function */ +int32 fl_esr = 0; /* error status */ +int32 fl_ecode = 0; /* error code */ +int32 fl_track = 0; /* desired track */ +int32 fl_sector = 0; /* desired sector */ +int32 fl_state = FL_IDLE; /* controller state */ +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 */ + +uint8 comm_region[COMM_LNT] = { 0 }; /* comm region */ + +extern int32 sim_switches; +extern jmp_buf save_env; + +t_stat tti_svc (UNIT *uptr); +t_stat tto_svc (UNIT *uptr); +t_stat clk_svc (UNIT *uptr); +t_stat tmr_svc (UNIT *uptr); +t_stat tti_reset (DEVICE *dptr); +t_stat tto_reset (DEVICE *dptr); +t_stat clk_reset (DEVICE *dptr); +t_stat tmr_reset (DEVICE *dptr); +t_stat fl_svc (UNIT *uptr); +t_stat fl_reset (DEVICE *dptr); +int32 icr_rd (t_bool interp); +void tmr_incr (uint32 inc); +void tmr_sched (void); +t_stat todr_powerup (void); +t_stat fl_wr_txdb (int32 data); +t_bool fl_test_xfr (UNIT *uptr, t_bool wr); +void fl_protocol_error (void); + +/* TTI data structures + + tti_dev TTI device descriptor + tti_unit TTI unit descriptor + tti_reg TTI register list +*/ + +UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_8B, 0), KBD_POLL_WAIT }; + +REG tti_reg[] = { + { HRDATA (RXDB, tti_buf, 16) }, + { HRDATA (RXCS, tti_csr, 16) }, + { FLDATA (INT, tti_int, 0) }, + { FLDATA (DONE, tti_csr, CSR_V_DONE) }, + { FLDATA (IE, tti_csr, CSR_V_IE) }, + { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT }, + { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT }, + { NULL } + }; + +MTAB tti_mod[] = { + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { 0 } + }; + +DEVICE tti_dev = { + "TTI", &tti_unit, tti_reg, tti_mod, + 1, 10, 31, 1, 16, 8, + NULL, NULL, &tti_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +/* TTO data structures + + tto_dev TTO device descriptor + tto_unit TTO unit descriptor + tto_reg TTO register list +*/ + +UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_8B, 0), SERIAL_OUT_WAIT }; + +REG tto_reg[] = { + { HRDATA (TXDB, tto_buf, 16) }, + { HRDATA (TXCS, tto_csr, 16) }, + { FLDATA (INT, tto_int, 0) }, + { FLDATA (DONE, tto_csr, CSR_V_DONE) }, + { FLDATA (IE, tto_csr, CSR_V_IE) }, + { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT }, + { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT }, + { NULL } + }; + +MTAB tto_mod[] = { + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, + { 0 } + }; + +DEVICE tto_dev = { + "TTO", &tto_unit, tto_reg, tto_mod, + 1, 10, 31, 1, 16, 8, + NULL, NULL, &tto_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +/* TODR and TMR data structures */ + +UNIT clk_unit = { UDATA (&clk_svc, 0, 0), CLK_DELAY }; /* 100Hz */ + +REG clk_reg[] = { + { DRDATA (TODR, todr_reg, 32), PV_LEFT }, + { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, + { DRDATA (TPS, clk_tps, 8), REG_HIDDEN + REG_NZ + PV_LEFT }, + { NULL } + }; + +DEVICE clk_dev = { + "TODR", &clk_unit, clk_reg, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &clk_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +UNIT tmr_unit = { UDATA (&tmr_svc, 0, 0) }; /* timer */ + +REG tmr_reg[] = { + { HRDATA (ICCS, tmr_iccs, 32) }, + { HRDATA (ICR, tmr_icr, 32) }, + { HRDATA (NICR, tmr_nicr, 32) }, + { HRDATA (INCR, tmr_inc, 32), REG_HIDDEN }, + { HRDATA (SAVE, tmr_sav, 32), REG_HIDDEN }, + { FLDATA (INT, tmr_int, 0) }, + { NULL } + }; + +DEVICE tmr_dev = { + "TMR", &tmr_unit, tmr_reg, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &tmr_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +/* 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) }; + +REG fl_reg[] = { + { HRDATA (FNC, fl_fnc, 8) }, + { HRDATA (ES, fl_esr, 8) }, + { HRDATA (ECODE, fl_ecode, 8) }, + { HRDATA (TA, fl_track, 8) }, + { HRDATA (SA, fl_sector, 8) }, + { DRDATA (STATE, fl_state, 4), REG_RO }, + { DRDATA (BPTR, fl_bptr, 7) }, + { DRDATA (CTIME, fl_cwait, 24), PV_LEFT }, + { DRDATA (STIME, fl_swait, 24), PV_LEFT }, + { DRDATA (XTIME, fl_xwait, 24), PV_LEFT }, + { FLDATA (STOP_IOE, fl_stopioe, 0) }, + { BRDATA (DBUF, fl_buf, 16, 8, FL_NUMBY) }, + { BRDATA (COMM, comm_region, 16, 8, COMM_LNT) }, + { NULL } + }; + +MTAB fl_mod[] = { + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL }, + { 0 } + }; + +DEVICE fl_dev = { + "RX", &fl_unit, fl_reg, fl_mod, + 1, DEV_RDX, 20, 1, DEV_RDX, 8, + NULL, NULL, &fl_reset, + NULL, NULL, NULL, + NULL, 0 + }; + +/* Terminal MxPR routines + + rxcs_rd/wr input control/status + rxdb_rd input buffer + txcs_rd/wr output control/status + txdb_wr output buffer +*/ + +int32 rxcs_rd (void) +{ +return (tti_csr & RXCS_RD); +} + +void rxcs_wr (int32 data) +{ +if ((data & CSR_IE) == 0) tto_int = 0; +else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) + tti_int = 1; +tti_csr = (tti_csr & ~RXCS_WR) | (data & RXCS_WR); +return; +} + +int32 rxdb_rd (void) +{ +int32 t = tti_buf; /* char + error */ + +tti_csr = tti_csr & ~CSR_DONE; /* clr done */ +tti_buf = tti_buf & BMASK; /* clr errors */ +tti_int = 0; +return t; +} + +int32 txcs_rd (void) +{ +return (tto_csr & TXCS_RD); +} + +void txcs_wr (int32 data) +{ +if ((data & CSR_IE) == 0) tto_int = 0; +else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) + tto_int = 1; +tto_csr = (tto_csr & ~TXCS_WR) | (data & TXCS_WR); +return; +} + +void txdb_wr (int32 data) +{ +tto_buf = data & WMASK; /* save data */ +tto_csr = tto_csr & ~CSR_DONE; /* clear flag */ +tto_int = 0; /* clear int */ +if (tto_buf & TXDB_SEL) fl_wr_txdb (tto_buf); /* floppy? */ +else sim_activate (&tto_unit, tto_unit.wait); /* no, console */ +return; +} + +/* Terminal input service (poll for character) */ + +t_stat tti_svc (UNIT *uptr) +{ +int32 c; + +sim_activate (uptr, uptr->wait); /* continue poll */ +if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ +if (c & SCPE_BREAK) /* break? */ + tti_buf = RXDB_ERR | RXDB_FRM; +else tti_buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags)); +uptr->pos = uptr->pos + 1; +tti_csr = tti_csr | CSR_DONE; +if (tti_csr & CSR_IE) tti_int = 1; +return SCPE_OK; +} + +/* Terminal input reset */ + +t_stat tti_reset (DEVICE *dptr) +{ +tti_buf = 0; +tti_csr = 0; +tti_int = 0; +sim_activate (&tti_unit, tti_unit.wait); /* activate unit */ +return SCPE_OK; +} + +/* Terminal output service (output character) */ + +t_stat tto_svc (UNIT *uptr) +{ +int32 c; +t_stat r; + +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 = tto_csr | CSR_DONE; +if (tto_csr & CSR_IE) tto_int = 1; +return SCPE_OK; +} + +/* Terminal output reset */ + +t_stat tto_reset (DEVICE *dptr) +{ +tto_buf = 0; +tto_csr = CSR_DONE; +tto_int = 0; +sim_cancel (&tto_unit); /* deactivate unit */ +return SCPE_OK; +} + +/* Programmable timer + + The architected VAX timer, which increments at 1Mhz, cannot be + accurately simulated due to the overhead that would be required + for 1M clock events per second. Instead, a hidden calibrated + 100Hz timer is run (because that's what VMS expects), and a + gross hack is used for the interval timer. + + When the timer is started, the timer interval is inspected. + + if the interval is the standard 10msec, then the 100Hz timer + supplies timer interrupts + if the interval is non-standard then count instructions + + If the interval register is read, then its value between events + is interpolated using the current instruction count versus the + count when the most recent event started, the result is scaled + to the calibrated system clock, unless the interval being timed + is less than a calibrated system clock tick (or the calibrated + clock is running very slowly) at which time the result will be + the elapsed instruction count. +*/ + +int32 iccs_rd (void) +{ +return tmr_iccs & TMR_CSR_RD; +} + +void iccs_wr (int32 val) +{ +if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */ + sim_cancel (&tmr_unit); /* cancel timer */ + if (tmr_iccs & TMR_CSR_RUN) /* run 1 -> 0? */ + tmr_icr = icr_rd (TRUE); /* update itr */ + } +tmr_iccs = tmr_iccs & ~(val & TMR_CSR_W1C); /* W1C csr */ +tmr_iccs = (tmr_iccs & ~TMR_CSR_WR) | /* new r/w */ + (val & TMR_CSR_WR); +if (val & TMR_CSR_XFR) tmr_icr = tmr_nicr; /* xfr set? */ +if (val & TMR_CSR_RUN) { /* run? */ + if (val & TMR_CSR_XFR) /* new tir? */ + sim_cancel (&tmr_unit); /* stop prev */ + if (!sim_is_active (&tmr_unit)) /* not running? */ + tmr_sched (); /* activate */ + } +else if (val & TMR_CSR_SGL) { /* single step? */ + tmr_incr (1); /* incr tmr */ + if (tmr_icr == 0) /* if ovflo, */ + tmr_icr = tmr_nicr; /* reload tir */ + } +if ((tmr_iccs & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */ + (TMR_CSR_DON | TMR_CSR_IE)) tmr_int = 0; +return; +} + +int32 icr_rd (t_bool interp) +{ +uint32 delta; + +if (interp || (tmr_iccs & TMR_CSR_RUN)) { /* interp, running? */ + delta = sim_grtime () - tmr_sav; /* delta inst */ + if ((tmr_inc == TMR_INC) && /* scale large int */ + (tmr_poll > TMR_INC)) + delta = (uint32) ((((double) delta) * TMR_INC) / tmr_poll); + if (delta >= tmr_inc) delta = tmr_inc - 1; + return tmr_icr + delta; + } +return tmr_icr; +} + +int32 nicr_rd () +{ +return tmr_nicr; +} + +void nicr_wr (int32 val) +{ +tmr_nicr = val; +} + +/* 100Hz base clock unit service */ + +t_stat clk_svc (UNIT *uptr) +{ +int32 t; + +t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */ +sim_activate (&clk_unit, t); /* reactivate unit */ +tmr_poll = t; /* set tmr poll */ +tmxr_poll = t * TMXR_MULT; /* set mux poll */ +todr_reg = todr_reg + 1; /* incr TODR */ +if ((tmr_iccs & TMR_CSR_RUN) && /* timer running? */ + (tmr_nicr == TMR_NICR_STD)) /* standard interval? */ + tmr_incr (TMR_INC); /* do timer service */ +return SCPE_OK; +} + +/* Interval timer unit service */ + +t_stat tmr_svc (UNIT *uptr) +{ +tmr_incr (tmr_inc); /* incr timer */ +return SCPE_OK; +} + +/* Timer increment */ + +void tmr_incr (uint32 inc) +{ +uint32 new_icr = (tmr_icr + inc) & LMASK; /* add incr */ + +if (new_icr < tmr_icr) { /* ovflo? */ + tmr_icr = 0; /* now 0 */ + if (tmr_iccs & TMR_CSR_DON) /* done? set err */ + tmr_iccs = tmr_iccs | TMR_CSR_ERR; + else tmr_iccs = tmr_iccs | TMR_CSR_DON; /* set done */ + if (tmr_iccs & TMR_CSR_RUN) { /* run? */ + tmr_icr = tmr_nicr; /* reload */ + tmr_sched (); /* reactivate */ + } + if (tmr_iccs & TMR_CSR_IE) tmr_int = 1; /* ie? set int req */ + else tmr_int = 0; + } +else { + tmr_icr = new_icr; /* no, update icr */ + if (tmr_iccs & TMR_CSR_RUN) /* still running? */ + tmr_sched (); /* reactivate */ + } +return; +} + +/* Timer scheduling */ + +void tmr_sched (void) +{ +tmr_sav = sim_grtime (); /* save intvl base */ +if (tmr_nicr != TMR_NICR_STD) { /* non-std interval? */ + tmr_inc = (~tmr_icr + 1); /* inc = interval */ + if (tmr_inc == 0) tmr_inc = 1; + sim_activate (&tmr_unit, tmr_inc); + } +return; /* let clk handle */ +} + +/* 100Hz clock reset */ + +t_stat clk_reset (DEVICE *dptr) +{ +int32 t; + +t = sim_rtcn_init (clk_unit.wait, TMR_CLK); /* init 100Hz timer */ +sim_activate (&clk_unit, t); /* activate 100Hz unit */ +tmr_poll = t; /* set tmr poll */ +tmxr_poll = t * TMXR_MULT; /* set mux poll */ +return SCPE_OK; +} + +/* Interval timer reset */ + +t_stat tmr_reset (DEVICE *dptr) +{ +tmr_iccs = 0; +tmr_icr = 0; +tmr_nicr = 0; +tmr_int = 0; +sim_cancel (&tmr_unit); /* cancel timer */ +if (sim_switches & SWMASK ('P')) todr_powerup (); /* powerup? set TODR */ +return SCPE_OK; +} + +/* TODR routines */ + +int32 todr_rd (void) +{ +return todr_reg; +} + +void todr_wr (int32 data) +{ +todr_reg = data; +return; +} + +t_stat todr_powerup (void) +{ +uint32 base; +time_t curr; +struct tm *ctm; + +curr = time (NULL); /* get curr time */ +if (curr == (time_t) -1) return SCPE_NOFNC; /* error? */ +ctm = localtime (&curr); /* decompose */ +if (ctm == NULL) return SCPE_NOFNC; /* error? */ +base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */ + ctm->tm_hour) * 60) + + ctm->tm_min) * 60) + + ctm->tm_sec; +todr_reg = (base * 100) + 0x10000000; /* cvt to VAX form */ +return SCPE_OK; +} + +/* Console write, txdb<11:8> != 0 (console unit) */ + +t_stat fl_wr_txdb (int32 data) +{ +int32 sel = TXDB_GETSEL (data); /* get selection */ + +if (sel == TXDB_FCMD) { /* floppy command? */ + fl_fnc = FL_GETFNC (data); /* get function */ + if (fl_state != FL_IDLE) switch (fl_fnc) { /* cmd in prog? */ + + case FL_FNCCA: /* cancel? */ + sim_cancel (&fl_unit); /* stop op */ + fl_state = FL_DONE; + break; + + default: /* all others */ + fl_protocol_error (); + return SCPE_OK; + } + + else switch (fl_fnc) { /* idle, case */ + + case FL_FNCRS: /* read status */ + fl_state = FL_READSTA; + break; + + case FL_FNCCA: /* cancel, nop */ + fl_state = FL_DONE; + break; + + case FL_FNCRD: case FL_FNCWR: /* data xfer */ + case FL_FNCWD: + fl_esr = 0; /* clear errors */ + fl_ecode = 0; + fl_bptr = 0; /* init buffer */ + fl_state = FL_RWDS; /* sector next */ + break; + + default: /* all others */ + fl_protocol_error (); + return SCPE_OK; + } + + sim_activate (&fl_unit, fl_cwait); /* sched command */ + } /* end command */ +else if (sel == TXDB_FDAT) { /* floppy data? */ + switch (fl_state) { /* data */ + + case FL_RWDS: /* expecting sector */ + fl_sector = data & FL_M_SECTOR; + fl_state = FL_RWDT; + break; + + case FL_RWDT: /* expecting track */ + fl_track = data & FL_M_TRACK; + if (fl_fnc == FL_FNCRD) fl_state = FL_READ; + else fl_state = FL_FILL; + break; + + case FL_FILL: /* expecting wr data */ + fl_buf[fl_bptr++] = data & BMASK; + if (fl_bptr >= FL_NUMBY) fl_state = FL_WRITE; + break; + + default: + fl_protocol_error (); + return SCPE_OK; + } + + sim_activate (&fl_unit, fl_xwait); /* schedule xfer */ + } /* end else data */ +else { + sim_activate (&tto_unit, tto_unit.wait); /* set up timeout */ + if (sel == TXDB_COMM) { /* read comm region? */ + data = data & COMM_MASK; /* byte to select */ + tti_buf = comm_region[data] | COMM_DATA; + tti_csr = tti_csr | CSR_DONE; /* set input flag */ + if (tti_csr & CSR_IE) tti_int = 1; + } + else if (sel == TXDB_MISC) { /* misc function? */ + switch (data & MISC_MASK) { /* case on function */ + case MISC_CLWS: + comm_region[COMM_WRMS] = 0; + case MISC_CLCS: + comm_region[COMM_CLDS] = 0; + break; + case MISC_SWDN: + ABORT (STOP_SWDN); + break; + case MISC_BOOT: + ABORT (STOP_BOOT); + break; + } + } + } +return SCPE_OK; +} + +/* 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 i, t; +uint32 da; +int8 *fbuf = uptr->filebuf; + +switch (fl_state) { /* case on state */ + + case FL_IDLE: /* idle */ + return SCPE_IERR; /* done */ + + case FL_READ: case FL_WRITE: /* read, write */ + fl_state = fl_state + 1; /* set next state */ + t = abs (fl_track - uptr->TRACK); /* # tracks to seek */ + if (t == 0) t = 1; /* minimum 1 */ + sim_activate (uptr, fl_swait * t); /* schedule seek */ + /* fall thru, set flag */ + case FL_RWDS: case FL_RWDT: case FL_FILL: /* rwds, rwdt, fill */ + tto_csr = tto_csr | CSR_DONE; /* set output done */ + if (tto_csr & CSR_IE) tto_int = 1; + break; + + case FL_READ1: /* read, seek done */ + 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]; + tti_buf = fl_esr | FL_CDONE; /* completion code */ + tti_csr = tti_csr | CSR_DONE; /* set input flag */ + if (tti_csr & CSR_IE) tti_int = 1; + fl_state = FL_EMPTY; /* go empty */ + } + else fl_state = FL_DONE; /* error? cmd done */ + sim_activate (uptr, fl_xwait); /* schedule next */ + break; + + case FL_EMPTY: /* empty buffer */ + if ((tti_csr & CSR_DONE) == 0) { /* prev data taken? */ + tti_buf = FL_CDATA | fl_buf[fl_bptr++]; /* get next byte */ + tti_csr = tti_csr | CSR_DONE; /* set input flag */ + if (tti_csr & CSR_IE) tti_int = 1; + if (fl_bptr >= FL_NUMBY) { /* buffer empty? */ + fl_state = FL_IDLE; /* cmd done */ + break; + } + } + sim_activate (uptr, fl_xwait); /* schedule next */ + break; + + case FL_WRITE1: /* write, seek done */ + 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) uptr->hwmark = da; /* update hwmark */ + } + if (fl_fnc == FL_FNCWD) fl_esr |= FL_STADDA; /* wrdel? set status*/ + fl_state = FL_DONE; /* command done */ + sim_activate (uptr, fl_xwait); /* schedule */ + break; + + case FL_DONE: /* command done */ + if (tti_csr & CSR_DONE) /* input buf empty? */ + sim_activate (uptr, fl_xwait); /* no, wait */ + else { /* yes */ + tti_buf = fl_esr | FL_CDONE; /* completion code */ + tti_csr = tti_csr | CSR_DONE; /* set input flag */ + if (tti_csr & CSR_IE) tti_int = 1; + fl_state = FL_IDLE; /* floppy idle */ + } + break; + + case FL_READSTA: /* read status */ + if ((tti_csr & CSR_DONE) == 0) { /* input buf empty? */ + tti_buf = fl_ecode; /* return err code */ + tti_csr = tti_csr | CSR_DONE; /* set input flag */ + if (tti_csr & CSR_IE) tti_int = 1; + fl_state = FL_DONE; /* command done */ + } + sim_activate (uptr, fl_xwait); + 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 = 0110; +else if (fl_track >= FL_NUMTR) /* bad track? */ + fl_ecode = 0040; /* done, error */ +else if ((fl_sector == 0) || (fl_sector > FL_NUMSC)) /* bad sect? */ + fl_ecode = 0070; /* done, error */ +else if (wr && (uptr->flags & UNIT_WPRT)) /* write and locked? */ + fl_ecode = 0100; /* done, error */ +else { + uptr->TRACK = fl_track; /* now on track */ + return TRUE; + } +fl_esr = fl_esr | FL_STAERR; /* set error */ +return FALSE; +} + +/* Set protocol error */ + +void fl_protocol_error (void) +{ +if ((tto_csr & CSR_DONE) == 0) { /* output busy? */ + tto_csr = tto_csr | CSR_DONE; /* set done */ + if (tto_csr & CSR_IE) tto_int = 1; + } +if ((tti_csr & CSR_DONE) == 0) { /* input idle? */ + tti_csr = tti_csr | CSR_DONE; /* set done */ + if (tti_csr & CSR_IE) tti_int = 1; + } +tti_buf = FL_CPROT; /* status */ +fl_state = FL_IDLE; /* floppy idle */ +return; +} + +/* Reset */ + +t_stat fl_reset (DEVICE *dptr) +{ +uint32 i; + +fl_esr = FL_STAINC; +fl_ecode = 0; /* clear error */ +fl_sector = 0; /* clear addr */ +fl_track = 0; +fl_state = FL_IDLE; /* ctrl idle */ +fl_bptr = 0; +sim_cancel (&fl_unit); /* cancel drive */ +fl_unit.TRACK = 0; +for (i = 0; i < COMM_LNT; i++) comm_region[i] = 0; +comm_region[COMM_FPLV] = VER_FPLA; +comm_region[COMM_PCSV] = VER_PCS; +comm_region[COMM_WCSV] = VER_WCSP; +comm_region[COMM_WCSS] = VER_WCSS; +comm_region[COMM_GH] = 1; +return SCPE_OK; +} diff --git a/VAX/vax780_syslist.c b/VAX/vax780_syslist.c new file mode 100644 index 00000000..f2172fca --- /dev/null +++ b/VAX/vax780_syslist.c @@ -0,0 +1,135 @@ +/* vax_syslist.c: VAX device list + + Copyright (c) 1998-2005, 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 + ROBERT M SUPNIK 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 Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + 01-Oct-2004 RMS Cloned from vax_sys.c +*/ + +#include "vax_defs.h" + +char sim_name[] = "VAX780"; + +extern DEVICE cpu_dev; +extern DEVICE tlb_dev; +extern DEVICE sbi_dev; +extern DEVICE mctl_dev[MCTL_NUM]; +extern DEVICE uba_dev; +extern DEVICE mba_dev[MBA_NUM]; +extern DEVICE clk_dev; +extern DEVICE tmr_dev; +extern DEVICE tti_dev, tto_dev; +extern DEVICE fl_dev; +extern DEVICE lpt_dev; +extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; +extern DEVICE rl_dev; +extern DEVICE hk_dev; +extern DEVICE rp_dev; +extern DEVICE ry_dev; +extern DEVICE ts_dev; +extern DEVICE tq_dev; +extern DEVICE tu_dev; +extern DEVICE dz_dev; +extern DEVICE xu_dev, xub_dev; + +extern int32 sim_switches; +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, + &sbi_dev, + &mctl_dev[0], + &mctl_dev[1], + &uba_dev, + &mba_dev[0], + &mba_dev[1], + &clk_dev, + &tmr_dev, + &tti_dev, + &tto_dev, + &fl_dev, + &dz_dev, + &lpt_dev, + &rp_dev, + &rl_dev, + &hk_dev, + &rq_dev, + &rqb_dev, + &rqc_dev, + &rqd_dev, + &ry_dev, + &tu_dev, + &ts_dev, + &tq_dev, + &xu_dev, + &xub_dev, + 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. + + -r load ROM0 + -s load ROM1 + -o for memory, specify origin +*/ + +t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +{ +t_stat r; +int32 val; +uint32 origin, limit; + +if (flag) return SCPE_ARG; /* dump? */ +origin = 0; /* memory */ +limit = (uint32) cpu_unit.capac; +if (sim_switches & SWMASK ('O')) { /* origin? */ + origin = (int32) get_uint (cptr, 16, 0xFFFFFFFF, &r); + if (r != SCPE_OK) return SCPE_ARG; + } + +while ((val = getc (fileref)) != EOF) { /* read byte stream */ + if (sim_switches & SWMASK ('R')) { /* ROM0? */ + if (origin >= ROMSIZE) return SCPE_NXM; + rom_wr_B (ROM0BASE + origin, val); + } + else if (sim_switches & SWMASK ('S')) { /* ROM1? */ + if (origin >= ROMSIZE) return SCPE_NXM; + rom_wr_B (ROM1BASE + origin, val); + } + else { + if (origin >= limit) return SCPE_NXM; /* NXM? */ + WriteB (origin, val); /* memory */ + } + origin = origin + 1; + } +return SCPE_OK; +} + + diff --git a/VAX/vax780_uba.c b/VAX/vax780_uba.c new file mode 100644 index 00000000..02822129 --- /dev/null +++ b/VAX/vax780_uba.c @@ -0,0 +1,1325 @@ +/* vax780_uba.c: VAX 11/780 Unibus adapter + + Copyright (c) 2004-2005, 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 + ROBERT M SUPNIK 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 Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + uba DW780 Unibus adapter +*/ + +#include "vax_defs.h" + +/* Unibus adapter */ + +#define UBA_NDPATH 16 /* number of data paths */ +#define UBA_NMAPR 496 /* number of map reg */ + +/* Unibus configuration register */ + +#define UBACNF_OF 0x00 +#define UBACNF_ADPDN 0x00800000 /* adap pdn - ni */ +#define UBACNF_ADPUP 0x00400000 /* adap pup - ni */ +#define UBACNF_UBINIT 0x00040000 /* UB INIT - ni */ +#define UBACNF_UBPDN 0x00020000 /* UB pdn */ +#define UBACNF_UBIC 0x00010000 /* UB init done */ +#define UBACNF_CODE 0x00000028 /* adapter code */ +#define UBACNF_RD (SBI_FAULTS|UBACNF_W1C) +#define UBACNF_W1C 0x00C70000 + +/* Control register */ + +#define UBACR_OF 0x01 +#define UBACR_V_DSB 26 /* map disable */ +#define UBACR_M_DSB 0x1F +#define UBACR_GETDSB(x) (((x) >> (UBACR_V_DSB - 4)) & (UBACR_M_DSB << 4)) +#define UBACR_IFS 0x00000040 /* SBI field intr */ +#define UBACR_BRIE 0x00000020 /* BR int enable */ +#define UBACR_USEFIE 0x00000010 /* UB to SBI int enb */ +#define UBACR_SUEFIE 0x00000008 /* SBI to UB int enb */ +#define UBACR_CNFIE 0x00000004 /* config int enb */ +#define UBACR_UPF 0x00000002 /* power fail UB */ +#define UBACR_ADINIT 0x00000001 /* adapter init */ +#define UBACR_RD ((UBACR_M_DSB << UBACR_V_DSB) | 0x0000007E) +#define UBACR_WR (UBACR_RD) + +#define UBA_USEFIE_SR (UBASR_RDTO|UBASR_RDS|UBASR_CRD|UBASR_CXTER| \ + UBASR_CXTO|UBASR_DPPE|UBASR_IVMR|UBASR_MRPF) +#define UBA_SUEFIE_SR (UBASR_UBSTO|UBASR_UBTMO) +#define UBA_CNFIE_CR (UBACNF_ADPDN|UBACNF_ADPUP|UBACNF_UBINIT|\ + UBACNF_UBPDN|UBACNF_UBIC) + +/* Status register */ + +#define UBASR_OF 0x02 +#define UBASR_V_BR4 24 /* filled br's - ni */ +#define UBASR_RDTO 0x00000400 /* read tmo - ni */ +#define UBASR_RDS 0x00000200 /* read sub - ni */ +#define UBASR_CRD 0x00000100 /* read crd - ni */ +#define UBASR_CXTER 0x00000080 /* cmd xfr err - ni */ +#define UBASR_CXTO 0x00000040 /* cmd xfr tmo - ni */ +#define UBASR_DPPE 0x00000020 /* parity err - ni */ +#define UBASR_IVMR 0x00000010 /* invalid map reg */ +#define UBASR_MRPF 0x00000008 /* map reg par - ni */ +#define UBASR_LEB 0x00000004 /* locked err */ +#define UBASR_UBSTO 0x00000002 /* UB select tmo - ni */ +#define UBASR_UBTMO 0x00000001 /* UB nxm */ +#define UBASR_RD 0x0F0007FF +#define UBASR_W1C 0x000007FF + +/* Diagnostic register */ + +#define UBADR_OF 0x03 +#define UBADR_SPARE 0x80000000 /* spare */ +#define UBADR_DINTR 0x40000000 /* disable intr */ +#define UBADR_DMP 0x20000000 +#define UBADR_DDPP 0x10000000 +#define UBADR_MICOK 0x08000000 /* microseq ok */ +#define UBADR_RD 0xF8000000 +#define UBADR_WR 0xF0000000 +#define UBADR_CNF_RD 0x07FFFFFF + +/* Failing map entry - read only */ + +#define UBAFMER_OF 0x04 +#define UBAFMER_OF1 0x06 +#define UBAFMER_RD 0x1FF + +/* Failing Unibus address - read only */ + +#define UBAFUBAR_OF 0x05 +#define UBAFUBAR_OF1 0x07 +#define UBAFUBAR_RD 0xFFFF + +/* Spare registers - read/write */ + +#define UBABRSVR_OF 0x08 + +/* Vector registers - read only */ + +#define UBABRRVR_OF 0x0C +#define UBA_UVEC 0x80000000 + +/* Data path registers */ + +#define UBADPR_OF 0x010 +#define UBADPR_BNE 0x80000000 /* buf not empty - ni */ +#define UBADPR_BTE 0x40000000 /* buf xfr err - ni */ +#define UBADPR_DIR 0x20000000 /* buf rd/wr */ +#define UBADPR_STATE 0x00FF0000 /* byte full state - ni */ +#define UBADPR_UA 0x0000FFFF /* Unibus addr<17:2> */ +#define UBADPR_UA 0x0000FFFF /* last UB addr */ +#define UBADPR_RD 0xC0FFFFFF +#define UBADPR_W1C 0xC0000000 + +/* Map registers */ + +#define UBAMAP_OF 0x200 +#define UBAMAP_VLD 0x80000000 /* valid */ +#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 0xF +#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 (0x86000000 | 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 */ +uint32 uba_cnf = 0; /* config reg */ +uint32 uba_cr = 0; /* control reg */ +uint32 uba_sr = 0; /* status reg */ +uint32 uba_dr = 0; /* diag ctrl */ +uint32 uba_int = 0; /* UBA interrupt */ +uint32 uba_fmer = 0; /* failing map reg */ +uint32 uba_fubar = 0; /* failing Unibus addr */ +uint32 uba_svr[4] = { 0 }; /* diag registers */ +uint32 uba_rvr[4] = { 0 }; /* vector reg */ +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 int32 trpirq; +extern int32 autcon_enb; +extern jmp_buf save_env; +extern DEVICE *sim_devices[]; +extern UNIT cpu_unit; +extern uint32 nexus_req[NEXUS_HLVL]; +extern int32 sim_switches; +extern FILE *sim_log, *sim_deb; + +t_stat uba_svc (UNIT *uptr); +t_stat uba_reset (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_inv_map (int32 ublk); +void uba_eval_int (void); +void uba_adap_set_int (int32 flg); +void uba_adap_clr_int (); +void uba_set_dpr (uint32 ua, t_bool wr); +void uba_ubpdn (int32 time); +t_bool uba_map_addr (uint32 ua, uint32 *ma); +t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat uba_show_virt (FILE *st, UNIT *uptr, int32 val, void *desc); + +extern int32 ReadB (uint32 pa); +extern int32 ReadW (uint32 pa); +extern int32 ReadL (uint32 pa); +extern void WriteB (uint32 pa, int32 val); +extern void WriteW (uint32 pa, int32 val); +extern void WriteL (uint32 pa, int32 val); +extern int32 eval_int (void); +extern t_stat build_dib_tab (void); + +/* Unibus IO page dispatches */ + +static t_stat (*iodispR[IOPAGESIZE >> 1])(int32 *dat, int32 ad, int32 md); +static t_stat (*iodispW[IOPAGESIZE >> 1])(int32 dat, int32 ad, int32 md); +static DIB *iodibp[IOPAGESIZE >> 1]; + +/* Unibus interrupt request to interrupt action map */ + +int32 (*int_ack[IPL_HLVL][32])(); /* 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 (CNFR, uba_cnf, 32) }, + { HRDATA (CR, uba_cr, 32) }, + { HRDATA (SR, uba_sr, 32) }, + { HRDATA (DR, uba_dr, 32) }, + { FLDATA (INT, uba_int, 0) }, + { FLDATA (NEXINT, nexus_req[IPL_UBA], TR_UBA) }, + { FLDATA (AIIP, uba_aiip, 0) }, + { FLDATA (UIIP, uba_uiip, 0) }, + { HRDATA (FMER, uba_fmer, 32) }, + { HRDATA (FUBAR, uba_fubar, 32) }, + { HRDATA (BRSVR0, uba_svr[0], 32) }, + { HRDATA (BRSVR1, uba_svr[1], 32) }, + { HRDATA (BRSVR2, uba_svr[2], 32) }, + { HRDATA (BRSVR3, uba_svr[3], 32) }, + { HRDATA (BRRVR4, uba_rvr[0], 32) }, + { HRDATA (BRRVR5, uba_rvr[1], 32) }, + { HRDATA (BRRVR6, uba_rvr[2], 32) }, + { HRDATA (BRRVR7, uba_rvr[3], 32) }, + { BRDATA (DPR, uba_dpr, 16, 32, 16) }, + { BRDATA (MAP, uba_map, 16, 32, 496) }, + { DRDATA (AITIME, uba_aitime, 24), PV_LEFT + REG_NZ }, + { DRDATA (UITIME, uba_uitime, 24), PV_LEFT + REG_NZ }, + { 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, 0, 0 + }; + +/* Read Unibus adapter register - aligned lw only */ + +t_stat uba_rdreg (int32 *val, int32 pa, int32 lnt) +{ +int32 idx, ofs; + +if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? */ + printf (">>UBA: invalid adapter read mask, pa = %X, lnt = %d\r\n", pa, lnt); + sbi_set_errcnf (); /* err confirmation */ + return SCPE_OK; + } +ofs = NEXUS_GETOFS (pa); /* get offset */ +if (uba_aiip && (ofs != UBACNF_OF) /* init in prog? */ + && (ofs != UBADR_OF)) return SCPE_NXM; /* only cnf, dr */ +if (ofs >= UBAMAP_OF) { /* map? */ + idx = ofs - UBAMAP_OF; + if (idx >= UBA_NMAPR) return SCPE_NXM; /* valid? */ + *val = uba_map[idx] & UBAMAP_RD; + if (DEBUG_PRI (uba_dev, UBA_DEB_MRD)) + fprintf (sim_deb, ">>UBA: map %d read, value = %X\n", idx, *val); + return SCPE_OK; + } + +switch (ofs) { /* case on offset */ + + case UBACNF_OF: /* CNF */ + *val = (uba_cnf & UBACNF_RD) | UBACNF_CODE; + break; + + case UBACR_OF: /* CR */ + *val = uba_cr & UBACR_RD; + break; + + case UBASR_OF: /* SR */ + *val = uba_sr & UBASR_RD; + break; + + case UBADR_OF: /* DR */ + *val = (uba_dr & UBADR_RD) | UBADR_MICOK | + ((uba_cnf & UBADR_CNF_RD) | UBACNF_CODE); + break; + + case UBAFMER_OF: case UBAFMER_OF1: /* FMER */ + *val = uba_fmer & UBAFMER_RD; + break; + + case UBAFUBAR_OF: case UBAFUBAR_OF1: /* FUBAR */ + *val = uba_fubar & UBAFUBAR_RD; + break; + + case UBABRSVR_OF + 0: case UBABRSVR_OF + 1: /* BRSVR */ + case UBABRSVR_OF + 2: case UBABRSVR_OF + 3: + idx = ofs - UBABRSVR_OF; + *val = uba_svr[idx]; + break; + + case UBABRRVR_OF + 0: case UBABRRVR_OF + 1: /* BRRVR */ + case UBABRRVR_OF + 2: case UBABRRVR_OF + 3: + idx = ofs - UBABRRVR_OF; + uba_rvr[idx] = uba_get_ubvector (idx); + *val = uba_rvr[idx]; + break; + + case UBADPR_OF + 0: /* DPR */ + *val = 0; /* direct */ + break; + + case UBADPR_OF + 1: + case UBADPR_OF + 2: case UBADPR_OF + 3: + case UBADPR_OF + 4: case UBADPR_OF + 5: + case UBADPR_OF + 6: case UBADPR_OF + 7: + case UBADPR_OF + 8: case UBADPR_OF + 9: + case UBADPR_OF + 10: case UBADPR_OF + 11: + case UBADPR_OF + 12: case UBADPR_OF + 13: + case UBADPR_OF + 14: case UBADPR_OF + 15: + idx = ofs - UBADPR_OF; + *val = uba_dpr[idx] & UBADPR_RD; + 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, old_cr; + +if ((pa & 3) || (lnt != L_LONG)) { /* unaligned or not lw? */ + printf (">>UBA: invalid adapter write mask, pa = %X, lnt = %d\r\n", pa, lnt); + sbi_set_errcnf (); /* err confirmation */ + return SCPE_OK; + } +ofs = NEXUS_GETOFS (pa); /* get offset */ +if (uba_aiip && (ofs != UBACNF_OF) && (ofs != UBADR_OF) && + (ofs != UBACR_OF) && (ofs != UBASR_OF)) return SCPE_NXM; +if (ofs >= UBAMAP_OF) { /* map? */ + idx = ofs - UBAMAP_OF; + if (idx >= UBA_NMAPR) return SCPE_NXM; /* valid? */ + uba_map[idx] = val & UBAMAP_WR; + if (DEBUG_PRI (uba_dev, UBA_DEB_MWR)) + fprintf (sim_deb, ">>UBA: map %d write, value = %X\n", idx, val); + return SCPE_OK; + } + +switch (ofs) { /* case on offset */ + + case UBACNF_OF: /* CNF */ + uba_cnf = uba_cnf & ~(val & UBACNF_W1C); /* W1C bits */ + uba_adap_clr_int (); /* possible clr int */ + break; + + case UBACR_OF: /* CR */ + old_cr = uba_cr; + if (val & UBACR_ADINIT) { /* adapter init */ + uba_reset (&uba_dev); /* reset adapter */ + uba_aiip = 1; /* set init in prog */ + uba_ubpdn (uba_aitime); /* power fail UB */ + } + if ((val & UBACR_UPF) && !(old_cr & UBACR_UPF) /* Unibus power clear */ + && !sim_is_active (&uba_unit)) + uba_ubpdn (uba_aitime + uba_uitime); /* power fail UB */ + uba_cr = (uba_cr & ~UBACR_WR) | (val & UBACR_WR); + uba_adap_set_int (uba_cr & ~old_cr); /* possible int set */ + uba_adap_clr_int (); /* possible int clr */ + break; + + case UBASR_OF: /* SR */ + uba_sr = uba_sr & ~(val & UBASR_W1C); /* W1C bits */ + uba_adap_clr_int (); /* possible clr int */ + break; + + case UBADR_OF: /* DR */ + uba_dr = (uba_dr & ~UBADR_WR) | (val & UBADR_WR); + uba_cnf = uba_cnf & ~(val & UBACNF_W1C); + uba_adap_clr_int (); /* possible clr int */ + break; + + case UBABRSVR_OF + 0: case UBABRSVR_OF + 1: /* BRSVR */ + case UBABRSVR_OF + 2: case UBABRSVR_OF + 3: + idx = ofs - UBABRSVR_OF; + uba_svr[idx] = val; + break; + + case UBADPR_OF + 0: /* DPR */ + break; /* direct */ + + case UBADPR_OF + 1: + case UBADPR_OF + 2: case UBADPR_OF + 3: + case UBADPR_OF + 4: case UBADPR_OF + 5: + case UBADPR_OF + 6: case UBADPR_OF + 7: + case UBADPR_OF + 8: case UBADPR_OF + 9: + case UBADPR_OF + 10: case UBADPR_OF + 11: + case UBADPR_OF + 12: case UBADPR_OF + 13: + case UBADPR_OF + 14: case UBADPR_OF + 15: + idx = ofs - UBADPR_OF; + uba_dpr[idx] = uba_dpr[idx] & ~(val & UBADPR_W1C); + 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) && !uba_uiip) { /* iopage,!init */ + idx = (pa & IOPAGEMASK) >> 1; + if (iodispR[idx]) { + iodispR[idx] (&val, pa, READ); + return val; + } + } +uba_ub_nxm (pa); /* UB nxm */ +return 0; +} + +void WriteUb (uint32 pa, int32 val, int32 mode) +{ +int32 idx; + +if (ADDR_IS_IOP (pa) && !uba_uiip) { /* 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 (int32 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) iod = iod << 16; /* position */ + } +else { + printf (">>UBA: invalid read mask, pa = %x, lnt = %d\n", pa, lnt); + sbi_set_errcnf (); /* err confirmation */ + 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 (int32 pa, int32 val, int32 lnt) +{ +if (lnt == L_BYTE) WriteUb (pa, val, WRITEB); /* byte? DATOB */ +else if ((lnt == L_WORD) && ((pa & 1) == 0)) /* aligned word? */ + WriteUb (pa, val, WRITE); /* DATO */ +else { + printf (">>UBA: invalid write mask, pa = %x, lnt = %d\n", pa, lnt); + sbi_set_errcnf (); /* err confirmation */ + } +SET_IRQL; /* update ints */ +return; +} + +/* Update UBA nexus interrupts */ + +void uba_eval_int (void) +{ +int32 i; + +for (i = 0; i < (IPL_HMAX - IPL_HMIN); i++) /* clear all UBA req */ + nexus_req[i] &= ~(1 << TR_UBA); +if (((uba_dr & UBADR_DINTR) == 0) && !uba_uiip && /* intr enabled? */ + (uba_cr & UBACR_IFS) && (uba_cr & UBACR_BRIE)) { + for (i = 0; i < (IPL_HMAX - IPL_HMIN); i++) { + if (int_req[i]) nexus_req[i] |= (1 << TR_UBA); + } + } +if (uba_int) SET_NEXUS_INT (UBA); /* adapter int? */ +return; +} + +/* Return vector for Unibus interrupt at relative IPL level [0-3] */ + +int32 uba_get_ubvector (int32 lvl) +{ +int32 i, vec; + +vec = 0; +if ((lvl == (IPL_UBA - IPL_HMIN)) && uba_int) { /* UBA lvl, int? */ + vec = UBA_UVEC; /* set flag */ + uba_int = 0; /* clear int */ + } +if (((uba_dr & UBADR_DINTR) == 0) && !uba_uiip && /* intr enabled? */ + (uba_cr & UBACR_IFS) && (uba_cr & UBACR_BRIE)) { + 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)) return (bc - i); /* page inv or NXM? */ + pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ + if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + 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; + } + } + uba_set_dpr (ba + i + pbc - L_BYTE, FALSE); + } +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)) return (bc - i); /* page inv or NXM? */ + pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ + if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + if (DEBUG_PRI (uba_dev, UBA_DEB_XFR)) + fprintf (sim_deb, ">>UBA: 16b read, ma = %X, bc = %X\n", 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 */ + } + } + uba_set_dpr (ba + i + pbc - L_WORD, FALSE); + } +return 0; +} + +int32 Map_WriteB (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)) return (bc - i); /* page inv or NXM? */ + pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ + if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + 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 */ + } + } + uba_set_dpr (ba + i + pbc - L_BYTE, TRUE); + } +return 0; +} + +int32 Map_WriteW (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)) return (bc - i); /* page inv or NXM? */ + pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */ + if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */ + 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 */ + } + } + uba_set_dpr (ba + i + pbc - L_WORD, TRUE); + } +return 0; +} + +/* Map an address via the translation map */ + +t_bool uba_map_addr (uint32 ua, uint32 *ma) +{ +uint32 ublk, umap; + +ublk = ua >> VA_V_VPN; /* Unibus blk */ +if ((ublk < UBACR_GETDSB (uba_cr)) || /* map disabled? */ + (ublk >= UBA_NMAPR)) return FALSE; /* unimplemented? */ +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 (ADDR_IS_MEM (*ma)); /* legit addr */ + } +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? */ + (ublk >= UBA_NMAPR)) return FALSE; /* unimplemented? */ +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; +} + +/* At end of page or transfer, update DPR register, in case next page + gets an error */ + +void uba_set_dpr (uint32 ua, t_bool wr) +{ +uint32 ublk, umap, dpr; + +ublk = ua >> VA_V_VPN; /* Unibus blk */ +if (ublk >= UBA_NMAPR) return; /* paranoia */ +umap = uba_map[ublk]; /* get map */ +dpr = UBAMAP_GETDP (umap); /* get bdp */ +if (dpr) uba_dpr[dpr] = (uba_dpr[dpr] & ~(UBADPR_UA|UBADPR_DIR)) | + (wr? UBADPR_DIR: 0) | + (((ua >> 2) + ((umap & UBAMAP_ODD)? 1: 0)) & UBADPR_UA); +return; +} + +/* 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_sr & UBASR_UBTMO) == 0) { + uba_sr |= UBASR_UBTMO; + uba_adap_set_int (uba_cr & UBACR_SUEFIE); + uba_fubar = (ua >> 2) & UBAFUBAR_RD; + } +else uba_sr |= UBASR_LEB; +if (DEBUG_PRI (uba_dev, UBA_DEB_ERR)) + fprintf (sim_deb, ">>UBA: nxm error, ua = %X\n", ua); +return; +} + +void uba_inv_map (int32 ublk) +{ +if ((uba_sr & UBASR_IVMR) == 0) { + uba_sr |= UBASR_IVMR; + uba_adap_set_int (uba_cr & UBACR_USEFIE); + uba_fmer = ublk & UBAFMER_RD; + } +else uba_sr |= UBASR_LEB; +if (DEBUG_PRI (uba_dev, UBA_DEB_ERR)) + fprintf (sim_deb, ">>UBA: inv map error, ublk = %X\n", ublk); +return; +} + +/* Unibus power fail routines */ + +void uba_ubpdn (int32 time) +{ +int32 i; +DEVICE *dptr; + +uba_cnf = (uba_cnf & ~UBACNF_UBIC) | UBACNF_UBPDN; /* update cnf */ +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_cnf = (uba_cnf & ~UBACNF_UBPDN) | UBACNF_UBIC; + uba_adap_set_int (uba_cr & UBACR_CNFIE); /* possible int */ + } +return SCPE_OK; +} + +/* Interrupt routines */ + +void uba_adap_set_int (int32 flg) +{ +if (((flg & UBACR_SUEFIE) && (uba_sr & UBA_SUEFIE_SR)) || + ((flg & UBACR_USEFIE) && (uba_sr & UBA_USEFIE_SR)) || + ((flg & UBACR_CNFIE) && (uba_cr & UBA_CNFIE_CR))) { + uba_int = 1; + if (DEBUG_PRI (uba_dev, UBA_DEB_ERR)) fprintf (sim_deb, + ">>UBA: adapter int req, sr = %X, cr = %X\n", uba_sr, uba_cr); + } +return; +} + +void uba_adap_clr_int () +{ +if ((!(uba_cr & UBACR_SUEFIE) || !(uba_sr & UBA_SUEFIE_SR)) && + (!(uba_cr & UBACR_USEFIE) || !(uba_sr & UBA_USEFIE_SR)) && + (!(uba_cr & UBACR_CNFIE) || !(uba_cr & UBA_CNFIE_CR))) + 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; + uba_svr[i] = 0; + uba_rvr[i] = 0; + } +for (i = 0; i < UBA_NMAPR; i++) uba_map[i] = 0; +for (i = 0; i < UBA_NDPATH; i++) uba_dpr[i] = 0; +uba_sr = 0; +uba_cr = 0; +uba_dr = 0; +uba_cnf = UBACNF_UBIC; +return SCPE_OK; +} + +/* 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; +} + +/* Enable/disable autoconfiguration */ + +t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (cptr != NULL) return SCPE_ARG; +autcon_enb = val; +return auto_config (NULL, 0); +} + +/* Show autoconfiguration status */ + +t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "autoconfiguration "); +fprintf (st, autcon_enb? "enabled": "disabled"); +return SCPE_OK; +} + +/* Change device address */ + +t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 newba; +t_stat r; + +if (cptr == NULL) return SCPE_ARG; +if ((val == 0) || (uptr == NULL)) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +newba = (uint32) get_uint (cptr, 16, IOPAGEBASE+IOPAGEMASK, &r); +if (r != SCPE_OK) return r; +if ((newba <= IOPAGEBASE) || /* must be > 0 */ + (newba % ((uint32) val))) return SCPE_ARG; /* check modulus */ +dibp->ba = newba; /* store */ +dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ +autcon_enb = 0; /* autoconfig off */ +return SCPE_OK; +} + +/* Show device address */ + +t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +DEVICE *dptr; +DIB *dibp; + +if (uptr == NULL) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if ((dibp == NULL) || (dibp->ba <= IOPAGEBASE)) return SCPE_IERR; +fprintf (st, "address=%08X", dibp->ba); +if (dibp->lnt > 1) + fprintf (st, "-%08X", dibp->ba + dibp->lnt - 1); +if (dptr->flags & DEV_FLTA) fprintf (st, "*"); +return SCPE_OK; +} + +/* Set address floating */ + +t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +DEVICE *dptr; + +if (cptr == NULL) return SCPE_ARG; +if ((val == 0) || (uptr == NULL)) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dptr->flags = dptr->flags | DEV_FLTA; /* floating */ +return auto_config (NULL, 0); /* autoconfigure */ +} + +/* Change device vector */ + +t_stat set_vec (UNIT *uptr, int32 arg, char *cptr, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 newvec; +t_stat r; + +if (cptr == NULL) return SCPE_ARG; +if (uptr == NULL) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +newvec = (uint32) get_uint (cptr, 16, 01000, &r); +if ((r != SCPE_OK) || + ((newvec + (dibp->vnum * 4)) >= 01000) || + (newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG; +dibp->vec = newvec; +dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */ +autcon_enb = 0; /* autoconfig off */ +return SCPE_OK; +} + +/* Show device vector */ + +t_stat show_vec (FILE *st, UNIT *uptr, int32 arg, void *desc) +{ +DEVICE *dptr; +DIB *dibp; +uint32 vec, numvec; + +if (uptr == NULL) return SCPE_IERR; +dptr = find_dev_from_unit (uptr); +if (dptr == NULL) return SCPE_IERR; +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +vec = dibp->vec; +if (arg) numvec = arg; +else numvec = dibp->vnum; +if (vec == 0) fprintf (st, "no vector"); +else { + fprintf (st, "vector=%X", vec); + if (numvec > 1) fprintf (st, "-%X", vec + (4 * (numvec - 1))); + } +return SCPE_OK; +} + +/* Init Unibus tables */ + +void init_ubus_tab (void) +{ +int32 i, j; + +for (i = 0; i < IPL_HLVL; i++) { /* clear int tables */ + for (j = 0; j < 32; j++) { + int_vec[i][j] = 0; + int_ack[i][j] = NULL; + } + } +for (i = 0; i < (IOPAGESIZE >> 1); i++) { /* clear dispatch tab */ + iodispR[i] = NULL; + iodispW[i] = NULL; + iodibp[i] = NULL; + } +return; +} + +/* Build Unibus tables */ + +t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp) +{ +int32 i, idx, vec, ilvl, ibit; + +if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */ +if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR; +for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */ + idx = dibp->vloc + i; /* vector index */ + vec = dibp->vec? (dibp->vec + (i * 4)): 0; /* vector addr */ + ilvl = idx / 32; + ibit = idx % 32; + if ((int_ack[ilvl][ibit] && dibp->ack[i] && /* conflict? */ + (int_ack[ilvl][ibit] != dibp->ack[i])) || + (int_vec[ilvl][ibit] && vec && + (int_vec[ilvl][ibit] != vec))) { + printf ("Device %s interrupt slot conflict at %d\n", + sim_dname (dptr), idx); + if (sim_log) fprintf (sim_log, + "Device %s interrupt slot conflict at %d\n", + sim_dname (dptr), idx); + return SCPE_STOP; + } + if (dibp->ack[i]) int_ack[ilvl][ibit] = dibp->ack[i]; + else if (vec) int_vec[ilvl][ibit] = vec; + } +for (i = 0; i < (int32) dibp->lnt; i = i + 2) { /* create entries */ + idx = ((dibp->ba + i) & IOPAGEMASK) >> 1; /* index into disp */ + if ((iodispR[idx] && dibp->rd && /* conflict? */ + (iodispR[idx] != dibp->rd)) || + (iodispW[idx] && dibp->wr && + (iodispW[idx] != dibp->wr))) { + printf ("Device %s address conflict at %08o\n", + sim_dname (dptr), dibp->ba); + if (sim_log) fprintf (sim_log, + "Device %s address conflict at %08o\n", + sim_dname (dptr), dibp->ba); + return SCPE_STOP; + } + if (dibp->rd) iodispR[idx] = dibp->rd; /* set rd dispatch */ + if (dibp->wr) iodispW[idx] = dibp->wr; /* set wr dispatch */ + iodibp[idx] = dibp; /* remember DIB */ + } +return SCPE_OK; +} + +/* Show IO space */ + +t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +uint32 i, j; +DEVICE *dptr; +DIB *dibp; + +if (build_dib_tab ()) return SCPE_OK; /* build IO page */ +for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ + if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */ + dibp = iodibp[i]; /* DIB for block */ + for (j = 0, dptr = NULL; sim_devices[j] != NULL; j++) { + if (((DIB*) sim_devices[j]->ctxt) == dibp) { + dptr = sim_devices[j]; /* locate device */ + break; + } /* end if */ + } /* end for j */ + fprintf (st, "%08X - %08X%c\t%s\n", dibp->ba, + dibp->ba + dibp->lnt - 1, + (dptr && (dptr->flags & DEV_FLTA))? '*': ' ', + dptr? sim_dname (dptr): "CPU"); + } /* end if */ + } /* end for i */ +return SCPE_OK; +} + +/* Show UBA virtual address */ + +t_stat uba_show_virt (FILE *of, UNIT *uptr, int32 val, 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; +} + +/* Autoconfiguration + + The table reflects the MicroVAX 3900 microcode, with one addition - the + number of controllers field handles devices where multiple instances + are simulated through a single DEVICE structure (e.g., DZ, VH). + + A minus number of vectors indicates a field that should be calculated + but not placed in the DIB (RQ, TQ dynamic vectors) */ + +#define AUTO_MAXC 4 +#define AUTO_CSRBASE 0010 +#define AUTO_VECBASE 0300 + +typedef struct { + char *dnam[AUTO_MAXC]; + int32 numc; + int32 numv; + uint32 amod; + uint32 vmod; + uint32 fixa[AUTO_MAXC]; + uint32 fixv[AUTO_MAXC]; + } AUTO_CON; + +AUTO_CON auto_tab[] = { + { { NULL }, 1, 2, 0, 8, { 0 } }, /* DLV11J - fx CSRs */ + { { NULL }, 1, 2, 8, 8 }, /* DJ11 */ + { { NULL }, 1, 2, 16, 8 }, /* DH11 */ + { { NULL }, 1, 2, 8, 8 }, /* DQ11 */ + { { NULL }, 1, 2, 8, 8 }, /* DU11 */ + { { NULL }, 1, 2, 8, 8 }, /* DUP11 */ + { { NULL }, 10, 2, 8, 8 }, /* LK11A */ + { { NULL }, 1, 2, 8, 8 }, /* DMC11 */ + { { "DZ" }, DZ_MUXES, 2, 8, 8 }, /* DZ11 */ + { { NULL }, 1, 2, 8, 8 }, /* KMC11 */ + { { NULL }, 1, 2, 8, 8 }, /* LPP11 */ + { { NULL }, 1, 2, 8, 8 }, /* VMV21 */ + { { NULL }, 1, 2, 16, 8 }, /* VMV31 */ + { { NULL }, 1, 2, 8, 8 }, /* DWR70 */ + { { "RL", "RLB" }, 1, 1, 8, 4, {IOBA_RL}, {VEC_RL} }, /* RL11 */ + { { "TS", "TSB", "TSC", "TSD" }, 1, 1, 0, 4, /* TS11 */ + {IOBA_TS, IOBA_TS + 4, IOBA_TS + 8, IOBA_TS + 12}, + {VEC_TS} }, + { { NULL }, 1, 2, 16, 8 }, /* LPA11K */ + { { NULL }, 1, 2, 8, 8 }, /* KW11C */ + { { NULL }, 1, 1, 8, 8 }, /* reserved */ + { { "RX", "RY" }, 1, 1, 8, 4, {IOBA_RX} , {VEC_RX} }, /* RX11/RX211 */ + { { NULL }, 1, 1, 8, 4 }, /* DR11W */ + { { NULL }, 1, 1, 8, 4, { 0, 0 }, { 0 } }, /* DR11B - fx CSRs,vec */ + { { NULL }, 1, 2, 8, 8 }, /* DMP11 */ + { { NULL }, 1, 2, 8, 8 }, /* DPV11 */ + { { NULL }, 1, 2, 8, 8 }, /* ISB11 */ + { { NULL }, 1, 2, 16, 8 }, /* DMV11 */ + { { "XU", "XUB" }, 1, 1, 8, 4, {IOBA_XU}, {VEC_XU} }, /* DEUNA */ + { { "XQ", "XQB" }, 1, 1, 0, 4, /* DEQNA */ + {IOBA_XQ,IOBA_XQB}, {VEC_XQ} }, /* */ + { { "RQ", "RQB", "RQC", "RQD" }, 1, -1, 4, 4, /* RQDX3 */ + {IOBA_RQ}, {VEC_RQ} }, + { { NULL }, 1, 8, 32, 4 }, /* DMF32 */ + { { NULL }, 1, 2, 16, 8 }, /* KMS11 */ + { { NULL }, 1, 1, 16, 4 }, /* VS100 */ + { { "TQ", "TQB" }, 1, -1, 4, 4, {IOBA_TQ}, {VEC_TQ} }, /* TQK50 */ + { { NULL }, 1, 2, 16, 8 }, /* KMV11 */ + { { "VH" }, VH_MUXES, 2, 16, 8 }, /* DHU11/DHQ11 */ + { { NULL }, 1, 6, 32, 4 }, /* DMZ32 */ + { { NULL }, 1, 6, 32, 4 }, /* CP132 */ + { { NULL }, 1, 2, 64, 8, { 0 } }, /* QVSS - fx CSR */ + { { NULL }, 1, 1, 8, 4 }, /* VS31 */ + { { NULL }, 1, 1, 0, 4, { 0 } }, /* LNV11 - fx CSR */ + { { NULL }, 1, 1, 16, 4 }, /* LNV21/QPSS */ + { { NULL }, 1, 1, 8, 4, { 0 } }, /* QTA - fx CSR */ + { { NULL }, 1, 1, 8, 4 }, /* DSV11 */ + { { NULL }, 1, 2, 8, 8 }, /* CSAM */ + { { NULL }, 1, 2, 8, 8 }, /* ADV11C */ + { { NULL }, 1, 0, 8, 0 }, /* AAV11C */ + { { NULL }, 1, 2, 8, 8, { 0 }, { 0 } }, /* AXV11C - fx CSR,vec */ + { { NULL }, 1, 2, 4, 8, { 0 } }, /* KWV11C - fx CSR */ + { { NULL }, 1, 2, 8, 8, { 0 } }, /* ADV11D - fx CSR */ + { { NULL }, 1, 2, 8, 8, { 0 } }, /* AAV11D - fx CSR */ + { { "QDSS" }, 1, 3, 0, 16, {IOBA_QDSS} }, /* QDSS - fx CSR */ + { { NULL }, -1 } /* end table */ +}; + +t_stat auto_config (char *name, int32 nctrl) +{ +uint32 csr = IOPAGEBASE + AUTO_CSRBASE; +uint32 vec = VEC_Q + AUTO_VECBASE; +AUTO_CON *autp; +DEVICE *dptr; +DIB *dibp; +uint32 j, k, vmask, amask; + +if (autcon_enb == 0) return SCPE_OK; /* enabled? */ +if (name) { /* updating? */ + if (nctrl < 0) return SCPE_ARG; + for (autp = auto_tab; autp->numc >= 0; autp++) { + for (j = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) { + if (strcmp (name, autp->dnam[j]) == 0) + autp->numc = nctrl; + } + } + } +for (autp = auto_tab; autp->numc >= 0; autp++) { /* loop thru table */ + if (autp->amod) { /* floating csr? */ + amask = autp->amod - 1; + csr = (csr + amask) & ~amask; /* align csr */ + } + for (j = k = 0; (j < AUTO_MAXC) && autp->dnam[j]; j++) { + dptr = find_dev (autp->dnam[j]); /* find ctrl */ + if ((dptr == NULL) || (dptr->flags & DEV_DIS) || + !(dptr->flags & DEV_FLTA)) continue; /* enabled, floating? */ + dibp = (DIB *) dptr->ctxt; /* get DIB */ + if (dibp == NULL) return SCPE_IERR; /* not there??? */ + if (autp->amod) { /* dyn csr needed? */ + if (autp->fixa[k]) /* fixed csr avail? */ + dibp->ba = autp->fixa[k]; /* use it */ + else { /* no fixed left */ + dibp->ba = csr; /* set CSR */ + csr += (autp->numc * autp->amod); /* next CSR */ + } /* end else */ + } /* end if dyn csr */ + if (autp->numv && autp->vmod) { /* dyn vec needed? */ + uint32 numv = abs (autp->numv); /* get num vec */ + if (autp->fixv[k]) { /* fixed vec avail? */ + if (autp->numv > 0) + dibp->vec = autp->fixv[k]; /* use it */ + } + else { /* no fixed left */ + vmask = autp->vmod - 1; + vec = (vec + vmask) & ~vmask; /* align vector */ + if (autp->numv > 0) + dibp->vec = vec; /* set vector */ + vec += (autp->numc * numv * 4); + } /* end else */ + } /* end if dyn vec */ + k++; /* next instance */ + } /* end for j */ + if (autp->amod) csr = csr + 2; /* flt CSR? gap */ + } /* end for i */ +return SCPE_OK; +} diff --git a/VAX/vax_cis.c b/VAX/vax_cis.c index cda1eec0..4bfcb99d 100644 --- a/VAX/vax_cis.c +++ b/VAX/vax_cis.c @@ -615,7 +615,7 @@ switch (opc) { /* case on opcode */ if ((PSL & PSL_FPD) || (op[0] > 31) || (op[2] > 31)) RSVD_OPND_FAULT; ReadDstr (op[0], op[1], &src1, acc); /* get src1 */ - ReadDstr (op[1], op[2], &src2, acc); /* get src2 */ + ReadDstr (op[2], op[3], &src2, acc); /* get src2 */ cc = 0; if (src1.sign != src2.sign) cc = (src1.sign)? CC_N: 0; else { @@ -710,7 +710,7 @@ switch (opc) { /* case on opcode */ if (src1.sign ^ ((result & LSIGN) != 0)) V = 1; /* test for overflow */ if (op[2] >= 0) R[op[2]] = result; else Write (op[3], result, L_LONG, WA); - if (V) SET_TRAP (TRAP_INTOV); + if (V && (PSL & PSW_IV)) SET_TRAP (TRAP_INTOV); /* ovflo and IV? trap */ R[0] = 0; R[1] = op[1]; R[2] = 0; @@ -1221,7 +1221,8 @@ for (i = 0; i < DSTRLNT; i++) { /* loop thru value */ if (i == limit) mask = masktab[lnt % 8]; /* at limit, get mask */ else if (i > limit) mask = 0xFFFFFFFF; /* beyond, all ovflo */ if (dst->val[i] & mask) pslv = 1; /* test for ovflo */ - if (dst->val[i] = dst->val[i] & ~mask) pslz = 0; /* test nz */ + dst->val[i] = dst->val[i] & ~mask; /* clr digits past end */ + if (dst->val[i]) pslz = 0; /* test nz */ } dst->sign = dst->sign & ~(pslz & ~pslv); psln = dst->sign & ~pslz; /* N = sign, if ~zero */ @@ -1451,7 +1452,7 @@ if (s = sc * 4) { for (i = DSTRMAX; i >= 0; i--) { nc = dsrc->val[i]; dsrc->val[i] = ((dsrc->val[i] >> s) | - (cin << rs)) & 0xFFFFFFFF; + (cin << rs)) & LMASK; cin = nc; } return cin; @@ -1476,7 +1477,7 @@ if (s = sc * 4) { for (i = 0; i < DSTRLNT; i++) { nc = dsrc->val[i]; dsrc->val[i] = ((dsrc->val[i] << s) | - (cin >> rs)) & 0xFFFFFFFF; + (cin >> rs)) & LMASK; cin = nc; } return cin; diff --git a/VAX/vax_cpu.c b/VAX/vax_cpu.c index 158d8d45..57bc3435 100644 --- a/VAX/vax_cpu.c +++ b/VAX/vax_cpu.c @@ -25,6 +25,9 @@ cpu VAX central processor + 17-Nov-05 RMS Fixed CVTfi with integer overflow to trap if PSW set + 13-Nov-05 RMS Fixed breakpoint test with 64b addresses + 25-Oct-05 RMS Removed cpu_extmem 22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 16-Aug-05 RMS Fixed C++ declaration and cast problems 13-Jan-05 RMS Fixed initial state of cpu_extmem @@ -150,10 +153,8 @@ #define OP_MEM -1 #define UNIT_V_CONH (UNIT_V_UF + 0) /* halt to console */ -#define UNIT_V_EXTM (UNIT_V_UF + 1) /* ext memory enable */ -#define UNIT_V_MSIZE (UNIT_V_UF + 2) /* dummy */ +#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy */ #define UNIT_CONH (1u << UNIT_V_CONH) -#define UNIT_EXTM (1u << UNIT_V_EXTM) #define UNIT_MSIZE (1u << UNIT_V_MSIZE) #define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL)) @@ -231,7 +232,6 @@ int32 cpu_astop = 0; int32 mchk_va, mchk_ref; /* mem ref param */ int32 ibufl, ibufh; /* prefetch buf */ int32 ibcnt, ppc; /* prefetch ctl */ -int32 cpu_extmem = 1; /* extended memory */ jmp_buf save_env; REG *pcq_r = NULL; /* PC queue reg ptr */ int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ @@ -306,7 +306,7 @@ extern int32 op_mnegg (int32 val); extern int32 op_cmpfd (int32 h1, int32 l1, int32 h2, int32 l2); extern int32 op_cmpg (int32 h1, int32 l1, int32 h2, int32 l2); extern int32 op_cvtifdg (int32 val, int32 *rh, int32 opc); -extern int32 op_cvtfdgi (int32 *opnd, int32 *rh, int32 opc); +extern int32 op_cvtfdgi (int32 *opnd, int32 *flg, int32 opc); extern int32 op_cvtdf (int32 *opnd); extern int32 op_cvtgf (int32 *opnd); extern int32 op_cvtfg (int32 *opnd, int32 *rh); @@ -350,7 +350,6 @@ t_stat cpu_reset (DEVICE *dptr); t_stat cpu_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); t_stat cpu_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw); t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_set_extm (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat cpu_show_virt (FILE *st, UNIT *uptr, int32 val, void *desc); @@ -365,7 +364,7 @@ int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc); cpu_mod CPU modifier list */ -UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_EXTM, INITMEMSIZE) }; +UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK, INITMEMSIZE) }; REG cpu_reg[] = { { HRDATA (PC, R[nPC], 32) }, @@ -418,16 +417,16 @@ REG cpu_reg[] = { }; MTAB cpu_mod[] = { - { UNIT_EXTM, UNIT_EXTM, NULL, "EXTENDEDMEMORY", &cpu_set_extm }, - { UNIT_EXTM, 0, NULL, "NOEXTENDEDMEMORY", &cpu_set_extm }, { UNIT_MSIZE, (1u << 23), NULL, "8M", &cpu_set_size }, { UNIT_MSIZE, (1u << 24), NULL, "16M", &cpu_set_size }, { UNIT_MSIZE, (1u << 25), NULL, "32M", &cpu_set_size }, { UNIT_MSIZE, (1u << 25) + (1u << 24), NULL, "48M", &cpu_set_size }, { UNIT_MSIZE, (1u << 26), NULL, "64M", &cpu_set_size }, { UNIT_MSIZE, (1u << 27), NULL, "128M", &cpu_set_size }, +#if !defined (VAX_780) { UNIT_MSIZE, (1u << 28), NULL, "256M", &cpu_set_size }, { UNIT_MSIZE, (1u << 29), NULL, "512M", &cpu_set_size }, +#endif { UNIT_CONH, 0, "HALT to SIMH", "SIMHALT", NULL }, { UNIT_CONH, UNIT_CONH, "HALT to console", "CONHALT", NULL }, { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", @@ -525,7 +524,7 @@ else if (abortval < 0) { /* mm or rsrv or int */ GET_CUR; } else { - cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ + cc = intexc (-abortval, cc, 0, IE_EXC); /* take exception */ GET_CUR; in_ie = 1; Write (SP - 8, p1, L_LONG, WA); /* write mm params */ @@ -627,7 +626,8 @@ for ( ;; ) { } } /* end PSL event */ - if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ + if (sim_brk_summ && + sim_brk_test ((uint32) PC, SWMASK ('E'))) { /* breakpoint? */ ABORT (STOP_IBKPT); /* stop simulation */ } @@ -2292,25 +2292,25 @@ for ( ;; ) { break; case CVTFB: case CVTDB: case CVTGB: - r = op_cvtfdgi (opnd, &temp, opc) & BMASK; + r = op_cvtfdgi (opnd, &flg, opc) & BMASK; WRITE_B (r); CC_IIZZ_B (r); - cc = cc | temp; + if (flg) { V_INTOV; } break; case CVTFW: case CVTDW: case CVTGW: - r = op_cvtfdgi (opnd, &temp, opc) & WMASK; + r = op_cvtfdgi (opnd, &flg, opc) & WMASK; WRITE_W (r); CC_IIZZ_W (r); - cc = cc | temp; + if (flg) { V_INTOV; } break; case CVTFL: case CVTDL: case CVTGL: case CVTRFL: case CVTRDL: case CVTRGL: - r = op_cvtfdgi (opnd, &temp, opc) & LMASK; + r = op_cvtfdgi (opnd, &flg, opc) & LMASK; WRITE_L (r); CC_IIZZ_L (r); - cc = cc | temp; + if (flg) { V_INTOV; } break; case CVTFD: @@ -2703,15 +2703,6 @@ if (ADDR_IS_ROM (addr)) { return SCPE_NXM; } -/* Enable/disable extended physical memory */ - -t_stat cpu_set_extm (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -if ((val == 0) && (MEMSIZE > MAXMEMSIZE)) return SCPE_ARG; -cpu_extmem = val; -return SCPE_OK; -} - /* Memory allocation */ t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -2720,8 +2711,7 @@ int32 mc = 0; uint32 i, clim; uint32 *nM = NULL; -if ((val <= 0) || - (val > ((uptr->flags & UNIT_EXTM)? MAXMEMSIZE_X: MAXMEMSIZE))) return SCPE_ARG; +if ((val <= 0) || (val > MAXMEMSIZE_X)) return SCPE_ARG; for (i = val; i < MEMSIZE; i = i + 4) mc = mc | M[i >> 2]; if ((mc != 0) && !get_yn ("Really truncate memory [N]?", FALSE)) return SCPE_OK; @@ -2757,12 +2747,12 @@ if (cptr) { va = (uint32) get_uint (cptr, 16, 0xFFFFFFFF, &r); if (r == SCPE_OK) { pa = Test (va, RD, &st); - if (st == PR_OK) fprintf (of, "Virtual %-X = physical %-X", va, pa); - else fprintf (of, "Virtual %-X: %s", va, mm_str[st]); + if (st == PR_OK) fprintf (of, "Virtual %-X = physical %-X\n", va, pa); + else fprintf (of, "Virtual %-X: %s\n", va, mm_str[st]); return SCPE_OK; } } -fprintf (of, "Invalid argument"); +fprintf (of, "Invalid argument\n"); return SCPE_OK; } diff --git a/VAX/vax_defs.h b/VAX/vax_defs.h index df38dba4..ad517a94 100644 --- a/VAX/vax_defs.h +++ b/VAX/vax_defs.h @@ -26,6 +26,7 @@ The author gratefully acknowledges the help of Stephen Shirron, Antonio Carlini, and Kevin Peterson in providing specifications for the Qbus VAX's + 03-Nov-05 RMS Added 780 stop codes 22-Jul-05 RMS Fixed warning from Solaris C (from Doug Gwyn) 02-Sep-04 RMS Added octa specifier definitions 30-Aug-04 RMS Added octa, h_floating instruction definitions @@ -58,8 +59,10 @@ #define STOP_RQ 8 /* fatal RQ err */ #define STOP_LOOP 9 /* infinite loop */ #define STOP_SANITY 10 /* sanity timer exp */ -#define STOP_UNKNOWN 11 /* unknown reason */ -#define STOP_UNKABO 12 /* unknown abort */ +#define STOP_SWDN 11 /* software done (780) */ +#define STOP_BOOT 12 /* reboot (780) */ +#define STOP_UNKNOWN 13 /* unknown reason */ +#define STOP_UNKABO 14 /* unknown abort */ #define ABORT_INTR -1 /* interrupt */ #define ABORT_MCHK (-SCB_MCHK) /* machine check */ #define ABORT_RESIN (-SCB_RESIN) /* rsvd instruction */ diff --git a/VAX/vax_doc.txt b/VAX/vax_doc.txt index e3fff9f5..348273bb 100644 --- a/VAX/vax_doc.txt +++ b/VAX/vax_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: VAX Simulator Usage -Date: 01-Jul-2005 +Date: 01-Dec-2005 COPYRIGHT NOTICE @@ -148,8 +148,6 @@ ROM, or the non-volatile memory. CPU options include the size of main memory and the treatment of the HALT instruction. - SET CPU EXTEND enable extended memory support - SET CPU NOEXTEND disable extended memory support SET CPU 16M set memory size = 16MB SET CPU 32M set memory size = 32MB SET CPU 48M set memory size = 48MB @@ -173,9 +171,7 @@ Notes on memory size: - The real KA655 CPU only supported 16MB to 64MB of memory. The simulator provides a KA655"X" mode, which increases supported memory to 512MB. - Extended memory is enabled by default. If extended memory is enabled, - and memory size exceeds 64MB, the CPU will boot using special firmware - ka655x.bin. This firmware contains code to determine the size of extended + The firmware (ka655x.bin) contains code to determine the size of extended memory and set up the PFN bit map accordingly. Other than setting up the PFN bootmap, the firmware does not recognize extended memory and will behave as though memory size was 64MB. @@ -391,15 +387,15 @@ floating addresses; that is, the assigned device address depends on the presense of other devices in the configuration: DZ11 all instances have floating addresses - DQH11 all instances have floating addresses + DHQ11 all instances have floating addresses RL11 first instance has fixed address, rest floating - RX11/RX211 first instance has fixed address, second floating + RX11/RX211 first instance has fixed address, rest floating MSCP disk first instance has fixed address, rest floating TMSCP tape first instance has fixed address, rest floating To maintain addressing consistency as the configuration changes, the simulator implements DEC's standard I/O address and vector autoconfiguration -algorithms for devices DZ, VH, RL, RQ, and TQ. This allows the user to +algorithms for devices DZ, VH, RL, RQn, and TQ. This allows the user to enable or disable devices without needing to manage I/O addresses and vectors. @@ -425,10 +421,18 @@ the device address and vector, respectively. 2.3.1 Terminal Input (TTI) -The terminal interfaces (TTI, TTO) can be set to one of two modes: -7B or 8B. In 7B mode, input and output characters are masked to 7 -bits. In 8B mode, characters are not modified. Changing the mode -of either interface changes both. The default mode is 8B. +The console interfaces (TTI, TTO) can be set to one of three modes, +7P, 7B or 8B: + + mode input characters output characters + + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default mode is 8B. When the console terminal is attached to a Telnet session, it recognizes BREAK. If BREAK is entered, and BDR<7> is set, control @@ -824,12 +828,17 @@ are supported. The number of lines can be changed with the command The line count must be a multiple of 4, with a maximum of 16. -The DZV11 supports 8-bit input and output of characters. 8-bit output -may be incompatible with certain operating systems. The command +The DZ11 supports three character processing modes, 7P, 7B, and 8B: - SET DZ 7B + mode input characters output characters -forces output characters to be masked to 7 bits. + 7P high-order bit cleared high-order bit cleared, + non-printing characters + suppressed + 7B high-order bit cleared high-order bit cleared + 8B no changes no changes + +The default is 8B. The DZ11 supports logging on a per-line basis. The command diff --git a/VAX/vax_io.c b/VAX/vax_io.c index 3cc948f9..b385a7a9 100644 --- a/VAX/vax_io.c +++ b/VAX/vax_io.c @@ -25,6 +25,7 @@ qba Qbus adapter + 03-Dec-05 RMS Added SHOW QBA VIRT and ex/dep via map 05-Oct-05 RMS Fixed bug in autoconfiguration (missing XU) 25-Jul-05 RMS Revised autoconfiguration algorithm and interface 30-Sep-04 RMS Revised Qbus interface @@ -130,10 +131,14 @@ int32 eval_int (void); void cq_merr (int32 pa); void cq_serr (int32 pa); t_stat qba_reset (DEVICE *dptr); -t_bool map_addr (uint32 qa, uint32 *ma); +t_stat qba_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); +t_stat qba_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw); +t_bool qba_map_addr (uint32 qa, uint32 *ma); +t_bool qba_map_addr_c (uint32 qa, uint32 *ma); t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc); t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat qba_show_virt (FILE *of, UNIT *uptr, int32 val, void *desc); /* Qbus adapter data structures @@ -168,13 +173,15 @@ MTAB qba_mod[] = { &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, &qba_show_virt }, { 0 } }; DEVICE qba_dev = { "QBA", &qba_unit, qba_reg, qba_mod, - 1, 0, 0, 0, 0, 0, - NULL, NULL, &qba_reset, + 1, 16, CQMAWIDTH, 2, 16, 16, + &qba_ex, &qba_dep, &qba_reset, NULL, NULL, NULL, &qba_dib, DEV_QBUS }; @@ -479,7 +486,7 @@ int32 cqmem_rd (int32 pa) int32 qa = pa & CQMAMASK; /* Qbus addr */ uint32 ma; -if (map_addr (qa, &ma)) return M[ma >> 2]; /* map addr */ +if (qba_map_addr (qa, &ma)) return M[ma >> 2]; /* map addr */ MACH_CHECK (MCHK_READ); /* err? mcheck */ return 0; } @@ -489,7 +496,7 @@ void cqmem_wr (int32 pa, int32 val, int32 lnt) int32 qa = pa & CQMAMASK; /* Qbus addr */ uint32 ma; -if (map_addr (qa, &ma)) { /* map addr */ +if (qba_map_addr (qa, &ma)) { /* map addr */ if (lnt < L_LONG) { int32 sc = (pa & 3) << 3; int32 mask = (lnt == L_WORD)? 0xFFFF: 0xFF; @@ -504,7 +511,7 @@ return; /* Map an address via the translation map */ -t_bool map_addr (uint32 qa, uint32 *ma) +t_bool qba_map_addr (uint32 qa, uint32 *ma) { int32 qblk = (qa >> VA_V_VPN); /* Qbus blk */ int32 qmma = ((qblk << 2) & CQMAPAMASK) + cq_mbr; /* map entry */ @@ -513,15 +520,32 @@ if (ADDR_IS_MEM (qmma)) { /* legit? */ int32 qmap = M[qmma >> 2]; /* get map */ if (qmap & CQMAP_VLD) { /* valid? */ *ma = ((qmap & CQMAP_PAG) << VA_V_VPN) + VA_GETOFF (qa); - if (ADDR_IS_MEM (*ma)) return 1; /* legit addr */ + if (ADDR_IS_MEM (*ma)) return TRUE; /* legit addr */ cq_serr (*ma); /* slave nxm */ - return 0; + return FALSE; } cq_merr (qa); /* master nxm */ - return 0; + return FALSE; } cq_serr (0); /* inv mem */ -return 0; +return FALSE; +} + +/* Map an address via the translation map - console version (no status changes) */ + +t_bool qba_map_addr_c (uint32 qa, uint32 *ma) +{ +int32 qblk = (qa >> VA_V_VPN); /* Qbus blk */ +int32 qmma = ((qblk << 2) & CQMAPAMASK) + cq_mbr; /* map entry */ + +if (ADDR_IS_MEM (qmma)) { /* legit? */ + int32 qmap = M[qmma >> 2]; /* get map */ + if (qmap & CQMAP_VLD) { /* valid? */ + *ma = ((qmap & CQMAP_PAG) << VA_V_VPN) + VA_GETOFF (qa); + return TRUE; /* legit addr */ + } + } +return FALSE; } /* Set master error */ @@ -590,8 +614,8 @@ uint32 ma, dat; if ((ba | bc) & 03) { /* check alignment */ for (i = ma = 0; i < bc; i++, buf++) { /* by bytes */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); + if (!qba_map_addr (ba + i, &ma)) /* inv or NXM? */ + return (bc - i); } *buf = ReadB (ma); ma = ma + 1; @@ -600,8 +624,8 @@ if ((ba | bc) & 03) { /* check alignment */ else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); + if (!qba_map_addr (ba + i, &ma)) /* inv or NXM? */ + return (bc - i); } dat = ReadL (ma); /* get lw */ *buf++ = dat & BMASK; /* low 8b */ @@ -624,8 +648,8 @@ bc = bc & ~01; if ((ba | bc) & 03) { /* check alignment */ for (i = ma = 0; i < bc; i = i + 2, buf++) { /* by words */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); + if (!qba_map_addr (ba + i, &ma)) /* inv or NXM? */ + return (bc - i); } *buf = ReadW (ma); ma = ma + 2; @@ -634,8 +658,8 @@ if ((ba | bc) & 03) { /* check alignment */ else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); + if (!qba_map_addr (ba + i, &ma)) /* inv or NXM? */ + return (bc - i); } dat = ReadL (ma); /* get lw */ *buf++ = dat & WMASK; /* low 16b */ @@ -654,8 +678,8 @@ uint32 ma, dat; if ((ba | bc) & 03) { /* check alignment */ for (i = ma = 0; i < bc; i++, buf++) { /* by bytes */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); + if (!qba_map_addr (ba + i, &ma)) /* inv or NXM? */ + return (bc - i); } WriteB (ma, *buf); ma = ma + 1; @@ -664,8 +688,8 @@ if ((ba | bc) & 03) { /* check alignment */ else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); + if (!qba_map_addr (ba + i, &ma)) /* inv or NXM? */ + return (bc - i); } dat = (uint32) *buf++; /* get low 8b */ dat = dat | (((uint32) *buf++) << 8); /* merge next 8b */ @@ -688,8 +712,8 @@ bc = bc & ~01; if ((ba | bc) & 03) { /* check alignment */ for (i = ma = 0; i < bc; i = i + 2, buf++) { /* by words */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); + if (!qba_map_addr (ba + i, &ma)) /* inv or NXM? */ + return (bc - i); } WriteW (ma, *buf); ma = ma + 2; @@ -698,8 +722,8 @@ if ((ba | bc) & 03) { /* check alignment */ else { for (i = ma = 0; i < bc; i = i + 4, buf++) { /* by longwords */ if ((ma & VA_M_OFF) == 0) { /* need map? */ - if (!map_addr (ba + i, &ma) || /* inv or NXM? */ - !ADDR_IS_MEM (ma)) return (bc - i); + if (!qba_map_addr (ba + i, &ma)) /* inv or NXM? */ + return (bc - i); } dat = (uint32) *buf++; /* get low 16b */ dat = dat | (((uint32) *buf) << 16); /* merge hi 16b */ @@ -710,6 +734,34 @@ else { return 0; } +/* Memory examine via map (word only) */ + +t_stat qba_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw) +{ +uint32 qa = (uint32) exta, pa; + +if ((vptr == NULL) || (qa >= CQMSIZE)) return SCPE_ARG; +if (qba_map_addr_c (qa, &pa) && ADDR_IS_MEM (pa)) { + *vptr = (uint32) ReadW (pa); + return SCPE_OK; + } +return SCPE_NXM; +} + +/* Memory deposit via map (word only) */ + +t_stat qba_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw) +{ +uint32 qa = (uint32) exta, pa; + +if (qa >= CQMSIZE) return SCPE_ARG; +if (qba_map_addr_c (qa, &pa) && ADDR_IS_MEM (pa)) { + WriteW (pa, (int32) val); + return SCPE_OK; + } +return SCPE_NXM; +} + /* Enable/disable autoconfiguration */ t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -952,6 +1004,27 @@ for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */ return SCPE_OK; } +/* Show QBA virtual address */ + +t_stat qba_show_virt (FILE *of, UNIT *uptr, int32 val, void *desc) +{ +t_stat r; +char *cptr = (char *) desc; +uint32 qa, pa; + +if (cptr) { + qa = (uint32) get_uint (cptr, 16, CQMSIZE - 1, &r); + if (r == SCPE_OK) { + if (qba_map_addr_c (qa, &pa)) + fprintf (of, "Qbus %-X = physical %-X\n", qa, pa); + else fprintf (of, "Qbus %-X: invalid mapping\n", qa); + return SCPE_OK; + } + } +fprintf (of, "Invalid argument\n"); +return SCPE_OK; +} + /* Autoconfiguration The table reflects the MicroVAX 3900 microcode, with one addition - the diff --git a/VAX/vax_octa.c b/VAX/vax_octa.c index e78b86d2..9f826118 100644 --- a/VAX/vax_octa.c +++ b/VAX/vax_octa.c @@ -232,24 +232,24 @@ switch (opc) { */ case CVTHB: - r = op_cvthi (opnd, &temp, opc) & BMASK; /* convert */ + r = op_cvthi (opnd, &flg, opc) & BMASK; /* convert */ h_write_b (spec, va, r, acc); /* write result */ CC_IIZZ_B (r); /* set cc's */ - cc = cc | temp; /* or in V */ + if (flg) { V_INTOV; } break; case CVTHW: - r = op_cvthi (opnd, &temp, opc) & WMASK; /* convert */ + r = op_cvthi (opnd, &flg, opc) & WMASK; /* convert */ h_write_w (spec, va, r, acc); /* write result */ CC_IIZZ_W (r); /* set cc's */ - cc = cc | temp; /* or in V */ + if (flg) { V_INTOV; } break; case CVTHL: case CVTRHL: - r = op_cvthi (opnd, &temp, opc) & LMASK; /* convert */ + r = op_cvthi (opnd, &flg, opc) & LMASK; /* convert */ h_write_l (spec, va, r, acc); /* write result */ CC_IIZZ_L (r); /* set cc's */ - cc = cc | temp; /* or in V */ + if (flg) { V_INTOV; } break; /* CVTFH diff --git a/VAX/vax_stddev.c b/VAX/vax_stddev.c index 3fcd0a71..224ef3b3 100644 --- a/VAX/vax_stddev.c +++ b/VAX/vax_stddev.c @@ -27,6 +27,7 @@ tto terminal output clk 100Hz and TODR clock + 22-Nov-05 RMS Revised for new terminal processing routines 09-Sep-04 RMS Integrated powerup into RESET (with -p) 28-May-04 RMS Removed SET TTI CTRL-C 29-Dec-03 RMS Added console backpressure support @@ -55,9 +56,6 @@ #define CLK_DELAY 5000 /* 100 Hz */ #define TMXR_MULT 2 /* 50 Hz */ -#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B mode */ -#define UNIT_8B (1 << UNIT_V_8B) - extern int32 int_req[IPL_HLVL]; extern int32 hlt_pin; extern int32 sim_switches; @@ -89,7 +87,7 @@ extern int32 sysd_hlt_enb (void); DIB tti_dib = { 0, 0, NULL, NULL, 1, IVCL (TTI), SCB_TTI, { NULL } }; -UNIT tti_unit = { UDATA (&tti_svc, UNIT_8B, 0), KBD_POLL_WAIT }; +UNIT tti_unit = { UDATA (&tti_svc, TT_MODE_8B, 0), KBD_POLL_WAIT }; REG tti_reg[] = { { HRDATA (BUF, tti_unit.buf, 16) }, @@ -103,8 +101,8 @@ REG tti_reg[] = { }; MTAB tti_mod[] = { - { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { UNIT_8B, 0 , "7b", "7B", NULL }, + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec, NULL }, { 0 } @@ -127,7 +125,7 @@ DEVICE tti_dev = { DIB tto_dib = { 0, 0, NULL, NULL, 1, IVCL (TTO), SCB_TTO, { NULL } }; -UNIT tto_unit = { UDATA (&tto_svc, UNIT_8B, 0), SERIAL_OUT_WAIT }; +UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_8B, 0), SERIAL_OUT_WAIT }; REG tto_reg[] = { { HRDATA (BUF, tto_unit.buf, 8) }, @@ -141,8 +139,9 @@ REG tto_reg[] = { }; MTAB tto_mod[] = { - { UNIT_8B, UNIT_8B, "8b", "8B", NULL }, - { UNIT_8B, 0 , "7b", "7B", NULL }, + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec }, { 0 } }; @@ -173,6 +172,7 @@ REG clk_reg[] = { { DRDATA (TODR, todr_reg, 32), PV_LEFT }, { FLDATA (BLOW, todr_blow, 0) }, { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, + { DRDATA (POLL, tmr_poll, 24), REG_NZ + PV_LEFT + REG_HRO }, { DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT }, { NULL } }; @@ -281,14 +281,14 @@ t_stat tti_svc (UNIT *uptr) { int32 c; -sim_activate (&tti_unit, tti_unit.wait); /* continue poll */ +sim_activate (uptr, uptr->wait); /* continue poll */ if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ if (c & SCPE_BREAK) { /* break? */ if (sysd_hlt_enb ()) hlt_pin = 1; /* if enabled, halt */ tti_unit.buf = TTIBUF_ERR | TTIBUF_FRM | TTIBUF_RBR; } -else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177); -tti_unit.pos = tti_unit.pos + 1; +else tti_unit.buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags)); +uptr->pos = uptr->pos + 1; tti_csr = tti_csr | CSR_DONE; if (tti_csr & CSR_IE) SET_INT (TTI); return SCPE_OK; @@ -314,14 +314,16 @@ t_stat tto_svc (UNIT *uptr) int32 c; t_stat r; -c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177); -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 */ +c = sim_tt_outcvt (tto_unit.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 */ + } } tto_csr = tto_csr | CSR_DONE; if (tto_csr & CSR_IE) SET_INT (TTO); -tto_unit.pos = tto_unit.pos + 1; +uptr->pos = uptr->pos + 1; return SCPE_OK; } diff --git a/VAX/vax_sys.c b/VAX/vax_sys.c index 8b363f0e..63c22d57 100644 --- a/VAX/vax_sys.c +++ b/VAX/vax_sys.c @@ -23,6 +23,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 03-Nov-05 RMS Added 780 stop codes 04-Sep-05 RMS Fixed missing assignment (found by Peter Schorn) 16-Aug-05 RMS Fixed C++ declaration and cast problems 15-Sep-04 RMS Fixed bugs in character display and parse @@ -97,6 +98,8 @@ const char *sim_stop_messages[] = { "Fatal RQDX3 error", "Infinite loop", "Sanity timer expired", + "Software done", + "Reboot requested", "Unknown error", "Unknown abort code" }; @@ -673,7 +676,7 @@ const char *opcode[] = { "CVTPS", "CVTSP", "INDEX", "CRC", "PROBER", "PROBEW", "INSQUE", "REMQUE", "BSBB", "BRB", "BNEQ", "BEQL", "BGTR", "BLEQ", "JSB", "JMP", "BGEQ", "BLSS", "BGTRU", "BLEQU", "BVC", "BVS", "BGEQU", "BLSSU", -"ADDP4", "ADDP6", "SUBP4", "SUBP6", "CVTPT", "MULP6", "CVTTP", "DIVP", +"ADDP4", "ADDP6", "SUBP4", "SUBP6", "CVTPT", "MULP", "CVTTP", "DIVP", "MOVC3", "CMPC3", "SCANC", "SPANC", "MOVC5", "CMPC5", "MOVTC", "MOVTUC", "BSBW", "BRW", "CVTWL", "CVTWB", "MOVP", "CMPP3", "CVTPL", "CMPP4", "EDITPC", "MATCHC", "LOCC", "SKPC", "MOVZWL", "ACBW", "MOVAW", "PUSHAW", diff --git a/VAX/vax_sysdev.c b/VAX/vax_sysdev.c index b29f047d..1b850dff 100644 --- a/VAX/vax_sysdev.c +++ b/VAX/vax_sysdev.c @@ -32,6 +32,7 @@ cso console storage output sysd system devices (SSC miscellany) + 25-Oct-05 RMS Automated CMCTL extended memory 16-Aug-05 RMS Fixed C++ declaration and cast problems 10-Mar-05 RMS Fixed bug in timer schedule routine (from Mark Hittinger) 30-Sep-04 RMS Moved CADR, MSER, CONPC, CONPSL, machine_check, cpu_boot, @@ -187,7 +188,6 @@ extern int32 p1; extern int32 sim_switches; extern int32 MSER; extern int32 tmr_poll; -extern int32 cpu_extmem; uint32 *rom = NULL; /* boot ROM */ uint32 *nvr = NULL; /* non-volatile mem */ @@ -994,7 +994,8 @@ switch (rg) { return cmctl_reg[rg] & CMCSR_MASK; case 18: /* KA655X ext mem */ - if (cpu_extmem) return ((int32) MEMSIZE); + if (MEMSIZE > MAXMEMSIZE) /* more than 128MB? */ + return ((int32) MEMSIZE); MACH_CHECK (MCHK_READ); } diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index 5a70791a..b0d30363 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -128,7 +128,7 @@ #define CTG_V (1u << (CTGAWIDTH + 0)) /* tag valid */ #define CTG_WP (1u << (CTGAWIDTH + 1)) /* wrong parity */ #define ADDR_IS_CDG(x) ((((uint32) (x)) >= CDGBASE) && \ - (((uint32) (x)) < (CDGBASE + CDGSIZE))) + (((uint32) (x)) < (CDGBASE + CDGSIZE))) /* Qbus I/O registers */ @@ -137,7 +137,7 @@ #define IOPAGEMASK (IOPAGESIZE - 1) /* IO addr mask */ #define IOPAGEBASE 0x20000000 /* IO page base */ #define ADDR_IS_IO(x) ((((uint32) (x)) >= IOPAGEBASE) && \ - (((uint32) (x)) < (IOPAGEBASE + IOPAGESIZE))) + (((uint32) (x)) < (IOPAGEBASE + IOPAGESIZE))) /* Read only memory - appears twice */ @@ -146,7 +146,7 @@ #define ROMAMASK (ROMSIZE - 1) /* ROM addr mask */ #define ROMBASE 0x20040000 /* ROM base */ #define ADDR_IS_ROM(x) ((((uint32) (x)) >= ROMBASE) && \ - (((uint32) (x)) < (ROMBASE + ROMSIZE + ROMSIZE))) + (((uint32) (x)) < (ROMBASE + ROMSIZE + ROMSIZE))) /* Local register space */ @@ -189,7 +189,7 @@ #define NVRAMASK (NVRSIZE - 1) /* NVR addr mask */ #define NVRBASE 0x20140400 /* NVR base */ #define ADDR_IS_NVR(x) ((((uint32) (x)) >= NVRBASE) && \ - (((uint32) (x)) < (NVRBASE + NVRSIZE))) + (((uint32) (x)) < (NVRBASE + NVRSIZE))) /* CQBIC Qbus memory space (seen from CVAX) */ diff --git a/descrip.mms b/descrip.mms index 9da3aa7c..25dd6310 100644 --- a/descrip.mms +++ b/descrip.mms @@ -41,6 +41,7 @@ # S3 Just Build The IBM System 3. # SDS Just Build The SDS 940. # VAX Just Build The DEC VAX. +# VAX780 Just Build The DEC VAX780. # CLEAN Will Clean Files Back To Base Kit. # # To build with debugging enabled (which will also enable traceback @@ -422,11 +423,13 @@ SDS_OPTIONS = /INCLUDE=($(SIMH_DIR),$(SDS_DIR))/DEFINE=($(CC_DEFS)) # VAX_DIR = SYS$DISK:[.VAX] VAX_LIB = $(LIB_DIR)VAX-$(ARCH).OLB -VAX_SOURCE = $(VAX_DIR)VAX_CPU1.C,$(VAX_DIR)VAX_CPU.C,\ - $(VAX_DIR)VAX_FPA.C,$(VAX_DIR)VAX_IO.C,\ - $(VAX_DIR)VAX_MMU.C,$(VAX_DIR)VAX_STDDEV.C,\ - $(VAX_DIR)VAX_SYS.C,$(VAX_DIR)VAX_SYSDEV.C,\ - $(VAX_DIR)VAX_SYSCM.C,$(VAX_DIR)VAX_SYSLIST.C,\ +VAX_SOURCE = $(VAX_DIR)VAX_CIS.C,$(VAX_DIR)VAX_CMODE.C,\ + $(VAX_DIR)VAX_CPU.C,$(VAX_DIR)VAX_CPU1.C,\ + $(VAX_DIR)VAX_FPA.C,$(VAX_DIR)VAX_MMU.C,\ + $(VAX_DIR)VAX_OCTA.C,$(VAX_DIR)VAX_SYS.C,\ + $(VAX_DIR)VAX_SYSCM.C,$(VAX_DIR)VAX_SYSDEV.C,\ + $(VAX_DIR)VAX_SYSLIST.C,$(VAX_DIR)VAX_IO.C,\ + $(VAX_DIR)VAX_STDDEV.C,\ $(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_TQ.C,\ @@ -435,6 +438,28 @@ VAX_SOURCE = $(VAX_DIR)VAX_CPU1.C,$(VAX_DIR)VAX_CPU.C,\ VAX_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX_DIR),$(PDP11_DIR)$(PCAP_INC))\ /DEFINE=($(CC_DEFS),"VM_VAX=1"$(PCAP_DEFS)) +# +# Digital Equipment VAX780 Simulator Definitions. +# +VAX780_DIR = SYS$DISK:[.VAX] +VAX780_LIB = $(LIB_DIR)VAX780-$(ARCH).OLB +VAX780_SOURCE = $(VAX780_DIR)VAX_CIS.C,$(VAX780_DIR)VAX_CMODE.C,\ + $(VAX780_DIR)VAX_CPU.C,$(VAX780_DIR)VAX_CPU1.C,\ + $(VAX780_DIR)VAX_FPA.C,$(VAX780_DIR)VAX_MMU.C,\ + $(VAX780_DIR)VAX_OCTA.C,$(VAX780_DIR)VAX_SYS.C,\ + $(VAX780_DIR)VAX_SYSCM.C,\ + $(VAX780_DIR)VAX780_MBA.C,$(VAX780_DIR)VAX780_MEM.C,\ + $(VAX780_DIR)VAX_SBI.C,$(VAX780_DIR)VAX780_STDDEV.C,\ + $(VAX780_DIR)VAX780_SYSLIST.C,$(VAX780_DIR)VAX780_UBA.C,\ + $(PDP11_DIR)PDP11_DZ.C,$(PDP11_DIR)PDP11_HK.C,\ + $(PDP11_DIR)PDP11_LP.C,$(PDP11_DIR)PDP11_RL.C,\ + $(PDP11_DIR)PDP11_RP.C,$(PDP11_DIR)PDP11_RQ.C,\ + $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_TQ.C,\ + $(PDP11_DIR)PDP11_TS.C,$(PDP11_DIR)PDP11_TU.C,\ + $(PDP11_DIR)PDP11_XU.C +VAX780_OPTIONS = /INCLUDE=($(SIMH_DIR),$(VAX780_DIR),$(PDP11_DIR)$(PCAP_INC))\ + /DEFINE=($(CC_DEFS),"VM_VAX=1"$(PCAP_DEFS)) + # # If we're not a VAX, Build Everything # @@ -447,7 +472,7 @@ ALL : ALTAIR ALTAIRZ80 ECLIPSE GRI LGP H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 # Since VAX Dosen't Have INT64 # ALL : ALTAIR ALTAIRZ80 GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \ - NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 VAX SDS + NOVA PDP1 PDP4 PDP7 PDP8 PDP9 PDP11 PDP15 S3 VAX VAX780 SDS .ENDIF CLEAN : @@ -782,6 +807,17 @@ $(VAX_LIB) : $(VAX_SOURCE) $ LIBRARY/REPLACE $(MMS$TARGET) $(BLD_DIR)*.OBJ $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* +$(VAX780_LIB) : $(VAX780_SOURCE) + $! + $! Building The $(VAX_780LIB) Library. + $! + $ $(CC)$(VAX780_OPTIONS)/OBJECT=$(VAX780_DIR) - + /OBJECT=$(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;* + $(PCAP_LIB) : $(PCAP_SOURCE) $! $! Building The $(PCAP_LIB) Library. @@ -1043,6 +1079,15 @@ VAX : $(SIMH_LIB) $(PCAP_LIBD) $(VAX_LIB) $(PCAP_EXECLET) $(BLD_DIR)SCP.OBJ,$(VAX_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY$(PCAP_LIBR) $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* +VAX780 : $(SIMH_LIB) $(PCAP_LIBD) $(VAX780_LIB) $(PCAP_EXECLET) + $! + $! Building The $(BIN_DIR)VAX780-$(ARCH).EXE Simulator. + $! + $ $(CC)$(VAX780_OPTIONS)/OBJECT=$(BLD_DIR) SCP.C + $ LINK $(LINK_DEBUG)/EXE=$(BIN_DIR)VAX780-$(ARCH).EXE - + $(BLD_DIR)SCP.OBJ,$(VAX780_LIB)/LIBRARY,$(SIMH_LIB)/LIBRARY$(PCAP_LIBR) + $ DELETE/NOLOG/NOCONFIRM $(BLD_DIR)*.OBJ;* + # # PCAP VCI Components # diff --git a/makefile b/makefile index 8bdb9ccc..e7804df5 100644 --- a/makefile +++ b/makefile @@ -96,20 +96,20 @@ VAX = ${VAXD}vax_cpu.c ${VAXD}vax_cpu1.c ${VAXD}vax_fpa.c ${VAXD}vax_io.c \ ${PDP11D}pdp11_dz.c ${PDP11D}pdp11_lp.c ${PDP11D}pdp11_tq.c \ ${PDP11D}pdp11_xq.c ${PDP11D}pdp11_ry.c \ ${PDP11D}pdp11_vh.c -VAX_OPT = -DVM_VAX -DUSE_INT64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} +VAX_OPT = -DVM_VAX -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} VAX780 = ${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}vax780_stddev.c ${VAXD}vax780_sbimem.c \ - ${VAXD}vax780_uba.c ${VAXD}vax780_mba.c \ + ${VAXD}vax_mmu.c ${VAXD}vax780_stddev.c ${VAXD}vax780_sbi.c \ + ${VAXD}vax780_mem.c ${VAXD}vax780_uba.c ${VAXD}vax780_mba.c \ ${VAXD}vax_sys.c ${VAXD}vax_syscm.c ${VAXD}vax780_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_rp.c ${PDP11D}pdp11_tu.c ${PDP11D}pdp11_hk.c -VAX780_OPT = -DVM_VAX -DVAX_780 -DUSE_INT64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} +VAX780_OPT = -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} @@ -244,11 +244,11 @@ SDS_OPT = -I ${SDSD} # ALL = ${BIN}pdp1${EXE} ${BIN}pdp4${EXE} ${BIN}pdp7${EXE} ${BIN}pdp8${EXE} \ ${BIN}pdp9${EXE} ${BIN}pdp15${EXE} ${BIN}pdp11${EXE} ${BIN}pdp10${EXE} \ - ${BIN}vax${EXE} ${BIN}nova${EXE} ${BIN}eclipse${EXE} ${BIN}h316${EXE} \ + ${BIN}vax${EXE} ${BIN}vax780${EXE} ${BIN}nova${EXE} ${BIN}eclipse${EXE} \ ${BIN}hp2100${EXE} ${BIN}i1401${EXE} ${BIN}i1620${EXE} ${BIN}s3${EXE} \ ${BIN}altair${EXE} ${BIN}altairz80${EXE} ${BIN}gri${EXE} \ ${BIN}i1620${EXE} ${BIN}ibm1130${EXE} ${BIN}id16${EXE} \ - ${BIN}id32${EXE} ${BIN}sds${EXE} ${BIN}lgp${EXE} + ${BIN}id32${EXE} ${BIN}sds${EXE} ${BIN}lgp${EXE} ${BIN}h316${EXE} all : ${ALL} diff --git a/scp.c b/scp.c index f16c65dd..67213575 100644 --- a/scp.c +++ b/scp.c @@ -1,6 +1,6 @@ /* scp.c: simulator control program - Copyright (c) 1993-2005, Robert M Supnik + Copyright (c) 1993-2006, 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"), @@ -23,6 +23,9 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 18-Jan-06 RMS Added fprint_stopped_gen + Added breakpoint spaces + Fixed unaligned register access (found by Doug Carman) 22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 30-Aug-05 RMS Revised to trim trailing spaces on file names 25-Aug-05 RMS Added variable default device support @@ -284,7 +287,7 @@ t_stat sim_brk_show (FILE *st, t_addr loc, int32 sw); t_stat sim_brk_showall (FILE *st, int32 sw); char *sim_brk_getact (char *buf, int32 size); void sim_brk_clract (void); -void sim_brk_npc (void); +void sim_brk_npc (uint32 cnt); BRKTAB *sim_brk_new (t_addr loc); /* Commands support routines */ @@ -345,8 +348,8 @@ BRKTAB *sim_brk_tab = NULL; int32 sim_brk_ent = 0; int32 sim_brk_lnt = 0; int32 sim_brk_ins = 0; -t_bool sim_brk_pend = FALSE; -t_addr sim_brk_ploc = 0; +t_bool sim_brk_pend[SIM_BKPT_N_SPC] = { FALSE }; +t_addr sim_brk_ploc[SIM_BKPT_N_SPC] = { 0 }; int32 sim_quiet = 0; int32 sim_step = 0; static double sim_time; @@ -2325,22 +2328,21 @@ return SCPE_OK; /* Print stopped message */ -void fprint_stopped (FILE *st, t_stat v) +void fprint_stopped_gen (FILE *st, t_stat v, REG *pc, DEVICE *dptr) { int32 i; t_stat r = 0; t_addr k; t_value pcval; -DEVICE *dptr; if (v >= SCPE_BASE) fprintf (st, "\n%s, %s: ", - scp_error_messages[v - SCPE_BASE], sim_PC->name); -else fprintf (st, "\n%s, %s: ", sim_stop_messages[v], sim_PC->name); -pcval = get_rval (sim_PC, 0); -if (sim_vm_fprint_addr) sim_vm_fprint_addr (st, sim_dflt_dev, (t_addr) pcval); -else fprint_val (st, pcval, sim_PC->radix, sim_PC->width, - sim_PC->flags & REG_FMT); -if (((dptr = sim_dflt_dev) != NULL) && (dptr->examine != NULL)) { + scp_error_messages[v - SCPE_BASE], pc->name); +else fprintf (st, "\n%s, %s: ", sim_stop_messages[v], pc->name); +pcval = get_rval (pc, 0); +if (sim_vm_fprint_addr) sim_vm_fprint_addr (st, dptr, (t_addr) pcval); +else fprint_val (st, pcval, pc->radix, pc->width, + pc->flags & REG_FMT); +if ((dptr != NULL) && (dptr->examine != NULL)) { for (i = 0; i < sim_emax; i++) sim_eval[i] = 0; for (i = 0, k = (t_addr) pcval; i < sim_emax; i++, k = k + dptr->aincr) { if ((r = dptr->examine (&sim_eval[i], k, dptr->units, @@ -2357,6 +2359,12 @@ fprintf (st, "\n"); return; } +void fprint_stopped (FILE *st, t_stat v) +{ +fprint_stopped_gen (st, v, sim_PC, sim_dflt_dev); +return; +} + /* Unit service for step timeout, originally scheduled by STEP n command Return step timeout SCP code, will cause simulation to stop */ @@ -2598,9 +2606,11 @@ if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) { val = *((uint32 *) uptr); #endif } -else if ((rptr->depth > 1) && (sz == sizeof (uint8))) +else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) && + (sz == sizeof (uint8))) val = *(((uint8 *) rptr->loc) + idx); -else if ((rptr->depth > 1) && (sz == sizeof (uint16))) +else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) && + (sz == sizeof (uint16))) val = *(((uint16 *) rptr->loc) + idx); #if defined (USE_INT64) else if (sz <= sizeof (uint32)) @@ -2678,7 +2688,7 @@ UNIT *uptr; (*(((sz *) rp->loc) + id) & \ ~((m) << (rp)->offset)) | ((v) << (rp)->offset) -if (rptr == sim_PC) sim_brk_npc (); +if (rptr == sim_PC) sim_brk_npc (0); sz = SZ_R (rptr); mask = width_mask[rptr->width]; if ((rptr->depth > 1) && (rptr->flags & REG_CIRC)) { @@ -2700,9 +2710,11 @@ if ((rptr->depth > 1) && (rptr->flags & REG_UNIT)) { (((uint32) val) << rptr->offset); #endif } -else if ((rptr->depth > 1) && (sz == sizeof (uint8))) +else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) && + (sz == sizeof (uint8))) PUT_RVAL (uint8, rptr, idx, (uint32) val, (uint32) mask); -else if ((rptr->depth > 1) && (sz == sizeof (uint16))) +else if (((rptr->depth > 1) || (rptr->flags & REG_FIT)) && + (sz == sizeof (uint16))) PUT_RVAL (uint16, rptr, idx, (uint32) val, (uint32) mask); #if defined (USE_INT64) else if (sz <= sizeof (uint32)) @@ -3868,8 +3880,8 @@ sim_brk_lnt = SIM_BRK_INILNT; sim_brk_tab = (BRKTAB *) calloc (sim_brk_lnt, sizeof (BRKTAB)); if (sim_brk_tab == NULL) return SCPE_MEM; sim_brk_ent = sim_brk_ins = 0; -sim_brk_pend = FALSE; sim_brk_act = NULL; +sim_brk_npc (0); return SCPE_OK; } @@ -4034,22 +4046,22 @@ return SCPE_OK; /* Test for breakpoint */ -t_bool sim_brk_test (t_addr loc, int32 btyp) +uint32 sim_brk_test (t_addr loc, uint32 btyp) { BRKTAB *bp; +uint32 spc = (btyp >> SIM_BKPT_V_SPC) & (SIM_BKPT_N_SPC - 1); -if ((bp = sim_brk_fnd (loc)) && /* entry in table? */ - (btyp & bp->typ) && /* type match? */ - (!sim_brk_pend || (loc != sim_brk_ploc)) && /* new location? */ - (--(bp->cnt) <= 0)) { /* count reach 0? */ +if ((bp = sim_brk_fnd (loc)) && (btyp & bp->typ)) { /* in table, type match? */ + if ((sim_brk_pend[spc] && (loc == sim_brk_ploc[spc])) || /* previous location? */ + (--bp->cnt > 0)) return 0; /* count > 0? */ bp->cnt = 0; /* reset count */ - sim_brk_ploc = loc; /* save location */ + sim_brk_ploc[spc] = loc; /* save location */ + sim_brk_pend[spc] = TRUE; /* don't do twice */ sim_brk_act = bp->act; /* set up actions */ - sim_brk_pend = TRUE; /* don't do twice */ - return TRUE; + return (btyp & bp->typ); } -sim_brk_pend = FALSE; -return FALSE; +sim_brk_pend[spc] = FALSE; +return 0; } /* Get next pending action, if any */ @@ -4084,9 +4096,26 @@ sim_brk_act = NULL; /* New PC */ -void sim_brk_npc (void) +void sim_brk_npc (uint32 cnt) { -sim_brk_pend = FALSE; +uint32 i; + +if ((cnt == 0) || (cnt > SIM_BKPT_N_SPC)) cnt = SIM_BKPT_N_SPC; +for (i = 0; i < cnt; i++) { + sim_brk_pend[i] = FALSE; + sim_brk_ploc[i] = 0; + } +return; +} + +/* Clear breakpoint space */ + +void sim_brk_clrspc (uint32 spc) +{ +if (spc < SIM_BKPT_N_SPC) { + sim_brk_pend[spc] = FALSE; + sim_brk_ploc[spc] = 0; + } return; } diff --git a/scp.h b/scp.h index bf376b17..c3d150a3 100644 --- a/scp.h +++ b/scp.h @@ -1,6 +1,6 @@ /* scp.h: simulator control program headers - Copyright (c) 1993-2005, Robert M Supnik + Copyright (c) 1993-2006, 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"), @@ -23,6 +23,8 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 06-Jan-06 RMS Added fprint_stopped_gen + Changed arg type in sim_brk_test 07-Feb-05 RMS Added ASSERT command 09-Sep-04 RMS Added reset_all_p 14-Feb-04 RMS Added debug prototypes (from Dave Hittner) @@ -103,11 +105,13 @@ CTAB *find_ctab (CTAB *tab, char *gbuf); C1TAB *find_c1tab (C1TAB *tab, char *gbuf); SHTAB *find_shtab (SHTAB *tab, char *gbuf); BRKTAB *sim_brk_fnd (t_addr loc); -t_bool sim_brk_test (t_addr bloc, int32 btyp); +uint32 sim_brk_test (t_addr bloc, uint32 btyp); +void sim_brk_clrspc (uint32 spc); char *match_ext (char *fnam, char *ext); t_stat sim_cancel_step (void); void sim_debug_u16 (uint32 dbits, DEVICE* dptr, const char* const* bitdefs, uint16 before, uint16 after, int terminate); void sim_debug (uint32 dbits, DEVICE* dptr, const char* fmt, ...); +void fprint_stopped_gen (FILE *st, t_stat v, REG *pc, DEVICE *dptr); #endif diff --git a/sim_console.c b/sim_console.c index 64664558..714c3095 100644 --- a/sim_console.c +++ b/sim_console.c @@ -23,6 +23,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 22-Nov-05 RMS Added central input/output conversion support 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy 28-Oct-04 JDB Fixed SET CONSOLE to allow comma-separated parameters 20-Aug-04 RMS Added OS/2 EMX fixes (from Holger Veit) @@ -58,6 +59,8 @@ sim_putchar_s - output character to console, stall if congested sim_set_console - set console parameters sim_show_console - show console parameters + sim_tt_inpcvt - convert input character per mode + sim_tt_outcvt - convert output character per mode sim_ttinit - called once to get initial terminal state sim_ttrun - called to put terminal into run state @@ -78,6 +81,7 @@ #include "sim_defs.h" #include "sim_sock.h" #include "sim_tmxr.h" +#include #define KMAP_WRU 0 #define KMAP_BRK 1 @@ -87,6 +91,7 @@ int32 sim_int_char = 005; /* interrupt character */ int32 sim_brk_char = 000; /* break character */ +int32 sim_tt_pchar = 0x00002780; #if defined (_WIN32) || defined (__OS2__) || (defined (__MWERKS__) && defined (macintosh)) int32 sim_del_char = '\b'; /* delete character */ #else @@ -416,6 +421,41 @@ tmxr_poll_tx (&sim_con_tmxr); /* poll xmt */ return r; /* return status */ } +/* Input character processing */ + +int32 sim_tt_inpcvt (int32 c, uint32 mode) +{ +uint32 md = mode & TTUF_M_MODE; + +if (md != TTUF_MODE_8B) { + c = c & 0177; + if (md == TTUF_MODE_UC) { + if (islower (c)) c = toupper (c); + if (mode & TTUF_KSR) c = c | 0200; + } + } +else c = c & 0377; +return c; +} + +/* Output character processing */ + +int32 sim_tt_outcvt (int32 c, uint32 mode) +{ +uint32 md = mode & TTUF_M_MODE; + +if (md != TTUF_MODE_8B) { + c = c & 0177; + if ((md == TTUF_MODE_UC) && islower (c)) c = toupper (c); + if (((md == TTUF_MODE_UC) || (md == TTUF_MODE_7P)) && + ((c == 0177) || + ((c < 040) && !((sim_tt_pchar >> c) & 1)))) + return -1; + } +else c = c & 0377; +return c; +} + /* VMS routines, from Ben Thomas, with fixes from Robert Alan Byer */ #if defined (VMS) diff --git a/sim_console.h b/sim_console.h index 769bfcb2..17e4be69 100644 --- a/sim_console.h +++ b/sim_console.h @@ -23,6 +23,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 22-Nov-05 RMS Added central input/output conversion support 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy 28-May-04 RMS Added SET/SHOW CONSOLE 02-Jan-04 RMS Removed timer routines, added Telnet console routines @@ -31,6 +32,23 @@ #ifndef _SIM_CONSOLE_H_ #define _SIM_CONSOLE_H_ 0 +#define TTUF_V_MODE (UNIT_V_UF + 0) +#define TTUF_W_MODE 2 +#define TTUF_MODE_7B 0 +#define TTUF_MODE_8B 1 +#define TTUF_MODE_UC 2 +#define TTUF_MODE_7P 3 +#define TTUF_KSR (1u << TTUF_W_MODE) +#define TTUF_M_MODE ((1u << TTUF_W_MODE) - 1) +#define TTUF_V_UF (TTUF_V_MODE + TTUF_W_MODE) +#define TT_MODE (TTUF_M_MODE << TTUF_V_MODE) +#define TT_MODE_7B (TTUF_MODE_7B << TTUF_V_MODE) +#define TT_MODE_8B (TTUF_MODE_8B << TTUF_V_MODE) +#define TT_MODE_UC (TTUF_MODE_UC << TTUF_V_MODE) +#define TT_MODE_7P (TTUF_MODE_7P << TTUF_V_MODE) +#define TT_MODE_KSR (TT_MODE_UC) +#define TT_GET_MODE(x) (((x) >> TTUF_V_MODE) & TTUF_M_MODE) + t_stat sim_set_console (int32 flag, char *cptr); t_stat sim_set_kmap (int32 flag, char *cptr); t_stat sim_set_telnet (int32 flag, char *cptr); @@ -54,5 +72,7 @@ t_stat sim_ttcmd (void); t_stat sim_ttclose (void); t_stat sim_os_poll_kbd (void); t_stat sim_os_putchar (int32 out); +int32 sim_tt_inpcvt (int32 c, uint32 mode); +int32 sim_tt_outcvt (int32 c, uint32 mode); #endif diff --git a/sim_defs.h b/sim_defs.h index 55b3cc05..7a234623 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -1,6 +1,6 @@ /* sim_defs.h: simulator definitions - Copyright (c) 1993-2005, Robert M Supnik + Copyright (c) 1993-2006, 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"), @@ -23,6 +23,8 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 07-Jan-06 RMS Added support for breakpoint spaces + Added REG_FIT flag 16-Aug-05 RMS Fixed C++ declaration and cast problems 11-Mar-05 RMS Moved 64b data type definitions outside USE_INT64 07-Feb-05 RMS Added assertion fail stop @@ -160,6 +162,11 @@ typedef uint32 t_addr; #endif #define CBUFSIZE (128 + PATH_MAX) /* string buf size */ +/* Breakpoint spaces definitions */ + +#define SIM_BKPT_N_SPC 64 /* max number spaces */ +#define SIM_BKPT_V_SPC 26 /* location in arg */ + /* Extended switch definitions (bits >= 26) */ #define SIM_SW_HIDE (1u << 26) /* enable hiding */ @@ -365,14 +372,15 @@ struct sim_reg { uint32 qptr; /* circ q ptr */ }; -#define REG_FMT 0003 /* see PV_x */ -#define REG_RO 0004 /* read only */ -#define REG_HIDDEN 0010 /* hidden */ -#define REG_NZ 0020 /* must be non-zero */ -#define REG_UNIT 0040 /* in unit struct */ -#define REG_CIRC 0100 /* circular array */ -#define REG_VMIO 0200 /* use VM data print/parse */ -#define REG_VMAD 0400 /* use VM addr print/parse */ +#define REG_FMT 00003 /* see PV_x */ +#define REG_RO 00004 /* read only */ +#define REG_HIDDEN 00010 /* hidden */ +#define REG_NZ 00020 /* must be non-zero */ +#define REG_UNIT 00040 /* in unit struct */ +#define REG_CIRC 00100 /* circular array */ +#define REG_VMIO 00200 /* use VM data print/parse */ +#define REG_VMAD 00400 /* use VM addr print/parse */ +#define REG_FIT 01000 /* fit access to size */ #define REG_HRO (REG_RO | REG_HIDDEN) /* hidden, read only */ /* Command tables, base and alternate formats */ diff --git a/sim_ether.c b/sim_ether.c index 85ee81f0..774111f2 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -134,6 +134,13 @@ Modification history: + 15-Dec-05 DTH Patched eth_host_devices [remove non-ethernet devices] + (from Mark Pizzolato and Galen Tackett, 08-Jun-05) + Patched eth_open [tun fix](from Antal Ritter, 06-Oct-05) + 30-Nov-05 DTH Added option to regenerate CRC on received packets; some + ethernet devices need to pass it on to the simulation, and by + the time libpcap/winpcap gets the packet, the host OS network + layer has already stripped CRC out of the packet 01-Dec-04 DTH Added Windows user-defined adapter names (from Timothe Litt) 25-Mar-04 MP Revised comments and minor #defines to deal with updated libpcap which now provides pcap_sendpacket on all platforms. @@ -341,6 +348,24 @@ uint32 eth_crc32(uint32 crc, const void* vbuf, size_t len) return(crc ^ mask); } +void eth_add_crc32(ETH_PACK* packet) +{ + if (packet->len <= ETH_MAX_PACKET) { + uint32 crc = eth_crc32(0, packet->msg, packet->len); /* calculate CRC */ + uint32 ncrc = htonl(crc); /* CRC in network order */ + int size = sizeof(ncrc); /* size of crc field */ + memcpy(&packet->msg[packet->len], &ncrc, size); /* append crc to packet */ + packet->crc_len = packet->len + size; /* set packet crc length */ + } else { + packet->crc_len = 0; /* appending crc would destroy packet */ + } +} + +void eth_setcrc(ETH_DEV* dev, int need_crc) +{ + dev->need_crc = need_crc; +} + void eth_packet_trace_ex(ETH_DEV* dev, const uint8 *msg, int len, char* txt, int dmp) { if (dev->dptr->dctrl & dev->dbit) { @@ -387,7 +412,7 @@ void eth_packet_trace_ex(ETH_DEV* dev, const uint8 *msg, int len, char* txt, int void eth_packet_trace(ETH_DEV* dev, const uint8 *msg, int len, char* txt) { - eth_packet_trace_ex(dev, msg, len, txt, len > ETH_MAX_PACKET); + eth_packet_trace_ex(dev, msg, len, txt, 1/*len > ETH_MAX_PACKET*/); } char* eth_getname(int number, char* name) @@ -425,6 +450,48 @@ char* eth_getname_bydesc(char* desc, char* name) return 0; } +/* strncasecmp() is not available on all platforms */ +int eth_strncasecmp(char* string1, char* string2, int len) +{ + int i; + unsigned char s1, s2; + + for (i=0; i s2) + return 1; + if (s1 == 0) return 0; + } + return 0; +} + +char* eth_getname_byname(char* name, char* temp) +{ + ETH_LIST list[ETH_MAX_DEVICE]; + int count = eth_devices(ETH_MAX_DEVICE, list); + int i, n, found; + + found = 0; + n = strlen(name); + for (i=0; itype = type; item->packet.len = pack->len; item->packet.used = 0; - memcpy(item->packet.msg, pack->msg, pack->len); + item->packet.crc_len = pack->crc_len; + memcpy(item->packet.msg, pack->msg, ((pack->len > pack->crc_len) ? pack->len : pack->crc_len)); item->packet.status = status; } @@ -655,8 +723,12 @@ t_stat eth_open(ETH_DEV* dev, char* name, DEVICE* dptr, uint32 dbit) } else { /* are they trying to use device description? */ savname = eth_getname_bydesc(name, temp); - if (savname == 0) /* didn't translate */ - return SCPE_OPENERR; + if (savname == 0) { /* didn't translate */ + /* probably is not ethX and has no description */ + savname = eth_getname_byname(name, temp); + if (savname == 0) /* didn't translate */ + return SCPE_OPENERR; + } } /* attempt to connect device */ @@ -867,6 +939,8 @@ void eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* /* set data in passed read packet */ tmp_packet.len = header->len; memcpy(tmp_packet.msg, data, header->len); + if (dev->need_crc) + eth_add_crc32(&tmp_packet); eth_packet_trace (dev, tmp_packet.msg, tmp_packet.len, "rcvqd"); @@ -877,6 +951,8 @@ void eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* /* set data in passed read packet */ dev->read_packet->len = header->len; memcpy(dev->read_packet->msg, data, header->len); + if (dev->need_crc) + eth_add_crc32(dev->read_packet); eth_packet_trace (dev, dev->read_packet->msg, dev->read_packet->len, "reading"); @@ -892,6 +968,7 @@ t_stat eth_read(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine) int status; /* make sure device exists */ + if (!dev) return SCPE_UNATT; /* make sure packet exists */ @@ -1109,8 +1186,9 @@ int eth_host_devices(int used, int max, ETH_LIST* list) if (NULL != conn) datalink = pcap_datalink(conn), pcap_close(conn); if ((NULL == conn) || (datalink != DLT_EN10MB)) { for (j=i+1; j set + 1 15-Oct-05 All CPU's, other sources: fixed declaration inconsistencies (from Sterling Garwood) @@ -56,7 +100,7 @@ patch date module(s) and fix(es) vax_io.c: fixed bug in autoconfiguration (missing XU) - vax_fpa.c: fixed bug in 32b structure definitions (from Jason Stevens) + vax_fpa.c: fixed bug in 32b structure definitions (from Jason Stevens) 0 1-Sep-05 Note: most source modules have been edited to improve readability and to fix declaration and cast problems in C++ diff --git a/sim_sock.c b/sim_sock.c index 63de4067..3bc95d9f 100644 --- a/sim_sock.c +++ b/sim_sock.c @@ -23,6 +23,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 19-Nov-05 RMS Added conditional for OpenBSD (from Federico G. Schwindt) 16-Aug-05 RMS Fixed spurious SIGPIPE signal error in Unix 14-Apr-05 RMS Added WSAEINPROGRESS test (from Tim Riker) 09-Jan-04 RMS Fixed typing problem in Alpha Unix (found by Tim Chapman) @@ -191,7 +192,8 @@ return newsock; /* got it! */ SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr) { int32 sta, err; -#if defined (macintosh) || defined (__linux) || defined (__APPLE__) +#if defined (macintosh) || defined (__linux) || \ + defined (__APPLE__) || defined (__OpenBSD__) socklen_t size; #elif defined (_WIN32) || defined (__EMX__) ||\ (defined (__ALPHA) && defined (__unix__)) diff --git a/sim_tape.c b/sim_tape.c index 4eb27a27..7239833d 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -1,6 +1,6 @@ /* sim_tape.c: simulator tape support library - Copyright (c) 1993-2005, Robert M Supnik + Copyright (c) 1993-2006, 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"), @@ -26,6 +26,8 @@ Ultimately, this will be a place to hide processing of various tape formats, as well as OS-specific direct hardware access. + 23-Jan-05 RMS Fixed bug in write forward (found by Dave Bryan) + 17-Dec-05 RMS Added write support for Paul Pierce 7b format 16-Aug-05 RMS Fixed C++ declaration and cast problems 02-May-05 RMS Added support for Pierce 7b format 28-Jul-04 RMS Fixed bug in writing error records (found by Dave Bryan) @@ -44,6 +46,7 @@ sim_tape_sprecf space tape record forward sim_tape_sprecr space tape record reverse sim_tape_wrtmk write tape mark + sim_tape_wrtmk_7t write tape mark, 7 track with parity sim_tape_wreom erase remainder of tape sim_tape_rewind rewind sim_tape_reset reset unit @@ -67,7 +70,7 @@ static struct sim_tape_fmt fmts[MTUF_N_FMT] = { { "SIMH", 0, sizeof (t_mtrlnt) - 1 }, { "E11", 0, sizeof (t_mtrlnt) - 1 }, { "TPC", UNIT_RO, sizeof (t_tpclnt) - 1 }, - { "P7B", UNIT_RO, 0 }, + { "P7B", 0, 0 }, /* { "TPF", UNIT_RO, 0 }, */ { NULL, 0, 0 } }; @@ -220,7 +223,7 @@ switch (f) { /* switch on fmt */ break; /* treat like eor */ } if ((sbc != 0) && (c & P7B_SOR)) break; /* next record? */ - if ((c & P7B_DATA) != P7B_EOF) all_eof = 0; + if ((c & P7B_DPAR) != P7B_EOF) all_eof = 0; } *bc = sbc; /* save rec lnt */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* for read */ @@ -303,7 +306,7 @@ switch (f) { /* switch on fmt */ if (ferror (uptr->fileref)) /* error? */ return sim_tape_ioerr (uptr); if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */ - if ((c & P7B_DATA) != P7B_EOF) all_eof = 0; + if ((c & P7B_DPAR) != P7B_EOF) all_eof = 0; if (c & P7B_SOR) break; /* start of record? */ } uptr->pos = uptr->pos - sbc; /* update position */ @@ -429,17 +432,34 @@ t_mtrlnt sbc; MT_CLR_PNU (uptr); if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */ if (sim_tape_wrp (uptr)) return MTSE_WRP; /* write prot? */ -if (f == MTUF_F_STD) sbc = MTR_L ((bc + 1) & ~1); -else sbc = MTR_L (bc); +sbc = MTR_L (bc); sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */ -sim_fwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); -sim_fwrite (buf, sizeof (uint8), sbc, uptr->fileref); -sim_fwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); -if (ferror (uptr->fileref)) { /* error? */ - MT_SET_PNU (uptr); - return sim_tape_ioerr (uptr); - } -uptr->pos = uptr->pos + sbc + (2 * sizeof (t_mtrlnt)); /* move tape */ +switch (f) { /* case on format */ + + case MTUF_F_STD: /* standard */ + sbc = MTR_L ((bc + 1) & ~1); /* pad odd length */ + case MTUF_F_E11: /* E11 */ + sim_fwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); + sim_fwrite (buf, sizeof (uint8), sbc, uptr->fileref); + sim_fwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref); + if (ferror (uptr->fileref)) { /* error? */ + MT_SET_PNU (uptr); + return sim_tape_ioerr (uptr); + } + uptr->pos = uptr->pos + sbc + (2 * sizeof (t_mtrlnt)); /* move tape */ + break; + + case MTUF_F_P7B: /* Pierce 7B */ + buf[0] = buf[0] | P7B_SOR; /* mark start of rec */ + sim_fwrite (buf, sizeof (uint8), sbc, uptr->fileref); + if (ferror (uptr->fileref)) { /* error? */ + MT_SET_PNU (uptr); + return sim_tape_ioerr (uptr); + } + uptr->pos = uptr->pos + sbc; /* move tape */ + break; + } + return MTSE_OK; } @@ -464,6 +484,10 @@ return MTSE_OK; t_stat sim_tape_wrtmk (UNIT *uptr) { +if (MT_GET_FMT (uptr) == MTUF_F_P7B) { /* P7B? */ + uint8 buf= P7B_EOF; /* eof mark */ + return sim_tape_wrrecf (uptr, &buf, 1); /* write char */ + } return sim_tape_wrdata (uptr, MTR_TMK); } @@ -471,6 +495,7 @@ return sim_tape_wrdata (uptr, MTR_TMK); t_stat sim_tape_wreom (UNIT *uptr) { +if (MT_GET_FMT (uptr) == MTUF_F_P7B) return MTSE_FMT; /* cant do P7B */ return sim_tape_wrdata (uptr, MTR_EOM); } diff --git a/sim_tape.h b/sim_tape.h index 3003ab56..fd784ee4 100644 --- a/sim_tape.h +++ b/sim_tape.h @@ -23,6 +23,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 17-Dec-05 RMS Added write support for Paul Pierce 7b format 02-May-05 RMS Added support for Paul Pierce 7b format */ @@ -46,8 +47,9 @@ typedef uint16 t_tpclnt; /* magtape rec lnt */ /* P7B tape format */ #define P7B_SOR 0x80 /* start of record */ -#define P7B_DPAR 0x7F /* data and parity */ +#define P7B_PAR 0x40 /* parity */ #define P7B_DATA 0x3F /* data */ +#define P7B_DPAR (P7B_PAR|P7B_DATA) /* data and parity */ #define P7B_EOF 0x0F /* eof character */ #define TPC_TMK 0x0000 /* tape mark */ @@ -71,6 +73,12 @@ typedef uint16 t_tpclnt; /* magtape rec lnt */ #define MTUF_FMT (MTUF_M_FMT << MTUF_V_FMT) #define MTUF_WRP (MTUF_WLK | UNIT_RO) +#define MT_F_STD (MTUF_F_STD << MTUF_V_FMT) +#define MT_F_E11 (MTUF_F_E11 << MTUF_V_FMT) +#define MT_F_TPC (MTUF_F_TPC << MTUF_V_FMT) +#define MT_F_P7B (MTUF_F_P7B << MTUF_V_FMT) +#define MT_F_TDF (MTUF_F_TDF << MTUF_V_FMT) + #define MT_SET_PNU(u) (u)->flags = (u)->flags | MTUF_PNU #define MT_CLR_PNU(u) (u)->flags = (u)->flags & ~MTUF_PNU #define MT_TST_PNU(u) ((u)->flags & MTUF_PNU) diff --git a/simh_doc.txt b/simh_doc.txt index 0f158f30..dc39d382 100644 --- a/simh_doc.txt +++ b/simh_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik -Subj: Simulator Usage, V3.4 -Date: 20-Jul-2005 +Subj: Simulator Usage, V3.5 +Date: 01-Nov-2005 COPYRIGHT NOTICE @@ -35,7 +35,7 @@ This memorandum documents SIMH simulators. These simulators are freeware; refer to the license terms above for conditions of use. Support is not available. The best way to fix problems or add features is to read and modify the sources yourself. Alternately, you can send Internet mail to -bob AT supnik DOT org, but a response is not guaranteed. +simh AT trailing-edge DOT com, but a response is not guaranteed. The simulators use a common command interface. This memorandum describes the features of the command interface. The details of each simulator are @@ -107,7 +107,7 @@ as the file name and arguments for a DO command: % pdp10 { {arg,arg,...}}(cr) If no file is specified on the command line, the simulator looks for -an startup file consisting of the simulator name (including its path +a startup file consisting of the simulator name (including its path components) plus the extension .ini. If a startup file is specified, either on the command line or implicitly via the .ini capability, it should contain a series of non-interactive simulator command, one @@ -166,17 +166,17 @@ Examples: 1.2.1 Compiling PDP-11 and VAX with Ethernet Support -The Windows-specific Ethernet code uses the WinPCAP 3.0 package. -This package for windows simulates the libpcap package that is freely +The Windows-specific Ethernet code uses the WinPCAP 3.x package. +This package for Windows simulates the libpcap package that is freely available for Unix systems. WinPCAP must be installed prior to building the PDP-11 and VAX simulators with Ethernet support. -- Download V3.0 from http://winpcap.polito.it. +- Download V3.x from http://www.winpcap.org. - Install the package as directed. - Copy the required .h files (bittypes.h, devioctl.h, ip6_misc.h, - packet32.h, pcap.h, pcap-stdinc.h) from the WinPCAP 3.0 developer's + packet32.h, pcap.h, pcap-stdinc.h) from the WinPCAP 3.x developer's kit to the top level simulation directory. - Get the required .lib files (packet.lib, wpcap.lib) from the WinPCAP 3.0 developer's kit. If you're using Borland C++, use COFF2OMF to @@ -279,16 +279,15 @@ ignored. 3.1 Loading and Saving Programs -The LOAD command (abbreviation LO) loads a file in binary paper-tape -loader format: +The LOAD command (abbreviation LO) loads a file in binary loader format: sim> load {implementation options}(cr) The types of formats supported are implementation specific. Options (such as load within range) are also implementation specific. -The DUMP command (abbreviation DU) dumps memory in binary paper- -tape loader format: +The DUMP command (abbreviation DU) dumps memory in binary loader +format: sim> dump {implementation options}(cr) @@ -359,6 +358,7 @@ The currently supported tape image file formats are: SIMH SIMH simulator format E11 E11 simulator format TPC TPC format + P7B Pierce simulator 7-track format The tape format can also be set with the SET command prior to ATTACH: @@ -403,7 +403,7 @@ There are four commands to examine and change state: All four commands take the form - command {modifiers} + command {modifiers} Deposit must also include a deposit value at the end of the command. @@ -435,10 +435,10 @@ valid file name. Modifiers may be specified in any order. If multiple modifiers of the same type are specified, later modifiers override earlier modifiers. Note that if the device/unit name comes after the search specifier, -the values will interpreted in the radix of the CPU, rather than of the -device/unit. +the search values will interpreted in the radix of the CPU, rather than +of the device/unit. -The "state list" consists of one or more of the following, separated +The "object list" consists of one or more of the following, separated by commas: register the specified register @@ -467,14 +467,14 @@ Switches can be used to control the format of display information: -m display as instruction mnemonics -o display as octal -d display as decimal - -h display as hexidecimal + -h display as hexadecimal The simulators typically accept symbolic input (see documentation with each simulator). Examples: - sim> ex 1000-1100 -- examine 1100:1100 + sim> ex 1000-1100 -- examine 1000:1100 sim> de PC 1040 -- set PC to 1040 sim> ie 40-50 -- interactively examine 40:50 sim> ie >1000 40-50 -- interactively examine the subset @@ -514,9 +514,9 @@ The STEP command (abbreviated S) resumes execution at the current PC for the number of instructions given by its argument. If no argument is supplied, one instruction is executed. -The BOOT command (abbreviated BO) bootstraps the device and unit given -by its argument. If no unit is supplied, unit 0 is bootstrapped. The -specified unit must be attached. +The BOOT command (abbreviated BO) resets all devices and bootstraps the +device and unit given by its argument. If no unit is supplied, unit 0 +is bootstrapped. The specified unit must be attached. 3.8 Stopping Programs @@ -702,6 +702,8 @@ The console provides a limited key remapping capability: value as BREAK (0 disables) sim> SET CONSOLE DEL= -- interpret ASCII code value as DELETE + sim> SET CONSOLE PCHAR= -- bit mask of printable + characters in range [31,0] Values are hexadecimal on hex CPU's, octal on all others. @@ -954,7 +956,7 @@ mag tape y y y - h device CPU y y y h y FPU - y y - y -EIS/CIS - y y - h +EIS/CIS - y y - - console h y y h y paper tape - y h h y card reader y - - - - @@ -986,23 +988,23 @@ drum - - - - h DECtape - - - - - mag tape - - d y h - system LGP-30 1130 7094 + system LGP-30 1130 780 device -CPU h y d -FPU - - d -CIS - - - -console h y - +CPU h y y +FPU - - y +CIS - - y +console h y y paper tape h - - -card reader - y h -line printer - y h -clock - - n -extra terminal - - n -hard disk - y d -fixed disk - - d -floppy disk - - - -drum - - d +card reader - y - +line printer - y y +clock - - y +extra terminal - - y +hard disk - y y +fixed disk - - - +floppy disk - - y +drum - - - DECtape - - - -mag tape - - h +mag tape - - y legend: y = runs operating system or sample program d = runs diagnostics @@ -1015,9 +1017,12 @@ Revision History (covering Rev 2.0 to present) Starting with Rev 2.7, detailed revision histories can be found in file sim_rev.c. +Rev 3.5, Sep, 05 + Overhauled sources for readability + Added VAX-11/780 + Rev 3.4, May, 05 Revised memory interaction model - Added IBM 7094 Rev 3.3, Nov, 04 Added PDP-11/VAX DHQ11 support diff --git a/simh_swre.txt b/simh_swre.txt index a59257cf..b0627cd1 100644 --- a/simh_swre.txt +++ b/simh_swre.txt @@ -77,7 +77,7 @@ images, and to Digital Equipment Corporation, which provided the license. To boot and run OS/8: - sim> att rx0 os8sys_rx.dsk + sim> att rx0 os8_rx.dsk sim> att rx1 os8f4_rx.dsk sim> boot rx0