diff --git a/H316/h316_fhd.c b/H316/h316_fhd.c index 4f20a45a..3f984da3 100644 --- a/H316/h316_fhd.c +++ b/H316/h316_fhd.c @@ -1,6 +1,6 @@ /* h316_fhd.c: H316/516 fixed head simulator - Copyright (c) 2003-2012, Robert M. Supnik + Copyright (c) 2003-2013, 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 @@ fhd 516-4400 fixed head disk + 03-Sep-13 RMS Added explicit cast on void * pointer 19-Mar-12 RMS Fixed declaration of chan_req (Mark Pizzolato) 15-May-06 RMS Fixed bug in autosize attach (David Gesswein) 04-Jan-04 RMS Changed sim_fsize calling sequence @@ -373,7 +374,7 @@ uint32 tk = CW1_GETTK (fhd_cw1); /* track */ uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */ uint32 wa = ca >> 1; /* word addr */ uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */ -uint16 *fbuf = uptr->filebuf; /* buffer base */ +uint16 *fbuf = (uint16 *) uptr->filebuf; /* buffer base */ uint32 wd; if (fhd_bad_wa (wa)) /* addr bad? */ diff --git a/H316/h316_stddev.c b/H316/h316_stddev.c index c358841e..151a3513 100644 --- a/H316/h316_stddev.c +++ b/H316/h316_stddev.c @@ -1,6 +1,6 @@ /* h316_stddev.c: Honeywell 316/516 standard devices - Copyright (c) 1999-2008, Robert M. Supnik + Copyright (c) 1999-2013, 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"), @@ -28,6 +28,8 @@ tty 316/516-33 teleprinter clk/options 316/516-12 real time clocks/internal options + 10-Sep-13 RMS Fixed several bugs in the TTY logic + Added SET file type commands to PTR/PTP 09-Jun-07 RMS Fixed bug in clock increment (Theo Engel) 30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode 03-Apr-06 RMS Fixed bugs in punch state handling (Theo Engel) @@ -50,21 +52,37 @@ 07-Sep-01 RMS Moved function prototypes The ASR-33/35 reader/punch logic, and the ASCII file support for all paper tape - devices, logic is taken, with grateful thanks, from Adrian Wise's H316 emulator. + devices, is taken, with grateful thanks, from Adrian Wise's H316 emulator. + + Teletype transitions: + + - An OCP '1 starts an output sequence, unconditionally. Ready and Busy are both + set, and a dummy output sequence is started. + - If OTA "overtakes" the dummy output sequence, the dummy sequence is stopped, + and normal output takes place. + - If OTA is not issued before the dummy sequence completes, Busy is cleared. + Because Ready is set, an interrupt is requested. + - An OCP '0 starts an input sequence, unconditionally. Ready and Busy are both + cleared. + - When a character is available (either from the keyboard or the reader), Busy + is set. + - At the end of a delay, Busy is cleared and Ready is set, and an interrupt is + requested. + - At all times, the interrupt flag reflects the equation Ready & ~Busy. Teletype reader transitions: - - SET TTY2 START puts the reader in RUN - - XOFF from keyboard/reader stops the reader after 1-2 more characters are read - - XON from program starts the reader - - Detach, SET TTY2 STOP, or end of file stops the reader + - SET TTY2 START puts the reader in RUN. + - XOFF from keyboard/reader stops the reader after 1-2 more characters are read. + - XON from program starts the reader. + - Detach, SET TTY2 STOP, or end of file stops the reader. Teletype punch transitions: - - SET TTY3 START puts the punch in RUN - - XOFF from program stops the punch after 1 more character is punched - - TAPE from program starts the punch after 1 character delay - - Detach or SET TTY3 STOP stops the punch + - SET TTY3 START puts the punch in RUN. + - XOFF from program stops the punch after 1 more character is punched. + - TAPE from program starts the punch after 1 character delay. + - Detach or SET TTY3 STOP stops the punch. */ #include "h316_defs.h" @@ -99,9 +117,13 @@ int32 ptp_ptime; uint32 ttr_stopioe = 0; uint32 tty_mode = 0; /* input (0), output (1) */ uint32 tty_buf = 0; /* tty buffer */ +uint32 tty_ready = 1; /* tty ready */ +uint32 tty_busy = 0; /* tty busy */ +uint32 tty_2nd = 0; /* tty input second state */ uint32 ttr_xoff_read = 0; uint32 ttp_tape_rcvd = 0; uint32 ttp_xoff_rcvd = 0; +int32 tty_busy_wait = SERIAL_IN_WAIT; /* busy state on input */ int32 clk_tps = 60; /* ticks per second */ int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev); @@ -156,8 +178,12 @@ REG ptr_reg[] = { }; MTAB pt_mod[] = { - { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC, "ASCII", NULL }, - { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC+UNIT_UASC, "Unix ASCII", NULL }, + { 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", + &ttrp_set_mode }, + { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, "Unix ASCII", "UASCII", + &ttrp_set_mode }, { 0 } }; @@ -228,11 +254,15 @@ UNIT tty_unit[] = { REG tty_reg[] = { { ORDATA (BUF, tty_buf, 8) }, + { ORDATA (IN2ND, tty_2nd, 9) }, { FLDATA (MODE, tty_mode, 0) }, - { FLDATA (READY, dev_int, INT_V_TTY) }, + { FLDATA (READY, tty_ready, 0) }, + { FLDATA (BUSY, tty_busy, 0) }, + { FLDATA (INT, dev_int, INT_V_TTY) }, { FLDATA (ENABLE, dev_enb, INT_V_TTY) }, { DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT }, { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, + { DRDATA (KBTIME, tty_busy_wait, 24), REG_NZ + PV_LEFT }, { DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT }, { DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, { ORDATA (RXOFF, ttr_xoff_read, 2), REG_HIDDEN }, @@ -315,16 +345,16 @@ int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev) switch (inst) { /* case on opcode */ case ioOCP: /* OCP */ - if (fnc & 016) /* only fnc 0,1 */ + if ((fnc & 016) != 0) /* only fnc 0,1 */ return IOBADFNC (dat); ptr_motion = fnc ^ 1; - if (fnc) /* fnc 1? stop */ + if (fnc != 0) /* fnc 1? stop */ sim_cancel (&ptr_unit); else sim_activate (&ptr_unit, ptr_unit.wait); /* fnc 0? start */ break; case ioSKS: /* SKS */ - if (fnc & 013) /* only fnc 0,4 */ + if ((fnc & 013) != 0) /* only fnc 0,4 */ return IOBADFNC (dat); if (((fnc == 000) && TST_INT (INT_PTR)) || /* fnc 0? skip rdy */ ((fnc == 004) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */ @@ -332,7 +362,7 @@ switch (inst) { /* case on opcode */ break; case ioINA: /* INA */ - if (fnc) /* only fnc 0 */ + if (fnc != 0) /* only fnc 0 */ return IOBADFNC (dat); if (TST_INT (INT_PTR)) { /* ready? */ CLR_INT (INT_PTR); /* clear ready */ @@ -372,7 +402,7 @@ else { if ((uptr->flags & UNIT_UASC) && (c == '\n')) { /* Unix newline? */ c = 0215; /* insert CR */ uptr->STA |= LF_PEND; /* lf pending */ - } + } else if ((uptr->flags & UNIT_ASC) && (c != 0)) /* ASCII? */ c = c | 0200; uptr->pos = ftell (uptr->fileref); /* update pos */ @@ -382,13 +412,14 @@ uptr->buf = c & 0377; /* get byte */ return SCPE_OK; } -/* Paper tape attach routine - set or clear ASC/UASC flags if specified */ +/* Paper tape attach routine - set or clear ASC/UASC flags if specified + Can be called for TTY units at well, hence, check for attachability */ t_stat pt_attach (UNIT *uptr, char *cptr) { t_stat r; -if (!(uptr->flags & UNIT_ATTABLE)) +if (!(uptr->flags & UNIT_ATTABLE)) /* not tti,tto */ return SCPE_NOFNC; if (r = attach_unit (uptr, cptr)) return r; @@ -406,7 +437,10 @@ return r; t_stat pt_detach (UNIT *uptr) { -if (!(sim_switches & SIM_SW_REST)) sim_cancel (uptr); /* stop motion */ +if (!(uptr->flags & UNIT_ATTABLE)) /* not tti,tto */ + return SCPE_NOFNC; +if (!(sim_switches & SIM_SW_REST)) /* stop motion */ + sim_cancel (uptr); uptr->STA = 0; return detach_unit (uptr); } @@ -464,9 +498,9 @@ int32 ptpio (int32 inst, int32 fnc, int32 dat, int32 dev) switch (inst) { /* case on opcode */ case ioOCP: /* OCP */ - if (fnc & 016) /* only fnc 0,1 */ + if ((fnc & 016) != 0) /* only fnc 0,1 */ return IOBADFNC (dat); - if (fnc) { /* fnc 1? pwr off */ + if (fnc != 0) { /* fnc 1? pwr off */ CLR_INT (INT_PTP); /* not ready */ ptp_power = 0; /* turn off power */ sim_cancel (&ptp_unit); /* stop punch */ @@ -476,7 +510,7 @@ switch (inst) { /* case on opcode */ break; case ioSKS: /* SKS */ - if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */ + if (((fnc & 012) !=0) || (fnc == 005)) /* only 0, 1, 4 */ return IOBADFNC (dat); if (((fnc == 000) && TST_INT (INT_PTP)) || /* fnc 0? skip rdy */ ((fnc == 001) && /* fnc 1? skip ptp on */ @@ -486,7 +520,7 @@ switch (inst) { /* case on opcode */ break; case ioOTA: /* OTA */ - if (fnc) /* only fnc 0 */ + if (fnc != 0) /* only fnc 0 */ return IOBADFNC (dat); if (TST_INT (INT_PTP)) { /* if ptp ready */ CLR_INT (INT_PTP); /* clear ready */ @@ -550,25 +584,29 @@ int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev) switch (inst) { /* case on opcode */ case ioOCP: /* OCP */ - if (fnc & 016) /* only fnc 0,1 */ + if ((fnc & 016) != 0) /* only fnc 0,1 */ return IOBADFNC (dat); - if (fnc && (tty_mode == 0)) { /* input to output? */ - if (!sim_is_active (&tty_unit[TTO])) /* set ready */ - SET_INT (INT_TTY); + if (fnc != 0) { /* output */ + tty_ready = 1; /* set rdy, busy */ + tty_busy = 1; /* start dummy out */ tty_mode = 1; /* mode is output */ + sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); } - else if ((fnc == 0) && tty_mode) { /* output to input? */ - CLR_INT (INT_TTY); /* clear ready */ + else { /* input? */ + tty_ready = 0; /* clr rdy, busy */ + tty_busy = 0; tty_mode = 0; /* mode is input */ + tty_2nd = 0; +/* sim_cancel (&tty_unit[TTO]); /* cancel output */ } + CLR_INT (INT_TTY); /* clear intr */ break; case ioSKS: /* SKS */ - if (fnc & 012) /* fnc 0,1,4,5 */ + if ((fnc & 012) != 0) /* fnc 0,1,4,5 */ return IOBADFNC (dat); - if (((fnc == 000) && TST_INT (INT_TTY)) || /* fnc 0? skip rdy */ - ((fnc == 001) && /* fnc 1? skip !busy */ - (!tty_mode || !sim_is_active (&tty_unit[TTO]))) || + if (((fnc == 000) && tty_ready) || /* fnc 0? skip rdy */ + ((fnc == 001) && !tty_busy) || /* fnc 1? skip !busy */ ((fnc == 004) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */ ((fnc == 005) && (tty_mode || /* fnc 5? skip !xoff */ ((tty_buf & 0177) != XOFF)))) /* input & XOFF char */ @@ -576,30 +614,30 @@ switch (inst) { /* case on opcode */ break; case ioINA: /* INA */ - if (fnc & 005) /* only 0,2 */ + if ((fnc & 005) != 0) /* only 0,2 */ return IOBADFNC (dat); - if (TST_INT (INT_TTY)) { /* ready? */ - if (tty_mode == 0) /* inp? clear rdy */ - CLR_INT (INT_TTY); + if (tty_ready) { /* ready? */ + tty_ready = 0; /* clear rdy */ + CLR_INT (INT_TTY); /* no interrupt */ return IOSKIP (dat | (tty_buf & ((fnc & 002)? 077: 0377))); } break; case ioOTA: - if (fnc & 015) /* only 0,2 */ + if ((fnc & 015) != 0) /* only 0,2 */ return IOBADFNC (dat); - if (TST_INT (INT_TTY)) { /* ready? */ + if (tty_ready) { /* ready? */ tty_buf = dat & 0377; /* store char */ if (fnc & 002) { /* binary mode? */ tty_buf = tty_buf | 0100; /* set ch 7 */ if (tty_buf & 040) tty_buf = tty_buf & 0277; } - if (tty_mode) { - sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); - CLR_INT (INT_TTY); - } + tty_ready = 0; /* clear ready */ + tty_busy = 1; /* set busy */ + CLR_INT (INT_TTY); /* clr int */ + sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); return IOSKIP (dat); } break; @@ -616,6 +654,14 @@ int32 out, c; UNIT *ruptr = &tty_unit[TTR]; sim_activate (uptr, uptr->wait); /* continue poll */ +if (tty_2nd) { /* char pending? */ + tty_buf = tty_2nd & 0377; + tty_2nd = 0; + tty_busy = 0; /* clr busy */ + tty_ready = 1; /* set ready */ + SET_INT (INT_TTY); /* set int */ + return SCPE_OK; + } if ((c = sim_poll_kbd ()) >= SCPE_KFLAG) { /* character? */ out = c & 0177; /* mask echo to 7b */ if (c & SCPE_BREAK) /* break? */ @@ -663,12 +709,15 @@ else if ((ruptr->flags & UNIT_ATT) && /* TTR attached */ out = c; /* echo char */ } else return SCPE_OK; /* no char */ -if (tty_mode == 0) { /* input mode? */ - tty_buf = c & 0377; /* put char in buf */ - SET_INT (INT_TTY); /* set flag */ - } tto_write (out); /* echo to printer */ -return ttp_write (out); /* and punch */ +ttp_write (out); /* and punch */ +if (tty_mode == 0) { /* input mode? */ + tty_2nd = (c & 0377) | 0400; /* flag 2nd state */ + tty_busy = 1; /* set busy */ + CLR_INT (INT_TTY); /* clear interrupt */ + sim_activate_abs (uptr, tty_busy_wait); /* sched busy period */ + } +return SCPE_OK; } /* Output service - printer and punch */ @@ -680,6 +729,11 @@ UNIT *ruptr = &tty_unit[TTR]; UNIT *puptr = &tty_unit[TTP]; t_stat r; +if ((tty_ready != 0) && (tty_busy != 0)) { /* dummy cycle? */ + tty_busy = 0; /* clr busy */ + SET_INT (INT_TTY); /* set intr */ + return SCPE_OK; + } c7b = tty_buf & 0177; if (ttp_tape_rcvd != 0) { /* prev = tape? */ ttp_tape_rcvd--; /* decrement state */ @@ -705,7 +759,9 @@ if ((r = tto_write (tty_buf)) != SCPE_OK) { /* print; error? */ } if ((r = ttp_write (tty_buf)) != SCPE_OK) /* punch; error? */ return r; -SET_INT (INT_TTY); /* set done flag */ +tty_busy = 0; /* clr busy, set rdy */ +tty_ready = 1; +SET_INT (INT_TTY); /* set intr */ return SCPE_OK; } @@ -757,6 +813,9 @@ CLR_INT (INT_TTY); /* clear ready, enb */ CLR_ENB (INT_TTY); tty_mode = 0; /* mode = input */ tty_buf = 0; +tty_2nd = 0; +tty_ready = 1; +tty_busy = 0; ttr_xoff_read = 0; /* clr TTR, TTP flags */ ttp_tape_rcvd = 0; ttp_xoff_rcvd = 0; @@ -784,7 +843,7 @@ return SCPE_OK; t_stat ttrp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { -if (!(uptr->flags & UNIT_ATTABLE)) /* TTR, TTP only */ +if (!(uptr->flags & UNIT_ATTABLE)) /* PTR, PTP, TTR, TTP only */ return SCPE_NOFNC; if (!(val & UNIT_UASC)) uptr->STA &= ~LF_PEND; @@ -799,10 +858,10 @@ if (!(uptr->flags & UNIT_ATTABLE)) /* TTR, TTP only */ return SCPE_NOFNC; if (!(uptr->flags & UNIT_ATT)) /* must be attached */ return SCPE_UNATT; -if (val) /* start? set running */ +if (val != 0) /* start? set running */ uptr->STA |= RUNNING; else uptr->STA &= ~RUNNING; /* stop? clr running */ -if (uptr->flags & UNIT_ROABLE) /* TTR? cancel stop */ +if ((uptr->flags & UNIT_ROABLE) != 0) /* TTR? cancel stop */ ttr_xoff_read = 0; else ttp_tape_rcvd = ttp_xoff_rcvd = 0; /* TTP? cancel all */ return SCPE_OK; @@ -815,10 +874,10 @@ int32 clkio (int32 inst, int32 fnc, int32 dat, int32 dev) switch (inst) { /* case on opcode */ case ioOCP: /* OCP */ - if (fnc & 015) /* only fnc 0,2 */ + if ((fnc & 015) != 0) /* only fnc 0,2 */ return IOBADFNC (dat); CLR_INT (INT_CLK); /* reset ready */ - if (fnc) /* fnc = 2? stop */ + if (fnc != 0) /* fnc = 2? stop */ sim_cancel (&clk_unit); else { /* fnc = 0? */ if (!sim_is_active (&clk_unit)) @@ -831,7 +890,7 @@ switch (inst) { /* case on opcode */ if (fnc == 000) { /* clock skip !int */ if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); - } + } else if ((fnc & 007) == 002) { /* mem parity? */ if (((fnc == 002) && !TST_INT (INT_MPE)) || ((fnc == 012) && TST_INT (INT_MPE))) diff --git a/H316/h316_stddev_old.c b/H316/h316_stddev_old.c new file mode 100644 index 00000000..c358841e --- /dev/null +++ b/H316/h316_stddev_old.c @@ -0,0 +1,906 @@ +/* h316_stddev.c: Honeywell 316/516 standard devices + + Copyright (c) 1999-2008, Robert M. Supnik + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + 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. + + ptr 316/516-50 paper tape reader + ptp 316/516-52 paper tape punch + tty 316/516-33 teleprinter + clk/options 316/516-12 real time clocks/internal options + + 09-Jun-07 RMS Fixed bug in clock increment (Theo Engel) + 30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode + 03-Apr-06 RMS Fixed bugs in punch state handling (Theo Engel) + 22-Nov-05 RMS Revised for new terminal processing routines + 05-Feb-05 RMS Fixed bug in OCP '0001 (Philipp Hachtmann) + 31-Jan-05 RMS Fixed bug in TTY print (Philipp Hachtmann) + 01-Dec-04 RMS Fixed problem in SKS '104 (Philipp Hachtmann) + Fixed bug in SKS '504 + Added PTR detach routine, stops motion + Added PTR/PTP ASCII file support + Added TTR/TTP support + 24-Oct-03 RMS Added DMA/DMC support + 25-Apr-03 RMS Revised for extended file support + 01-Mar-03 RMS Added SET/SHOW CLK FREQ support + 22-Dec-02 RMS Added break support + 01-Nov-02 RMS Added 7b/8b support to terminal + 30-May-02 RMS Widened POS to 32b + 03-Nov-01 RMS Implemented upper case for console output + 29-Nov-01 RMS Added read only unit support + 07-Sep-01 RMS Moved function prototypes + + The ASR-33/35 reader/punch logic, and the ASCII file support for all paper tape + devices, logic is taken, with grateful thanks, from Adrian Wise's H316 emulator. + + Teletype reader transitions: + + - SET TTY2 START puts the reader in RUN + - XOFF from keyboard/reader stops the reader after 1-2 more characters are read + - XON from program starts the reader + - Detach, SET TTY2 STOP, or end of file stops the reader + + Teletype punch transitions: + + - SET TTY3 START puts the punch in RUN + - XOFF from program stops the punch after 1 more character is punched + - TAPE from program starts the punch after 1 character delay + - Detach or SET TTY3 STOP stops the punch +*/ + +#include "h316_defs.h" +#include + +#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 */ +#define LF_PEND 01 /* lf pending */ +#define RUNNING 02 /* tape running */ + +#define XON 0021 +#define TAPE 0022 +#define XOFF 0023 +#define RUBOUT 0377 + +extern uint16 M[]; +extern int32 PC; +extern int32 stop_inst; +extern int32 C, dp, ext, extoff_pending, sc; +extern int32 dev_int, dev_enb; +extern int32 sim_switches; +extern UNIT cpu_unit; + +uint32 ptr_motion = 0; /* read motion */ +uint32 ptr_stopioe = 0; /* stop on error */ +uint32 ptp_stopioe = 0; +uint32 ptp_power = 0; /* punch power, time */ +int32 ptp_ptime; +uint32 ttr_stopioe = 0; +uint32 tty_mode = 0; /* input (0), output (1) */ +uint32 tty_buf = 0; /* tty buffer */ +uint32 ttr_xoff_read = 0; +uint32 ttp_tape_rcvd = 0; +uint32 ttp_xoff_rcvd = 0; +int32 clk_tps = 60; /* ticks per second */ + +int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev); +t_stat ptr_svc (UNIT *uptr); +t_stat ptr_reset (DEVICE *dptr); +t_stat ptr_boot (int32 unitno, DEVICE *dptr); +int32 ptpio (int32 inst, int32 fnc, int32 dat, int32 dev); +t_stat ptp_svc (UNIT *uptr); +t_stat ptp_reset (DEVICE *dptr); +int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev); +t_stat tti_svc (UNIT *uptr); +t_stat tto_svc (UNIT *uptr); +t_stat tty_reset (DEVICE *dptr); +t_stat ttio_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat ttrp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat ttrp_set_start_stop (UNIT *uptr, int32 val, char *cptr, void *desc); +int32 clkio (int32 inst, int32 fnc, int32 dat, int32 dev); +t_stat clk_svc (UNIT *uptr); +t_stat clk_reset (DEVICE *dptr); +t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat pt_attach (UNIT *uptr, char *cptr); +t_stat pt_detach (UNIT *uptr); +t_stat tto_write (int32 c); +t_stat ttp_write (int32 c); + +/* PTR data structures + + ptr_dev PTR device descriptor + ptr_unit PTR unit descriptor + ptr_mod PTR modifiers + ptr_reg PTR register list +*/ + +DIB ptr_dib = { PTR, IOBUS, 1, &ptrio }; + +UNIT ptr_unit = { + UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), + SERIAL_IN_WAIT + }; + +REG ptr_reg[] = { + { ORDATA (BUF, ptr_unit.buf, 8) }, + { FLDATA (READY, dev_int, INT_V_PTR) }, + { FLDATA (ENABLE, dev_enb, INT_V_PTR) }, + { FLDATA (MOTION, ptr_motion, 0) }, + { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, + { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, + { ORDATA (RSTATE, ptr_unit.STA, 2), REG_HIDDEN }, + { FLDATA (STOP_IOE, ptr_stopioe, 0) }, + { NULL } + }; + +MTAB pt_mod[] = { + { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC, "ASCII", NULL }, + { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC+UNIT_UASC, "Unix ASCII", NULL }, + { 0 } + }; + +DEVICE ptr_dev = { + "PTR", &ptr_unit, ptr_reg, pt_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptr_reset, + &ptr_boot, &pt_attach, &pt_detach, + &ptr_dib, 0 + }; + +/* PTP data structures + + ptp_dev PTP device descriptor + ptp_unit PTP unit descriptor + ptp_mod PTP modifiers + ptp_reg PTP register list +*/ + +DIB ptp_dib = { PTP, IOBUS, 1, &ptpio }; + +UNIT ptp_unit = { + UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT + }; + +REG ptp_reg[] = { + { ORDATA (BUF, ptp_unit.buf, 8) }, + { FLDATA (READY, dev_int, INT_V_PTP) }, + { FLDATA (ENABLE, dev_enb, INT_V_PTP) }, + { FLDATA (POWER, ptp_power, 0) }, + { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, + { ORDATA (PSTATE, ptp_unit.STA, 2), REG_HIDDEN }, + { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, + { DRDATA (PWRTIME, ptp_ptime, 24), PV_LEFT }, + { FLDATA (STOP_IOE, ptp_stopioe, 0) }, + { NULL } + }; + +DEVICE ptp_dev = { + "PTP", &ptp_unit, ptp_reg, pt_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &ptp_reset, + NULL, &pt_attach, NULL, + &ptp_dib, 0 + }; + +/* TTY data structures + + tty_dev TTY device descriptor + tty_unit TTY unit descriptor + tty_reg TTY register list + tty_mod TTy modifiers list +*/ + +#define TTI 0 +#define TTO 1 +#define TTR 2 +#define TTP 3 + +DIB tty_dib = { TTY, IOBUS, 1, &ttyio }; + +UNIT tty_unit[] = { + { 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) } + }; + +REG tty_reg[] = { + { ORDATA (BUF, tty_buf, 8) }, + { FLDATA (MODE, tty_mode, 0) }, + { FLDATA (READY, dev_int, INT_V_TTY) }, + { FLDATA (ENABLE, dev_enb, INT_V_TTY) }, + { DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT }, + { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, + { DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT }, + { DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, + { ORDATA (RXOFF, ttr_xoff_read, 2), REG_HIDDEN }, + { ORDATA (RSTATE, tty_unit[TTR].STA, 2), REG_HIDDEN }, + { DRDATA (RPOS, tty_unit[TTR].pos, T_ADDR_W), PV_LEFT }, + { ORDATA (PTAPE, ttp_tape_rcvd, 2), REG_HIDDEN }, + { ORDATA (PXOFF, ttp_xoff_rcvd, 2), REG_HIDDEN }, + { ORDATA (PSTATE, tty_unit[TTP].STA, 2), REG_HIDDEN }, + { DRDATA (PPOS, tty_unit[TTP].pos, T_ADDR_W), PV_LEFT }, + { FLDATA (STOP_IOE, ttr_stopioe, 0) }, + { NULL } + }; + +MTAB tty_mod[] = { + { 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", + &ttrp_set_mode }, + { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, "Unix ASCII", "UASCII", + &ttrp_set_mode }, + { MTAB_XTD|MTAB_VUN|MTAB_NMO, 1, NULL, "START", &ttrp_set_start_stop }, + { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, NULL, "STOP", &ttrp_set_start_stop }, + { 0 } + }; + +DEVICE tty_dev = { + "TTY", tty_unit, tty_reg, tty_mod, + 4, 10, 31, 1, 8, 8, + NULL, NULL, &tty_reset, + NULL, &pt_attach, &pt_detach, + &tty_dib, 0 + }; + +/* CLK data structures + + clk_dev CLK device descriptor + clk_unit CLK unit descriptor + clk_mod CLK modifiers + clk_reg CLK register list +*/ + +DIB clk_dib = { CLK_KEYS, IOBUS, 1, &clkio }; + +UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 16000 }; + +REG clk_reg[] = { + { FLDATA (READY, dev_int, INT_V_CLK) }, + { FLDATA (ENABLE, dev_enb, INT_V_CLK) }, + { DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT }, + { DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO }, + { NULL } + }; + +MTAB clk_mod[] = { + { MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ", + &clk_set_freq, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ", + &clk_set_freq, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL, + NULL, &clk_show_freq, NULL }, + { 0 } + }; + +DEVICE clk_dev = { + "CLK", &clk_unit, clk_reg, clk_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &clk_reset, + NULL, NULL, NULL, + &clk_dib, 0 + }; + +/* Paper tape reader: IO routine */ + +int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev) +{ +switch (inst) { /* case on opcode */ + + case ioOCP: /* OCP */ + if (fnc & 016) /* only fnc 0,1 */ + return IOBADFNC (dat); + ptr_motion = fnc ^ 1; + if (fnc) /* fnc 1? stop */ + sim_cancel (&ptr_unit); + else sim_activate (&ptr_unit, ptr_unit.wait); /* fnc 0? start */ + break; + + case ioSKS: /* SKS */ + if (fnc & 013) /* only fnc 0,4 */ + return IOBADFNC (dat); + if (((fnc == 000) && TST_INT (INT_PTR)) || /* fnc 0? skip rdy */ + ((fnc == 004) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */ + return IOSKIP (dat); + break; + + case ioINA: /* INA */ + if (fnc) /* only fnc 0 */ + return IOBADFNC (dat); + if (TST_INT (INT_PTR)) { /* ready? */ + CLR_INT (INT_PTR); /* clear ready */ + if (ptr_motion) /* if motion, restart */ + sim_activate (&ptr_unit, ptr_unit.wait); + return IOSKIP (ptr_unit.buf | dat); /* ret buf, skip */ + } + break; + } /* end case op */ + +return dat; +} + +/* Unit service */ + +t_stat ptr_svc (UNIT *uptr) +{ +int32 c; + +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (ptr_stopioe, SCPE_UNATT); +if (uptr->STA & LF_PEND) { /* lf pending? */ + uptr->STA &= ~LF_PEND; /* clear flag */ + c = 0212; /* insert LF */ + } +else { + if ((c = getc (uptr->fileref)) == EOF) { /* read byte */ + if (feof (uptr->fileref)) { + if (ptr_stopioe) + printf ("PTR end of file\n"); + else return SCPE_OK; + } + else perror ("PTR I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } + if ((uptr->flags & UNIT_UASC) && (c == '\n')) { /* Unix newline? */ + c = 0215; /* insert CR */ + uptr->STA |= LF_PEND; /* lf pending */ + } + else if ((uptr->flags & UNIT_ASC) && (c != 0)) /* ASCII? */ + c = c | 0200; + uptr->pos = ftell (uptr->fileref); /* update pos */ + } +SET_INT (INT_PTR); /* set ready flag */ +uptr->buf = c & 0377; /* get byte */ +return SCPE_OK; +} + +/* Paper tape attach routine - set or clear ASC/UASC flags if specified */ + +t_stat pt_attach (UNIT *uptr, char *cptr) +{ +t_stat r; + +if (!(uptr->flags & UNIT_ATTABLE)) + return SCPE_NOFNC; +if (r = attach_unit (uptr, cptr)) + return r; +if (sim_switches & SWMASK ('A')) /* -a? ASCII */ + uptr->flags |= UNIT_ASC; +else if (sim_switches & SWMASK ('U')) /* -u? Unix ASCII */ + uptr->flags |= (UNIT_ASC|UNIT_UASC); +else if (sim_switches & SWMASK ('B')) /* -b? binary */ + uptr->flags &= ~(UNIT_ASC|UNIT_UASC); +uptr->STA = 0; +return r; +} + +/* Detach routine - stop motion if not restore */ + +t_stat pt_detach (UNIT *uptr) +{ +if (!(sim_switches & SIM_SW_REST)) sim_cancel (uptr); /* stop motion */ +uptr->STA = 0; +return detach_unit (uptr); +} + +/* Reset routine */ + +t_stat ptr_reset (DEVICE *dptr) +{ +CLR_INT (INT_PTR); /* clear ready, enb */ +CLR_ENB (INT_PTR); +ptr_unit.buf = 0; /* clear buffer */ +ptr_unit.STA = 0; +ptr_motion = 0; /* unit stopped */ +sim_cancel (&ptr_unit); /* deactivate unit */ +return SCPE_OK; +} + +/* Paper tape reader bootstrap routine */ + +#define PBOOT_START 1 +#define PBOOT_SIZE (sizeof (pboot) / sizeof (int32)) + +static const int32 pboot[] = { + 0010057, /* STA 57 */ + 0030001, /* OCP 1 */ + 0131001, /* READ, INA 1001 */ + 0002003, /* JMP READ */ + 0101040, /* SNZ */ + 0002003, /* JMP READ */ + 0010000, /* STA 0 */ + 0131001, /* READ1, INA 1001 */ + 0002010, /* JMP READ1 */ + 0041470, /* LGL 8 */ + 0130001, /* READ2, INA 1 */ + 0002013, /* JMP READ2 */ + 0110000, /* STA* 0 */ + 0024000, /* IRS 0 */ + 0100040 /* SZE */ + }; + +t_stat ptr_boot (int32 unitno, DEVICE *dptr) +{ +int32 i; + +for (i = 0; i < PBOOT_SIZE; i++) /* copy bootstrap */ + M[PBOOT_START + i] = pboot[i]; +PC = PBOOT_START; +return SCPE_OK; +} + +/* Paper tape punch: IO routine */ + +int32 ptpio (int32 inst, int32 fnc, int32 dat, int32 dev) +{ +switch (inst) { /* case on opcode */ + + case ioOCP: /* OCP */ + if (fnc & 016) /* only fnc 0,1 */ + return IOBADFNC (dat); + if (fnc) { /* fnc 1? pwr off */ + CLR_INT (INT_PTP); /* not ready */ + ptp_power = 0; /* turn off power */ + sim_cancel (&ptp_unit); /* stop punch */ + } + else if (ptp_power == 0) /* fnc 0? start */ + sim_activate (&ptp_unit, ptp_ptime); + break; + + case ioSKS: /* SKS */ + if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */ + return IOBADFNC (dat); + if (((fnc == 000) && TST_INT (INT_PTP)) || /* fnc 0? skip rdy */ + ((fnc == 001) && /* fnc 1? skip ptp on */ + (ptp_power || sim_is_active (&ptp_unit))) || + ((fnc == 004) && !TST_INTREQ (INT_PTP))) /* fnc 4? skip !int */ + return IOSKIP (dat); + break; + + case ioOTA: /* OTA */ + if (fnc) /* only fnc 0 */ + return IOBADFNC (dat); + if (TST_INT (INT_PTP)) { /* if ptp ready */ + CLR_INT (INT_PTP); /* clear ready */ + ptp_unit.buf = dat & 0377; /* store byte */ + sim_activate (&ptp_unit, ptp_unit.wait); + return IOSKIP (dat); /* skip return */ + } + break; + } + +return dat; +} + +/* Unit service */ + +t_stat ptp_svc (UNIT *uptr) +{ +int32 c; + +SET_INT (INT_PTP); /* set flag */ +if (ptp_power == 0) { /* power on? */ + ptp_power = 1; /* ptp is ready */ + return SCPE_OK; + } +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return IORETURN (ptp_stopioe, SCPE_UNATT); +if (uptr->flags & UNIT_ASC) { /* ASCII? */ + c = uptr->buf & 0177; /* mask to 7b */ + if ((uptr->flags & UNIT_UASC) && (c == 015)) /* cr? drop if Unix */ + return SCPE_OK; + else if (c == 012) /* lf? cvt to nl */ + c = '\n'; + } +else c = uptr->buf & 0377; /* no, binary */ +if (putc (c, uptr->fileref) == EOF) { /* output byte */ + perror ("PTP I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; + } +uptr->pos = ftell (uptr->fileref); /* update pos */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat ptp_reset (DEVICE *dptr) +{ +CLR_INT (INT_PTP); /* clear ready, enb */ +CLR_ENB (INT_PTP); +ptp_power = 0; /* power off */ +ptp_unit.buf = 0; /* clear buffer */ +ptp_unit.STA = 0; +sim_cancel (&ptp_unit); /* deactivate unit */ +return SCPE_OK; +} + +/* Terminal: IO routine */ + +int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev) +{ +switch (inst) { /* case on opcode */ + + case ioOCP: /* OCP */ + if (fnc & 016) /* only fnc 0,1 */ + return IOBADFNC (dat); + if (fnc && (tty_mode == 0)) { /* input to output? */ + if (!sim_is_active (&tty_unit[TTO])) /* set ready */ + SET_INT (INT_TTY); + tty_mode = 1; /* mode is output */ + } + else if ((fnc == 0) && tty_mode) { /* output to input? */ + CLR_INT (INT_TTY); /* clear ready */ + tty_mode = 0; /* mode is input */ + } + break; + + case ioSKS: /* SKS */ + if (fnc & 012) /* fnc 0,1,4,5 */ + return IOBADFNC (dat); + if (((fnc == 000) && TST_INT (INT_TTY)) || /* fnc 0? skip rdy */ + ((fnc == 001) && /* fnc 1? skip !busy */ + (!tty_mode || !sim_is_active (&tty_unit[TTO]))) || + ((fnc == 004) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */ + ((fnc == 005) && (tty_mode || /* fnc 5? skip !xoff */ + ((tty_buf & 0177) != XOFF)))) /* input & XOFF char */ + return IOSKIP (dat); + break; + + case ioINA: /* INA */ + if (fnc & 005) /* only 0,2 */ + return IOBADFNC (dat); + if (TST_INT (INT_TTY)) { /* ready? */ + if (tty_mode == 0) /* inp? clear rdy */ + CLR_INT (INT_TTY); + return IOSKIP (dat | + (tty_buf & ((fnc & 002)? 077: 0377))); + } + break; + + case ioOTA: + if (fnc & 015) /* only 0,2 */ + return IOBADFNC (dat); + if (TST_INT (INT_TTY)) { /* ready? */ + tty_buf = dat & 0377; /* store char */ + if (fnc & 002) { /* binary mode? */ + tty_buf = tty_buf | 0100; /* set ch 7 */ + if (tty_buf & 040) + tty_buf = tty_buf & 0277; + } + if (tty_mode) { + sim_activate (&tty_unit[TTO], tty_unit[TTO].wait); + CLR_INT (INT_TTY); + } + return IOSKIP (dat); + } + break; + } /* end case op */ + +return dat; +} + +/* Input service - keyboard and reader */ + +t_stat tti_svc (UNIT *uptr) +{ +int32 out, c; +UNIT *ruptr = &tty_unit[TTR]; + +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) /* break? */ + c = 0; + else c = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR); + uptr->pos = uptr->pos + 1; + } +else if (c != SCPE_OK) /* error? */ + return c; +else if ((ruptr->flags & UNIT_ATT) && /* TTR attached */ + (ruptr->STA & RUNNING)) { /* and running? */ + if (ruptr->STA & LF_PEND) { /* lf pending? */ + c = 0212; /* char is lf */ + ruptr->STA &= ~LF_PEND; /* clear flag */ + } + else { /* normal read */ + if ((c = getc (ruptr->fileref)) == EOF) { /* read byte */ + if (feof (ruptr->fileref)) { /* EOF? */ + ruptr->STA &= ~RUNNING; /* stop reader */ + if (ttr_stopioe) + printf ("TTR end of file\n"); + else return SCPE_OK; + } + else perror ("TTR I/O error"); + clearerr (ruptr->fileref); + return SCPE_IOERR; + } + if ((ruptr->flags & UNIT_UASC) && (c == '\n')) { + c = 0215; /* Unix ASCII NL? */ + ruptr->STA |= LF_PEND; /* LF pending */ + } + else if ((ruptr->flags & UNIT_ASC) && (c != 0)) + c = c | 0200; /* ASCII nz? cvt */ + ruptr->pos = ftell (ruptr->fileref); + } + if (ttr_xoff_read != 0) { /* reader stopping? */ + if (c == RUBOUT) /* rubout? stop */ + ttr_xoff_read = 0; + else ttr_xoff_read--; /* else decr state */ + if (ttr_xoff_read == 0) /* delay done? */ + ruptr->STA &= ~RUNNING; /* stop reader */ + } + else if ((c & 0177) == XOFF) /* XOFF read? */ + ttr_xoff_read = 2; + out = c; /* echo char */ + } +else return SCPE_OK; /* no char */ +if (tty_mode == 0) { /* input mode? */ + tty_buf = c & 0377; /* put char in buf */ + SET_INT (INT_TTY); /* set flag */ + } +tto_write (out); /* echo to printer */ +return ttp_write (out); /* and punch */ +} + +/* Output service - printer and punch */ + +t_stat tto_svc (UNIT *uptr) +{ +uint32 c7b; +UNIT *ruptr = &tty_unit[TTR]; +UNIT *puptr = &tty_unit[TTP]; +t_stat r; + +c7b = tty_buf & 0177; +if (ttp_tape_rcvd != 0) { /* prev = tape? */ + ttp_tape_rcvd--; /* decrement state */ + if ((ttp_tape_rcvd == 0) && (puptr->flags & UNIT_ATT)) + puptr->STA |= RUNNING; /* start after delay */ + } +else if (c7b == TAPE) /* char = TAPE? */ + ttp_tape_rcvd = 2; +if (ttp_xoff_rcvd != 0) { /* prev = XOFF? */ + ttp_xoff_rcvd--; /* decrement state */ + if (ttp_xoff_rcvd == 0) /* stop after delay */ + puptr->STA &= ~RUNNING; + } +else if (c7b == XOFF) /* char = XOFF? */ + ttp_xoff_rcvd = 2; +if ((c7b == XON) && (ruptr->flags & UNIT_ATT)) { /* char = XON? */ + ruptr->STA |= RUNNING; /* start reader */ + ttr_xoff_read = 0; /* cancel stop */ + } +if ((r = tto_write (tty_buf)) != SCPE_OK) { /* print; error? */ + sim_activate (uptr, uptr->wait); /* try again */ + return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */ + } +if ((r = ttp_write (tty_buf)) != SCPE_OK) /* punch; error? */ + return r; +SET_INT (INT_TTY); /* set done flag */ +return SCPE_OK; +} + +/* Output to printer */ + +t_stat tto_write (int32 c) +{ +UNIT *tuptr = &tty_unit[TTO]; + +c = sim_tt_outcvt (c, TT_GET_MODE (tuptr->flags) | TTUF_KSR); +tuptr->pos = tuptr->pos + 1; +if (c >= 0) + return sim_putchar_s (c); +else return SCPE_OK; +} + +/* Output to punch */ + +t_stat ttp_write (int32 c) +{ +uint32 p, c7b; +UNIT *puptr = &tty_unit[TTP]; + +if ((puptr->flags & UNIT_ATT) && /* TTP attached */ + (puptr->STA & RUNNING)) { /* and running? */ + c7b = c & 0177; + if (!(puptr->flags & UNIT_UASC) || (c7b != 015)) { + if (puptr->flags & UNIT_ASC) { /* ASCII? */ + if (c7b == 012) p = '\n'; /* cvt LF */ + else p = c7b; /* else 7b */ + } + else p = c; /* untouched */ + if (putc (p, puptr->fileref) == EOF) { /* output byte */ + perror ("TTP I/O error"); + clearerr (puptr->fileref); + return SCPE_IOERR; + } + puptr->pos = ftell (puptr->fileref); /* update pos */ + } + } +return SCPE_OK; +} + +/* Reset routine */ + +t_stat tty_reset (DEVICE *dptr) +{ +CLR_INT (INT_TTY); /* clear ready, enb */ +CLR_ENB (INT_TTY); +tty_mode = 0; /* mode = input */ +tty_buf = 0; +ttr_xoff_read = 0; /* clr TTR, TTP flags */ +ttp_tape_rcvd = 0; +ttp_xoff_rcvd = 0; +tty_unit[TTR].STA = 0; +tty_unit[TTP].STA = 0; +sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ +sim_cancel (&tty_unit[TTO]); /* cancel output */ +return SCPE_OK; +} + +/* Set keyboard/printer mode - make sure flags agree */ + +t_stat ttio_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (uptr->flags & UNIT_ATTABLE) /* not TTR, TTP */ + 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; +} + +/* Set reader/punch mode */ + +t_stat ttrp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (!(uptr->flags & UNIT_ATTABLE)) /* TTR, TTP only */ + return SCPE_NOFNC; +if (!(val & UNIT_UASC)) + uptr->STA &= ~LF_PEND; +return SCPE_OK; +} + +/* Set reader/punch start/stop */ + +t_stat ttrp_set_start_stop (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (!(uptr->flags & UNIT_ATTABLE)) /* TTR, TTP only */ + return SCPE_NOFNC; +if (!(uptr->flags & UNIT_ATT)) /* must be attached */ + return SCPE_UNATT; +if (val) /* start? set running */ + uptr->STA |= RUNNING; +else uptr->STA &= ~RUNNING; /* stop? clr running */ +if (uptr->flags & UNIT_ROABLE) /* TTR? cancel stop */ + ttr_xoff_read = 0; +else ttp_tape_rcvd = ttp_xoff_rcvd = 0; /* TTP? cancel all */ +return SCPE_OK; +} + +/* Clock/options: IO routine */ + +int32 clkio (int32 inst, int32 fnc, int32 dat, int32 dev) +{ +switch (inst) { /* case on opcode */ + + case ioOCP: /* OCP */ + if (fnc & 015) /* only fnc 0,2 */ + return IOBADFNC (dat); + CLR_INT (INT_CLK); /* reset ready */ + if (fnc) /* fnc = 2? stop */ + sim_cancel (&clk_unit); + else { /* fnc = 0? */ + if (!sim_is_active (&clk_unit)) + sim_activate (&clk_unit, /* activate */ + sim_rtc_init (clk_unit.wait)); /* init calibr */ + } + break; + + case ioSKS: /* SKS */ + if (fnc == 000) { /* clock skip !int */ + if (!TST_INTREQ (INT_CLK)) + return IOSKIP (dat); + } + else if ((fnc & 007) == 002) { /* mem parity? */ + if (((fnc == 002) && !TST_INT (INT_MPE)) || + ((fnc == 012) && TST_INT (INT_MPE))) + return IOSKIP (dat); + } + else return IOBADFNC (dat); /* invalid fnc */ + break; + + case ioOTA: /* OTA */ + if (fnc == 000) /* SMK */ + dev_enb = dat; + else if (fnc == 010) { /* OTK */ + C = (dat >> 15) & 1; /* set C */ + if (cpu_unit.flags & UNIT_HSA) /* HSA included? */ + dp = (dat >> 14) & 1; /* set dp */ + if (cpu_unit.flags & UNIT_EXT) { /* ext opt? */ + if (dat & 020000) { /* ext set? */ + ext = 1; /* yes, set */ + extoff_pending = 0; + } + else extoff_pending = 1; /* no, clr later */ + } + sc = dat & 037; /* set sc */ + } + else return IOBADFNC (dat); + break; + } + +return dat; +} + +/* Unit service */ + +t_stat clk_svc (UNIT *uptr) +{ + +M[M_CLK] = (M[M_CLK] + 1) & DMASK; /* increment mem ctr */ +if (M[M_CLK] == 0) /* = 0? set flag */ + SET_INT (INT_CLK); +sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */ +return SCPE_OK; +} + +/* Reset routine */ + +t_stat clk_reset (DEVICE *dptr) +{ +CLR_INT (INT_CLK); /* clear ready, enb */ +CLR_ENB (INT_CLK); +sim_cancel (&clk_unit); /* deactivate unit */ +return SCPE_OK; +} + +/* Set frequency */ + +t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (cptr) + return SCPE_ARG; +if ((val != 50) && (val != 60)) + return SCPE_IERR; +clk_tps = val; +return SCPE_OK; +} + +/* Show frequency */ + +t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, (clk_tps == 50)? "50Hz": "60Hz"); +return SCPE_OK; +} diff --git a/H316/h316_sys.c b/H316/h316_sys.c index ca4ff61e..2dabbeff 100644 --- a/H316/h316_sys.c +++ b/H316/h316_sys.c @@ -1,6 +1,6 @@ /* h316_sys.c: Honeywell 316/516 simulator interface - Copyright (c) 1999-2008, Robert M Supnik + Copyright (c) 1999-2013, 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. + 15-Sep-13 RMS Added device name support for IO instructions + Fixed handling of OTK 01-Dec-04 RMS Fixed fprint_opr calling sequence 24-Oct-03 RMS Added DMA/DMC support 17-Sep-01 RMS Removed multiconsole support @@ -132,7 +134,7 @@ static const char *opcode[] = { "CAR", "CAL", "ICL", "AOA", "ACA", "ICR", "ICA", "NOP", "SKP", "SSR", "SSS", - "JMP", "JMP*", + "OTK", "JMP", "JMP*", "LDA", "LDA*", "ANA", "ANA*", "STA", "STA*", "ERA", "ERA*", "ADD", "ADD*", "SUB", "SUB*", @@ -155,6 +157,17 @@ static const char *opcode[] = { NULL, NULL, /* decode only */ NULL }; + +static const char *ioname[DEV_MAX] = { + NULL, "PTR", "PTP", "LPT", "TTY", "CDR", NULL, NULL, + "MT", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "CLK", NULL, "FHD", NULL, "DMA", "DP", NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }; static const int32 opc_val[] = { 0000000+I_NPN, 0000005+I_NPN, 0000007+I_NPN, @@ -167,7 +180,7 @@ static const int32 opc_val[] = { 0141044+I_NPN, 0141050+I_NPN, 0141140+I_NPN, 0141206+I_NPN, 0141216+I_NPN, 0141240+I_NPN, 0141340+I_NPN, 0101000+I_NPN, 0100000+I_NPN, 0100036+I_NPN, 0101036+I_NPN, - 0002000+I_MRF, 0102000+I_MRF, + 0171020+I_NPN, 0002000+I_MRF, 0102000+I_MRF, 0004000+I_MRF, 0104000+I_MRF, 0006000+I_MRF, 0106000+I_MRF, 0010000+I_MRF, 0110000+I_MRF, 0012000+I_MRF, 0112000+I_MRF, 0014000+I_MRF, 0114000+I_MRF, 0016000+I_MRF, 0116000+I_MRF, @@ -234,7 +247,7 @@ return; t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw) { -int32 cflag, i, j, inst, disp; +int32 cflag, i, j, inst, fnc, disp; cflag = (uptr == NULL) || (uptr == &cpu_unit); inst = val[0]; @@ -278,8 +291,11 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ break; case I_V_IOT: /* I/O */ - disp = inst & 01777; /* pulse+dev */ - fprintf (of, "%s %o", opcode[i], disp); + fnc = I_GETFNC (inst); /* get func */ + disp = inst & DEVMASK; /* get dev */ + if (ioname[disp] != NULL) + fprintf (of, "%s %o,%s", opcode[i], fnc, ioname[disp]); + else fprintf (of, "%s %o,%o", opcode[i], fnc, disp); break; case I_V_SHF: /* shift */ @@ -347,11 +363,29 @@ switch (j) { /* case on class */ break; case I_V_IOT: /* IOT */ - cptr = get_glyph (cptr, gbuf, 0); /* get pulse+dev */ - d = get_uint (gbuf, 8, 01777, &r); - if (r != SCPE_OK) - return SCPE_ARG; - val[0] = val[0] | d; + cptr = get_glyph (cptr, gbuf, ','); /* get field */ + if (*cptr == 0) { /* single field? */ + d = get_uint (gbuf, 8, 01777, &r); /* pulse+dev */ + if (r != SCPE_OK) + return SCPE_ARG; + val[0] = val[0] | d; + } + else { /* multiple fields */ + d = get_uint (gbuf, 8, 017, &r); /* get pulse */ + if (r != SCPE_OK) + return SCPE_ARG; + cptr = get_glyph (cptr, gbuf, 0); /* get dev name */ + for (k = 0; k < DEV_MAX; k++) { /* sch for name */ + if ((ioname[k] != NULL) && (strcmp (gbuf, ioname[k]) == 0)) + break; /* match? */ + } + if (k >= DEV_MAX) { /* no match */ + k = get_uint (gbuf, 8, DEV_MAX - 1, &r);/* integer */ + if (r != SCPE_OK) + return SCPE_ARG; + } + val[0] = val[0] | (d << I_V_FNC) | k; + } break; case I_V_SHF: /* shift */ diff --git a/I1401/i1401_cpu.c b/I1401/i1401_cpu.c index 6868556b..99cad93f 100644 --- a/I1401/i1401_cpu.c +++ b/I1401/i1401_cpu.c @@ -1,6 +1,6 @@ /* i1401_cpu.c: IBM 1401 CPU simulator - Copyright (c) 1993-2011, Robert M. Supnik + Copyright (c) 1993-2012, 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,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. + 08-Oct-12 RMS Clear storage and branch preserves B register (Van Snyder) 19-Mar-11 RMS Reverted multiple tape indicator implementation 20-Jan-11 RMS Fixed branch on EOT indicator per hardware (Van Snyder) 07-Nov-10 RMS Fixed divide not to clear word marks in quotient @@ -178,6 +179,14 @@ typedef struct { PCQ_ENTRY; \ IS = AS; +#define BRANCH_CS if (ADDR_ERR (AS)) { \ + reason = STOP_INVBR; \ + break; \ + } \ + PCQ_ENTRY; \ + IS = AS; + + uint8 M[MAXMEMSIZE] = { 0 }; /* main memory */ int32 saved_IS = 0; /* saved IS */ int32 AS = 0; /* AS */ @@ -1568,6 +1577,9 @@ CHECK_LENGTH: 5,6 invalid B-address 7 branch 8+ one operand, branch ignored + + Note that clear storage and branch does not overwrite the B register, + unlike all other branches */ case OP_CS: /* clear storage */ @@ -1577,7 +1589,7 @@ CHECK_LENGTH: if (BS < 0) /* wrap if needed */ BS = BS + MEMSIZE; if (ilnt == 7) { /* branch variant? */ - BRANCH; + BRANCH_CS; /* special branch */ } break; diff --git a/I1401/i1401_lp.c b/I1401/i1401_lp.c index a7906b91..cec020da 100644 --- a/I1401/i1401_lp.c +++ b/I1401/i1401_lp.c @@ -1,6 +1,6 @@ /* i1401_lp.c: IBM 1403 line printer simulator - Copyright (c) 1993-2008, Robert M. Supnik + Copyright (c) 1993-2013, 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 @@ lpt 1403 line printer + 16-Apr-13 RMS Fixed printer chain selection 19-Jan-07 RMS Added UNIT_TEXT flag 07-Mar-05 RMS Fixed bug in write_line (Van Snyder) 25-Apr-03 RMS Revised for extended file support @@ -49,17 +50,17 @@ t_stat lpt_attach (UNIT *uptr, char *cptr); t_stat space (int32 lines, int32 lflag); char *pch_table_old[4] = { - bcd_to_ascii_old, bcd_to_pca, bcd_to_pch, bcd_to_ascii_old + bcd_to_ascii_old, bcd_to_ascii_old, bcd_to_pca, bcd_to_pch }; char *pch_table[4] = { - bcd_to_ascii_a, bcd_to_pca, bcd_to_pch, bcd_to_ascii_h + bcd_to_ascii_a, bcd_to_ascii_h, bcd_to_pca, bcd_to_pch }; #define UNIT_V_FT (UNIT_V_UF + 0) #define UNIT_V_48 (UNIT_V_UF + 1) #define UNIT_FT (1 << UNIT_V_FT) #define UNIT_48 (1 << UNIT_V_48) -#define GET_PCHAIN(x) (((x) >> UNIT_V_FT) & (UNIT_FT|UNIT_48)) +#define GET_PCHAIN(x) (((x) >> UNIT_V_FT) & 03) #define CHP(ch,val) ((val) & (1 << (ch))) /* LPT data structures @@ -119,9 +120,10 @@ if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */ wm = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_SQUARE); sup = ((ilnt == 2) || (ilnt == 5)) && (mod == BCD_S); ind[IN_LPT] = 0; /* clear error */ +t = GET_PCHAIN (lpt_unit.flags); if (conv_old) /* get print chain */ - bcd2asc = pch_table_old[GET_PCHAIN (lpt_unit.flags)]; -else bcd2asc = pch_table[GET_PCHAIN (lpt_unit.flags)]; + bcd2asc = pch_table_old[t]; +else bcd2asc = pch_table[t]; for (i = 0; i < LPT_WIDTH; i++) { /* convert print buf */ t = M[LPT_BUF + i]; if (wm) /* wmarks -> 1 or sp */ diff --git a/I1401/i1401_mt.c b/I1401/i1401_mt.c index fcd2dea1..0ac21bf0 100644 --- a/I1401/i1401_mt.c +++ b/I1401/i1401_mt.c @@ -25,6 +25,7 @@ mt 7-track magtape + 03-Sep-13 RMS Read TMK does not write GM+WM to memory 19-Mar-11 RMS Restored lost edit to insert EOF in memory on read EOF Reverted multiple tape indicator implementation 20-Jan-11 RMS Fixed branch on END indicator per hardware (Van Snyder) @@ -342,6 +343,8 @@ switch (mod) { return STOP_WRAP; } } + if (st == MTSE_TMK) /* if TMK, no GM+WM */ + break; if (M[BS] != (BCD_GRPMRK + WM)) { /* not GM+WM at end? */ if (flag & MD_WM) /* LCA: clear WM */ M[BS] = BCD_GRPMRK; diff --git a/I1401/i1401_mt_38.c b/I1401/i1401_mt_38.c new file mode 100644 index 00000000..65edf46a --- /dev/null +++ b/I1401/i1401_mt_38.c @@ -0,0 +1,408 @@ +/* i1401_mt.c: IBM 1401 magnetic tape simulator + + Copyright (c) 1993-2007, 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. + + mt 7-track magtape + + 07-Jul-07 RMS Removed restriction on load-mode binary tape + 28-Jun-07 RMS Revised read tape mark behavior based on real hardware + (found by Van Snyder) + 16-Feb-06 RMS Added tape capacity checking + 15-Sep-05 RMS Yet another fix to load read group mark plus word mark + Added debug printouts (from Van Snyder) + 26-Aug-05 RMS Revised to use API for write lock check + 16-Aug-03 RMS End-of-record on load read works like move read + (verified on real 1401) + Added diagnostic read (space forward) + 25-Apr-03 RMS Revised for extended file support + 28-Mar-03 RMS Added multiformat support + 15-Mar-03 RMS Fixed end-of-record on load read yet again + 28-Feb-03 RMS Modified for magtape library + 31-Oct-02 RMS Added error record handling + 10-Oct-02 RMS Fixed end-of-record on load read writes WM plus GM + 30-Sep-02 RMS Revamped error handling + 28-Aug-02 RMS Added end of medium support + 12-Jun-02 RMS End-of-record on move read preserves old WM under GM + (found by Van Snyder) + 03-Jun-02 RMS Modified for 1311 support + 30-May-02 RMS Widened POS to 32b + 22-Apr-02 RMS Added protection against bad record lengths + 30-Jan-02 RMS New zero footprint tape bootstrap from Van Snyder + 20-Jan-02 RMS Changed write enabled modifier + 29-Nov-01 RMS Added read only unit support + 18-Apr-01 RMS Changed to rewind tape before boot + 07-Dec-00 RMS Widened display width from 6 to 8 bits to see record lnt + CEO Added tape bootstrap + 14-Apr-99 RMS Changed t_addr to unsigned + 04-Oct-98 RMS V2.4 magtape format + + Magnetic tapes are represented as a series of variable 16b records + of the form: + + 32b byte count + byte 0 + byte 1 + : + byte n-2 + byte n-1 + 32b byte count + + If the byte count is odd, the record is padded with an extra byte + of junk. File marks are represented by a byte count of 0. +*/ + +#include "i1401_defs.h" +#include "sim_tape.h" + +#define MT_NUMDR 7 /* #drives */ +#define MT_MAXFR (MAXMEMSIZE * 2) /* max transfer */ + +uint8 dbuf[MT_MAXFR]; /* tape buffer */ + +extern uint8 M[]; /* memory */ +extern int32 ind[64]; +extern int32 BS, iochk; +extern UNIT cpu_unit; +extern FILE *sim_deb; + +t_stat mt_reset (DEVICE *dptr); +t_stat mt_boot (int32 unitno, DEVICE *dptr); +t_stat mt_map_status (t_stat st); +UNIT *get_unit (int32 unit); + +/* MT data structures + + mt_dev MT device descriptor + mt_unit MT unit list + mt_reg MT register list + mt_mod MT modifier list +*/ + +UNIT mt_unit[] = { + { UDATA (NULL, UNIT_DIS, 0) }, /* doesn't exist */ + { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + + UNIT_ROABLE + UNIT_BCD, 0) }, + { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + + UNIT_ROABLE + UNIT_BCD, 0) }, + { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + + UNIT_ROABLE + UNIT_BCD, 0) }, + { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + + UNIT_ROABLE + UNIT_BCD, 0) }, + { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + + UNIT_ROABLE + UNIT_BCD, 0) }, + { UDATA (NULL, UNIT_DISABLE + UNIT_ATTABLE + + UNIT_ROABLE + UNIT_BCD, 0) } + }; + +REG mt_reg[] = { + { FLDATA (END, ind[IN_END], 0) }, + { FLDATA (ERR, ind[IN_TAP], 0) }, + { DRDATA (POS1, mt_unit[1].pos, T_ADDR_W), PV_LEFT + REG_RO }, + { DRDATA (POS2, mt_unit[2].pos, T_ADDR_W), PV_LEFT + REG_RO }, + { DRDATA (POS3, mt_unit[3].pos, T_ADDR_W), PV_LEFT + REG_RO }, + { DRDATA (POS4, mt_unit[4].pos, T_ADDR_W), PV_LEFT + REG_RO }, + { DRDATA (POS5, mt_unit[5].pos, T_ADDR_W), PV_LEFT + REG_RO }, + { DRDATA (POS6, mt_unit[6].pos, T_ADDR_W), PV_LEFT + REG_RO }, + { NULL } + }; + +MTAB mt_mod[] = { + { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, + { MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", + &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, + { MTAB_XTD|MTAB_VUN, 0, "CAPACITY", "CAPACITY", + &sim_tape_set_capac, &sim_tape_show_capac, NULL }, + { 0 } + }; + +DEVICE mt_dev = { + "MT", mt_unit, mt_reg, mt_mod, + MT_NUMDR, 10, 31, 1, 8, 8, + NULL, NULL, &mt_reset, + &mt_boot, &sim_tape_attach, &sim_tape_detach, + NULL, DEV_DEBUG + }; + +/* Function routine + + Inputs: + unit = unit character + mod = modifier character + Outputs: + status = status +*/ + +t_stat mt_func (int32 unit, int32 mod) +{ +t_mtrlnt tbc; +UNIT *uptr; +t_stat st; + +if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */ +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ +switch (mod) { /* case on modifier */ + + case BCD_A: /* diagnostic read */ + if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, + ">>MT%d: diagnostic read\n", unit); + ind[IN_END] = 0; /* clear end of file */ + st = sim_tape_sprecf (uptr, &tbc); /* space fwd */ + break; + + case BCD_B: /* backspace */ + if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, + ">>MT%d: backspace\n", unit); + ind[IN_END] = 0; /* clear end of file */ + st = sim_tape_sprecr (uptr, &tbc); /* space rev */ + break; /* end case */ + + case BCD_E: /* erase = nop */ + if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, + ">>MT%d: erase\n", unit); + if (sim_tape_wrp (uptr)) return STOP_MTL; + return SCPE_OK; + + case BCD_M: /* write tapemark */ + if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, + ">>MT%d: write tape mark\n", unit); + st = sim_tape_wrtmk (uptr); /* write tmk */ + break; + + case BCD_R: /* rewind */ + if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, + ">>MT%d: rewind\n", unit); + sim_tape_rewind (uptr); /* update position */ + return SCPE_OK; + + case BCD_U: /* unload */ + if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, + ">>MT%d: rewind and unload\n", unit); + sim_tape_rewind (uptr); /* update position */ + return detach_unit (uptr); /* detach */ + + default: + return STOP_INVM; + } + +return mt_map_status (st); +} + +/* Read and write routines + + Inputs: + unit = unit character + flag = normal, word mark, or binary mode + mod = modifier character + Outputs: + status = status + + Fine point: after a read, the system writes a group mark just + beyond the end of the record. However, first it checks for a + GM + WM; if present, the GM + WM is not changed. Otherwise, + an MCW read sets a GM, preserving the current WM; while an LCA + read sets a GM and clears the WM. +*/ + +t_stat mt_io (int32 unit, int32 flag, int32 mod) +{ +int32 t, wm_seen; +t_mtrlnt i, tbc; +t_stat st; +t_bool passed_eot; +UNIT *uptr; + +if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */ +if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */ + +switch (mod) { + + case BCD_R: /* read */ + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ">>MT%d: read from %d", unit, BS); + ind[IN_TAP] = ind[IN_END] = 0; /* clear error */ + wm_seen = 0; /* no word mk seen */ + st = sim_tape_rdrecf (uptr, dbuf, &tbc, MT_MAXFR); /* read rec */ + if (st == MTSE_RECE) ind[IN_TAP] = 1; /* rec in error? */ + else if (st == MTSE_TMK) { /* tape mark? */ + ind[IN_END] = 1; /* set indicator */ + tbc = 1; /* one char read */ + dbuf[0] = BCD_TAPMRK; /* BCD tapemark */ + } + else if (st != MTSE_OK) { /* stop on error */ + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ", stopped by status = %d\n", st); + break; + } + for (i = 0; i < tbc; i++) { /* loop thru buf */ + if (M[BS] == (BCD_GRPMRK + WM)) { /* GWM in memory? */ + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, " to %d, stopped by GMWM\n", BS); + BS++; /* incr BS */ + if (ADDR_ERR (BS)) { /* test for wrap */ + BS = BA | (BS % MAXMEMSIZE); + return STOP_WRAP; + } + return SCPE_OK; /* done */ + } + t = dbuf[i]; /* get char */ + if (!(flag & MD_BIN) && (t == BCD_ALT)) /* BCD mode alt blank? */ + t = BCD_BLANK; /* real blank */ + if (flag & MD_WM) { /* word mk mode? */ + if ((t == BCD_WM) && (wm_seen == 0)) /* WM char, none prev? */ + wm_seen = WM; /* set flag */ + else { + M[BS] = wm_seen | (t & CHAR); /* char + wm seen */ + wm_seen = 0; /* clear flag */ + } + } + else M[BS] = (M[BS] & WM) | (t & CHAR); /* preserve mem WM */ + if (!wm_seen) BS++; + if (ADDR_ERR (BS)) { /* check next BS */ + BS = BA | (BS % MAXMEMSIZE); + return STOP_WRAP; + } + } + 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 */ + if (ADDR_ERR (BS)) { /* check final BS */ + BS = BA | (BS % MAXMEMSIZE); + return STOP_WRAP; + } + break; + + case BCD_W: + if (sim_tape_wrp (uptr)) return STOP_MTL; /* locked? */ + if (M[BS] == (BCD_GRPMRK + WM)) return STOP_MTZ;/* eor? */ + if (DEBUG_PRS (mt_dev)) + fprintf (sim_deb, ">>MT%d: write from %d", unit, BS); + ind[IN_TAP] = ind[IN_END] = 0; /* clear error */ + for (tbc = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); ) { + if ((t & WM) && (flag & MD_WM)) /* WM in wm mode? */ + dbuf[tbc++] = BCD_WM; + if (((t & CHAR) == BCD_BLANK) && !(flag & MD_BIN)) + dbuf[tbc++] = BCD_ALT; + else dbuf[tbc++] = t & CHAR; + if (ADDR_ERR (BS)) { /* check next BS */ + BS = BA | (BS % MAXMEMSIZE); + return STOP_WRAP; + } + } + if (DEBUG_PRS (mt_dev)) fprintf (sim_deb, " to %d\n", BS - 1); + passed_eot = sim_tape_eot (uptr); /* passed EOT? */ + st = sim_tape_wrrecf (uptr, dbuf, tbc); /* write record */ + if (!passed_eot && sim_tape_eot (uptr)) /* just passed EOT? */ + ind[IN_END] = 1; + if (ADDR_ERR (BS)) { /* check final BS */ + BS = BA | (BS % MAXMEMSIZE); + return STOP_WRAP; + } + break; + + default: + return STOP_INVM; + } + +return mt_map_status (st); +} + +/* Get unit pointer from unit number */ + +UNIT *get_unit (int32 unit) +{ +if ((unit <= 0) || (unit >= MT_NUMDR)) return NULL; +return mt_dev.units + unit; +} + +/* Map tape status */ + +t_stat mt_map_status (t_stat st) +{ +switch (st) { + + case MTSE_OK: /* no error */ + case MTSE_BOT: /* reverse into BOT */ + break; + + case MTSE_FMT: /* illegal fmt */ + return SCPE_IERR; + + case MTSE_UNATT: /* not attached */ + return SCPE_UNATT; + + case MTSE_INVRL: /* invalid rec lnt */ + return SCPE_MTRLNT; + + case MTSE_TMK: /* end of file */ + ind[IN_END] = 1; /* set end mark */ + break; + + case MTSE_IOERR: /* IO error */ + ind[IN_TAP] = 1; /* set error */ + if (iochk) return SCPE_IOERR; + break; + + case MTSE_RECE: /* record in error */ + case MTSE_EOM: /* end of medium */ + ind[IN_TAP] = 1; /* set error */ + break; + + case MTSE_WRP: /* write protect */ + return STOP_MTL; + } + +return SCPE_OK; +} + +/* Reset routine */ + +t_stat mt_reset (DEVICE *dptr) +{ +int32 i; +UNIT *uptr; + +for (i = 0; i < MT_NUMDR; i++) { /* clear pos flag */ + if (uptr = get_unit (i)) MT_CLR_PNU (uptr); + } +ind[IN_END] = ind[IN_TAP] = 0; /* clear indicators */ +return SCPE_OK; +} + +/* Bootstrap routine */ + +t_stat mt_boot (int32 unitno, DEVICE *dptr) +{ +extern int32 saved_IS; + +sim_tape_rewind (&mt_unit[unitno]); /* force rewind */ +BS = 1; /* set BS = 001 */ +mt_io (unitno, MD_WM, BCD_R); /* LDA %U1 001 R */ +saved_IS = 1; +return SCPE_OK; +} diff --git a/I1620/i1620_cpu.c b/I1620/i1620_cpu.c index 4bf36b49..1a8bbd52 100644 --- a/I1620/i1620_cpu.c +++ b/I1620/i1620_cpu.c @@ -26,7 +26,7 @@ This CPU module incorporates code and comments from the 1620 simulator by Geoff Kuenning, with his permission. - 28-May-06 RMS Fixed bug in cpu history Peter Schorn) + 28-May-06 RMS Fixed bug in cpu history (Peter Schorn) 22-Sep-05 RMS Fixed declarations (Sterling Garwood) 16-Aug-05 RMS Fixed C++ declaration and cast problems 07-Nov-04 RMS Added instruction history @@ -523,7 +523,7 @@ while (reason == 0) { /* loop until halted */ break; } } - else if (flags & IF_IMM) /* immediate? */ + else if (flags & IF_IMM) /* immediate? */ QAR = qla; if (hst_lnt) { /* history enabled? */ @@ -1376,7 +1376,8 @@ uint32 add_one_digit (uint32 dst, uint32 src, uint32 *cry) { uint32 res; -if (*cry) src = src + 1; /* cry in? incr src */ +if (*cry) /* cry in? incr src */ + src = src + 1; if (src >= 10) { /* src > 10? */ src = src - 10; /* src -= 10 */ *cry = 1; /* carry out */ diff --git a/Interdata/id_fd.c b/Interdata/id_fd.c index a016436c..10e83fc0 100644 --- a/Interdata/id_fd.c +++ b/Interdata/id_fd.c @@ -1,6 +1,6 @@ /* id_fd.c: Interdata floppy disk simulator - Copyright (c) 2001-2012, Robert M Supnik + Copyright (c) 2001-2013, 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 @@ fd M46-630 floppy disk + 03-Sep-13 RMS Added explicit void * cast 19-Mar-12 RMS Fixed macro naming conflict (Mark Pizzolato) A diskette consists of 77 tracks, each with 26 sectors of 128B. The @@ -306,7 +307,7 @@ return 0; t_stat fd_svc (UNIT *uptr) { uint32 i, u, tk, sc, crc, fnc, da; -uint8 *fbuf = uptr->filebuf; +uint8 *fbuf = (uint8 *) uptr->filebuf; u = uptr - fd_dev.units; /* get unit number */ fnc = GET_FNC (uptr->FNC); /* get function */ diff --git a/Interdata/id_pas.c b/Interdata/id_pas.c index dfc27ccf..ad3672b2 100644 --- a/Interdata/id_pas.c +++ b/Interdata/id_pas.c @@ -1,6 +1,6 @@ /* id_pas.c: Interdata programmable async line adapter simulator - Copyright (c) 2001-2012, Robert M Supnik + Copyright (c) 2001-2013, 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 @@ pas Programmable asynchronous line adapter(s) + 11-Oct-13 RMS Poll PAS immediately to pick up initial connect 18-Apr-12 RMS Revised to use clock coscheduling 21-Mar-12 RMS Fixed TT_GET_MODE test to use TTUF_MODE_x (Michael Bloom) 19-Nov-08 RMS Revised for common TMXR show routines @@ -485,7 +486,7 @@ t_stat r; r = tmxr_attach (&pas_desc, uptr, cptr); /* attach */ if (r != SCPE_OK) /* error */ return r; -sim_activate (uptr, 100); /* quick poll */ +sim_activate (uptr, 0); /* immediate poll */ return SCPE_OK; } diff --git a/NOVA/eclipse_cpu.c b/NOVA/eclipse_cpu.c index 2e9efc42..2a70b789 100644 --- a/NOVA/eclipse_cpu.c +++ b/NOVA/eclipse_cpu.c @@ -3632,7 +3632,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all PC = (PC + 1) & AMASK; continue; } - if ((IR & 0103777) == 0100650) { /* FDD Div double by AC */ + if ((IR & 0103777) == 0100750) { /* FDD Div double by AC */ if (!(fpu_unit.flags & UNIT_UP)) continue; if (Debug_Flags == 1) { @@ -3687,7 +3687,7 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all FPSR |= ((PC - 1) & AMASK); continue; } - if ((IR & 0103777) == 0101650) { /* FDMD Div double by memory */ + if ((IR & 0103777) == 0101750) { /* FDMD Div double by memory */ if (!(fpu_unit.flags & UNIT_UP)) continue; if (Debug_Flags == 1) { diff --git a/NOVA/nova_cpu.c b/NOVA/nova_cpu.c index a1caf573..209f16da 100644 --- a/NOVA/nova_cpu.c +++ b/NOVA/nova_cpu.c @@ -1,6 +1,6 @@ /* nova_cpu.c: NOVA CPU simulator - Copyright (c) 1993-2008, Robert M. Supnik + Copyright (c) 1993-2013, 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 @@ cpu Nova central processor + 17-Mar-13 RMS Added clarifying brances to IND_STEP macro (Dave Bryan) 04-Jul-07 BKR DEV_SET/CLR macros now used, support for non-existant devices added CPU bootstrap code warning: high-speed devices may not boot properly, @@ -243,11 +244,14 @@ #define STK_CHECK(x,y) if (((x) & 0377) < (y)) \ int_req = int_req | INT_STK #define IND_STEP(x) M[x] & A_IND; /* return next level indicator */ \ - if ( ((x) <= AUTO_TOP) && ((x) >= AUTO_INC) ) \ - if ( (x) < AUTO_DEC ) \ + if (((x) <= AUTO_TOP) && ((x) >= AUTO_INC)) { \ + if ( (x) < AUTO_DEC ) { \ M[x] = (M[x] + 1) & DMASK; \ - else \ + } \ + else { \ M[x] = (M[x] - 1) & DMASK; \ + } \ + } \ x = M[x] & AMASK #define INCREMENT_PC PC = (PC + 1) & AMASK /* increment PC */ diff --git a/NOVA/nova_dsk.c b/NOVA/nova_dsk.c index b1cfff3e..af4d3f6e 100644 --- a/NOVA/nova_dsk.c +++ b/NOVA/nova_dsk.c @@ -1,6 +1,6 @@ /* nova_dsk.c: 4019 fixed head disk simulator - Copyright (c) 1993-2008, Robert M. Supnik + Copyright (c) 1993-2013, 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 @@ dsk fixed head disk + 03-Sep-13 RMS Added explicit void * cast 04-Jul-07 BKR device name changed to DG's DSK from DEC's DK, DEV_xxx macros now used for consistency, added secret DG DIC function, @@ -235,7 +236,7 @@ return rval; t_stat dsk_svc (UNIT *uptr) { int32 i, da, pa; -int16 *fbuf = uptr->filebuf; +int16 *fbuf = (int16 *) uptr->filebuf; DEV_CLR_BUSY( INT_DSK ) ; DEV_SET_DONE( INT_DSK ) ; diff --git a/NOVA/nova_qty.c b/NOVA/nova_qty.c index 215ac3fe..1e5f3c1f 100644 --- a/NOVA/nova_qty.c +++ b/NOVA/nova_qty.c @@ -1,6 +1,6 @@ /* nova_qty.c: NOVA multiplexor (QTY/ALM) simulator - Copyright (c) 2000-2008, Robert M. Supnik + Copyright (c) 2000-2013, Robert M. Supnik Written by Bruce Ray and used with his gracious permission. Permission is hereby granted, free of charge, to any person obtaining a @@ -26,7 +26,8 @@ qty multiplexor: QTY = 4060, ALM = 42xx - 04-Jul-07 BKR fixed QTY output line number calculation (affected higher line numbers), + 14-Mar-12 RMS Fixed dangling else clauses + 04-Jul-07 BKR Fixed QTY output line number calculation (affected higher line numbers), 25-Mar-04 RMS Updated for V3.2 12-Jan-04 BKR Initial release includes both original DG "quad" multiplexor (QTY) @@ -604,12 +605,11 @@ t_stat qty_common_svc( DIB * dibp, UNIT * unitp ) ++qty_polls ; /* another time 'round the track */ newln = tmxr_poll_conn( &qty_desc ) ; /* anybody knocking at the door? */ if ( (newln >= 0) && qty_mdm ) + { if ( newln >= qty_max ) - { - return SCPE_IERR; /* WTF - sanity check failed, over? */ - } - else - { + { + return SCPE_IERR; /* WTF - sanity check failed, over? */ + } line = newln ; /* handle modem control */ tmlnp =&qty_ldsc[ line ] ; tmlnp->rcve = tmlnp->xmte = 1 ; @@ -628,7 +628,7 @@ t_stat qty_common_svc( DIB * dibp, UNIT * unitp ) sim_activate( unitp, tmxr_poll ) ; /* restart the bubble machine */ return ( SCPE_OK ) ; - } /* end of 'qty_common_svc' */ + } /* end of 'qty_common_svc' */ /*--------------------------------------------------------------*/ @@ -638,7 +638,7 @@ t_stat qty_common_svc( DIB * dibp, UNIT * unitp ) t_stat qty_svc( UNIT * uptr ) { return ( qty_common_svc(&qty_dib,uptr) ) ; - } /* end of 'qty_svc' */ + } /* end of 'qty_svc' */ /*--------------------------------------------------------------*/ @@ -992,18 +992,20 @@ int32 alm( int32 pulse, int32 code, int32 AC ) case ioDIC : /* get modem or receiver status */ if ( alm_line < qty_max ) + { if ( alm_section ) - { - /* get modem section status */ - if ( qty_ldsc[ alm_line ].xmte ) { - iodata = 0035 ; /* set CD, CTS, DSR, MDM flags */ + /* get modem section status */ + if ( qty_ldsc[ alm_line ].xmte ) + { + iodata = 0035 ; /* set CD, CTS, DSR, MDM flags */ + } + } + else + { + /* get receiver section status */ + iodata = 0 ; /* receiver error status - no errors by default */ } - } - else - { - /* get receiver section status */ - iodata = 0 ; /* receiver error status - no errors by default */ } break ; diff --git a/PDP1/pdp1_cpu.c b/PDP1/pdp1_cpu.c index 7be63f73..4e9920e4 100644 --- a/PDP1/pdp1_cpu.c +++ b/PDP1/pdp1_cpu.c @@ -25,7 +25,7 @@ cpu PDP-1 central processor - 210Mar-12 RMS Fixed & vs && in Ea_ch (Michael Bloom) + 21-Mar-12 RMS Fixed & vs && in Ea_ch (Michael Bloom) 30-May-07 RMS Fixed typo in SBS clear (Norm Lastovica) 28-Dec-06 RMS Added 16-channel SBS support, PDP-1D support 28-Jun-06 RMS Fixed bugs in MUS and DIV diff --git a/PDP1/pdp1_dcs.c b/PDP1/pdp1_dcs.c index dd54ce18..66de9e35 100644 --- a/PDP1/pdp1_dcs.c +++ b/PDP1/pdp1_dcs.c @@ -1,6 +1,6 @@ /* pdp1_dcs.c: PDP-1D terminal multiplexor simulator - Copyright (c) 2006-2008, Robert M Supnik + Copyright (c) 2006-2013, 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 @@ dcs Type 630 data communications subsystem + 11-Oct-2013 RMS Poll DCS immediately after attach to pick up connect 19-Nov-2008 RMS Revised for common TMXR show routines This module implements up to 32 individual serial interfaces. @@ -347,7 +348,7 @@ t_stat r; r = tmxr_attach (&dcs_desc, uptr, cptr); /* attach */ if (r != SCPE_OK) /* error */ return r; -sim_activate_abs (uptr, tmxr_poll); /* start poll */ +sim_activate_abs (uptr, 0); /* start poll at once */ return SCPE_OK; } diff --git a/PDP1/pdp1_drm.c b/PDP1/pdp1_drm.c index 5842db1f..aeaae3c6 100644 --- a/PDP1/pdp1_drm.c +++ b/PDP1/pdp1_drm.c @@ -1,6 +1,6 @@ /* pdp1_drm.c: PDP-1 drum simulator - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2013, 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,7 @@ drp Type 23 parallel drum drm Type 24 serial drum + 03-Sep-13 RMS Added explicit void * cast 21-Dec-06 RMS Added 16-chan SBS support 08-Dec-03 RMS Added parallel drum support Fixed bug in DBL/DCN decoding @@ -276,7 +277,7 @@ return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */ t_stat drm_svc (UNIT *uptr) { uint32 i, da; -uint32 *fbuf = uptr->filebuf; +uint32 *fbuf = (uint32 *) uptr->filebuf; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ drm_err = 1; /* set error */ diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h index a6eea9cb..86d72ecd 100644 --- a/PDP10/pdp10_defs.h +++ b/PDP10/pdp10_defs.h @@ -1,6 +1,6 @@ /* pdp10_defs.h: PDP-10 simulator definitions - Copyright (c) 1993-2010, Robert M Supnik + Copyright (c) 1993-2013, 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,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. + 30-Jun-13 RMS Fixed IPL4 mask definition (Tim Litt) 22-May-10 RMS Added check for 64b addresses 01-Feb-07 RMS Added CD support 29-Oct-06 RMS Added clock coscheduling function @@ -734,7 +735,7 @@ typedef struct pdp_dib DIB; #define INT_IPL7 0x0000000F /* int level masks */ #define INT_IPL6 0x000000F0 #define INT_IPL5 0x000FFF00 -#define INT_IPL4 0x3FF00000 +#define INT_IPL4 0x7FF00000 #define VEC_Q 0000 /* vector base */ #define VEC_PTR 0070 /* interrupt vectors */ diff --git a/PDP10/pdp10_ksio.c b/PDP10/pdp10_ksio.c index b37e8039..7807016d 100644 --- a/PDP10/pdp10_ksio.c +++ b/PDP10/pdp10_ksio.c @@ -1,6 +1,6 @@ /* pdp10_ksio.c: PDP-10 KS10 I/O subsystem simulator - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ uba Unibus adapters + 27-May-13 RMS Fixed bugs in Unibus adapter code 22-Sep-05 RMS Fixed declarations (from Sterling Garwood) 25-Jan-04 RMS Added stub floating address routine 12-Mar-03 RMS Added logical name support @@ -429,7 +430,14 @@ for (i = 0; dibp = dib_tab[i]; i++ ) { UBNXM_FAIL (pa, mode); } -/* Mapped read and write routines - used by standard Unibus devices on Unibus 1 */ +/* Mapped read and write routines - used by standard Unibus devices on Unibus 1 + The only devices that use these routines are standard 16b Unibus devices. + 18b Unibus devices (the RP and TU) do their own reads and writes. + + These routines would be more efficient if Map_Addr10 was only called + at a page boundary, but I don't think it's worth the added complexity. + + The upper two bits of the 18b halfword are not preserved on writes to memory. */ a10 Map_Addr10 (a10 ba, int32 ub) { @@ -493,7 +501,7 @@ for ( ; ba < lim; ba++) { /* by bytes */ } mask = 0377; M[pa10] = (M[pa10] & ~(mask << ubashf[ba & 3])) | - (((d10) *buf++) << ubashf[ba & 3]); + (((d10) (*buf++ & 0377)) << ubashf[ba & 3]); } return 0; } @@ -506,16 +514,16 @@ d10 val; ba = ba & ~01; /* align start */ lim = ba + (bc & ~01); -for ( ; ba < lim; ba++) { /* by bytes */ +for ( ; ba < lim; ba = ba + 2) { /* by words */ pa10 = Map_Addr10 (ba, 1); /* map addr */ if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */ return (lim - ba); /* return bc */ } - val = *buf++; /* get data */ + val = (*buf++) & 0177777; /* get 16b data */ if (ba & 2) - M[pa10] = (M[pa10] & 0777777600000) | val; - else M[pa10] = (M[pa10] & 0600000777777) | (val << 18); + M[pa10] = (M[pa10] & 0777777000000) | val; + else M[pa10] = (M[pa10] & 0000000777777) | (val << 18); } return 0; } diff --git a/PDP10/pdp10_rp.c b/PDP10/pdp10_rp.c index ad55f313..f16320e7 100644 --- a/PDP10/pdp10_rp.c +++ b/PDP10/pdp10_rp.c @@ -1,6 +1,6 @@ /* pdp10_rp.c - RH11/RP04/05/06/07 RM02/03/05/80 "Massbus" disk controller - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2012, 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,8 @@ rp RH/RP/RM moving head disks + 17-Mar-13 RMS Fixed incorrect copy/paste from pdp11_rp.c + 08-Dec-12 RMS UNLOAD does not set ATTN (Mark Pizzolato) 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 @@ -32,7 +34,7 @@ 04-Jan-04 RMS Changed sim_fsize calling sequence 23-Jul-03 RMS Fixed bug in read header stub 25-Apr-03 RMS Revised for extended file support - 21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson) + 21-Nov-02 RMS Fixed bug in bootstrap (Michael Thompson) 29-Sep-02 RMS Added variable vector support New data structures 30-Nov-01 RMS Added read only unit, extended SET/SHOW support support @@ -45,7 +47,7 @@ 28-Sep-01 RMS Fixed interrupt handling for SC/ATA 23-Aug-01 RMS Added read/write header stubs for ITS (found by Mirian Crzig Lennox) - 13-Jul-01 RMS Changed fread call to fxread (found by Peter Schorn) + 13-Jul-01 RMS Changed fread call to fxread (Peter Schorn) 14-May-01 RMS Added check for unattached drive The "Massbus style" disks consisted of several different large @@ -807,6 +809,13 @@ switch (fnc) { /* case on function */ return; case FNC_UNLOAD: /* unload */ + if (drv_tab[dtype].ctrl == MBA_RM_CTRL) { /* RM? */ + set_rper (ER1_ILF, drv); /* not supported */ + break; + } + rp_detach (uptr); /* detach unit */ + return; + case FNC_RECAL: /* recalibrate */ dc = 0; /* seek to 0 */ case FNC_SEEK: /* seek */ @@ -1155,6 +1164,7 @@ return SCPE_OK; t_stat rp_detach (UNIT *uptr) { int32 drv; +extern int32 sim_is_running; if (!(uptr->flags & UNIT_ATT)) /* attached? */ return SCPE_OK; @@ -1167,7 +1177,8 @@ if (sim_is_active (uptr)) { /* unit active? */ if (uptr->FUNC >= FNC_WCHK) /* data transfer? */ rpcs1 = rpcs1 | CS1_DONE | CS1_TRE; /* set done, err */ } -update_rpcs (CS1_SC, drv); /* request intr */ +if (!sim_is_running) /* from console? */ + update_rpcs (CS1_SC, drv); /* request intr */ return detach_unit (uptr); } diff --git a/PDP10/pdp10_tu.c b/PDP10/pdp10_tu.c index 0e73ec13..198c380b 100644 --- a/PDP10/pdp10_tu.c +++ b/PDP10/pdp10_tu.c @@ -1,6 +1,6 @@ /* pdp10_tu.c - PDP-10 RH11/TM03/TU45 magnetic tape simulator - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2013, 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,7 +25,8 @@ tu RH11/TM03/TU45 magtape - 29-Apr-07 RMS Fixed bug in setting FCE on TMK (found by Naoki Hamada) + 17-Mar-13 RMS Fixed bug in read/write check reverse (Dave Bryan) + 29-Apr-07 RMS Fixed bug in setting FCE on TMK (Naoki Hamada) 16-Feb-06 RMS Added tape capacity checking 16-Aug-05 RMS Fixed C++ declaration and cast problems 07-Jul-05 RMS Removed extraneous externs @@ -42,8 +43,8 @@ 28-Mar-03 RMS Added multiformat support 28-Feb-03 RMS Revised for magtape library 27-Jan-03 RMS Changed to dynamically allocate buffer - 21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson) - Fixed bug in read (reported by Harris Newman) + 21-Nov-02 RMS Fixed bug in bootstrap (Michael Thompson) + Fixed bug in read (Harris Newman) 29-Sep-02 RMS Added variable vector support New data structures 28-Aug-02 RMS Added end of medium support @@ -964,7 +965,7 @@ switch (fnc) { /* case on function */ MAPM (ba10 - i, mpa10, UMAP_RRV); } val = ((fmt == TC_10C)? (((d10) xbuf [--j]) & 017): 0); - for (k = 0; k < 4; i++) + for (k = 0; k < 4; k++) v[k] = xbuf[--j]; val = val | (v[0] << 4) | (v[1] << 12) | (v[2] << 20) | (v[3] << 28); if (fnc == FNC_READR) /* read? store */ diff --git a/PDP11/old/pdp11_defs.h b/PDP11/old/pdp11_defs.h new file mode 100644 index 00000000..be281cb4 --- /dev/null +++ b/PDP11/old/pdp11_defs.h @@ -0,0 +1,862 @@ +/* pdp11_defs.h: PDP-11 simulator definitions + + Copyright (c) 1993-2012, 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. + + The author gratefully acknowledges the help of Max Burnet, Megan Gentry, + and John Wilson in resolving questions about the PDP-11 + + 12-Dec-12 RMS Fixed base address for RQB, RQC, RQD + 11-Dec-11 RMS Fixed priority of PIRQ vs IO; added INT_INTERNALn + 22-May-10 RMS Added check for 64b definitions + 19-Nov-08 RMS Moved I/O support routines to I/O library + 16-May-08 RMS Added KE11A, DC11 support + 02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas) + 25-Jan-08 RMS Added RC11, KG11A support (from John Dundas) + 16-Dec-06 RMS Added TA11 support + 29-Oct-06 RMS Added clock coscheduling + 06-Jul-06 RMS Added multiple KL11/DL11 support + 26-Jun-06 RMS Added RF11 support + 24-May-06 RMS Added 11/44 DR support (from CIS diagnostic) + 17-May-06 RMS Added CR11/CD11 support (from John Dundas) + 30-Sep-04 RMS Added Massbus support + Removed Map_Addr prototype + Removed map argument from Unibus routines + Added framework for model selection + 28-May-04 RMS Added DHQ support + 25-Jan-04 RMS Removed local debug logging support + 22-Dec-03 RMS Added second DEUNA/DELUA support + 18-Oct-03 RMS Added DECtape off reel message + 19-May-03 RMS Revised for new conditional compilation + 05-Apr-03 RMS Fixed bug in MMR1 update (found by Tim Stark) + 28-Feb-03 RMS Added TM logging support + 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict + 11-Nov-02 RMS Changed log definitions to be VAX compatible + 10-Oct-02 RMS Added vector information to DIB + Changed DZ11 vector to Unibus standard + Added DEQNA/DELQA, DEUNA/DELUA support + Added multiple RQDX3, autoconfigure support + 12-Sep-02 RMS Added TMSCP, KW11P,and RX211 support + 28-Apr-02 RMS Clarified PDF ACF mnemonics + 22-Apr-02 RMS Added HTRAP, BPOK maint register flags, MT_MAXFR + 06-Mar-02 RMS Changed system type to KDJ11A + 20-Jan-02 RMS Added multiboard DZ11 support + 09-Nov-01 RMS Added bus map support + 07-Nov-01 RMS Added RQDX3 support + 26-Oct-01 RMS Added symbolic definitions for IO page + 19-Oct-01 RMS Added DZ definitions + 15-Oct-01 RMS Added logging capabilities + 07-Sep-01 RMS Revised for multilevel interrupts + 01-Jun-01 RMS Added DZ11 support + 23-Apr-01 RMS Added RK611 support + 05-Apr-01 RMS Added TS11/TSV05 support + 10-Feb-01 RMS Added DECtape support +*/ + +#ifndef _PDP11_DEFS_H +#define _PDP11_DEFS_H 0 + +#ifndef VM_PDP11 +#define VM_PDP11 0 +#endif + +#include "sim_defs.h" /* simulator defns */ +#include + +#if defined(USE_INT64) || defined(USE_ADDR64) +#error "PDP-11 does not support 64b values!" +#endif + +/* Architectural constants */ + +#define STKL_R 0340 /* stack limit */ +#define STKL_Y 0400 +#define VASIZE 0200000 /* 2**16 */ +#define VAMASK (VASIZE - 1) /* 2**16 - 1 */ +#define MEMSIZE64K 0200000 /* 2**16 */ +#define INIMEMSIZE 001000000 /* 2**18 */ +#define UNIMEMSIZE 001000000 /* 2**18 */ +#define UNIMASK (UNIMEMSIZE - 1) /* 2**18 - 1 */ +#define IOPAGEBASE 017760000 /* 2**22 - 2**13 */ +#define IOPAGESIZE 000020000 /* 2**13 */ +#define IOPAGEMASK (IOPAGESIZE - 1) /* 2**13 - 1 */ +#define MAXMEMSIZE 020000000 /* 2**22 */ +#define PAMASK (MAXMEMSIZE - 1) /* 2**22 - 1 */ +#define MEMSIZE (cpu_unit.capac) +#define ADDR_IS_MEM(x) (((t_addr) (x)) < cpu_memsize) /* use only in sim! */ +#define DMASK 0177777 + +/* CPU models */ + +#define MOD_1103 0 +#define MOD_1104 1 +#define MOD_1105 2 +#define MOD_1120 3 +#define MOD_1123 4 +#define MOD_1123P 5 +#define MOD_1124 6 +#define MOD_1134 7 +#define MOD_1140 8 +#define MOD_1144 9 +#define MOD_1145 10 +#define MOD_1160 11 +#define MOD_1170 12 +#define MOD_1173 13 +#define MOD_1153 14 +#define MOD_1173B 15 +#define MOD_1183 16 +#define MOD_1184 17 +#define MOD_1193 18 +#define MOD_1194 19 +#define MOD_T 20 + +#define CPUT_03 (1u << MOD_1103) /* LSI-11 */ +#define CPUT_04 (1u << MOD_1104) /* 11/04 */ +#define CPUT_05 (1u << MOD_1105) /* 11/05 */ +#define CPUT_20 (1u << MOD_1120) /* 11/20 */ +#define CPUT_23 (1u << MOD_1123) /* 11/23 */ +#define CPUT_23P (1u << MOD_1123P) /* 11/23+ */ +#define CPUT_24 (1u << MOD_1124) /* 11/24 */ +#define CPUT_34 (1u << MOD_1134) /* 11/34 */ +#define CPUT_40 (1u << MOD_1140) /* 11/40 */ +#define CPUT_44 (1u << MOD_1144) /* 11/44 */ +#define CPUT_45 (1u << MOD_1145) /* 11/45 */ +#define CPUT_60 (1u << MOD_1160) /* 11/60 */ +#define CPUT_70 (1u << MOD_1170) /* 11/70 */ +#define CPUT_73 (1u << MOD_1173) /* 11/73 */ +#define CPUT_53 (1u << MOD_1153) /* 11/53 */ +#define CPUT_73B (1u << MOD_1173B) /* 11/73B */ +#define CPUT_83 (1u << MOD_1183) /* 11/83 */ +#define CPUT_84 (1u << MOD_1184) /* 11/84 */ +#define CPUT_93 (1u << MOD_1193) /* 11/93 */ +#define CPUT_94 (1u << MOD_1194) /* 11/94 */ +#define CPUT_T (1u << MOD_T) /* T-11 */ + +#define CPUT_F (CPUT_23|CPUT_23P|CPUT_24) /* all F11's */ +#define CPUT_J (CPUT_53|CPUT_73|CPUT_73B| \ + CPUT_83|CPUT_84|CPUT_93|CPUT_94) +#define CPUT_JB (CPUT_73B|CPUT_83|CPUT_84) /* KDJ11B */ +#define CPUT_JE (CPUT_93|CPUT_94) /* KDJ11E */ +#define CPUT_JU (CPUT_84|CPUT_94) /* KTJ11B UBA */ +#define CPUT_ALL 0xFFFFFFFF + +/* CPU options */ + +#define BUS_U (1u << 0) /* Unibus */ +#define BUS_Q (0) /* Qbus */ +#define OPT_EIS (1u << 1) /* EIS */ +#define OPT_FIS (1u << 2) /* FIS */ +#define OPT_FPP (1u << 3) /* FPP */ +#define OPT_CIS (1u << 4) /* CIS */ +#define OPT_MMU (1u << 5) /* MMU */ +#define OPT_RH11 (1u << 6) /* RH11 */ +#define OPT_PAR (1u << 7) /* parity */ +#define OPT_UBM (1u << 8) /* UBM */ + +#define CPUT(x) ((cpu_type & (x)) != 0) +#define CPUO(x) ((cpu_opt & (x)) != 0) +#define UNIBUS (cpu_opt & BUS_U) + +/* Feature sets + + SDSD source addr, dest addr, source fetch, dest fetch + SR switch register + DR display register + RTT RTT instruction + SXS SXT, XOR, SOB instructions + MARK MARK instruction + SPL SPL instruction + MXPY MTPI, MTPD, MFPI, MFPD instructions + MXPS MTPS, MFPS instructions + MFPT MFPT instruction + CSM CSM instruction + TSWLK TSTSET, WRLCK instructions + PSW PSW register + EXPT explicit PSW writes can alter T-bit + IOSR general registers readable from programs in IO space + 2REG dual register set + MMR3 MMR3 register + MMTR mem mgt traps + STKLR STKLIM register + STKLF fixed stack limit + SID supervisor mode, I/D spaces + ODD odd address trap + HALT4 halt in kernel mode traps to 4 + JREG4 JMP/JSR R traps to 4 + STKA stop on stack abort + LTCR LTC CSR + LTCM LTC CSR<7> +*/ + +#define IS_SDSD (CPUT_20|CPUT_F|CPUT_40|CPUT_60|CPUT_J|CPUT_T) +#define HAS_SR (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \ + CPUT_44|CPUT_45|CPUT_60|CPUT_70) +#define HAS_DR (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \ + CPUT_40|CPUT_44|CPUT_45|CPUT_60|CPUT_70) +#define HAS_RTT (CPUT_03|CPUT_04|CPUT_F|CPUT_34|CPUT_40| \ + CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T) +#define HAS_SXS (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \ + CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T) +#define HAS_MARK (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \ + CPUT_45|CPUT_60|CPUT_70|CPUT_J) +#define HAS_SPL (CPUT_44|CPUT_45|CPUT_70|CPUT_J) +#define HAS_MXPY (CPUT_F|CPUT_34|CPUT_40|CPUT_44|CPUT_45| \ + CPUT_60|CPUT_70|CPUT_J) +#define HAS_MXPS (CPUT_03|CPUT_F|CPUT_34|CPUT_J|CPUT_T) +#define HAS_MFPT (CPUT_F|CPUT_44|CPUT_J|CPUT_T) +#define HAS_CSM (CPUT_44|CPUT_J) +#define HAS_TSWLK (CPUT_J) +#define HAS_PSW (CPUT_04|CPUT_05|CPUT_20|CPUT_F|CPUT_34|CPUT_40| \ + CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J) +#define HAS_EXPT (CPUT_04|CPUT_05|CPUT_20) +#define HAS_IOSR (CPUT_04|CPUT_05) +#define HAS_2REG (CPUT_45|CPUT_70|CPUT_J) +#define HAS_MMR3 (CPUT_F|CPUT_44|CPUT_45|CPUT_70|CPUT_J) +#define HAS_MMTR (CPUT_45|CPUT_70) +#define HAS_STKLR (CPUT_45|CPUT_60|CPUT_70) +#define HAS_STKLF (CPUT_04|CPUT_05|CPUT_20|CPUT_F|CPUT_34| \ + CPUT_40|CPUT_44|CPUT_J) +#define HAS_SID (CPUT_44|CPUT_45|CPUT_70|CPUT_J) +#define HAS_ODD (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \ + CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J) +#define HAS_HALT4 (CPUT_44|CPUT_45|CPUT_70|CPUT_J) +#define HAS_JREG4 (CPUT_03|CPUT_04|CPUT_05|CPUT_20|CPUT_F| \ + CPUT_34|CPUT_40|CPUT_60|CPUT_T) +#define STOP_STKA (CPUT_03|CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_44) +#define HAS_LTCR (CPUT_04|CPUT_05|CPUT_20|CPUT_23P|CPUT_24| \ + CPUT_34|CPUT_40|CPUT_44|CPUT_45|CPUT_60| \ + CPUT_70|CPUT_J) +#define HAS_LTCM (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \ + CPUT_40|CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J) + +/* Protection modes */ + +#define MD_KER 0 +#define MD_SUP 1 +#define MD_UND 2 +#define MD_USR 3 + +/* I/O access modes */ + +#define READ 0 +#define READC 1 /* read console */ +#define WRITE 2 +#define WRITEC 3 /* write console */ +#define WRITEB 4 + +/* PSW */ + +#define PSW_V_C 0 /* condition codes */ +#define PSW_V_V 1 +#define PSW_V_Z 2 +#define PSW_V_N 3 +#define PSW_V_TBIT 4 /* trace trap */ +#define PSW_V_IPL 5 /* int priority */ +#define PSW_V_FPD 8 /* first part done */ +#define PSW_V_RS 11 /* register set */ +#define PSW_V_PM 12 /* previous mode */ +#define PSW_V_CM 14 /* current mode */ +#define PSW_CC 017 +#define PSW_TBIT (1 << PSW_V_TBIT) +#define PSW_PM (3 << PSW_V_PM) + +/* FPS */ + +#define FPS_V_C 0 /* condition codes */ +#define FPS_V_V 1 +#define FPS_V_Z 2 +#define FPS_V_N 3 +#define FPS_V_T 5 /* truncate */ +#define FPS_V_L 6 /* long */ +#define FPS_V_D 7 /* double */ +#define FPS_V_IC 8 /* ic err int */ +#define FPS_V_IV 9 /* overflo err int */ +#define FPS_V_IU 10 /* underflo err int */ +#define FPS_V_IUV 11 /* undef var err int */ +#define FPS_V_ID 14 /* int disable */ +#define FPS_V_ER 15 /* error */ + +/* PIRQ */ + +#define PIRQ_PIR1 0001000 +#define PIRQ_PIR2 0002000 +#define PIRQ_PIR3 0004000 +#define PIRQ_PIR4 0010000 +#define PIRQ_PIR5 0020000 +#define PIRQ_PIR6 0040000 +#define PIRQ_PIR7 0100000 +#define PIRQ_IMP 0177356 /* implemented bits */ +#define PIRQ_RW 0177000 /* read/write bits */ + +/* STKLIM */ + +#define STKLIM_RW 0177400 + +/* MMR0 */ + +#define MMR0_MME 0000001 /* mem mgt enable */ +#define MMR0_V_PAGE 1 /* offset to pageno */ +#define MMR0_M_PAGE 077 /* mask for pageno */ +#define MMR0_PAGE (MMR0_M_PAGE << MMR0_V_PAGE) +#define MMR0_IC 0000200 /* instr complete */ +#define MMR0_MAINT 0000400 /* maintenance */ +#define MMR0_TENB 0001000 /* trap enable */ +#define MMR0_TRAP 0010000 /* mem mgt trap */ +#define MMR0_RO 0020000 /* read only error */ +#define MMR0_PL 0040000 /* page lnt error */ +#define MMR0_NR 0100000 /* no access error */ +#define MMR0_FREEZE 0160000 /* if set, no update */ +#define MMR0_WR 0171401 /* writeable bits */ + +/* MMR3 */ + +#define MMR3_UDS 001 /* user dspace enbl */ +#define MMR3_SDS 002 /* super dspace enbl */ +#define MMR3_KDS 004 /* krnl dspace enbl */ +#define MMR3_CSM 010 /* CSM enable */ +#define MMR3_M22E 020 /* 22b mem mgt enbl */ +#define MMR3_BME 040 /* DMA bus map enbl */ + +/* PAR */ + +#define PAR_18B 0007777 /* 18b addressing */ +#define PAR_22B 0177777 /* 22b addressing */ + +/* PDR */ + +#define PDR_ACF 0000007 /* access control */ +#define PDR_ACS 0000006 /* 2b access control */ +#define PDR_ED 0000010 /* expansion dir */ +#define PDR_W 0000100 /* written flag */ +#define PDR_A 0000200 /* access flag */ +#define PDR_PLF 0077400 /* page lnt field */ +#define PDR_NOC 0100000 /* don't cache */ + +#define PDR_PRD 0000003 /* page readable if 2 */ + +/* Virtual address */ + +#define VA_DF 0017777 /* displacement */ +#define VA_BN 0017700 /* block number */ +#define VA_V_APF 13 /* offset to APF */ +#define VA_V_DS 16 /* offset to space */ +#define VA_V_MODE 17 /* offset to mode */ +#define VA_DS (1u << VA_V_DS) /* data space flag */ + +/* Unibus map (if present) */ + +#define UBM_LNT_LW 32 /* size in LW */ +#define UBM_V_PN 13 /* page number */ +#define UBM_M_PN 037 +#define UBM_V_OFF 0 /* offset */ +#define UBM_M_OFF 017777 +#define UBM_PAGSIZE (UBM_M_OFF + 1) /* page size */ +#define UBM_GETPN(x) (((x) >> UBM_V_PN) & UBM_M_PN) +#define UBM_GETOFF(x) ((x) & UBM_M_OFF) + +/* CPUERR */ + +#define CPUE_RED 0004 /* red stack */ +#define CPUE_YEL 0010 /* yellow stack */ +#define CPUE_TMO 0020 /* IO page nxm */ +#define CPUE_NXM 0040 /* memory nxm */ +#define CPUE_ODD 0100 /* odd address */ +#define CPUE_HALT 0200 /* HALT not kernel */ +#define CPUE_IMP 0374 /* implemented bits */ + +/* Floating point accumulators */ + +typedef struct { + uint32 l; /* low 32b */ + uint32 h; /* high 32b */ + } fpac_t; + +/* Device CSRs */ + +#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) + +/* Trap masks, descending priority order, following J-11 + An interrupt summary bit is kept with traps, to minimize overhead +*/ + +#define TRAP_V_RED 0 /* red stk abort 4 */ +#define TRAP_V_ODD 1 /* odd address 4 */ +#define TRAP_V_MME 2 /* mem mgt 250 */ +#define TRAP_V_NXM 3 /* nx memory 4 */ +#define TRAP_V_PAR 4 /* parity err 114 */ +#define TRAP_V_PRV 5 /* priv inst 4 */ +#define TRAP_V_ILL 6 /* illegal inst 10 */ +#define TRAP_V_BPT 7 /* BPT 14 */ +#define TRAP_V_IOT 8 /* IOT 20 */ +#define TRAP_V_EMT 9 /* EMT 30 */ +#define TRAP_V_TRAP 10 /* TRAP 34 */ +#define TRAP_V_TRC 11 /* T bit 14 */ +#define TRAP_V_YEL 12 /* stack 4 */ +#define TRAP_V_PWRFL 13 /* power fail 24 */ +#define TRAP_V_FPE 14 /* fpe 244 */ +#define TRAP_V_MAX 15 /* intr = max trp # */ +#define TRAP_RED (1u << TRAP_V_RED) +#define TRAP_ODD (1u << TRAP_V_ODD) +#define TRAP_MME (1u << TRAP_V_MME) +#define TRAP_NXM (1u << TRAP_V_NXM) +#define TRAP_PAR (1u << TRAP_V_PAR) +#define TRAP_PRV (1u << TRAP_V_PRV) +#define TRAP_ILL (1u << TRAP_V_ILL) +#define TRAP_BPT (1u << TRAP_V_BPT) +#define TRAP_IOT (1u << TRAP_V_IOT) +#define TRAP_EMT (1u << TRAP_V_EMT) +#define TRAP_TRAP (1u << TRAP_V_TRAP) +#define TRAP_TRC (1u << TRAP_V_TRC) +#define TRAP_YEL (1u << TRAP_V_YEL) +#define TRAP_PWRFL (1u << TRAP_V_PWRFL) +#define TRAP_FPE (1u << TRAP_V_FPE) +#define TRAP_INT (1u << TRAP_V_MAX) +#define TRAP_ALL ((1u << TRAP_V_MAX) - 1) /* all traps */ + +#define VEC_RED 0004 /* trap vectors */ +#define VEC_ODD 0004 +#define VEC_MME 0250 +#define VEC_NXM 0004 +#define VEC_PAR 0114 +#define VEC_PRV 0004 +#define VEC_ILL 0010 +#define VEC_BPT 0014 +#define VEC_IOT 0020 +#define VEC_EMT 0030 +#define VEC_TRAP 0034 +#define VEC_TRC 0014 +#define VEC_YEL 0004 +#define VEC_PWRFL 0024 +#define VEC_FPE 0244 + +/* Simulator stop codes; codes 1:TRAP_V_MAX correspond to traps 0:TRAPMAX-1 */ + +#define STOP_HALT (TRAP_V_MAX + 1) /* HALT instruction */ +#define STOP_IBKPT (TRAP_V_MAX + 2) /* instruction bkpt */ +#define STOP_WAIT (TRAP_V_MAX + 3) /* wait, no events */ +#define STOP_VECABORT (TRAP_V_MAX + 4) /* abort vector read */ +#define STOP_SPABORT (TRAP_V_MAX + 5) /* abort trap push */ +#define STOP_RQ (TRAP_V_MAX + 6) /* RQDX3 panic */ +#define STOP_SANITY (TRAP_V_MAX + 7) /* sanity timer exp */ +#define STOP_DTOFF (TRAP_V_MAX + 8) /* DECtape off reel */ +#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ + +/* Timers */ + +#define TMR_CLK 0 /* line clock */ +#define TMR_PCLK 1 /* KW11P */ + +/* IO parameters */ + +#define DZ_MUXES 4 /* max # of DZ muxes */ +#define DZ_LINES 8 /* lines per DZ mux */ +#define VH_MUXES 4 /* max # of VH muxes */ +#define DLX_LINES 16 /* max # of KL11/DL11's */ +#define DCX_LINES 16 /* max # of DC11's */ +#define MT_MAXFR (1 << 16) /* magtape max rec */ +#define AUTO_LNT 34 /* autoconfig ranks */ +#define DIB_MAX 100 /* max DIBs */ + +#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ +#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ +#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus with <= 256KB */ +#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */ +#define DEV_V_MBUS (DEV_V_UF + 4) /* Massbus */ +#define DEV_V_FFUF (DEV_V_UF + 5) /* first free flag */ +#define DEV_UBUS (1u << DEV_V_UBUS) +#define DEV_QBUS (1u << DEV_V_QBUS) +#define DEV_Q18 (1u << DEV_V_Q18) +#define DEV_FLTA (1u << DEV_V_FLTA) +#define DEV_MBUS (1u << DEV_V_MBUS) + +#define DEV_RDX 8 /* default device radix */ + +/* Device information block */ + +#define VEC_DEVMAX 4 /* max device vec */ + +struct pdp_dib { + 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 routines */ + }; + +typedef struct pdp_dib DIB; + +/* I/O page layout - XUB, RQB,RQC,RQD float based on number of DZ's */ + +#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 (IOBA_RQB + IOLN_RQB) +#define IOLN_RQC 004 +#define IOBA_RQD (IOBA_RQC + IOLN_RQC) +#define IOLN_RQD 004 +#define IOBA_VH (IOPAGEBASE + 000440) /* DHQ11 */ +#define IOLN_VH 020 +#define IOBA_UBM (IOPAGEBASE + 010200) /* Unibus map */ +#define IOLN_UBM (UBM_LNT_LW * sizeof (int32)) +#define IOBA_KG (IOPAGEBASE + 010700) /* KG11-A */ +#define IOLN_KG 006 +#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */ +#define IOLN_RQ 004 +#define IOBA_SUP (IOPAGEBASE + 012200) /* supervisor APR's */ +#define IOLN_SUP 0100 +#define IOBA_KIPDR (IOPAGEBASE + 012300) /* kernel APR's */ +#define IOLN_KIPDR 020 +#define IOBA_KDPDR (IOPAGEBASE + 012320) +#define IOLN_KDPDR 020 +#define IOBA_KIPAR (IOPAGEBASE + 012340) +#define IOLN_KIPAR 020 +#define IOBA_KDPAR (IOPAGEBASE + 012360) +#define IOLN_KDPAR 020 +#define IOBA_TU (IOPAGEBASE + 012440) /* TU */ +#define IOLN_TU 040 +#define IOBA_MMR3 (IOPAGEBASE + 012516) /* MMR3 */ +#define IOLN_MMR3 002 +#define IOBA_TM (IOPAGEBASE + 012520) /* TM11 */ +#define IOLN_TM 014 +#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */ +#define IOLN_TS 004 +#define IOBA_PCLK (IOPAGEBASE + 012540) /* KW11P */ +#define IOLN_PCLK 006 +#define IOBA_DC (IOPAGEBASE + 014000) /* DC11 */ +#define IOLN_DC (DCX_LINES * 010) +#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_DL (IOPAGEBASE + 016500) /* extra KL11/DL11 */ +#define IOLN_DL (DLX_LINES * 010) +#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */ +#define IOLN_RP 054 +#define IOBA_CR (IOPAGEBASE + 017160) /* CD/CR/CM */ +#define IOLN_CR 010 +#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */ +#define IOLN_RX 004 +#define IOBA_RY (IOPAGEBASE + 017170) /* RY11 */ +#define IOLN_RY 004 +#define IOBA_KE (IOPAGEBASE + 017300) /* KE11-A */ +#define IOLN_KE 020 +#define IOBA_TC (IOPAGEBASE + 017340) /* TC11 */ +#define IOLN_TC 012 +#define IOBA_QDSS (IOPAGEBASE + 017400) /* QDSS */ +#define IOLN_QDSS 002 +#define IOBA_RK (IOPAGEBASE + 017400) /* RK11 */ +#define IOLN_RK 020 +#define IOBA_RC (IOPAGEBASE + 017440) /* RC11/RS64 */ +#define IOLN_RC 020 +#define IOBA_HK (IOPAGEBASE + 017440) /* RK611 */ +#define IOLN_HK 040 +#define IOBA_RF (IOPAGEBASE + 017460) /* RF11 */ +#define IOLN_RF 020 +#define IOBA_TA (IOPAGEBASE + 017500) /* TA11 */ +#define IOLN_TA 004 +#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */ +#define IOLN_LPT 004 +#define IOBA_CTL (IOPAGEBASE + 017520) /* board ctrl */ +#define IOLN_CTL 010 +#define IOBA_CLK (IOPAGEBASE + 017546) /* KW11L */ +#define IOLN_CLK 002 +#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */ +#define IOLN_PTR 004 +#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */ +#define IOLN_PTP 004 +#define IOBA_TTI (IOPAGEBASE + 017560) /* DL11 rcv */ +#define IOLN_TTI 004 +#define IOBA_TTO (IOPAGEBASE + 017564) /* DL11 xmt */ +#define IOLN_TTO 004 +#define IOBA_SR (IOPAGEBASE + 017570) /* SR */ +#define IOLN_SR 002 +#define IOBA_MMR012 (IOPAGEBASE + 017572) /* MMR0-2 */ +#define IOLN_MMR012 006 +#define IOBA_UIPDR (IOPAGEBASE + 017600) /* user APR's */ +#define IOLN_UIPDR 020 +#define IOBA_UDPDR (IOPAGEBASE + 017620) +#define IOLN_UDPDR 020 +#define IOBA_UIPAR (IOPAGEBASE + 017640) +#define IOLN_UIPAR 020 +#define IOBA_UDPAR (IOPAGEBASE + 017660) +#define IOLN_UDPAR 020 +#define IOBA_GPR (IOPAGEBASE + 017700) /* GPR's */ +#define IOLN_GPR 010 +#define IOBA_UCTL (IOPAGEBASE + 017730) /* UBA ctrl */ +#define IOLN_UCTL 010 +#define IOBA_CPU (IOPAGEBASE + 017740) /* CPU reg */ +#define IOLN_CPU 036 +#define IOBA_PSW (IOPAGEBASE + 017776) /* PSW */ +#define IOLN_PSW 002 + +/* Interrupt assignments; within each level, priority is right to left + PIRQn has the highest priority with a level and is always bit <0> + On level 6, the clock is second highest priority */ + +#define IPL_HLVL 8 /* # int levels */ +#define IPL_HMIN 4 /* lowest IO int level */ + +#define INT_V_PIR7 0 /* BR7 */ + +#define INT_V_PIR6 0 /* BR6 */ +#define INT_V_CLK 1 +#define INT_V_PCLK 2 +#define INT_V_DTA 3 +#define INT_V_TA 4 + +#define INT_V_PIR5 0 /* BR5 */ +#define INT_V_RK 1 +#define INT_V_RL 2 +#define INT_V_RX 3 +#define INT_V_TM 4 +#define INT_V_RP 5 +#define INT_V_TS 6 +#define INT_V_HK 7 +#define INT_V_RQ 8 +#define INT_V_DZRX 9 +#define INT_V_DZTX 10 +#define INT_V_TQ 11 +#define INT_V_RY 12 +#define INT_V_XQ 13 +#define INT_V_XU 14 +#define INT_V_TU 15 +#define INT_V_RF 16 +#define INT_V_RC 17 + +#define INT_V_PIR4 0 /* BR4 */ +#define INT_V_TTI 1 +#define INT_V_TTO 2 +#define INT_V_PTR 3 +#define INT_V_PTP 4 +#define INT_V_LPT 5 +#define INT_V_VHRX 6 +#define INT_V_VHTX 7 +#define INT_V_CR 8 +#define INT_V_DLI 9 +#define INT_V_DLO 10 +#define INT_V_DCI 11 +#define INT_V_DCO 12 + +#define INT_V_PIR3 0 /* BR3 */ +#define INT_V_PIR2 0 /* BR2 */ +#define INT_V_PIR1 0 /* BR1 */ + +#define INT_PIR7 (1u << INT_V_PIR7) +#define INT_PIR6 (1u << INT_V_PIR6) +#define INT_CLK (1u << INT_V_CLK) +#define INT_PCLK (1u << INT_V_PCLK) +#define INT_DTA (1u << INT_V_DTA) +#define INT_TA (1u << INT_V_TA) +#define INT_PIR5 (1u << INT_V_PIR5) +#define INT_RK (1u << INT_V_RK) +#define INT_RL (1u << INT_V_RL) +#define INT_RX (1u << INT_V_RX) +#define INT_TM (1u << INT_V_TM) +#define INT_RP (1u << INT_V_RP) +#define INT_TS (1u << INT_V_TS) +#define INT_HK (1u << INT_V_HK) +#define INT_RQ (1u << INT_V_RQ) +#define INT_DZRX (1u << INT_V_DZRX) +#define INT_DZTX (1u << INT_V_DZTX) +#define INT_TQ (1u << INT_V_TQ) +#define INT_RY (1u << INT_V_RY) +#define INT_XQ (1u << INT_V_XQ) +#define INT_XU (1u << INT_V_XU) +#define INT_TU (1u << INT_V_TU) +#define INT_RF (1u << INT_V_RF) +#define INT_RC (1u << INT_V_RC) +#define INT_PIR4 (1u << INT_V_PIR4) +#define INT_TTI (1u << INT_V_TTI) +#define INT_TTO (1u << INT_V_TTO) +#define INT_PTR (1u << INT_V_PTR) +#define INT_PTP (1u << INT_V_PTP) +#define INT_LPT (1u << INT_V_LPT) +#define INT_VHRX (1u << INT_V_VHRX) +#define INT_VHTX (1u << INT_V_VHTX) +#define INT_CR (1u << INT_V_CR) +#define INT_DLI (1u << INT_V_DLI) +#define INT_DLO (1u << INT_V_DLO) +#define INT_DCI (1u << INT_V_DCI) +#define INT_DCO (1u << INT_V_DCO) +#define INT_PIR3 (1u << INT_V_PIR3) +#define INT_PIR2 (1u << INT_V_PIR2) +#define INT_PIR1 (1u << INT_V_PIR1) + +#define INT_INTERNAL7 (INT_PIR7) +#define INT_INTERNAL6 (INT_PIR6 | INT_CLK) +#define INT_INTERNAL5 (INT_PIR5) +#define INT_INTERNAL4 (INT_PIR4) +#define INT_INTERNAL3 (INT_PIR3) +#define INT_INTERNAL2 (INT_PIR2) +#define INT_INTERNAL1 (INT_PIR1) + +#define IPL_CLK 6 /* int pri levels */ +#define IPL_PCLK 6 +#define IPL_DTA 6 +#define IPL_TA 6 +#define IPL_RK 5 +#define IPL_RL 5 +#define IPL_RX 5 +#define IPL_TM 5 +#define IPL_RP 5 +#define IPL_TS 5 +#define IPL_HK 5 +#define IPL_RQ 5 +#define IPL_DZRX 5 +#define IPL_DZTX 5 +#define IPL_TQ 5 +#define IPL_RY 5 +#define IPL_XQ 5 +#define IPL_XU 5 +#define IPL_TU 5 +#define IPL_RF 5 +#define IPL_RC 5 +#define IPL_PTR 4 +#define IPL_PTP 4 +#define IPL_TTI 4 +#define IPL_TTO 4 +#define IPL_LPT 4 +#define IPL_VHRX 4 +#define IPL_VHTX 4 +#define IPL_CR 4 +#define IPL_DLI 4 +#define IPL_DLO 4 +#define IPL_DCI 4 +#define IPL_DCO 4 + +#define IPL_PIR7 7 +#define IPL_PIR6 6 +#define IPL_PIR5 5 +#define IPL_PIR4 4 +#define IPL_PIR3 3 +#define IPL_PIR2 2 +#define IPL_PIR1 1 + +/* Device vectors */ + +#define VEC_Q 0000 /* vector base */ +#define VEC_PIRQ 0240 +#define VEC_TTI 0060 +#define VEC_TTO 0064 +#define VEC_PTR 0070 +#define VEC_PTP 0074 +#define VEC_CLK 0100 +#define VEC_PCLK 0104 +#define VEC_XQ 0120 +#define VEC_XU 0120 +#define VEC_RQ 0154 +#define VEC_RL 0160 +#define VEC_LPT 0200 +#define VEC_RF 0204 +#define VEC_HK 0210 +#define VEC_RC 0210 +#define VEC_RK 0220 +#define VEC_DTA 0214 +#define VEC_TM 0224 +#define VEC_TS 0224 +#define VEC_TU 0224 +#define VEC_CR 0230 +#define VEC_RP 0254 +#define VEC_TQ 0260 +#define VEC_TA 0260 +#define VEC_RX 0264 +#define VEC_RY 0264 +#define VEC_DLI 0300 +#define VEC_DLO 0304 +#define VEC_DCI 0300 +#define VEC_DCO 0304 +#define VEC_DZRX 0300 +#define VEC_DZTX 0304 +#define VEC_VHRX 0310 +#define VEC_VHTX 0314 + +/* Interrupt macros */ + +#define IVCL(dv) ((IPL_##dv * 32) + INT_V_##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) + +/* Massbus definitions */ + +#define MBA_NUM 2 /* number of MBA's */ +#define MBA_RP 0 /* MBA for RP */ +#define MBA_TU 1 /* MBA for TU */ +#define MBA_RMASK 037 /* max 32 reg */ +#define MBE_NXD 1 /* nx drive */ +#define MBE_NXR 2 /* nx reg */ +#define MBE_GOE 3 /* err on GO */ + +/* CPU and FPU macros */ + +#define update_MM ((MMR0 & MMR0_FREEZE) == 0) +#define setTRAP(name) trap_req = trap_req | (name) +#define setCPUERR(name) CPUERR = CPUERR | (name) +#define ABORT(val) longjmp (save_env, (val)) +#define SP R[6] +#define PC R[7] + +/* Function prototypes */ + +int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf); +int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf); +int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf); +int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf); + +int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf); +int32 mba_wrbufW (uint32 mbus, int32 bc, uint16 *buf); +int32 mba_chbufW (uint32 mbus, int32 bc, uint16 *buf); +int32 mba_get_bc (uint32 mbus); +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); + +int32 clk_cosched (int32 wait); + +#include "pdp11_io_lib.h" + +#endif diff --git a/PDP11/old/pdp11_rh.c b/PDP11/old/pdp11_rh.c new file mode 100644 index 00000000..efc7c043 --- /dev/null +++ b/PDP11/old/pdp11_rh.c @@ -0,0 +1,856 @@ +/* pdp11_rh.c: PDP-11 Massbus adapter simulator + + Copyright (c) 2005-2012, 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. + + rha, rhb RH11/RH70 Massbus adapter + + 19-Mar-12 RMS Fixed declaration of cpu_opt (Mark Pizzolato) + 02-Feb-08 RMS Fixed DMA memory address limit test (John Dundas) + 17-May-07 RMS Moved CS1 drive enable to devices + 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 + simulated with great precision. The RH11 has an internal interrupt + request flop, CSTB INTR, which is controlled as follows: + + - Writing IE and DONE simultaneously sets CSTB INTR + - Controller clear, INIT, and interrupt acknowledge clear CSTB INTR + (and also clear IE) + - A transition of DONE from 0 to 1 sets CSTB INTR from IE + + The output of CSTB INTR is OR'd with the AND of RPCS1 to + create the interrupt request signal. Thus, + + - The DONE interrupt is edge sensitive, but the SC interrupt is + level sensitive. + - The DONE interrupt, once set, is not disabled if IE is cleared, + but the SC interrupt is. +*/ + +#if defined (VM_PDP10) /* PDP10 version */ +#error "PDP-10 uses pdp10_rp.c and pdp10_tu.c!" + +#elif defined (VM_VAX) /* VAX version */ +#error "VAX uses vax780_mba.c!" + +#else /* PDP-11 version */ +#include "pdp11_defs.h" +#endif + +/* CS1 - base + 000 - control/status 1 */ + +#define CS1_OF 0 +#define CS1_GO CSR_GO /* go */ +#define CS1_V_FNC 1 /* function pos */ +#define CS1_M_FNC 037 /* function mask */ +#define CS1_FNC (CS1_M_FNC << CS1_V_FNC) +#define FNC_XFER 024 /* >=? data xfr */ +#define CS1_IE CSR_IE /* int enable */ +#define CS1_DONE CSR_DONE /* ready */ +#define CS1_V_UAE 8 /* Unibus addr ext */ +#define CS1_M_UAE 03 +#define CS1_UAE (CS1_M_UAE << CS1_V_UAE) +#define CS1_MCPE 0020000 /* Mbus par err NI */ +#define CS1_TRE 0040000 /* transfer err */ +#define CS1_SC 0100000 /* special cond */ +#define CS1_MBZ 0012000 +#define CS1_DRV (CS1_FNC | CS1_GO) +#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) + +/* WC - base + 002 - word count */ + +#define WC_OF 1 + +/* BA - base + 004 - base address */ + +#define BA_OF 2 +#define BA_MBZ 0000001 /* must be zero */ + +/* CS2 - base + 010 - control/status 2 */ + +#define CS2_OF 3 +#define CS2_V_UNIT 0 /* unit pos */ +#define CS2_M_UNIT 07 /* unit mask */ +#define CS2_UNIT (CS2_M_UNIT << CS2_V_UNIT) +#define CS2_UAI 0000010 /* addr inhibit */ +#define CS2_PAT 0000020 /* parity test NI */ +#define CS2_CLR 0000040 /* controller clear */ +#define CS2_IR 0000100 /* input ready */ +#define CS2_OR 0000200 /* output ready */ +#define CS2_MDPE 0000400 /* Mbus par err NI */ +#define CS2_MXF 0001000 /* missed xfer NI */ +#define CS2_PGE 0002000 /* program err */ +#define CS2_NEM 0004000 /* nx mem err */ +#define CS2_NED 0010000 /* nx drive err */ +#define CS2_PE 0020000 /* parity err NI */ +#define CS2_WCE 0040000 /* write check err */ +#define CS2_DLT 0100000 /* data late NI */ +#define CS2_MBZ (CS2_CLR) +#define CS2_RW (CS2_UNIT | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE) +#define CS2_ERR (CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \ + CS2_NED | CS2_PE | CS2_WCE | CS2_DLT) +#define GET_UNIT(x) (((x) >> CS2_V_UNIT) & CS2_M_UNIT) + +/* DB - base + 022 - data buffer */ + +#define DB_OF 4 + +/* BAE - base + 050/34 - bus address extension */ + +#define BAE_OF 5 +#define AE_M_MAE 0 /* addr ext pos */ +#define AE_V_MAE 077 /* addr ext mask */ +#define AE_MBZ 0177700 + +/* CS3 - base + 052/36 - control/status 3 */ + +#define CS3_OF 6 +#define CS3_APE 0100000 /* addr perr - NI */ +#define CS3_DPO 0040000 /* data perr odd - NI */ +#define CS3_DPE 0020000 /* data perr even - NI */ +#define CS3_WCO 0010000 /* wchk err odd */ +#define CS3_WCE 0004000 /* wchk err even */ +#define CS3_DBL 0002000 /* dbl word xfer - NI */ +#define CS3_IPCK 0000017 /* wrong par - NI */ +#define CS3_ERR (CS3_APE|CS3_DPO|CS3_DPE|CS3_WCO|CS3_WCE) +#define CS3_MBZ 0001660 +#define CS3_RW (CS1_IE | CS3_IPCK) + +#define MBA_OFSMASK 077 /* max 32 reg */ +#define INT 0000 /* int reg flag */ +#define EXT 0100 /* ext reg flag */ + +/* Declarations */ + +#define RH11 (cpu_opt & OPT_RH11) + +typedef struct { + uint32 cs1; /* ctrl/status 1 */ + uint32 wc; /* word count */ + uint32 ba; /* bus addr */ + uint32 cs2; /* ctrl/status 2 */ + uint32 db; /* data buffer */ + uint32 bae; /* addr ext */ + uint32 cs3; /* ctrl/status 3 */ + uint32 iff; /* int flip flop */ + } MBACTX; + +MBACTX massbus[MBA_NUM]; + +extern uint32 cpu_opt; +extern int32 cpu_bme; +extern uint16 *M; +extern int32 int_req[IPL_HLVL]; +extern t_addr cpu_memsize; +extern FILE *sim_deb; +extern FILE *sim_log; +extern int32 sim_switches; + +t_stat mba_reset (DEVICE *dptr); +t_stat mba_rd (int32 *val, int32 pa, int32 access); +t_stat mba_wr (int32 val, int32 pa, int32 access); +t_stat mba_set_type (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat mba_show_type (FILE *st, UNIT *uptr, int32 val, void *desc); +int32 mba0_inta (void); +int32 mba1_inta (void); +void mba_set_int (uint32 mb); +void mba_clr_int (uint32 mb); +void mba_upd_cs1 (uint32 set, uint32 clr, uint32 mb); +void mba_set_cs2 (uint32 flg, uint32 mb); +uint32 mba_map_pa (int32 pa, int32 *ofs); +DEVICE mba0_dev, mba1_dev; + +extern uint32 Map_Addr (uint32 ba); + +/* 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); + +/* Unibus to register offset map */ + +static int32 mba_mapofs[(MBA_OFSMASK + 1) >> 1] = { + INT|0, INT|1, INT|2, EXT|5, INT|3, EXT|1, EXT|2, EXT|4, + EXT|7, INT|4, EXT|3, EXT|6, EXT|8, EXT|9, EXT|10, EXT|11, + EXT|12, EXT|13, EXT|14, EXT|15, EXT|16, EXT|17, EXT|18, EXT|19, + EXT|20, EXT|21, EXT|22, EXT|23, EXT|24, EXT|25, EXT|26, EXT|27 + }; + +/* Massbus adapter data structures + + mbax_dev RHx device descriptor + mbax_unit RHx units + mbax_reg RHx register list +*/ + +DIB mba0_dib = { + IOBA_RP, IOLN_RP, &mba_rd, &mba_wr, + 1, IVCL (RP), VEC_RP, { &mba0_inta } + }; + +UNIT mba0_unit = { UDATA (NULL, 0, 0) }; + +REG mba0_reg[] = { + { ORDATA (CS1, massbus[0].cs1, 16) }, + { ORDATA (WC, massbus[0].wc, 16) }, + { ORDATA (BA, massbus[0].ba, 16) }, + { ORDATA (CS2, massbus[0].cs2, 16) }, + { ORDATA (DB, massbus[0].db, 16) }, + { ORDATA (BAE, massbus[0].bae, 6) }, + { ORDATA (CS3, massbus[0].cs3, 16) }, + { FLDATA (IFF, massbus[0].iff, 0) }, + { FLDATA (INT, IREQ (RP), INT_V_RP) }, + { FLDATA (SC, massbus[0].cs1, CSR_V_ERR) }, + { FLDATA (DONE, massbus[0].cs1, CSR_V_DONE) }, + { FLDATA (IE, massbus[0].cs1, CSR_V_IE) }, + { ORDATA (DEVADDR, mba0_dib.ba, 32), REG_HRO }, + { ORDATA (DEVVEC, mba0_dib.vec, 16), REG_HRO }, + { NULL } + }; + +MTAB mba0_mod[] = { + { MTAB_XTD|MTAB_VDV, 0100, "ADDRESS", "ADDRESS", + &set_addr, &show_addr, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", + &set_vec, &show_vec, NULL }, + { 0 } + }; + +DIB mba1_dib = { + IOBA_TU, IOLN_TU, &mba_rd, &mba_wr, + 1, IVCL (TU), VEC_TU, { &mba1_inta } + }; + +UNIT mba1_unit = { UDATA (NULL, 0, 0) }; + +REG mba1_reg[] = { + { ORDATA (CS1, massbus[1].cs1, 16) }, + { ORDATA (WC, massbus[1].wc, 16) }, + { ORDATA (BA, massbus[1].ba, 16) }, + { ORDATA (CS2, massbus[1].cs2, 16) }, + { ORDATA (DB, massbus[1].db, 16) }, + { ORDATA (BAE, massbus[1].bae, 6) }, + { ORDATA (CS3, massbus[1].cs3, 16) }, + { FLDATA (IFF, massbus[1].iff, 0) }, + { FLDATA (INT, IREQ (TU), INT_V_TU) }, + { FLDATA (SC, massbus[1].cs1, CSR_V_ERR) }, + { FLDATA (DONE, massbus[1].cs1, CSR_V_DONE) }, + { FLDATA (IE, massbus[1].cs1, CSR_V_IE) }, + { ORDATA (DEVADDR, mba1_dib.ba, 32), REG_HRO }, + { ORDATA (DEVVEC, mba1_dib.vec, 16), REG_HRO }, + { NULL } + }; + +MTAB mba1_mod[] = { + { MTAB_XTD|MTAB_VDV, 0040, "ADDRESS", "ADDRESS", + &set_addr, &show_addr, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", + &set_vec, &show_vec, NULL }, + { 0 } + }; + +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 */ + +t_stat mba_rd (int32 *val, int32 pa, int32 mode) +{ +int32 ofs, dat, mb, drv; +t_stat r; + +mb = mba_map_pa (pa, &ofs); /* get mb number */ +if ((mb < 0) || (ofs < 0)) /* valid? */ + return SCPE_NXM; +drv = GET_UNIT (massbus[mb].cs2); /* get drive */ +mba_upd_cs1 (0, 0, mb); /* update CS1 */ + +if (ofs & EXT) { /* external? */ + if (!mbregR[mb]) /* device there? */ + return SCPE_NXM; + r = mbregR[mb] (val, ofs & ~EXT, drv); /* call device */ + if (r == MBE_NXD) /* nx drive? */ + mba_set_cs2 (CS2_NED, mb); + else if (r == MBE_NXR) /* nx reg? */ + return SCPE_NXM; + return SCPE_OK; + } + +switch (ofs) { /* case on reg */ + + case CS1_OF: /* CS1 */ + if (!mbregR[mb]) /* nx device? */ + return SCPE_NXM; + r = mbregR[mb] (&dat, ofs, drv); /* get dev cs1 */ + if (r == MBE_NXD) /* nx drive? */ + mba_set_cs2 (CS2_NED, mb); + *val = massbus[mb].cs1 | dat; + break; + + case WC_OF: /* WC */ + *val = massbus[mb].wc; + break; + + case BA_OF: /* BA */ + *val = massbus[mb].ba & ~BA_MBZ; + break; + + case CS2_OF: /* CS2 */ + *val = massbus[mb].cs2 = (massbus[mb].cs2 & ~CS2_MBZ) | CS2_IR | CS2_OR; + break; + + case DB_OF: /* DB */ + *val = massbus[mb].db; + break; + + case BAE_OF: /* BAE */ + *val = massbus[mb].bae = massbus[mb].bae & ~AE_MBZ; + break; + + case CS3_OF: /* CS3 */ + *val = massbus[mb].cs3 = (massbus[mb].cs3 & ~(CS1_IE | CS3_MBZ)) | + (massbus[mb].cs1 & CS1_IE); + break; + + default: /* huh? */ + return SCPE_NXM; + } + +return SCPE_OK; +} + +t_stat mba_wr (int32 val, int32 pa, int32 access) +{ +int32 ofs, cs1f, drv, mb; +t_stat r; +t_bool cs1dt; + +mb = mba_map_pa (pa, &ofs); /* get mb number */ +if ((mb < 0) || (ofs < 0)) /* valid? */ + return SCPE_NXM; +drv = GET_UNIT (massbus[mb].cs2); /* get drive */ + +if (ofs & EXT) { /* external? */ + if (!mbregW[mb]) /* device there? */ + return SCPE_NXM; + if ((access == WRITEB) && (pa & 1)) /* byte writes */ + val = val << 8; /* don't work */ + r = mbregW[mb] (val, ofs & ~EXT, drv); /* write dev reg */ + if (r == MBE_NXD) /* nx drive? */ + mba_set_cs2 (CS2_NED, mb); + else if (r == MBE_NXR) /* nx reg? */ + return SCPE_NXM; + mba_upd_cs1 (0, 0, mb); /* update status */ + return SCPE_OK; + } + +cs1f = 0; /* no int on cs1 upd */ +switch (ofs) { /* case on reg */ + + case CS1_OF: /* CS1 */ + if (!mbregW[mb]) /* device exist? */ + return SCPE_NXM; + if ((access == WRITEB) && (pa & 1)) + val = val << 8; + if (val & CS1_TRE) { /* error clear? */ + 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 (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? */ + 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 && ((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) /* nx drive? */ + mba_set_cs2 (CS2_NED, mb); + else if (r == MBE_NXR) /* nx reg? */ + return SCPE_NXM; + else if (cs1dt && (r == SCPE_OK)) { /* xfer, no err? */ + massbus[mb].cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE); + massbus[mb].cs2 &= ~CS2_ERR; /* clear errors */ + massbus[mb].cs3 &= ~(CS3_ERR | CS3_DBL); + } + } + } + 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)? + (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)? + (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) /* init? */ + mba_reset (&mba_dev[mb]); + else { + if ((val & ~massbus[mb].cs2) & (CS2_PE | CS2_MXF)) + cs1f = CS1_SC; /* diagn intr */ + if (access == WRITEB) /* merge val */ + val = (massbus[mb].cs2 & ((pa & 1)? 0377: 0177400)) | val; + 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)? + (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; + 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; + 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: + return SCPE_NXM; + } + +mba_upd_cs1 (cs1f, 0, mb); /* update status */ +return SCPE_OK; +} + +/* Massbus I/O routines + + 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; + +bc = bc & ~1; /* bc even */ +if (mb >= MBA_NUM) /* valid MBA? */ + return 0; +ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */ +mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */ +if (bc > mbc) /* use smaller */ + bc = mbc; +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (RH11 && cpu_bme) /* map addr */ + pa = Map_Addr (ba); + else pa = ba; + if (!ADDR_IS_MEM (pa)) { /* NXM? */ + mba_set_cs2 (CS2_NEM, mb); /* set error */ + break; + } + pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; + for (j = 0; j < pbc; j = j + 2) { /* loop by words */ + *buf++ = M[pa >> 1]; /* fetch word */ + if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */ + ba = ba + 2; /* incr ba, pa */ + pa = pa + 2; + } + } + } +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) +{ +int32 i, j, ba, mbc, pbc; +uint32 pa; + +bc = bc & ~1; /* bc even */ +if (mb >= MBA_NUM) /* valid MBA? */ + return 0; +ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */ +mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */ +if (bc > mbc) /* use smaller */ + bc = mbc; +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (RH11 && cpu_bme) /* map addr */ + pa = Map_Addr (ba); + else pa = ba; + if (!ADDR_IS_MEM (pa)) { /* NXM? */ + mba_set_cs2 (CS2_NEM, mb); /* set error */ + break; + } + pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; + for (j = 0; j < pbc; j = j + 2) { /* loop by words */ + M[pa >> 1] = *buf++; /* put word */ + if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */ + ba = ba + 2; /* incr ba, pa */ + pa = pa + 2; + } + } + } +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) +{ +int32 i, j, ba, mbc, pbc; +uint32 pa; + +bc = bc & ~1; /* bc even */ +if (mb >= MBA_NUM) /* valid MBA? */ + return 0; +ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */ +mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */ +if (bc > mbc) /* use smaller */ + bc = mbc; +for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ + if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */ + else pa = ba; + if (!ADDR_IS_MEM (pa)) { /* NXM? */ + mba_set_cs2 (CS2_NEM, mb); /* set error */ + break; + } + pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */ + if (pbc > (bc - i)) /* limit to rem xfr */ + pbc = bc - i; + for (j = 0; j < pbc; j = j + 2) { /* loop by words */ + massbus[mb].db = *buf++; /* get dev word */ + if (M[pa >> 1] != massbus[mb].db) { /* miscompare? */ + mba_set_cs2 (CS2_WCE, mb); /* set error */ + massbus[mb].cs3 = massbus[mb].cs3 | /* set even/odd */ + ((pa & 1)? CS3_WCO: CS3_WCE); + break; + } + if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */ + ba = ba + 2; /* incr ba, pa */ + pa = pa + 2; + } + } + } +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; +} + +/* Device access, status, and interrupt routines */ + +void mba_set_don (uint32 mb) +{ +mba_upd_cs1 (CS1_DONE, 0, mb); +return; +} + +void mba_upd_ata (uint32 mb, uint32 val) +{ +if (val) + mba_upd_cs1 (CS1_SC, 0, mb); +else mba_upd_cs1 (0, CS1_SC, mb); +return; +} + +void mba_set_exc (uint32 mb) +{ +mba_upd_cs1 (CS1_TRE | CS1_DONE, 0, mb); +return; +} + +int32 mba_get_bc (uint32 mb) +{ +if (mb >= MBA_NUM) + return 0; +return ((0200000 - massbus[mb].wc) << 1); +} + +int32 mba_get_csr (uint32 mb) +{ +DIB *dibp; + +if (mb >= MBA_NUM) + return 0; +dibp = (DIB *) mba_dev[mb].ctxt; +return dibp->ba; +} + +void mba_set_int (uint32 mb) +{ +DIB *dibp; + +if (mb >= MBA_NUM) + return; +dibp = (DIB *) mba_dev[mb].ctxt; +int_req[dibp->vloc >> 5] |= (1 << (dibp->vloc & 037)); +return; +} + +void mba_clr_int (uint32 mb) +{ +DIB *dibp; + +if (mb >= MBA_NUM) + return; +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) +{ +if (mb >= MBA_NUM) + return; +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)) | 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; +} + +void mba_set_cs2 (uint32 flag, uint32 mb) +{ +if (mb >= MBA_NUM) + return; +massbus[mb].cs2 = massbus[mb].cs2 | flag; +mba_upd_cs1 (0, 0, mb); +return; +} + +/* Interrupt acknowledge */ + +int32 mba0_inta (void) +{ +massbus[0].cs1 &= ~CS1_IE; /* clear int enable */ +massbus[0].cs3 &= ~CS1_IE; /* in both registers */ +massbus[0].iff = 0; /* clear CSTB INTR */ +return mba0_dib.vec; /* acknowledge */ +} + +int32 mba1_inta (void) +{ +massbus[1].cs1 &= ~CS1_IE; /* clear int enable */ +massbus[1].cs3 &= ~CS1_IE; /* in both registers */ +massbus[1].iff = 0; /* clear CSTB INTR */ +return mba1_dib.vec; /* acknowledge */ +} + +/* Map physical address to Massbus number, offset */ + +uint32 mba_map_pa (int32 pa, int32 *ofs) +{ +int32 i, uo, ba, lnt; +DIB *dibp; + +for (i = 0; i < MBA_NUM; i++) { /* loop thru ctrls */ + dibp = (DIB *) mba_dev[i].ctxt; /* get DIB */ + ba = dibp->ba; + lnt = dibp->lnt; + if ((pa >= ba) && /* in range? */ + (pa < (ba + lnt))) { + if (pa < (ba + (lnt - 4))) { /* not last two? */ + uo = ((pa - ba) & MBA_OFSMASK) >> 1; /* get Unibus offset */ + *ofs = mba_mapofs[uo]; /* map thru PROM */ + return i; /* return ctrl idx */ + } + else if (RH11) /* RH11? done */ + return -1; + else { /* RH70 */ + uo = (pa - (ba + (lnt - 4))) >> 1; /* offset relative */ + *ofs = BAE_OF + uo; /* to BAE */ + return i; + } + } + } +return -1; +} + +/* Reset Massbus adapter */ + +t_stat mba_reset (DEVICE *dptr) +{ +uint32 mb; + +mb = dptr - mba_dev; +if (mb >= MBA_NUM) + return SCPE_NOFNC; +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) /* valid MBA? */ + return; +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) +{ +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; +} + +/* 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)) /* validate args */ + return SCPE_IERR; +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) /* set rd dispatch */ + mbregR[idx] = dibp->rd; +if (dibp->wr) /* set wr dispatch */ + mbregW[idx] = dibp->wr; +if (dibp->ack[0]) /* set abort dispatch */ + mbabort[idx] = dibp->ack[0]; +return SCPE_OK; +} + diff --git a/PDP11/old/pdp11_sys.c b/PDP11/old/pdp11_sys.c new file mode 100644 index 00000000..b0b358cf --- /dev/null +++ b/PDP11/old/pdp11_sys.c @@ -0,0 +1,1089 @@ +/* pdp11_sys.c: PDP-11 simulator interface + + Copyright (c) 1993-2012, 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. + + 29-Apr-12 RMS Fixed compiler warning (Mark Pizzolato) + 19-Nov-08 RMS Moved I/O support routines to I/O library + 15-May-08 RMS Added KE11-A, DC11 support + Renamed DL11 + 04-Feb-08 RMS Modified to allow -A, -B use with 8b devices + 25-Jan-08 RMS Added RC11, KG11A support from John Dundas + 10-Sep-07 RMS Cleaned up binary loader + 20-Dec-06 RMS Added TA11 support + 12-Nov-06 RMS Fixed operand order in EIS instructions (W.F.J. Mueller) + 14-Jul-06 RMS Reordered device list + 06-Jul-06 RMS Added multiple KL11/DL11 support + 26-Jun-06 RMS Added RF11 support + 17-May-06 RMS Added CR11/CD11 support (John Dundas) + 16-Aug-05 RMS Fixed C++ declaration and cast problems + 22-Jul-05 RMS Fixed missing , in initializer (Doug Gwyn) + 22-Dec-03 RMS Added second DEUNA/DELUA support + 18-Oct-03 RMS Added DECtape off reel message + 06-May-03 RMS Added support for second DEQNA/DELQA + 09-Jan-03 RMS Added DELUA/DEUNA support + 17-Oct-02 RMS Fixed bugs in branch, SOB address parsing + 09-Oct-02 RMS Added DELQA support + 12-Sep-02 RMS Added TMSCP, KW11P, RX211 support, RAD50 examine + 29-Nov-01 RMS Added read only unit support + 17-Sep-01 RMS Removed multiconsole support + 26-Aug-01 RMS Added DZ11 + 20-Aug-01 RMS Updated bad block inquiry + 17-Jul-01 RMS Fixed warning from VC++ 6.0 + 27-May-01 RMS Added multiconsole support + 05-Apr-01 RMS Added support for TS11/TSV05 + 14-Mar-01 RMS Revised load/dump interface (again) + 11-Feb-01 RMS Added DECtape support + 30-Oct-00 RMS Added support for examine to file + 14-Apr-99 RMS Changed t_addr to unsigned + 09-Nov-98 RMS Fixed assignments of ROR/ROL (John Wilson) + 27-Oct-98 RMS V2.4 load interface + 08-Oct-98 RMS Fixed bug in bad block routine + 30-Mar-98 RMS Fixed bug in floating point display + 12-Nov-97 RMS Added bad block table routine +*/ + +#include "pdp11_defs.h" +#include + +extern DEVICE cpu_dev; +extern DEVICE sys_dev; +extern DEVICE ptr_dev; +extern DEVICE ptp_dev; +extern DEVICE tti_dev; +extern DEVICE tto_dev; +extern DEVICE lpt_dev; +extern DEVICE cr_dev; +extern DEVICE clk_dev; +extern DEVICE pclk_dev; +extern DEVICE dli_dev; +extern DEVICE dlo_dev; +extern DEVICE dci_dev; +extern DEVICE dco_dev; +extern DEVICE dz_dev; +extern DEVICE vh_dev; +extern DEVICE dt_dev; +extern DEVICE rc_dev; +extern DEVICE rf_dev; +extern DEVICE rk_dev; +extern DEVICE rl_dev; +extern DEVICE hk_dev; +extern DEVICE rx_dev; +extern DEVICE ry_dev; +extern DEVICE mba_dev[]; +extern DEVICE rp_dev; +extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; +extern DEVICE tm_dev; +extern DEVICE tq_dev; +extern DEVICE ts_dev; +extern DEVICE tu_dev; +extern DEVICE ta_dev; +extern DEVICE xq_dev, xqb_dev; +extern DEVICE xu_dev, xub_dev; +extern DEVICE ke_dev; +extern DEVICE kg_dev; +extern UNIT cpu_unit; +extern REG cpu_reg[]; +extern uint16 *M; +extern int32 saved_PC; + +/* SCP data structures and interface routines + + sim_name simulator name string + sim_PC pointer to saved PC register descriptor + sim_emax number of words for examine + sim_devices array of pointers to simulated devices + sim_stop_messages array of pointers to stop messages + sim_load binary loader +*/ + +char sim_name[] = "PDP-11"; + +REG *sim_PC = &cpu_reg[0]; + +int32 sim_emax = 4; + +DEVICE *sim_devices[] = { + &cpu_dev, + &sys_dev, + &mba_dev[0], + &mba_dev[1], + &clk_dev, + &pclk_dev, + &ptr_dev, + &ptp_dev, + &tti_dev, + &tto_dev, + &cr_dev, + &lpt_dev, + &dli_dev, + &dlo_dev, + &dci_dev, + &dco_dev, + &dz_dev, + &vh_dev, + &rc_dev, + &rf_dev, + &rk_dev, + &rl_dev, + &hk_dev, + &rx_dev, + &ry_dev, + &rp_dev, + &rq_dev, + &rqb_dev, + &rqc_dev, + &rqd_dev, + &dt_dev, + &tm_dev, + &ts_dev, + &tq_dev, + &tu_dev, + &ta_dev, + &xq_dev, + &xqb_dev, + &xu_dev, + &xub_dev, + &ke_dev, + &kg_dev, + NULL + }; + +const char *sim_stop_messages[] = { + "Unknown error", + "Red stack trap", + "Odd address trap", + "Memory management trap", + "Non-existent memory trap", + "Parity error trap", + "Privilege trap", + "Illegal instruction trap", + "BPT trap", + "IOT trap", + "EMT trap", + "TRAP trap", + "Trace trap", + "Yellow stack trap", + "Powerfail trap", + "Floating point exception", + "HALT instruction", + "Breakpoint", + "Wait state", + "Trap vector fetch abort", + "Trap stack push abort", + "RQDX3 consistency error", + "Sanity timer expired", + "DECtape off reel" + }; + +/* Binary loader. + + Loader format consists of blocks, optionally preceded, separated, and + followed by zeroes. Each block consists of: + + 001 --- + xxx | + lo_count | + hi_count | + lo_origin > count bytes + hi_origin | + data byte | + : | + data byte --- + checksum + + If the byte count is exactly six, the block is the last on the tape, and + there is no checksum. If the origin is not 000001, then the origin is + the PC at which to start the program. +*/ + +t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag) +{ +int32 c[6], d, i, cnt, csum; +uint32 org; + +if ((*cptr != 0) || (flag != 0)) + return SCPE_ARG; +do { /* block loop */ + csum = 0; /* init checksum */ + for (i = 0; i < 6; ) { /* 6 char header */ + if ((c[i] = getc (fileref)) == EOF) + return SCPE_FMT; + if ((i != 0) || (c[i] == 1)) /* 1st must be 1 */ + csum = csum + c[i++]; /* add into csum */ + } + cnt = (c[3] << 8) | c[2]; /* count */ + org = (c[5] << 8) | c[4]; /* origin */ + if (cnt < 6) /* invalid? */ + return SCPE_FMT; + if (cnt == 6) { /* end block? */ + if (org != 1) /* set PC? */ + saved_PC = org & 0177776; + return SCPE_OK; + } + for (i = 6; i < cnt; i++) { /* exclude hdr */ + if ((d = getc (fileref)) == EOF) /* data char */ + return SCPE_FMT; + csum = csum + d; /* add into csum */ + if (org >= MEMSIZE) /* invalid addr? */ + return SCPE_NXM; + M[org >> 1] = (org & 1)? /* store data */ + (M[org >> 1] & 0377) | (d << 8): + (M[org >> 1] & 0177400) | d; + org = (org + 1) & 0177777; /* inc origin */ + } + if ((d = getc (fileref)) == EOF) /* get csum */ + return SCPE_FMT; + csum = csum + d; /* add in */ + } while ((csum & 0377) == 0); /* result mbz */ +return SCPE_CSUM; +} + +/* Symbol tables */ + +#define I_V_L 16 /* long mode */ +#define I_V_D 17 /* double mode */ +#define I_L (1 << I_V_L) +#define I_D (1 << I_V_D) + +/* Warning: for literals, the class number MUST equal the field width!! */ + +#define I_V_CL 18 /* class bits */ +#define I_M_CL 037 /* class mask */ +#define I_V_NPN 0 /* no operands */ +#define I_V_REG 1 /* reg */ +#define I_V_SOP 2 /* operand */ +#define I_V_3B 3 /* 3b literal */ +#define I_V_FOP 4 /* flt operand */ +#define I_V_AFOP 5 /* fac, flt operand */ +#define I_V_6B 6 /* 6b literal */ +#define I_V_BR 7 /* cond branch */ +#define I_V_8B 8 /* 8b literal */ +#define I_V_SOB 9 /* reg, disp */ +#define I_V_RSOP 10 /* reg, operand */ +#define I_V_ASOP 11 /* fac, operand */ +#define I_V_ASMD 12 /* fac, moded int op */ +#define I_V_DOP 13 /* double operand */ +#define I_V_CCC 14 /* CC clear */ +#define I_V_CCS 15 /* CC set */ +#define I_V_SOPR 16 /* operand, reg */ +#define I_NPN (I_V_NPN << I_V_CL) +#define I_REG (I_V_REG << I_V_CL) +#define I_3B (I_V_3B << I_V_CL) +#define I_SOP (I_V_SOP << I_V_CL) +#define I_FOP (I_V_FOP << I_V_CL) +#define I_6B (I_V_6B << I_V_CL) +#define I_BR (I_V_BR << I_V_CL) +#define I_8B (I_V_8B << I_V_CL) +#define I_AFOP (I_V_AFOP << I_V_CL) +#define I_ASOP (I_V_ASOP << I_V_CL) +#define I_RSOP (I_V_RSOP << I_V_CL) +#define I_SOB (I_V_SOB << I_V_CL) +#define I_ASMD (I_V_ASMD << I_V_CL) +#define I_DOP (I_V_DOP << I_V_CL) +#define I_CCC (I_V_CCC << I_V_CL) +#define I_CCS (I_V_CCS << I_V_CL) +#define I_SOPR (I_V_SOPR << I_V_CL) + +static const int32 masks[] = { +0177777, 0177770, 0177700, 0177770, +0177700+I_D, 0177400+I_D, 0177700, 0177400, +0177400, 0177000, 0177000, 0177400, +0177400+I_D+I_L, 0170000, 0177777, 0177777, +0177000 +}; + +static const char *opcode[] = { +"HALT","WAIT","RTI","BPT", +"IOT","RESET","RTT","MFPT", +"JMP","RTS","SPL", +"NOP","CLC","CLV","CLV CLC", +"CLZ","CLZ CLC","CLZ CLV","CLZ CLV CLC", +"CLN","CLN CLC","CLN CLV","CLN CLV CLC", +"CLN CLZ","CLN CLZ CLC","CLN CLZ CLC","CCC", +"NOP","SEC","SEV","SEV SEC", +"SEZ","SEZ SEC","SEZ SEV","SEZ SEV SEC", +"SEN","SEN SEC","SEN SEV","SEN SEV SEC", +"SEN SEZ","SEN SEZ SEC","SEN SEZ SEC","SCC", +"SWAB","BR","BNE","BEQ", +"BGE","BLT","BGT","BLE", +"JSR", +"CLR","COM","INC","DEC", +"NEG","ADC","SBC","TST", +"ROR","ROL","ASR","ASL", +"MARK","MFPI","MTPI","SXT", +"CSM", "TSTSET","WRTLCK", +"MOV","CMP","BIT","BIC", +"BIS","ADD", +"MUL","DIV","ASH","ASHC", +"XOR", +"FADD","FSUB","FMUL","FDIV", +"L2DR", +"MOVC","MOVRC","MOVTC", +"LOCC","SKPC","SCANC","SPANC", +"CMPC","MATC", +"ADDN","SUBN","CMPN","CVTNL", +"CVTPN","CVTNP","ASHN","CVTLN", +"L3DR", +"ADDP","SUBP","CMPP","CVTPL", +"MULP","DIVP","ASHP","CVTLP", +"MOVCI","MOVRCI","MOVTCI", +"LOCCI","SKPCI","SCANCI","SPANCI", +"CMPCI","MATCI", +"ADDNI","SUBNI","CMPNI","CVTNLI", +"CVTPNI","CVTNPI","ASHNI","CVTLNI", +"ADDPI","SUBPI","CMPPI","CVTPLI", +"MULPI","DIVPI","ASHPI","CVTLPI", +"SOB", +"BPL","BMI","BHI","BLOS", +"BVC","BVS","BCC","BCS", +"BHIS","BLO", /* encode only */ +"EMT","TRAP", +"CLRB","COMB","INCB","DECB", +"NEGB","ADCB","SBCB","TSTB", +"RORB","ROLB","ASRB","ASLB", +"MTPS","MFPD","MTPD","MFPS", +"MOVB","CMPB","BITB","BICB", +"BISB","SUB", +"CFCC","SETF","SETI","SETD","SETL", +"LDFPS","STFPS","STST", +"CLRF","CLRD","TSTF","TSTD", +"ABSF","ABSD","NEGF","NEGD", +"MULF","MULD","MODF","MODD", +"ADDF","ADDD","LDF","LDD", +"SUBF","SUBD","CMPF","CMPD", +"STF","STD","DIVF","DIVD", +"STEXP", +"STCFI","STCDI","STCFL","STCDL", +"STCFD","STCDF", +"LDEXP", +"LDCIF","LDCID","LDCLF","LDCLD", +"LDCFD","LDCDF", +NULL +}; + +static const int32 opc_val[] = { +0000000+I_NPN, 0000001+I_NPN, 0000002+I_NPN, 0000003+I_NPN, +0000004+I_NPN, 0000005+I_NPN, 0000006+I_NPN, 0000007+I_NPN, +0000100+I_SOP, 0000200+I_REG, 0000230+I_3B, +0000240+I_CCC, 0000241+I_CCC, 0000242+I_CCC, 0000243+I_NPN, +0000244+I_CCC, 0000245+I_NPN, 0000246+I_NPN, 0000247+I_NPN, +0000250+I_CCC, 0000251+I_NPN, 0000252+I_NPN, 0000253+I_NPN, +0000254+I_NPN, 0000255+I_NPN, 0000256+I_NPN, 0000257+I_CCC, +0000260+I_CCS, 0000261+I_CCS, 0000262+I_CCS, 0000263+I_NPN, +0000264+I_CCS, 0000265+I_NPN, 0000266+I_NPN, 0000267+I_NPN, +0000270+I_CCS, 0000271+I_NPN, 0000272+I_NPN, 0000273+I_NPN, +0000274+I_NPN, 0000275+I_NPN, 0000276+I_NPN, 0000277+I_CCS, +0000300+I_SOP, 0000400+I_BR, 0001000+I_BR, 0001400+I_BR, +0002000+I_BR, 0002400+I_BR, 0003000+I_BR, 0003400+I_BR, +0004000+I_RSOP, +0005000+I_SOP, 0005100+I_SOP, 0005200+I_SOP, 0005300+I_SOP, +0005400+I_SOP, 0005500+I_SOP, 0005600+I_SOP, 0005700+I_SOP, +0006000+I_SOP, 0006100+I_SOP, 0006200+I_SOP, 0006300+I_SOP, +0006400+I_6B, 0006500+I_SOP, 0006600+I_SOP, 0006700+I_SOP, +0007000+I_SOP, 0007200+I_SOP, 0007300+I_SOP, +0010000+I_DOP, 0020000+I_DOP, 0030000+I_DOP, 0040000+I_DOP, +0050000+I_DOP, 0060000+I_DOP, +0070000+I_SOPR, 0071000+I_SOPR, 0072000+I_SOPR, 0073000+I_SOPR, +0074000+I_RSOP, +0075000+I_REG, 0075010+I_REG, 0075020+I_REG, 0075030+I_REG, +0076020+I_REG, +0076030+I_NPN, 0076031+I_NPN, 0076032+I_NPN, +0076040+I_NPN, 0076041+I_NPN, 0076042+I_NPN, 0076043+I_NPN, +0076044+I_NPN, 0076045+I_NPN, +0076050+I_NPN, 0076051+I_NPN, 0076052+I_NPN, 0076053+I_NPN, +0076054+I_NPN, 0076055+I_NPN, 0076056+I_NPN, 0076057+I_NPN, +0076060+I_REG, +0076070+I_NPN, 0076071+I_NPN, 0076072+I_NPN, 0076073+I_NPN, +0076074+I_NPN, 0076075+I_NPN, 0076076+I_NPN, 0076077+I_NPN, +0076130+I_NPN, 0076131+I_NPN, 0076132+I_NPN, +0076140+I_NPN, 0076141+I_NPN, 0076142+I_NPN, 0076143+I_NPN, +0076144+I_NPN, 0076145+I_NPN, +0076150+I_NPN, 0076151+I_NPN, 0076152+I_NPN, 0076153+I_NPN, +0076154+I_NPN, 0076155+I_NPN, 0076156+I_NPN, 0076157+I_NPN, +0076170+I_NPN, 0076171+I_NPN, 0076172+I_NPN, 0076173+I_NPN, +0076174+I_NPN, 0076175+I_NPN, 0076176+I_NPN, 0076177+I_NPN, +0077000+I_SOB, +0100000+I_BR, 0100400+I_BR, 0101000+I_BR, 0101400+I_BR, +0102000+I_BR, 0102400+I_BR, 0103000+I_BR, 0103400+I_BR, +0103000+I_BR, 0103400+I_BR, +0104000+I_8B, 0104400+I_8B, +0105000+I_SOP, 0105100+I_SOP, 0105200+I_SOP, 0105300+I_SOP, +0105400+I_SOP, 0105500+I_SOP, 0105600+I_SOP, 0105700+I_SOP, +0106000+I_SOP, 0106100+I_SOP, 0106200+I_SOP, 0106300+I_SOP, +0106400+I_SOP, 0106500+I_SOP, 0106600+I_SOP, 0106700+I_SOP, +0110000+I_DOP, 0120000+I_DOP, 0130000+I_DOP, 0140000+I_DOP, +0150000+I_DOP, 0160000+I_DOP, +0170000+I_NPN, 0170001+I_NPN, 0170002+I_NPN, 0170011+I_NPN, 0170012+I_NPN, +0170100+I_SOP, 0170200+I_SOP, 0170300+I_SOP, +0170400+I_FOP, 0170400+I_FOP+I_D, 0170500+I_FOP, 0170500+I_FOP+I_D, +0170600+I_FOP, 0170600+I_FOP+I_D, 0170700+I_FOP, 0170700+I_FOP+I_D, +0171000+I_AFOP, 0171000+I_AFOP+I_D, 0171400+I_AFOP, 0171400+I_AFOP+I_D, +0172000+I_AFOP, 0172000+I_AFOP+I_D, 0172400+I_AFOP, 0172400+I_AFOP+I_D, +0173000+I_AFOP, 0173000+I_AFOP+I_D, 0173400+I_AFOP, 0173400+I_AFOP+I_D, +0174000+I_AFOP, 0174000+I_AFOP+I_D, 0174400+I_AFOP, 0174400+I_AFOP+I_D, +0175000+I_ASOP, +0175400+I_ASMD, 0175400+I_ASMD+I_D, 0175400+I_ASMD+I_L, 0175400+I_ASMD+I_D+I_L, +0176000+I_AFOP, 0176000+I_AFOP+I_D, +0176400+I_ASOP, +0177000+I_ASMD, 0177000+I_ASMD+I_D, 0177000+I_ASMD+I_L, 0177000+I_ASMD+I_D+I_L, +0177400+I_AFOP, 0177400+I_AFOP+I_D, +-1 +}; + +static const char *rname [] = { + "R0", "R1", "R2", "R3", "R4", "R5", "SP", "PC" + }; + +static const char *fname [] = { + "F0", "F1", "F2", "F3", "F4", "F5", "?6", "?7" + }; + +static const char r50_to_asc[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$._0123456789"; + +/* Specifier decode + + Inputs: + *of = output stream + addr = current PC + spec = specifier + nval = next word + flag = TRUE if decoding for CPU + iflag = TRUE if decoding integer instruction + Outputs: + count = -number of extra words retired +*/ + +int32 fprint_spec (FILE *of, t_addr addr, int32 spec, t_value nval, + int32 flag, int32 iflag) +{ +int32 reg, mode; +static const int32 rgwd[8] = { 0, 0, 0, 0, 0, 0, -1, -1 }; +static const int32 pcwd[8] = { 0, 0, -1, -1, 0, 0, -1, -1 }; + +reg = spec & 07; +mode = ((spec >> 3) & 07); +switch (mode) { + + case 0: + if (iflag) + fprintf (of, "%s", rname[reg]); + else fprintf (of, "%s", fname[reg]); + break; + + case 1: + fprintf (of, "(%s)", rname[reg]); + break; + + case 2: + if (reg != 7) + fprintf (of, "(%s)+", rname[reg]); + else fprintf (of, "#%-o", nval); + break; + + case 3: + if (reg != 7) + fprintf (of, "@(%s)+", rname[reg]); + else fprintf (of, "@#%-o", nval); + break; + + case 4: + fprintf (of, "-(%s)", rname[reg]); + break; + + case 5: + fprintf (of, "@-(%s)", rname[reg]); + break; + + case 6: + if ((reg != 7) || !flag) + fprintf (of, "%-o(%s)", nval, rname[reg]); + else fprintf (of, "%-o", (nval + addr + 4) & 0177777); + break; + + case 7: + if ((reg != 7) || !flag) + fprintf (of, "@%-o(%s)", nval, rname[reg]); + else fprintf (of, "@%-o", (nval + addr + 4) & 0177777); + break; + } /* end case */ + +return ((reg == 07)? pcwd[mode]: rgwd[mode]); +} + +/* Symbolic decode + + Inputs: + *of = output stream + addr = current PC + *val = values to decode + *uptr = pointer to unit + sw = switches + Outputs: + return = if >= 0, error code + if < 0, number of extra words retired +*/ + +t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, + UNIT *uptr, int32 sw) +{ +int32 cflag, i, j, c1, c2, c3, inst, fac, srcm, srcr, dstm, dstr; +int32 bflag, l8b, brdisp, wd1, wd2; +extern int32 FPS; + +bflag = 0; /* assume 16b */ +cflag = (uptr == NULL) || (uptr == &cpu_unit); /* cpu? */ +if (!cflag) { /* not cpu? */ + DEVICE *dptr = find_dev_from_unit (uptr); + if (dptr == NULL) + return SCPE_IERR; + if (dptr->dwidth < 16) + bflag = 1; + } + +if (sw & SWMASK ('A')) { /* ASCII? */ + if (bflag) + c1 = val[0] & 0177; + else c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0177; + fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); + return 0; + } +if (sw & SWMASK ('B')) { /* byte? */ + if (bflag) + c1 = val[0] & 0177; + else c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0377; + fprintf (of, "%o", c1); + return 0; + } +if (bflag) /* 16b only */ + return SCPE_ARG; + +if (sw & SWMASK ('C')) { /* character? */ + c1 = val[0] & 0177; + c2 = (val[0] >> 8) & 0177; + fprintf (of, (c1 < 040)? "<%03o>": "%c", c1); + fprintf (of, (c2 < 040)? "<%03o>": "%c", c2); + return -1; + } +if (sw & SWMASK ('R')) { /* radix 50? */ + if (val[0] > 0174777) /* max value */ + return SCPE_ARG; + c3 = val[0] % 050; + c2 = (val[0] / 050) % 050; + c1 = val[0] / (050 * 050); + fprintf (of, "%c%c%c", r50_to_asc[c1], + r50_to_asc[c2], r50_to_asc[c3]); + return -1; + } +if (!(sw & SWMASK ('M'))) + return SCPE_ARG; + +inst = val[0] | ((FPS << (I_V_L - FPS_V_L)) & I_L) | + ((FPS << (I_V_D - FPS_V_D)) & I_D); /* inst + fp mode */ +for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ + j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */ + if ((opc_val[i] & 0777777) == (inst & masks[j])) { /* match? */ + srcm = (inst >> 6) & 077; /* opr fields */ + srcr = srcm & 07; + fac = srcm & 03; + dstm = inst & 077; + dstr = dstm & 07; + l8b = inst & 0377; + wd1 = wd2 = 0; + switch (j) { /* case on class */ + + case I_V_NPN: case I_V_CCC: case I_V_CCS: /* no operands */ + fprintf (of, "%s", opcode[i]); + break; + + case I_V_REG: /* reg */ + fprintf (of, "%s %-s", opcode[i], rname[dstr]); + break; + + case I_V_SOP: /* sop */ + fprintf (of, "%s ", opcode[i]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE); + break; + + case I_V_3B: /* 3b */ + fprintf (of, "%s %-o", opcode[i], dstr); + break; + + case I_V_FOP: /* fop */ + fprintf (of, "%s ", opcode[i]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE); + break; + + case I_V_AFOP: /* afop */ + fprintf (of, "%s %s,", opcode[i], fname[fac]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, FALSE); + break; + + case I_V_6B: /* 6b */ + fprintf (of, "%s %-o", opcode[i], dstm); + break; + + case I_V_BR: /* cond branch */ + fprintf (of, "%s ", opcode[i]); + brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777; + if (cflag) + fprintf (of, "%-o", (addr + brdisp) & 0177777); + else if (brdisp < 01000) + fprintf (of, ".+%-o", brdisp); + else fprintf (of, ".-%-o", 0200000 - brdisp); + break; + + case I_V_8B: /* 8b */ + fprintf (of, "%s %-o", opcode[i], l8b); + break; + + case I_V_SOB: /* sob */ + fprintf (of, "%s %s,", opcode[i], rname[srcr]); + brdisp = (dstm * 2) - 2; + if (cflag) + fprintf (of, "%-o", (addr - brdisp) & 0177777); + else if (brdisp <= 0) + fprintf (of, ".+%-o", -brdisp); + else fprintf (of, ".-%-o", brdisp); + break; + + case I_V_RSOP: /* rsop */ + fprintf (of, "%s %s,", opcode[i], rname[srcr]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE); + break; + + case I_V_SOPR: /* sopr */ + fprintf (of, "%s ", opcode[i]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE); + fprintf (of, ",%s", rname[srcr]); + break; + + case I_V_ASOP: case I_V_ASMD: /* asop, asmd */ + fprintf (of, "%s %s,", opcode[i], fname[fac]); + wd1 = fprint_spec (of, addr, dstm, val[1], cflag, TRUE); + break; + + case I_V_DOP: /* dop */ + fprintf (of, "%s ", opcode[i]); + wd1 = fprint_spec (of, addr, srcm, val[1], cflag, TRUE); + fprintf (of, ","); + wd2 = fprint_spec (of, addr - wd1 - wd1, dstm, + val[1 - wd1], cflag, TRUE); + break; + } /* end case */ + return ((wd1 + wd2) * 2) - 1; + } /* end if */ + } /* end for */ +return SCPE_ARG; /* no match */ +} + +#define A_PND 100 /* # seen */ +#define A_MIN 040 /* -( seen */ +#define A_PAR 020 /* (Rn) seen */ +#define A_REG 010 /* Rn seen */ +#define A_PLS 004 /* + seen */ +#define A_NUM 002 /* number seen */ +#define A_REL 001 /* relative addr seen */ + +/* Register number + + Inputs: + *cptr = pointer to input string + *strings = pointer to register names + mchar = character to match after register name + Outputs: + rnum = 0..7 if a legitimate register + < 0 if error +*/ + +int32 get_reg (char *cptr, const char *strings[], char mchar) +{ +int32 i; + +if (*(cptr + 2) != mchar) + return -1; +for (i = 0; i < 8; i++) { + if (strncmp (cptr, strings[i], 2) == 0) + return i; + } +return -1; +} + +/* Number or memory address + + Inputs: + *cptr = pointer to input string + *dptr = pointer to output displacement + *pflag = pointer to accumulating flags + Outputs: + cptr = pointer to next character in input string + NULL if parsing error + + Flags: 0 (no result), A_NUM (number), A_REL (relative) +*/ + +char *get_addr (char *cptr, int32 *dptr, int32 *pflag) +{ +int32 val, minus; +char *tptr; + +minus = 0; + +if (*cptr == '.') { /* relative? */ + *pflag = *pflag | A_REL; + cptr++; + } +if (*cptr == '+') { /* +? */ + *pflag = *pflag | A_NUM; + cptr++; + } +if (*cptr == '-') { /* -? */ + *pflag = *pflag | A_NUM; + minus = 1; + cptr++; + } +errno = 0; +val = strtoul (cptr, &tptr, 8); +if (cptr == tptr) { /* no number? */ + if (*pflag == (A_REL + A_NUM)) /* .+, .-? */ + return NULL; + *dptr = 0; + return cptr; + } +if (errno || (*pflag == A_REL)) /* .n? */ + return NULL; +*dptr = (minus? -val: val) & 0177777; +*pflag = *pflag | A_NUM; +return tptr; +} + +/* Specifier decode + + Inputs: + *cptr = pointer to input string + addr = current PC + n1 = 0 if no extra word used + -1 if extra word used in prior decode + *sptr = pointer to output specifier + *dptr = pointer to output displacement + cflag = true if parsing for the CPU + iflag = true if integer specifier + Outputs: + status = = -1 extra word decoded + = 0 ok + = +1 error +*/ + +t_stat get_spec (char *cptr, t_addr addr, int32 n1, int32 *sptr, t_value *dptr, + int32 cflag, int32 iflag) +{ +int32 reg, indir, pflag, disp; + +indir = 0; /* no indirect */ +pflag = 0; + +if (*cptr == '@') { /* indirect? */ + indir = 010; + cptr++; + } +if (*cptr == '#') { /* literal? */ + pflag = pflag | A_PND; + cptr++; + } +if (strncmp (cptr, "-(", 2) == 0) { /* autodecrement? */ + pflag = pflag | A_MIN; + cptr++; + } +else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) + return 1; +if (*cptr == '(') { /* register index? */ + pflag = pflag | A_PAR; + if ((reg = get_reg (cptr + 1, rname, ')')) < 0) + return 1; + cptr = cptr + 4; + if (*cptr == '+') { /* autoincrement? */ + pflag = pflag | A_PLS; + cptr++; + } + } +else if ((reg = get_reg (cptr, iflag? rname: fname, 0)) >= 0) { + pflag = pflag | A_REG; + cptr = cptr + 2; + } +if (*cptr != 0) /* all done? */ + return 1; +switch (pflag) { /* case on syntax */ + + case A_REG: /* Rn, @Rn */ + *sptr = indir + reg; + return 0; + + case A_PAR: /* (Rn), @(Rn) */ + if (indir) { /* @(Rn) = @0(Rn) */ + *sptr = 070 + reg; + *dptr = 0; + return -1; + } + else *sptr = 010 + reg; + return 0; + + case A_PAR+A_PLS: /* (Rn)+, @(Rn)+ */ + *sptr = 020 + indir + reg; + return 0; + + case A_MIN+A_PAR: /* -(Rn), @-(Rn) */ + *sptr = 040 + indir + reg; + return 0; + + case A_NUM+A_PAR: /* d(Rn), @d(Rn) */ + *sptr = 060 + indir + reg; + *dptr = disp; + return -1; + + case A_PND+A_REL: case A_PND+A_REL+A_NUM: /* #.+n, @#.+n */ + if (!cflag) + return 1; + disp = (disp + addr) & 0177777; /* fall through */ + case A_PND+A_NUM: /* #n, @#n */ + *sptr = 027 + indir; + *dptr = disp; + return -1; + + case A_REL: case A_REL+A_NUM: /* .+n, @.+n */ + *sptr = 067 + indir; + *dptr = (disp - 4 + (2 * n1)) & 0177777; + return -1; + + case A_NUM: /* n, @n */ + if (cflag) { /* CPU - use rel */ + *sptr = 067 + indir; + *dptr = (disp - addr - 4 + (2 * n1)) & 0177777; + } + else { + if (indir) return 1; /* other - use abs */ + *sptr = 037; + *dptr = disp; + } + return -1; + + default: + return 1; + } /* end case */ +} + +/* Symbolic input + + Inputs: + *cptr = pointer to input string + addr = current PC + *uptr = pointer to unit + *val = pointer to output values + sw = switches + Outputs: + status = > 0 error code + <= 0 -number of extra words +*/ + +t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw) +{ +int32 bflag, cflag, d, i, j, reg, spec, n1, n2, disp, pflag; +t_value by; +t_stat r; +char *tptr, gbuf[CBUFSIZE]; + +bflag = 0; /* assume 16b */ +cflag = (uptr == NULL) || (uptr == &cpu_unit); /* cpu? */ +if (!cflag) { /* not cpu? */ + DEVICE *dptr = find_dev_from_unit (uptr); + if (dptr == NULL) + return SCPE_IERR; + if (dptr->dwidth < 16) + bflag = 1; + } + +while (isspace (*cptr)) cptr++; /* absorb spaces */ +if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; + if (bflag) + val[0] = (t_value) cptr[0]; + else val[0] = (addr & 1)? + (val[0] & 0377) | (((t_value) cptr[0]) << 8): + (val[0] & ~0377) | ((t_value) cptr[0]); + return 0; + } +if (sw & SWMASK ('B')) { /* byte? */ + by = get_uint (cptr, 8, 0377, &r); /* get byte */ + if (r != SCPE_OK) + return SCPE_ARG; + if (bflag) + val[0] = by; + else val[0] = (addr & 1)? + (val[0] & 0377) | (by << 8): + (val[0] & ~0377) | by; + return 0; + } +if (bflag) + return SCPE_ARG; + +if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */ + if (cptr[0] == 0) /* must have 1 char */ + return SCPE_ARG; + val[0] = ((t_value) cptr[1] << 8) | (t_value) cptr[0]; + return -1; + } +if (sw & SWMASK ('R')) /* radix 50 */ + return SCPE_ARG; + +cptr = get_glyph (cptr, gbuf, 0); /* get opcode */ +n1 = n2 = pflag = 0; +for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ; +if (opcode[i] == NULL) + return SCPE_ARG; +val[0] = opc_val[i] & 0177777; /* get value */ +j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */ + +switch (j) { /* case on class */ + + case I_V_NPN: /* no operand */ + break; + + case I_V_REG: /* register */ + cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ + if ((reg = get_reg (gbuf, rname, 0)) < 0) + return SCPE_ARG; + val[0] = val[0] | reg; + break; + + case I_V_3B: case I_V_6B: case I_V_8B: /* xb literal */ + cptr = get_glyph (cptr, gbuf, 0); /* get literal */ + d = get_uint (gbuf, 8, (1 << j) - 1, &r); + if (r != SCPE_OK) + return SCPE_ARG; + val[0] = val[0] | d; /* put in place */ + break; + + case I_V_BR: /* cond br */ + cptr = get_glyph (cptr, gbuf, 0); /* get address */ + tptr = get_addr (gbuf, &disp, &pflag); /* parse */ + if ((tptr == NULL) || (*tptr != 0)) + return SCPE_ARG; + if ((pflag & A_REL) == 0) { + if (cflag) + disp = (disp - addr) & 0177777; + else return SCPE_ARG; + } + if ((disp & 1) || ((disp > 0400) && (disp < 0177402))) + return SCPE_ARG; + val[0] = val[0] | (((disp - 2) >> 1) & 0377); + break; + + case I_V_SOB: /* sob */ + cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ + if ((reg = get_reg (gbuf, rname, 0)) < 0) + return SCPE_ARG; + val[0] = val[0] | (reg << 6); + cptr = get_glyph (cptr, gbuf, 0); /* get address */ + tptr = get_addr (gbuf, &disp, &pflag); /* parse */ + if ((tptr == NULL) || (*tptr != 0)) + return SCPE_ARG; + if ((pflag & A_REL) == 0) { + if (cflag) + disp = (disp - addr) & 0177777; + else return SCPE_ARG; + } + if ((disp & 1) || ((disp > 2) && (disp < 0177604))) + return SCPE_ARG; + val[0] = val[0] | (((2 - disp) >> 1) & 077); + break; + + case I_V_RSOP: /* reg, sop */ + cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ + if ((reg = get_reg (gbuf, rname, 0)) < 0) + return SCPE_ARG; + val[0] = val[0] | (reg << 6); /* fall through */ + case I_V_SOP: /* sop */ + cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ + if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0) + return SCPE_ARG; + val[0] = val[0] | spec; + break; + + case I_V_SOPR: /* dop, reg */ + cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ + if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0) + return SCPE_ARG; + val[0] = val[0] | spec; + cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ + if ((reg = get_reg (gbuf, rname, 0)) < 0) + return SCPE_ARG; + val[0] = val[0] | (reg << 6); + break; + + case I_V_AFOP: case I_V_ASOP: case I_V_ASMD: /* fac, (s)fop */ + cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ + if ((reg = get_reg (gbuf, fname, 0)) < 0) + return SCPE_ARG; + if (reg > 3) + return SCPE_ARG; + val[0] = val[0] | (reg << 6); /* fall through */ + case I_V_FOP: /* fop */ + cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ + if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, + (j == I_V_ASOP) || (j == I_V_ASMD))) > 0) + return SCPE_ARG; + val[0] = val[0] | spec; + break; + + case I_V_DOP: /* double op */ + cptr = get_glyph (cptr, gbuf, ','); /* get glyph */ + if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag, TRUE)) > 0) + return SCPE_ARG; + val[0] = val[0] | (spec << 6); + cptr = get_glyph (cptr, gbuf, 0); /* get glyph */ + if ((n2 = get_spec (gbuf, addr, n1, &spec, &val[1 - n1], + cflag, TRUE)) > 0) + return SCPE_ARG; + val[0] = val[0] | spec; + break; + + case I_V_CCC: case I_V_CCS: /* cond code oper */ + for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0; + cptr = get_glyph (cptr, gbuf, 0)) { + for (i = 0; (opcode[i] != NULL) && + (strcmp (opcode[i], gbuf) != 0) ; i++) ; + if ((((opc_val[i] >> I_V_CL) & I_M_CL) != j) || + (opcode[i] == NULL)) + return SCPE_ARG; + val[0] = val[0] | (opc_val[i] & 0177777); + } + break; + + default: + return SCPE_ARG; + } + +if (*cptr != 0) /* junk at end? */ + return SCPE_ARG; +return ((n1 + n2) * 2) - 1; +} diff --git a/PDP11/pdp11_cis.c b/PDP11/pdp11_cis.c index 24dd0168..881c7fab 100644 --- a/PDP11/pdp11_cis.c +++ b/PDP11/pdp11_cis.c @@ -1324,7 +1324,7 @@ return; (a^x)(b^y) TMP Note that the low bit of each digit is the same as the low bit of - the sum of the digits, ignoring the cary, since the low bit of the + the sum of the digits, ignoring the carry, since the low bit of the sum is the xor of the bits. Now compute I+J+66 to get decimal addition with carry forced left diff --git a/PDP11/pdp11_cpu.c b/PDP11/pdp11_cpu.c index 1a11482f..1c4a9cf3 100644 --- a/PDP11/pdp11_cpu.c +++ b/PDP11/pdp11_cpu.c @@ -1,6 +1,6 @@ /* pdp11_cpu.c: PDP-11 CPU simulator - Copyright (c) 1993-2012, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ cpu PDP-11 CPU + 10-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist) 29-Apr-12 RMS Fixed compiler warning (Mark Pizzolato) 19-Mar-12 RMS Fixed declaration of sim_switches (Mark Pizzolato) 29-Dec-08 RMS Fixed failure to clear cpu_bme on RESET (Walter Mueller) @@ -696,7 +697,8 @@ if (abortval != 0) { if ((trapea > 0) && stop_vecabort) reason = STOP_VECABORT; if ((trapea < 0) && /* stack push abort? */ - (CPUT (STOP_STKA) || stop_spabort)) reason = STOP_SPABORT; + (CPUT (STOP_STKA) || stop_spabort)) + reason = STOP_SPABORT; if (trapea == ~MD_KER) { /* kernel stk abort? */ setTRAP (TRAP_RED); setCPUERR (CPUE_RED); @@ -722,7 +724,7 @@ while (reason == 0) { cpu_astop = 0; reason = SCPE_STOP; break; - } + } if (sim_interval <= 0) { /* intv cnt expired? */ reason = sim_process_event (); /* process events */ @@ -815,7 +817,7 @@ while (reason == 0) { if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ reason = STOP_IBKPT; /* stop simulation */ continue; - } + } if (update_MM) { /* if mm not frozen */ MMR1 = 0; @@ -913,7 +915,8 @@ while (reason == 0) { trap_req = calc_ints (ipl, trap_req); JMP_PC (src); if (CPUT (HAS_RTT) && tbit && /* RTT impl? */ - (IR == 000002)) setTRAP (TRAP_TRC); /* RTI immed trap */ + (IR == 000002)) + setTRAP (TRAP_TRC); /* RTI immed trap */ break; case 7: /* MFPT */ if (CPUT (HAS_MFPT)) /* implemented? */ @@ -1358,7 +1361,8 @@ while (reason == 0) { } else { dst = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - if (!dstreg) ea = GeteaW (dstspec); + if (!dstreg) + ea = GeteaW (dstspec); } N = GET_SIGN_W (dst); Z = GET_Z (dst); @@ -1894,6 +1898,7 @@ while (reason == 0) { R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; + /* Notes: - MTPS cannot alter the T bit - MxPD must mask GeteaW returned address, dspace is from cm not pm @@ -1987,7 +1992,8 @@ while (reason == 0) { } else { dst = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); - if (!dstreg) ea = GeteaB (dstspec); + if (!dstreg) + ea = GeteaB (dstspec); } N = GET_SIGN_B (dst); Z = GET_Z (dst); @@ -2167,20 +2173,20 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 2: /* (R)+ */ R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (020 | reg); return (adr | ds); case 3: /* @(R)+ */ R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (020 | reg); adr = ReadW (adr | ds); return (adr | dsenable); case 4: /* -(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (0360 | reg); if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); @@ -2188,7 +2194,7 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 5: /* @-(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (0360 | reg); if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); @@ -2225,13 +2231,13 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 2: /* (R)+ */ delta = 1 + (reg >= 6); /* 2 if R6, PC */ R[reg] = ((adr = R[reg]) + delta) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 ((delta << 3) | reg); return (adr | ds); case 3: /* @(R)+ */ R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (020 | reg); adr = ReadW (adr | ds); return (adr | dsenable); @@ -2239,7 +2245,7 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 4: /* -(R) */ delta = 1 + (reg >= 6); /* 2 if R6, PC */ adr = R[reg] = (R[reg] - delta) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 ((((-delta) & 037) << 3) | reg); if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); @@ -2247,7 +2253,7 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 5: /* @-(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (0360 | reg); if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); diff --git a/PDP11/pdp11_cpumod.c b/PDP11/pdp11_cpumod.c index 80a52dc4..171f51b1 100644 --- a/PDP11/pdp11_cpumod.c +++ b/PDP11/pdp11_cpumod.c @@ -1,6 +1,6 @@ /* pdp11_cpumod.c: PDP-11 CPU model-specific features - Copyright (c) 2004-2008, Robert M Supnik + Copyright (c) 2004-2013, 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 @@ system PDP-11 model-specific registers + 06-Jun-13 RMS Fixed change model to set memory size last 20-May-08 RMS Added JCSR default for KDJ11B, KDJ11E 22-Apr-08 RMS Fixed write behavior of 11/70 MBRK, LOSIZE, HISIZE (Walter Mueller) @@ -1092,14 +1093,14 @@ if (val >= MOD_MAX) return SCPE_IERR; if (val == (int32) cpu_model) return SCPE_OK; -if (MEMSIZE > cpu_tab[val].maxm) - cpu_set_size (uptr, cpu_tab[val].maxm, NULL, NULL); -if (MEMSIZE > cpu_tab[val].maxm) - return SCPE_INCOMP; cpu_model = val; cpu_type = 1u << cpu_model; cpu_opt = cpu_tab[cpu_model].std; cpu_set_bus (cpu_opt); +if (MEMSIZE > cpu_tab[val].maxm) + cpu_set_size (uptr, cpu_tab[val].maxm, NULL, NULL); +if (MEMSIZE > cpu_tab[val].maxm) + return SCPE_INCOMP; reset_all (0); /* reset world */ return SCPE_OK; } diff --git a/PDP11/pdp11_cr.c b/PDP11/pdp11_cr.c index d8ee8258..699c63f1 100644 --- a/PDP11/pdp11_cr.c +++ b/PDP11/pdp11_cr.c @@ -87,6 +87,7 @@ Revision History: + 06-Jun-13 RMS Default start state is disabled 03-Jan-10 JAD Eliminate gcc warnings 01-Feb-07 RMS Added PDP-10 support 12-May-06 JAD Modify the DEBUG code to use the SIMH DEBUG_x @@ -181,7 +182,7 @@ extern int32 int_req[IPL_HLVL]; #else /* PDP-11 version */ #include "pdp11_defs.h" extern int32 int_req[IPL_HLVL]; -#define DFLT_DIS (0) +#define DFLT_DIS (DEV_DIS) #define DFLT_CR11 (UNIT_CR11) #define DFLT_CPM 285 #endif diff --git a/PDP11/pdp11_dc.c b/PDP11/pdp11_dc.c index 1c653fe8..15c40bf4 100644 --- a/PDP11/pdp11_dc.c +++ b/PDP11/pdp11_dc.c @@ -1,6 +1,6 @@ /* pdp11_dc.c: PDP-11 DC11 multiple terminal interface simulator - Copyright (c) 1993-2012, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ dci,dco DC11 terminal input/output + 11-Oct-2013 RMS Poll DCI immediately after attach to pick up connect 18-Apr-2012 RMS Modified to use clock coscheduling 17-Aug-2011 RMS Added AUTOCONFIGURE modifier 19-Nov-2008 RMS Revised for common TMXR show routines @@ -541,7 +542,7 @@ t_stat r; r = tmxr_attach (&dcx_desc, uptr, cptr); /* attach */ if (r != SCPE_OK) /* error? */ return r; -sim_activate (uptr, tmxr_poll); /* start poll */ +sim_activate (uptr, 0); /* start poll at once */ return SCPE_OK; } diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h index 8f2d07ab..eefbd577 100644 --- a/PDP11/pdp11_defs.h +++ b/PDP11/pdp11_defs.h @@ -1,6 +1,6 @@ /* pdp11_defs.h: PDP-11 simulator definitions - Copyright (c) 1993-2011, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ The author gratefully acknowledges the help of Max Burnet, Megan Gentry, and John Wilson in resolving questions about the PDP-11 + 02-Sep-13 RMS Added third Massbus adapter and RS drive + 12-Dec-12 RMS Fixed base address for RQB, RQC, RQD 11-Dec-11 RMS Fixed priority of PIRQ vs IO; added INT_INTERNALn 22-May-10 RMS Added check for 64b definitions 19-Nov-08 RMS Moved I/O support routines to I/O library @@ -524,14 +526,16 @@ typedef struct pdp_dib DIB; #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 IOBA_RQC (IOBA_RQB + IOLN_RQB) #define IOLN_RQC 004 -#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC) +#define IOBA_RQD (IOBA_RQC + IOLN_RQC) #define IOLN_RQD 004 #define IOBA_VH (IOPAGEBASE + 000440) /* DHQ11 */ #define IOLN_VH 020 #define IOBA_UBM (IOPAGEBASE + 010200) /* Unibus map */ #define IOLN_UBM (UBM_LNT_LW * sizeof (int32)) +#define IOBA_RS (IOPAGEBASE + 012040) /* RHC: RS03/RS04 */ +#define IOLN_RS 040 #define IOBA_KG (IOPAGEBASE + 010700) /* KG11-A */ #define IOLN_KG 006 #define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */ @@ -546,7 +550,7 @@ typedef struct pdp_dib DIB; #define IOLN_KIPAR 020 #define IOBA_KDPAR (IOPAGEBASE + 012360) #define IOLN_KDPAR 020 -#define IOBA_TU (IOPAGEBASE + 012440) /* TU */ +#define IOBA_TU (IOPAGEBASE + 012440) /* RHB: TU */ #define IOLN_TU 040 #define IOBA_MMR3 (IOPAGEBASE + 012516) /* MMR3 */ #define IOLN_MMR3 002 @@ -570,7 +574,7 @@ typedef struct pdp_dib DIB; #define IOLN_XU 010 #define IOBA_DL (IOPAGEBASE + 016500) /* extra KL11/DL11 */ #define IOLN_DL (DLX_LINES * 010) -#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */ +#define IOBA_RP (IOPAGEBASE + 016700) /* RHA: RP/RM */ #define IOLN_RP 054 #define IOBA_CR (IOPAGEBASE + 017160) /* CD/CR/CM */ #define IOLN_CR 010 @@ -662,6 +666,7 @@ typedef struct pdp_dib DIB; #define INT_V_TU 15 #define INT_V_RF 16 #define INT_V_RC 17 +#define INT_V_RS 18 #define INT_V_PIR4 0 /* BR4 */ #define INT_V_TTI 1 @@ -705,6 +710,7 @@ typedef struct pdp_dib DIB; #define INT_TU (1u << INT_V_TU) #define INT_RF (1u << INT_V_RF) #define INT_RC (1u << INT_V_RC) +#define INT_RS (1u << INT_V_RS) #define INT_PIR4 (1u << INT_V_PIR4) #define INT_TTI (1u << INT_V_TTI) #define INT_TTO (1u << INT_V_TTO) @@ -751,6 +757,7 @@ typedef struct pdp_dib DIB; #define IPL_TU 5 #define IPL_RF 5 #define IPL_RC 5 +#define IPL_RS 5 #define IPL_PTR 4 #define IPL_PTP 4 #define IPL_TTI 4 @@ -788,6 +795,7 @@ typedef struct pdp_dib DIB; #define VEC_RL 0160 #define VEC_LPT 0200 #define VEC_RF 0204 +#define VEC_RS 0204 #define VEC_HK 0210 #define VEC_RC 0210 #define VEC_RK 0220 @@ -819,9 +827,10 @@ typedef struct pdp_dib DIB; /* Massbus definitions */ -#define MBA_NUM 2 /* number of MBA's */ +#define MBA_NUM 3 /* number of MBA's */ #define MBA_RP 0 /* MBA for RP */ #define MBA_TU 1 /* MBA for TU */ +#define MBA_RS 2 /* MBA for RS */ #define MBA_RMASK 037 /* max 32 reg */ #define MBE_NXD 1 /* nx drive */ #define MBE_NXR 2 /* nx reg */ diff --git a/PDP11/pdp11_dl.c b/PDP11/pdp11_dl.c index 2caf6832..f6b500dc 100644 --- a/PDP11/pdp11_dl.c +++ b/PDP11/pdp11_dl.c @@ -1,6 +1,6 @@ /* pdp11_dl.c: PDP-11 multiple terminal interface simulator - Copyright (c) 1993-2012, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ dli,dlo DL11 terminal input/output + 11-Oct-2013 RMS Poll DLI immediately after attach to pick up connect 18-Apr-2012 RMS Modified to use clock coscheduling 17-Aug-2011 RMS Added AUTOCONFIGURE modifier 19-Nov-2008 RMS Revised for common TMXR show routines @@ -500,7 +501,7 @@ t_stat r; r = tmxr_attach (&dlx_desc, uptr, cptr); /* attach */ if (r != SCPE_OK) /* error */ return r; -sim_activate (uptr, tmxr_poll); /* start poll */ +sim_activate (uptr, 0); /* start poll at once */ return SCPE_OK; } diff --git a/PDP11/pdp11_fp.c b/PDP11/pdp11_fp.c index 2d1db393..ad2041ad 100644 --- a/PDP11/pdp11_fp.c +++ b/PDP11/pdp11_fp.c @@ -1,6 +1,6 @@ /* pdp11_fp.c: PDP-11 floating point simulator (32b version) - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2013, 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,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. + 20-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist) 22-Sep-05 RMS Fixed declarations (Sterling Garwood) 04-Oct-04 RMS Added FIS instructions 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict @@ -106,7 +107,7 @@ #define FPS_C (1u << FPS_V_C) #define FPS_CC (FPS_N + FPS_Z + FPS_V + FPS_C) #define FPS_RW (FPS_ER + FPS_ID + FPS_IUV + FPS_IU + FPS_IV + \ - FPS_IC + FPS_D + FPS_L + FPS_T + FPS_CC) + FPS_IC + FPS_D + FPS_L + FPS_T + FPS_CC) /* Floating point exception codes */ @@ -584,20 +585,20 @@ switch (spec >> 3) { /* case on spec */ if (reg == 7) len = 2; R[reg] = ((adr = R[reg]) + len) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = (len << 3) | reg; return (adr | ds); case 3: /* @(R)+ */ R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = 020 | reg; adr = ReadW (adr | ds); return (adr | dsenable); case 4: /* -(R) */ adr = R[reg] = (R[reg] - len) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = (((-len) & 037) << 3) | reg; if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); @@ -605,7 +606,7 @@ switch (spec >> 3) { /* case on spec */ case 5: /* @-(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = 0360 | reg; if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); @@ -675,8 +676,10 @@ else { (ReadW (exta | ((VA + 6) & 0177777)) << FP_V_F3); else fptr->l = 0; } -if ((GET_SIGN (fptr->h) != 0) && (GET_EXP (fptr->h) == 0) && - (fpnotrap (FEC_UNDFV) == 0)) ABORT (TRAP_INT); +if ((GET_SIGN (fptr->h) != 0) && + (GET_EXP (fptr->h) == 0) && + (fpnotrap (FEC_UNDFV) == 0)) + ABORT (TRAP_INT); return; } @@ -744,7 +747,7 @@ if (IR & 000740) { /* defined? */ if (CPUT (CPUT_03)) /* 11/03 reads word */ ReadW (exta | R[reg]); ABORT (TRAP_ILL); - } + } FEC = 0; /* no errors */ FPS = FPS_IU|FPS_IV; /* trap ovf,unf */ @@ -1227,7 +1230,8 @@ int32 fpnotrap (int32 code) { static const int32 test_code[] = { 0, 0, 0, FPS_IC, FPS_IV, FPS_IU, FPS_IUV }; -if ((code >= FEC_ICVT) && (code <= FEC_UNDFV) && +if ((code >= FEC_ICVT) && + (code <= FEC_UNDFV) && ((FPS & test_code[code >> 1]) == 0)) return TRUE; FPS = FPS | FPS_ER; diff --git a/PDP11/pdp11_hk.c b/PDP11/pdp11_hk.c index 72aa9cfd..79169342 100644 --- a/PDP11/pdp11_hk.c +++ b/PDP11/pdp11_hk.c @@ -1,6 +1,6 @@ /* pdp11_hk.c - RK611/RK06/RK07 disk controller - Copyright (c) 1993-2012, Robert M Supnik + Copyright (c) 1993-2013, 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,8 +25,14 @@ hk RK611/RK06/RK07 disk + 01-Sep-13 RMS Revised error handling to command-response model + Revised interrupt logic to follow the hardware + 10-Jun-13 RMS Fixed bug to write through end of sector (Oleg Safiullin) + 18-Apr-13 RMS Fixed ATN setting on errors + Changed wrong drive type to status, not fatal error + 10-Dec-12 RMS Fixed interrupt logic and CCLR unit cancellation 19-Mar-12 RMS Fixed declaration of cpu_opt (Mark Pizzolato) - 29-Apr-07 RMS NOP and DCLR (at least) do not check drive type + 29-Apr-07 RMS NOP and DCLR (at least) do not check drive type [wrong] MR2 and MR3 only updated on NOP 17-Nov-05 RMS Removed unused variable 13-Nov-05 RMS Fixed overlapped seek interaction with NOP, DCLR, PACK @@ -41,16 +47,13 @@ 29-Dec-03 RMS Added 18b Qbus support 25-Apr-03 RMS Revised for extended file support - This is a somewhat abstracted implementation of the RK611, more closely - modelled on third party clones than DEC's own implementation. In particular, - the drive-to-controller serial communications system is simulated only at - a level equal to the Emulex SC21. - - The RK611 functions only in 18b Unibus systems with I/O maps. The Emulex - SC02/C was a Qbus work-alike with a unique extension to 22b addressing. It + The RK611 functions only in 18b Unibus systems with I/O maps. The Emulex + SC02/C was a Qbus work-alike with a unique extension to 22b addressing. It was only supported in Ultrix-11 and other third party software. This module includes ideas from a previous implementation by Fred Van Kempen. + However, the interrupt logic has been rewritten to follow the bug-for-bug + peculiarities of the RK611 controller. */ #if defined (VM_PDP10) /* PDP10 version */ @@ -97,7 +100,7 @@ extern uint16 *M; #define CYL u3 /* current cylinder */ #define FNC u4 /* function */ -/* HKCS1 - 177440 - control/status 1 */ +/* HKCS1 - 177440 - control/status 1 ^ = calculated dynamically */ #define CS1_GO CSR_GO /* go */ #define CS1_V_FNC 1 /* function pos */ @@ -128,7 +131,7 @@ extern uint16 *M; #define CS1_CTO 0004000 /* ctrl timeout NI */ #define CS1_FMT 0010000 /* 16b/18b NI */ #define CS1_PAR 0020000 /* par err NI */ -#define CS1_DI 0040000 /* drive intr */ +#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) @@ -198,7 +201,7 @@ extern uint16 *M; #define ER_SKI 0000002 /* seek incomp */ #define ER_NXF 0000004 /* non-exec func */ #define ER_PAR 0000010 /* parity err */ -#define ER_FER 0000020 /* format err NI */ +#define ER_FER 0000020 /* format err */ #define ER_DTY 0000040 /* drive type err */ #define ER_ECH 0000100 /* ECC hard err NI */ #define ER_BSE 0000200 /* bad sector err NI */ @@ -340,6 +343,9 @@ int32 hkmr2 = 0; int32 hkmr3 = 0; int32 hkdc = 0; /* cylinder */ int32 hkspr = 0; /* spare */ +int32 hkci = 0; /* ctlr interrupt */ +int32 hkdi = 0; /* drive interrupt */ +int32 hkei = 0; /* error interrupt */ int32 hk_cwait = 5; /* command time */ int32 hk_swait = 10; /* seek time */ int32 hk_rwait = 10; /* rotate time */ @@ -347,8 +353,13 @@ 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 */ -static uint8 reg_in_drive[16] = { +static const uint8 reg_in_drive[16] = { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static const char* reg_name[] = { + "HKCS1", "HKWC", "HKBA", "HKDA", + "HKCS2", "HKDS", "HKER", "HKAS", + "HKDC", "spare", "HKDB", "HKMR", + "HKEC1", "HKEC2", "HKMR2", "HKMR3" }; DEVICE hk_dev; t_stat hk_rd (int32 *data, int32 PA, int32 access); @@ -358,11 +369,12 @@ t_stat hk_reset (DEVICE *dptr); t_stat hk_boot (int32 unitno, DEVICE *dptr); t_stat hk_attach (UNIT *uptr, char *cptr); t_stat hk_detach (UNIT *uptr); +int32 hk_inta (void); int32 hk_rdmr2 (int32 msg); int32 hk_rdmr3 (int32 msg); void update_hkcs (int32 flags, int32 drv); void update_hkds (int32 drv); -void hk_cmderr (int32 err, int32 drv); +void hk_err (int32 cs1e, int32 cs2e, int32 drve, int32 drv); void hk_go (int32 drv); t_stat hk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat hk_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); @@ -377,7 +389,7 @@ t_stat hk_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc); DIB hk_dib = { IOBA_HK, IOLN_HK, &hk_rd, &hk_wr, - 1, IVCL (HK), VEC_HK, { NULL } + 1, IVCL (HK), VEC_HK, { &hk_inta } }; UNIT hk_unit[] = { @@ -414,6 +426,9 @@ REG hk_reg[] = { { GRDATA (HKMR2, hkmr2, DEV_RDX, 16, 0), REG_RO }, { GRDATA (HKMR3, hkmr3, DEV_RDX, 16, 0), REG_RO }, { GRDATA (HKSPR, hkspr, DEV_RDX, 16, 0) }, + { FLDATA (HKCI, hkci, 0) }, + { FLDATA (HKDI, hkdi, 0) }, + { FLDATA (HKEI, hkei, 0) }, { FLDATA (INT, IREQ (HK), INT_V_HK) }, { FLDATA (ERR, hkcs1, CSR_V_ERR) }, { FLDATA (DONE, hkcs1, CSR_V_DONE) }, @@ -421,6 +436,7 @@ REG hk_reg[] = { { 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 (M2TIME, hk_min2wait, 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) }, @@ -485,8 +501,7 @@ int32 drv, i, j; drv = GET_UNIT (hkcs2); /* get current unit */ j = (PA >> 1) & 017; /* get reg offset */ if (reg_in_drive[j] && (hk_unit[drv].flags & UNIT_DIS)) { /* nx disk */ - hkcs2 = hkcs2 | CS2_NED; /* set error flag */ - update_hkcs (0, drv); + hk_err (CS1_ERR|CS1_DONE, CS2_NED, 0, drv); /* set err, stop op */ *data = 0; return SCPE_OK; } @@ -495,7 +510,7 @@ update_hkcs (0, drv); /* update status */ switch (j) { /* decode PA<4:1> */ case 000: /* HKCS1 */ - *data = hkcs1; + *data = (hkcs1 & ~CS1_DI) | (hkdi? CS1_DI: 0); /* DI dynamic */ break; case 001: /* HKWC */ @@ -564,7 +579,7 @@ switch (j) { /* decode PA<4:1> */ } if (DEBUG_PRI (hk_dev, HKDEB_RRD)) - fprintf (sim_deb, ">>HK%d read: reg%d=%o\n", drv, j, *data); + fprintf (sim_deb, ">>HK%d read: %s=%o\n", drv, reg_name[j], *data); return SCPE_OK; } @@ -576,16 +591,19 @@ UNIT *uptr; drv = GET_UNIT (hkcs2); /* get current unit */ uptr = hk_dev.units + drv; /* get unit */ j = (PA >> 1) & 017; /* get reg offset */ +if (reg_in_drive[j] && (hk_unit[drv].flags & UNIT_DIS)) { /* nx disk */ + hk_err (CS1_ERR|CS1_DONE, CS2_NED, 0, drv); /* set err, stop op */ + return SCPE_OK; + } if ((hkcs1 & CS1_GO) && /* busy? */ !(((j == 0) && (data & CS1_CCLR)) || /* not cclr or sclr? */ ((j == 4) && (data & CS2_CLR)))) { - hkcs2 = hkcs2 | CS2_PGE; /* prog error */ - update_hkcs (0, drv); + hk_err (CS1_ERR|CS1_DONE, CS2_PGE, 0, drv); /* set err, stop op */ return SCPE_OK; } if (DEBUG_PRI (hk_dev, HKDEB_RWR)) - fprintf (sim_deb, ">>HK%d write: reg%d=%o\n", drv, j, data); + fprintf (sim_deb, ">>HK%d write: %s=%o\n", drv, reg_name[j], data); switch (j) { /* decode PA<4:1> */ case 000: /* HKCS1 */ @@ -596,25 +614,22 @@ switch (j) { /* decode PA<4:1> */ hkda = hkdc = 0; hkba = hkwc = 0; hkspr = hkof = 0; - CLR_INT (HK); /* clr int */ + hkci = hkdi = hkei = 0; /* clr int flops */ for (i = 0; i < HK_NUMDR; i++) { /* stop data xfr */ if (sim_is_active (&hk_unit[i]) && - ((uptr->FNC & CS1_M_FNC) >= FNC_XFER)) + ((hk_unit[i].FNC & CS1_M_FNC) >= FNC_XFER)) sim_cancel (&hk_unit[i]); } drv = 0; break; } - if (data & CS1_IE) { /* setting IE? */ - if (data & CS1_DONE) /* write to DONE+IE? */ - SET_INT (HK); - } - else CLR_INT (HK); /* no, clr intr */ + if (((data & CS1_IE) != 0) && ((data & CS1_DONE) != 0)) + hkci = 1; /* set ctlr intr */ hkcs1 = (hkcs1 & ~CS1_RW) | (data & CS1_RW); /* merge data */ if (SC02C) hkspr = (hkspr & ~CS1_M_UAE) | GET_UAE (hkcs1); - if ((data & CS1_GO) && !(hkcs1 & CS1_ERR)) /* go? */ - hk_go (drv); + if (((data & CS1_GO) != 0) && ((hkcs1 & CS1_ERR) == 0)) + hk_go (drv); /* go & ~err? */ break; case 001: /* HKWC */ @@ -671,12 +686,12 @@ return SCPE_OK; void hk_go (int32 drv) { int32 fnc, t; +t_bool dte; UNIT *uptr; -static uint8 fnc_cdt[16] = { - 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +static uint8 fnc_dte[16] = { + 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 }; - static uint8 fnc_nxf[16] = { 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0 }; @@ -695,51 +710,64 @@ if (DEBUG_PRI (hk_dev, HKDEB_OPS)) fprintf (sim_deb, ">>HK%d strt: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", drv, fnc, hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc); uptr = hk_dev.units + drv; /* get unit */ +dte = ((hkcs1 & CS1_DT) !=0) != ((uptr->flags & UNIT_DTYPE) != 0); + if (fnc != FNC_NOP) /* !nop, clr msg sel */ hkmr = hkmr & ~MR_MS; if (uptr->flags & UNIT_DIS) { /* nx unit? */ - hkcs2 = hkcs2 | CS2_NED; /* set error flag */ - update_hkcs (CS1_DONE, drv); /* done */ + hk_err (CS1_ERR|CS1_DONE, CS2_NED, 0, drv); /* set err, no op */ return; } -if (fnc_cdt[fnc] && /* need dtype match? */ - (((hkcs1 & CS1_DT) != 0) != ((uptr->flags & UNIT_DTYPE) != 0))) { - hk_cmderr (ER_DTY, drv); /* type error */ - return; +if ((hkcs1 & CS1_FMT) != 0) { /* 18b format? */ + hk_err (CS1_ERR|CS1_DONE, 0, ER_FER, drv); /* set err, no op */ + return; + } +if (fnc_dte[fnc] && dte) { /* need drv match ? */ + hker[drv] = hker[drv] | ER_DTY; /* drive type mismatch? */ + hk_err (CS1_ERR|CS1_DONE, 0, ER_DTY, drv); /* set err, no op */ } if (fnc_nxf[fnc] && ((hkds[drv] & DS_VV) == 0)) { /* need vol valid? */ - hk_cmderr (ER_NXF, drv); /* non exec func */ + hkds[drv] = hkds[drv] | DS_ATA; /* set ATTN */ + hk_err (CS1_ERR|CS1_DI|CS1_DONE, 0, ER_NXF, drv); /* set err, no op */ return; } if (fnc_att[fnc] && !(uptr->flags & UNIT_ATT)) { /* need attached? */ - hk_cmderr (ER_UNS, drv); /* unsafe */ + hkds[drv] = hkds[drv] | DS_ATA; /* set ATTN */ + hk_err (CS1_ERR|CS1_DI|CS1_DONE, 0, ER_UNS, drv); /* set err, no op */ return; } if (fnc_rdy[fnc] && sim_is_active (uptr)) /* need inactive? */ return; 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 */ + (GET_SF (hkda) >= HK_NUMSF))) { /* bad surface */ + hk_err (CS1_ERR|CS1_DONE, 0, ER_SKI|ER_IAE, drv); /* set err, no op */ return; } hkcs1 = (hkcs1 | CS1_GO) & ~CS1_DONE; /* set go, clear done */ +hkci = hkdi = hkei = 0; /* clear all intr */ +CLR_INT (HK); + switch (fnc) { /* case on function */ -/* Instantaneous functions (unit may be busy, can't schedule thread) */ +/* Instantaneous functions (unit may be busy, can't schedule thread, + can't overwrite unit function field) */ case FNC_NOP: /* no operation */ hkmr2 = hk_rdmr2 (GET_MS (hkmr)); /* get serial msgs */ hkmr3 = hk_rdmr3 (GET_MS (hkmr)); - update_hkcs (CS1_DONE, drv); /* done */ + if (dte) /* drive type err? */ + hk_err (CS1_ERR|CS1_DONE, 0, ER_DTY, drv); + else update_hkcs (CS1_DONE, drv); /* done */ break; case FNC_DCLR: /* drive clear */ hkds[drv] &= ~DS_ATA; /* clr ATA */ - hker[drv] = 0; /* clear errors */ - update_hkcs (CS1_DONE, drv); /* done */ + hker[drv] = 0; /* clr err */ + if (dte) /* drive type err? */ + hk_err (CS1_ERR|CS1_DONE, 0, ER_DTY, drv); + else update_hkcs (CS1_DONE, drv); /* done */ break; case FNC_PACK: /* pack acknowledge */ @@ -774,15 +802,19 @@ switch (fnc) { /* case on function */ case FNC_WCHK: /* write check */ case FNC_READ: /* read */ case FNC_READH: /* read headers */ + if (GET_SC (hkda) >= HK_NUMSC) { /* invalid sector? */ + hk_err (CS1_ERR|CS1_DONE, 0, ER_OPI, drv); /* set err, no op */ + return; + } 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 */ + sim_activate (uptr, hk_rwait + (hk_swait * t)); /* schedule */ uptr->CYL = hkdc; /* update cyl */ return; default: - hk_cmderr (ER_ILF, drv); /* not supported */ + hk_err (CS1_ERR|CS1_DONE, 0, ER_ILF, drv); /* not supported */ break; } return; @@ -821,7 +853,7 @@ switch (fnc) { /* case on function */ case FNC_OFFSET: /* offset */ if (uptr->FNC & FNC_2ND) { /* 2nd int? */ hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */ - update_hkcs (CS1_DI, drv); /* drive intr */ + update_hkcs (CS1_DI, drv); /* ATN set */ } else { uptr->FNC = uptr->FNC | FNC_2ND; /* second state */ @@ -835,7 +867,7 @@ switch (fnc) { /* case on function */ case FNC_SEEK: /* seek */ if (uptr->FNC & FNC_2ND) { /* 2nd int? */ hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */ - update_hkcs (CS1_DI, drv); /* drive intr */ + update_hkcs (CS1_DI, drv); /* ATN set */ } else { uptr->FNC = uptr->FNC | FNC_2ND; /* second state */ @@ -863,7 +895,7 @@ switch (fnc) { /* case on function */ case FNC_WRITE: /* write */ if (uptr->flags & UNIT_WPRT) { /* write locked? */ - hk_cmderr (ER_WLE, drv); /* command error */ + hk_err (CS1_ERR|CS1_DONE, 0, ER_WLE, drv); /* set err, stop op */ return SCPE_OK; } case FNC_WCHK: /* write check */ @@ -889,7 +921,7 @@ switch (fnc) { /* case on function */ if (hkcs2 & CS2_UAI) { /* no addr inc? */ if (t = Map_ReadW (ba, 2, &comp)) { /* get 1st wd */ wc = 0; /* NXM, no xfr */ - hkcs2 = hkcs2 | CS2_NEM; /* set nxm err */ + hk_err (CS1_ERR, CS2_NEM, 0, drv); } for (i = 0; i < wc; i++) hkxb[i] = comp; @@ -897,7 +929,7 @@ switch (fnc) { /* case on function */ else { /* normal */ if (t = Map_ReadW (ba, wc << 1, hkxb)) { /* get buf */ wc = wc - (t >> 1); /* NXM, adj wc */ - hkcs2 = hkcs2 | CS2_NEM; /* set nxm err */ + hk_err (CS1_ERR, CS2_NEM, 0, drv); } ba = ba + (wc << 1); /* adv ba */ } @@ -905,7 +937,7 @@ switch (fnc) { /* case on function */ for (i = wc; i < awc; i++) /* fill buf */ hkxb[i] = 0; if (wc && !err) { /* write buf */ - fxwrite (hkxb, sizeof (uint16), wc, uptr->fileref); + fxwrite (hkxb, sizeof (uint16), awc, uptr->fileref); err = ferror (uptr->fileref); } } /* end if wr */ @@ -917,13 +949,13 @@ switch (fnc) { /* case on function */ if (hkcs2 & CS2_UAI) { /* no addr inc? */ if (t = Map_WriteW (ba, 2, &hkxb[wc - 1])) { wc = 0; /* NXM, no xfr */ - hkcs2 = hkcs2 | CS2_NEM; /* set nxm err */ + hk_err (CS1_ERR, CS2_NEM, 0, drv); } } else { /* normal */ if (t = Map_WriteW (ba, wc << 1, hkxb)) { /* put buf */ wc = wc - (t >> 1); /* NXM, adj wc */ - hkcs2 = hkcs2 | CS2_NEM; /* set nxm err */ + hk_err (CS1_ERR, CS2_NEM, 0, drv); } ba = ba + (wc << 1); /* adv ba */ } @@ -936,15 +968,15 @@ switch (fnc) { /* case on function */ awc = wc; for (wc = 0; wc < awc; wc++) { /* loop thru buf */ if (Map_ReadW (ba, 2, &comp)) { /* read word */ - hkcs2 = hkcs2 | CS2_NEM; /* set error */ + hk_err (CS1_ERR, CS2_NEM, 0, drv); break; } if (comp != hkxb[wc]) { /* compare wd */ - hkcs2 = hkcs2 | CS2_WCE; /* set error */ + hk_err (CS1_ERR, CS2_WCE, 0, drv); break; } - if ((hkcs2 & CS2_UAI) - == 0) ba = ba + 2; + if ((hkcs2 & CS2_UAI) == 0) + ba = ba + 2; } } /* end else wchk */ @@ -961,7 +993,7 @@ switch (fnc) { /* case on function */ hkdc = da / HK_NUMSF; if (err != 0) { /* error? */ - hk_cmderr (ER_PAR, drv); /* set drive error */ + hk_err (CS1_ERR|CS1_DONE, 0, ER_PAR, drv); /* set drive error */ perror ("HK I/O error"); clearerr (uptr->fileref); return SCPE_IOERR; @@ -977,35 +1009,49 @@ return SCPE_OK; /* Controller status update - Check for done transition Update drive status Update HKCS1 + Check for done transition + clock CI from IE + set DI if any ATN bits set + Check for DI set if no transition but DONE is set Update interrupt request */ void update_hkcs (int32 flag, int32 drv) { int32 i; +int32 old_hkcs1 = hkcs1; update_hkds (drv); /* upd drv status */ -if (flag & CS1_DONE) /* clear go */ - hkcs1 = hkcs1 & ~CS1_GO; -if (hkcs1 & CS1_IE) { /* intr enable? */ - if (((flag & CS1_DONE) && ((hkcs1 & CS1_DONE) == 0)) || - ((flag & CS1_DI) && (hkcs1 & CS1_DONE))) /* done 0->1 or DI? */ - SET_INT (HK); +hkcs1 = (hkcs1 & (CS1_ERR|CS1_DT|CS1_UAE|CS1_DONE|CS1_IE|CS1_SPA|CS1_FNC|CS1_GO)) | + (flag & ~CS1_DI); +if ((hkcs1 & CS1_DONE) != 0) { /* done? */ + hkcs1 = hkcs1 & ~CS1_GO; /* clear go */ + if ((old_hkcs1 & CS1_DONE) == 0) { /* done 0->1? */ + hkci = (hkcs1 & CS1_IE)? 1: 0; /* clk CI from IE */ + for (i = 0; i < HK_NUMDR; i++) { /* if ATA, set DI */ + if (hkds[i] & DS_ATA) + hkdi = 1; + } + } + else if ((flag & CS1_DI) != 0) /* done set; new ATN? */ + hkdi = 1; /* set drv int */ } +else hkdi = 0; /* not done, clr DI */ +if (((hkcs1 & CS1_IE) != 0) && (hkci || hkdi || hkei)) /* int enab & set? */ + SET_INT (HK); 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 (DEBUG_PRI (hk_dev, HKDEB_OPS)) { /* debug info? */ + if (flag & CS1_DONE) /* set done? */ + fprintf (sim_deb, + ">>HK%d done: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o, ci=%d, di=%d\n", + drv, GET_FNC (hkcs1), hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc, hkci, hkdi); + if (flag & CS1_DI) /* set ATA? */ + fprintf (sim_deb, + ">>HK%d ATA: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o, ci=%d, di=%d\n", + drv, GET_FNC (hkcs1), hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc, hkci, hkdi); } -if (hker[drv] | (hkcs1 & (CS1_PAR | CS1_CTO)) | /* if err, set ERR */ - (hkcs2 & CS2_ERR)) hkcs1 = hkcs1 | CS1_ERR; -if ((flag & CS1_DONE) && /* set done && debug? */ - (DEBUG_PRI (hk_dev, HKDEB_OPS))) - fprintf (sim_deb, ">>HK%d done: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o\n", - drv, GET_FNC (hkcs1), hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc); return; } @@ -1018,35 +1064,42 @@ if (hk_unit[drv].flags & UNIT_DIS) { /* disabled? */ return; } hkds[drv] = (hkds[drv] & (DS_VV | DS_PIP | DS_ATA)) | DS_VLD | DS_DRA; +if (hk_unit[drv].flags & UNIT_RK07) + hkds[drv] = hkds[drv] | DS_DT; if (hk_unit[drv].flags & UNIT_ATT) { /* attached? */ if (!sim_is_active (&hk_unit[drv])) /* not busy? */ hkds[drv] = hkds[drv] | DS_RDY; /* set RDY */ - if (hker[drv]) /* err? set ATA */ - hkds[drv] = hkds[drv] | DS_ATA; if (hk_off[drv]) /* offset? set OF */ hkds[drv] = hkds[drv] | DS_OF; if (hk_unit[drv].flags & UNIT_WPRT) /* write locked? */ hkds[drv] = hkds[drv] | DS_WRL; /* set WRL */ } -else { - hkds[drv] = hkds[drv] & ~(DS_PIP | DS_VV); /* no, clr PIP,VV */ - hker[drv] = 0; /* no errors */ - } -if (hk_unit[drv].flags & UNIT_RK07) - hkds[drv] = hkds[drv] | DS_DT; +else hkds[drv] = hkds[drv] & ~(DS_PIP | DS_VV); /* no, clr PIP,VV */ return; } -/* Set error and abort command */ +/* Set errors */ -void hk_cmderr (int32 err, int32 drv) +void hk_err (int32 cs1e, int32 cs2e, int32 drve, int32 drv) { -hker[drv] = hker[drv] | err; /* set error */ -hkds[drv] = hkds[drv] | DS_ATA; /* set attn */ -update_hkcs (CS1_DONE, drv); /* set done */ +hker[drv] = hker[drv] | drve; /* set drv error */ +hkcs2 = hkcs2 | cs2e; /* set cs2 err */ +if ((cs1e & CS1_ERR) != 0) /* set combined err? */ + hkei = 1; /* then set EI */ +if ((cs1e & CS1_DONE) != 0) /* set done? */ + update_hkcs (CS1_ERR|CS1_DONE, drv); /* stop now */ +else hkcs1 = hkcs1 | cs1e; /* no, just upd */ return; } +/* Interrupt routine */ + +int32 hk_inta (void) +{ +hkci = hkdi = hkei = 0; /* clear all flops */ +return hk_dib.vec; /* return vector */ +} + /* Diagnostic registers It's unclear whether the drivers actually use these values, but the @@ -1164,12 +1217,13 @@ hkmr = hkmr2 = hkmr3 = 0; hkda = hkdc = 0; hkba = hkwc = 0; hkof = hkspr = 0; +hkci = hkdi = hkei = 0; /* clear intr flops */ CLR_INT (HK); /* clear intr req */ for (i = 0; i < HK_NUMDR; i++) { /* stop operations */ uptr = hk_dev.units + i; sim_cancel (uptr); if (uptr->flags & UNIT_ATT) - hkds[i] = hkds[i] & DS_VV; + hkds[i] = hkds[i] & (DS_VV | DS_DT); else hkds[i] = 0; uptr->CYL = uptr->FNC = 0; /* clear state */ hk_dif[i] = 0; @@ -1189,18 +1243,23 @@ t_stat hk_attach (UNIT *uptr, char *cptr) { uint32 drv, p; t_stat r; +int32 old_hkds; uptr->capac = HK_SIZE (uptr); r = attach_unit (uptr, cptr); /* attach unit */ if (r != SCPE_OK) /* error? */ return r; drv = (uint32) (uptr - hk_dev.units); /* get drv number */ -hkds[drv] = DS_ATA | DS_RDY | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0); +old_hkds = hkds[drv]; /* save hkds */ +hkds[drv] = DS_ATA | DS_RDY | + ((uptr->flags & UNIT_WPRT)? DS_WRL: 0) | + ((uptr->flags & UNIT_DTYPE)? DS_DT: 0); hker[drv] = 0; /* upd drv status */ hk_off[drv] = 0; hk_dif[drv] = 0; uptr->CYL = 0; -update_hkcs (CS1_DI, drv); /* upd ctlr status */ +if ((old_hkds & DS_ATA) == 0) /* ATN transition? */ + update_hkcs (CS1_DI, drv); /* upd ctlr status */ p = sim_fsize (uptr->fileref); /* get file size */ if (p == 0) { /* new disk image? */ @@ -1226,18 +1285,21 @@ return SCPE_OK; t_stat hk_detach (UNIT *uptr) { uint32 drv; +int32 old_hkds; if (!(uptr->flags & UNIT_ATT)) /* attached? */ return SCPE_OK; drv = (uint32) (uptr - hk_dev.units); /* get drv number */ -hkds[drv] = (hkds[drv] & ~(DS_RDY | DS_WRL | DS_VV | DS_OF)) | DS_ATA; +old_hkds = hkds[drv]; +hkds[drv] = (hkds[drv] & ~(DS_RDY | DS_WRL | DS_VV | DS_OF | DS_PIP)) | 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 & FNC_2ND) == 0) /* expecting done? */ - update_hkcs (CS1_DONE, drv); /* set done */ + update_hkcs (CS1_ERR|CS1_DONE, drv); /* set done */ } -update_hkcs (CS1_DI, drv); /* request intr */ +if ((old_hkds & DS_ATA) == 0) /* ATN transition? */ + update_hkcs (CS1_DI, drv); /* upd ctlr status */ return detach_unit (uptr); } diff --git a/PDP11/pdp11_rc.c b/PDP11/pdp11_rc.c index 1f32ec59..ec14279a 100644 --- a/PDP11/pdp11_rc.c +++ b/PDP11/pdp11_rc.c @@ -1,6 +1,6 @@ /* pdp11_rc.c: RC11/RS64 fixed head disk simulator - Copyright (c) 2007-2008, John A. Dundas III + Copyright (c) 2007-2013, John A. Dundas III 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 @@ rc RC11/RS64 fixed head disk + 03-Dec-13 RMS Added explicit void * cast 28-Dec-07 JAD Correct extraction of unit number from da in rc_svc. Clear _all_ error bits when a new operation starts. Passes all diagnostics in all configurations. @@ -439,7 +440,7 @@ static t_stat rc_svc (UNIT *uptr) { uint32 ma, da, t, u_old, u_new, last_da; uint16 dat; - uint16 *fbuf = uptr->filebuf; + uint16 *fbuf = (uint16 *) uptr->filebuf; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ update_rccs (RCCS_NED | RCCS_DONE, 0); /* nx disk */ diff --git a/PDP11/pdp11_rf.c b/PDP11/pdp11_rf.c index 439fa7b2..4f07ef41 100644 --- a/PDP11/pdp11_rf.c +++ b/PDP11/pdp11_rf.c @@ -1,6 +1,6 @@ /* pdp11_rf.c: RF11 fixed head disk simulator - Copyright (c) 2006-2012, Robert M Supnik + Copyright (c) 2006-2013, 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 RF11 fixed head disk + 03-Sep-13 RMS Added WC to debug printout 19-Mar-12 RMS Fixed bug in updating mem addr extension (Peter Schorn) 25-Dec-06 RMS Fixed bug in unit mask (John Dundas) 26-Jun-06 RMS Cloned from RF08 simulator @@ -266,8 +267,8 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */ rf_cs &= ~(RFCS_WCHK|RFCS_DPAR|RFCS_NED|RFCS_WLK|RFCS_MXFR|RFCS_DONE); CLR_INT (RF); if (DEBUG_PRS (rf_dev)) - fprintf (sim_deb, ">>RF start: cs = %o, da = %o, ma = %o\n", - update_rfcs (0, 0), GET_DEX (rf_dae) | rf_da, GET_MEX (rf_cs) | rf_cma); + fprintf (sim_deb, ">>RF start: cs = %o, da = %o, ma = %o, wc = %o\n", + update_rfcs (0, 0), GET_DEX (rf_dae) | rf_da, GET_MEX (rf_cs) | rf_cma, rf_wc); } break; @@ -321,7 +322,7 @@ t_stat rf_svc (UNIT *uptr) { uint32 ma, da, t; uint16 dat; -uint16 *fbuf = uptr->filebuf; +uint16 *fbuf = (uint16 *) uptr->filebuf; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ update_rfcs (RFCS_NED|RFCS_DONE, 0); /* nx disk */ diff --git a/PDP11/pdp11_rh.c b/PDP11/pdp11_rh.c index efc7c043..ce7d0a73 100644 --- a/PDP11/pdp11_rh.c +++ b/PDP11/pdp11_rh.c @@ -1,6 +1,6 @@ /* pdp11_rh.c: PDP-11 Massbus adapter simulator - Copyright (c) 2005-2012, Robert M Supnik + Copyright (c) 2005-2013, 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 @@ rha, rhb RH11/RH70 Massbus adapter + 02-Sep-13 RMS Added third Massbus adapter, debug printouts 19-Mar-12 RMS Fixed declaration of cpu_opt (Mark Pizzolato) 02-Feb-08 RMS Fixed DMA memory address limit test (John Dundas) 17-May-07 RMS Moved CS1 drive enable to devices @@ -175,11 +176,12 @@ t_stat mba_set_type (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat mba_show_type (FILE *st, UNIT *uptr, int32 val, void *desc); int32 mba0_inta (void); int32 mba1_inta (void); +int32 mba2_inta (void); void mba_set_int (uint32 mb); void mba_clr_int (uint32 mb); void mba_upd_cs1 (uint32 set, uint32 clr, uint32 mb); void mba_set_cs2 (uint32 flg, uint32 mb); -uint32 mba_map_pa (int32 pa, int32 *ofs); +int32 mba_map_pa (int32 pa, int32 *ofs); DEVICE mba0_dev, mba1_dev; extern uint32 Map_Addr (uint32 ba); @@ -272,6 +274,39 @@ MTAB mba1_mod[] = { { 0 } }; +DIB mba2_dib = { + IOBA_RS, IOLN_RS, &mba_rd, &mba_wr, + 1, IVCL (RS), VEC_RS, { &mba2_inta } + }; + +UNIT mba2_unit = { UDATA (NULL, 0, 0) }; + +REG mba2_reg[] = { + { ORDATA (CS1, massbus[2].cs1, 16) }, + { ORDATA (WC, massbus[2].wc, 16) }, + { ORDATA (BA, massbus[2].ba, 16) }, + { ORDATA (CS2, massbus[2].cs2, 16) }, + { ORDATA (DB, massbus[2].db, 16) }, + { ORDATA (BAE, massbus[2].bae, 6) }, + { ORDATA (CS3, massbus[2].cs3, 16) }, + { FLDATA (IFF, massbus[2].iff, 0) }, + { FLDATA (INT, IREQ (RS), INT_V_RS) }, + { FLDATA (SC, massbus[2].cs1, CSR_V_ERR) }, + { FLDATA (DONE, massbus[2].cs1, CSR_V_DONE) }, + { FLDATA (IE, massbus[2].cs1, CSR_V_IE) }, + { ORDATA (DEVADDR, mba2_dib.ba, 32), REG_HRO }, + { ORDATA (DEVVEC, mba2_dib.vec, 16), REG_HRO }, + { NULL } + }; + +MTAB mba2_mod[] = { + { MTAB_XTD|MTAB_VDV, 0040, "ADDRESS", "ADDRESS", + &set_addr, &show_addr, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR", + &set_vec, &show_vec, NULL }, + { 0 } + }; + DEVICE mba_dev[] = { { "RHA", &mba0_unit, mba0_reg, mba0_mod, @@ -286,6 +321,13 @@ DEVICE mba_dev[] = { NULL, NULL, &mba_reset, NULL, NULL, NULL, &mba1_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS + }, + { + "RHC", &mba2_unit, mba2_reg, mba2_mod, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &mba_reset, + NULL, NULL, NULL, + &mba2_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS } }; @@ -415,6 +457,9 @@ switch (ofs) { /* case on reg */ massbus[mb].cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE); massbus[mb].cs2 &= ~CS2_ERR; /* clear errors */ massbus[mb].cs3 &= ~(CS3_ERR | CS3_DBL); + if (DEBUG_PRS (mba_dev[mb])) + fprintf (sim_deb, ">>RH%d STRT: cs1=%o, cs2=%o,ba=%o, wc=%o\n", + mb, massbus[mb].cs1, massbus[mb].cs2, massbus[mb].ba, massbus[mb].wc); } } } @@ -623,6 +668,9 @@ return i; void mba_set_don (uint32 mb) { mba_upd_cs1 (CS1_DONE, 0, mb); +if (DEBUG_PRS (mba_dev[mb])) + fprintf (sim_deb, ">>RH%d DONE: cs1=%o, cs2=%o,ba=%o, wc=%o\n", + mb, massbus[mb].cs1, massbus[mb].cs2, massbus[mb].ba, massbus[mb].wc); return; } @@ -726,9 +774,17 @@ massbus[1].iff = 0; /* clear CSTB INTR */ return mba1_dib.vec; /* acknowledge */ } +int32 mba2_inta (void) +{ +massbus[2].cs1 &= ~CS1_IE; /* clear int enable */ +massbus[2].cs3 &= ~CS1_IE; /* in both registers */ +massbus[2].iff = 0; /* clear CSTB INTR */ +return mba2_dib.vec; /* acknowledge */ +} + /* Map physical address to Massbus number, offset */ -uint32 mba_map_pa (int32 pa, int32 *ofs) +int32 mba_map_pa (int32 pa, int32 *ofs) { int32 i, uo, ba, lnt; DIB *dibp; diff --git a/PDP11/pdp11_rk.c b/PDP11/pdp11_rk.c index 5e37d54d..f8d66ac4 100644 --- a/PDP11/pdp11_rk.c +++ b/PDP11/pdp11_rk.c @@ -1,6 +1,6 @@ /* pdp11_rk.c: RK11/RKV11 cartridge disk simulator - Copyright (c) 1993-2009, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ rk RK11/RKV11/RK05 cartridge disk + 06-Sep-13 RMS Fixed RKDS content for non-existent disk (Mark Pizzolato) 20-Mar-09 RMS Fixed bug in read header (Walter F Mueller) 16-Aug-05 RMS Fixed C++ declaration and cast problems 07-Jul-05 RMS Removed extraneous externs @@ -296,17 +297,20 @@ UNIT *uptr; switch ((PA >> 1) & 07) { /* decode PA<3:1> */ case 0: /* RKDS: read only */ - rkds = (rkds & RKDS_ID) | RKDS_RK05 | RKDS_SC_OK | - (rand () % RK_NUMSC); /* random sector */ + rkds = rkds & RKDS_ID; /* identified unit */ uptr = rk_dev.units + GET_DRIVE (rkda); /* selected unit */ - if (uptr->flags & UNIT_ATT) /* attached? */ - rkds = rkds | RKDS_RDY; - if (!sim_is_active (uptr)) /* idle? */ - rkds = rkds | RKDS_RWS; - if (uptr->flags & UNIT_WPRT) - rkds = rkds | RKDS_WLK; - if (GET_SECT (rkda) == (rkds & RKDS_SC)) - rkds = rkds | RKDS_ON_SC; + if (!(uptr->flags & UNIT_DIS)) { /* not disabled? */ + rkds = rkds | RKDS_RK05 | RKDS_SC_OK | /* random sector */ + (rand () % RK_NUMSC); + if (uptr->flags & UNIT_ATT) /* attached? */ + rkds = rkds | RKDS_RDY; + if (!sim_is_active (uptr)) /* idle? */ + rkds = rkds | RKDS_RWS; + if (uptr->flags & UNIT_WPRT) /* write locked? */ + rkds = rkds | RKDS_WLK; + if (GET_SECT (rkda) == (rkds & RKDS_SC)) + rkds = rkds | RKDS_ON_SC; + } *data = rkds; return SCPE_OK; @@ -413,7 +417,7 @@ if (func == RKCS_CTLRESET) { /* control reset? */ rker = rker & ~RKER_SOFT; /* clear soft errors */ if (rker == 0) /* redo summary */ rkcs = rkcs & ~RKCS_ERR; -rkcs = rkcs & ~RKCS_SCP; /* clear sch compl*/ +rkcs = rkcs & ~RKCS_SCP; /* clear sch compl */ rk_clr_done (); /* clear done */ last_drv = GET_DRIVE (rkda); /* get drive no */ uptr = rk_dev.units + last_drv; /* select unit */ diff --git a/PDP11/pdp11_rp.c b/PDP11/pdp11_rp.c index 1ae0bbe7..87d571ac 100644 --- a/PDP11/pdp11_rp.c +++ b/PDP11/pdp11_rp.c @@ -1,6 +1,6 @@ /* pdp11_rp.c - RP04/05/06/07 RM02/03/05/80 Massbus disk controller - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2012, 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 @@ rp RH/RP/RM moving head disks + 08-Dec-12 RMS UNLOAD shouldn't set ATTN (Mark Pizzolato) 17-May-07 RMS CS1 DVA resides in device, not MBA 21-Nov-05 RMS Enable/disable device also enables/disables Massbus adapter 12-Nov-05 RMS Fixed DriveClear, does not clear disk address @@ -709,6 +710,13 @@ switch (fnc) { /* case on function */ return SCPE_OK; case FNC_UNLOAD: /* unload */ + if (drv_tab[dtype].ctrl == RM_CTRL) { /* RM? */ + rp_set_er (ER1_ILF, drv); /* not supported */ + break; + } + rp_detach (uptr); /* detach unit */ + return SCPE_OK; + case FNC_RECAL: /* recalibrate */ dc = 0; /* seek to 0 */ case FNC_SEEK: /* seek */ @@ -1011,12 +1019,14 @@ return SCPE_OK; t_stat rp_detach (UNIT *uptr) { int32 drv; +extern int32 sim_is_running; if (!(uptr->flags & UNIT_ATT)) /* attached? */ return SCPE_OK; drv = (int32) (uptr - rp_dev.units); /* get drv number */ rpds[drv] = rpds[drv] & ~(DS_MOL | DS_RDY | DS_WRL | DS_VV | DS_OFM); -rp_update_ds (DS_ATA, drv); /* request intr */ +if (!sim_is_running) /* from console? */ + rp_update_ds (DS_ATA, drv); /* request intr */ return detach_unit (uptr); } diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c index 2b17c44b..29ae9103 100644 --- a/PDP11/pdp11_rq.c +++ b/PDP11/pdp11_rq.c @@ -1,6 +1,6 @@ /* pdp11_rq.c: MSCP disk controller simulator - Copyright (c) 2002-2010, Robert M Supnik + Copyright (c) 2002-2016, Robert M Supnik Derived from work by Stephen F. Shirron Permission is hereby granted, free of charge, to any person obtaining a @@ -26,6 +26,7 @@ rq RQDX3 disk controller + 17-Mar-13 RMS Fixed bug in ABORT link walk loop (Dave Bryan) 14-Jan-09 JH Added support for RD32 disc drive 18-Jun-07 RMS Added UNIT_IDLE flag to timer thread 31-Oct-05 RMS Fixed address width for large files @@ -1371,6 +1372,7 @@ if (uptr = rq_getucb (cp, lu)) { /* get unit */ cp->pak[prv].link = cp->pak[tpkt].link; break; } + prv = tpkt; /* no match, next */ } } if (tpkt) { /* found target? */ diff --git a/PDP11/pdp11_rs.c b/PDP11/pdp11_rs.c new file mode 100644 index 00000000..0ff3f523 --- /dev/null +++ b/PDP11/pdp11_rs.c @@ -0,0 +1,699 @@ +/* pdp11_rs.c - RS03/RS04 Massbus disk controller + + Copyright (c) 2013, 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. + + rs RS03/RS04 fixed head disks +*/ + +#if defined (VM_PDP10) +#error "RS03/RS04 not supported on the PDP-10!" + +#elif defined (VM_PDP11) +#include "pdp11_defs.h" +#define DEV_RADIX 8 + +#elif defined (VM_VAX) +#error "RS03/RS04 not supported on the VAX!" +#endif + +#include + +#define RS_NUMDR 8 /* #drives */ +#define RS03_NUMWD 64 /* words/sector */ +#define RS04_NUMWD 128 /* words/sector */ +#define RS_NUMSC 64 /* sectors/track */ +#define RS_NUMTK 64 /* tracks/disk */ +#define RS_MAXFR (1 << 16) /* max transfer */ +#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \ + ((double) (RS03_NUMWD * RS_NUMSC)))) +#define RS03_ID 0 +#define RS04_ID 2 +#define RS03_SIZE (RS_NUMTK * RS_NUMSC * RS03_NUMWD) +#define RS04_SIZE (RS_NUMTK * RS_NUMSC * RS04_NUMWD) +#define RS_NUMWD(d) ((d)? RS04_NUMWD: RS03_NUMWD) +#define RS_SIZE(d) ((d)? RS04_SIZE: RS03_SIZE) + +/* Flags in the unit flags word */ + +#define UNIT_V_DTYPE (UNIT_V_UF + 0) /* disk type */ +#define RS03_DTYPE (0) +#define RS04_DTYPE (1) +#define UNIT_V_AUTO (UNIT_V_UF + 1) /* autosize */ +#define UNIT_V_WLK (UNIT_V_UF + 2) /* write lock */ +#define UNIT_DTYPE (1 << UNIT_V_DTYPE) +#define UNIT_AUTO (1 << UNIT_V_AUTO) +#define UNIT_WLK (1 << UNIT_V_WLK) +#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & 1) + +/* RSCS1 - control/status 1 - offset 0 */ + +#define RS_CS1_OF 0 +#define CS1_GO CSR_GO /* go */ +#define CS1_V_FNC 1 /* function pos */ +#define CS1_M_FNC 037 /* function mask */ +#define CS1_N_FNC (CS1_M_FNC + 1) +#define FNC_NOP 000 /* no operation */ +#define FNC_DCLR 004 /* drive clear */ +#define FNC_SEARCH 014 /* search */ +#define FNC_XFR 020 /* divide line for xfr */ +#define FNC_WCHK 024 /* write check */ +#define FNC_WRITE 030 /* write */ +#define FNC_READ 034 /* read */ +#define CS1_RW 076 +#define CS1_DVA 04000 /* drive avail */ +#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC) + +/* RSDS - drive status - offset 1 */ + +#define RS_DS_OF 1 +#define DS_RDY 0000200 /* drive ready */ +#define DS_DPR 0000400 /* drive present */ +#define DS_LST 0002000 /* last sector */ +#define DS_WLK 0004000 /* write locked */ +#define DS_MOL 0010000 /* medium online */ +#define DS_PIP 0020000 /* pos in progress */ +#define DS_ERR 0040000 /* error */ +#define DS_ATA 0100000 /* attention active */ +#define DS_MBZ 0001177 + +/* RSER - error status - offset 2 */ + +#define RS_ER_OF 2 +#define ER_ILF 0000001 /* illegal func */ +#define ER_ILR 0000002 /* illegal register */ +#define ER_RMR 0000004 /* reg mod refused */ +#define ER_PAR 0000010 /* parity err */ +#define ER_AOE 0001000 /* addr ovflo err */ +#define ER_IAE 0002000 /* invalid addr err */ +#define ER_WLE 0004000 /* write lock err NI */ +#define ER_DTE 0010000 /* drive time err NI */ +#define ER_OPI 0020000 /* op incomplete */ +#define ER_UNS 0040000 /* drive unsafe */ +#define ER_DCK 0100000 /* data check NI */ +#define ER_MBZ 0000760 + +/* RSMR - maintenace register - offset 3 */ + +#define RS_MR_OF 3 + +/* RSAS - attention summary - offset 4 */ + +#define RS_AS_OF 4 +#define AS_U0 0000001 /* unit 0 flag */ + +/* RSDA - sector/track - offset 5 + All 16b are RW, but only <14:12> are tested for "invalid" address */ + +#define RS_DA_OF 5 +#define DA_V_SC 0 /* sector pos */ +#define DA_M_SC 077 /* sector mask */ +#define DA_V_TK 6 /* track pos */ +#define DA_M_TK 077 /* track mask */ +#define GET_SC(x) (((x) >> DA_V_SC) & DA_M_SC) +#define GET_TK(x) (((x) >> DA_V_TK) & DA_M_TK) +#define DA_INV 0070000 /* inv addr */ +#define DA_IGN 0100000 /* ignored */ + +/* RSDT - drive type - offset 6 */ + +#define RS_DT_OF 6 + +/* RSLA - look ahead register - offset 7 */ + +#define RS_LA_OF 7 + +/* This controller supports many two disk drive types: + + type #words/ #sectors/ #tracks/ + sector track drive + + RS03 64 64 64 =256KW + RS04 128 64 640 =512KW + + In theory, each drive can be a different type. The size field in + each unit selects the drive capacity for each drive and thus the + drive type. +*/ + +uint16 rscs1[RS_NUMDR] = { 0 }; /* control/status 1 */ +uint16 rsda[RS_NUMDR] = { 0 }; /* track/sector */ +uint16 rsds[RS_NUMDR] = { 0 }; /* drive status */ +uint16 rser[RS_NUMDR] = { 0 }; /* error status */ +uint16 rsmr[RS_NUMDR] = { 0 }; /* maint register */ +uint8 rswlk[RS_NUMDR] = { 0 }; /* wlk switches */ +int32 rs_stopioe = 1; /* stop on error */ +int32 rs_wait = 10; /* rotate time */ +static const char *rs_fname[CS1_N_FNC] = { + "NOP", "01", "02", "03", "DCLR", "05", "06", "07", + "10", "11", "12", "13", "SCH", "15", "16", "17", + "20", "21", "22", "23", "WRCHK", "25", "26", "27", + "WRITE", "31", "32", "33", "READ", "35", "36", "37" + }; + +extern FILE *sim_deb; + +t_stat rs_mbrd (int32 *data, int32 ofs, int32 drv); +t_stat rs_mbwr (int32 data, int32 ofs, int32 drv); +t_stat rs_svc (UNIT *uptr); +t_stat rs_reset (DEVICE *dptr); +t_stat rs_attach (UNIT *uptr, char *cptr); +t_stat rs_detach (UNIT *uptr); +t_stat rs_boot (int32 unitno, DEVICE *dptr); +void rs_set_er (int32 flg, int32 drv); +void rs_clr_as (int32 mask); +void rs_update_ds (int32 flg, int32 drv); +t_stat rs_go (int32 drv); +t_stat rs_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); +int32 rs_abort (void); + +/* RS data structures + + rs_dev RS device descriptor + rs_unit RS unit list + rs_reg RS register list + rs_mod RS modifier list +*/ + +DIB rs_dib = { MBA_RS, 0, &rs_mbrd, &rs_mbwr, 0, 0, 0, { &rs_abort } }; + +UNIT rs_unit[] = { + { UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+ + UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) }, + { UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+ + UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) }, + { UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+ + UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) }, + { UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+ + UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) }, + { UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+ + UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) }, + { UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+ + UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) }, + { UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+ + UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) }, + { UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+ + UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) } + }; + +REG rs_reg[] = { + { BRDATA (CS1, rscs1, DEV_RDX, 16, RS_NUMDR) }, + { BRDATA (DA, rsda, DEV_RDX, 16, RS_NUMDR) }, + { BRDATA (DS, rsds, DEV_RDX, 16, RS_NUMDR) }, + { BRDATA (ER, rser, DEV_RDX, 16, RS_NUMDR) }, + { BRDATA (MR, rsmr, DEV_RDX, 16, RS_NUMDR) }, + { BRDATA (WLKS, rswlk, DEV_RDX, 6, RS_NUMDR) }, + { DRDATA (TIME, rs_wait, 24), REG_NZ + PV_LEFT }, + { URDATA (CAPAC, rs_unit[0].capac, 10, T_ADDR_W, 0, + RS_NUMDR, PV_LEFT | REG_HRO) }, + { FLDATA (STOP_IOE, rs_stopioe, 0) }, + { NULL } + }; + +MTAB rs_mod[] = { + { MTAB_XTD|MTAB_VDV, 0, "MASSBUS", "MASSBUS", NULL, &mba_show_num }, + { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL }, + { UNIT_WLK, UNIT_WLK, "write lockable", "LOCKABLE", NULL }, + { (UNIT_DTYPE|UNIT_ATT), (RS03_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, + "RS03", NULL, NULL }, + { (UNIT_DTYPE|UNIT_ATT), (RS04_DTYPE << UNIT_V_DTYPE) + UNIT_ATT, + "RS04", NULL, NULL }, + { (UNIT_AUTO|UNIT_DTYPE|UNIT_ATT), (RS03_DTYPE << UNIT_V_DTYPE), + "RS03", NULL, NULL }, + { (UNIT_AUTO|UNIT_DTYPE|UNIT_ATT), (RS04_DTYPE << UNIT_V_DTYPE), + "RS04", NULL, NULL }, + { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL }, + { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL }, + { (UNIT_AUTO|UNIT_DTYPE), (RS03_DTYPE << UNIT_V_DTYPE), + NULL, "RS03", &rs_set_size }, + { (UNIT_AUTO|UNIT_DTYPE), (RS04_DTYPE << UNIT_V_DTYPE), + NULL, "RS04", &rs_set_size }, + { 0 } + }; + +DEVICE rs_dev = { + "RS", rs_unit, rs_reg, rs_mod, + RS_NUMDR, DEV_RADIX, 19, 1, DEV_RADIX, 16, + NULL, NULL, &rs_reset, + &rs_boot, &rs_attach, &rs_detach, + &rs_dib, DEV_DISABLE|DEV_DIS|DEV_UBUS|DEV_QBUS|DEV_MBUS|DEV_DEBUG + }; + +/* Massbus register read */ + +t_stat rs_mbrd (int32 *data, int32 ofs, int32 drv) +{ +uint32 val, dtype, i; +UNIT *uptr; + +rs_update_ds (0, drv); /* update ds */ +uptr = rs_dev.units + drv; /* get unit */ +if (uptr->flags & UNIT_DIS) { /* nx disk */ + *data = 0; + return MBE_NXD; + } +dtype = GET_DTYPE (uptr->flags); /* get drive type */ +ofs = ofs & MBA_RMASK; /* mask offset */ + +switch (ofs) { /* decode offset */ + + case RS_CS1_OF: /* RSCS1 */ + val = (rscs1[drv] & CS1_RW) | CS1_DVA; /* DVA always set */ + break; + + case RS_DA_OF: /* RSDA */ + val = rsda[drv]; + break; + + case RS_DS_OF: /* RSDS */ + val = rsds[drv] & ~DS_MBZ; + break; + + case RS_ER_OF: /* RSER */ + val = rser[drv] & ~ER_MBZ; + break; + + case RS_AS_OF: /* RSAS */ + val = 0; + for (i = 0; i < RS_NUMDR; i++) { + if (rsds[i] & DS_ATA) + val |= (AS_U0 << i); + } + break; + + case RS_LA_OF: /* RSLA */ + val = GET_POS (rs_wait); + break; + + case RS_MR_OF: /* RSMR */ + val = rsmr[drv]; + break; + + case RS_DT_OF: /* RSDT */ + val = dtype? RS04_ID: RS03_ID; + break; + + default: /* all others */ + *data = 0; + return MBE_NXR; + } + +*data = val; +return SCPE_OK; +} + +/* Massbus register write */ + +t_stat rs_mbwr (int32 data, int32 ofs, int32 drv) +{ +int32 dtype; +UNIT *uptr; + +uptr = rs_dev.units + drv; /* get unit */ +if (uptr->flags & UNIT_DIS) /* nx disk */ + return MBE_NXD; +if ((ofs != RS_AS_OF) && sim_is_active (uptr)) { /* unit busy? */ + rs_set_er (ER_RMR, drv); /* won't write */ + rs_update_ds (0, drv); + return SCPE_OK; + } +dtype = GET_DTYPE (uptr->flags); /* get drive type */ +ofs = ofs & MBA_RMASK; /* mask offset */ + +switch (ofs) { /* decode PA<5:1> */ + + case RS_CS1_OF: /* RSCS1 */ + rscs1[drv] = data & CS1_RW; + if (data & CS1_GO) /* start op */ + return rs_go (drv); + break; + + case RS_DA_OF: /* RSDA */ + rsda[drv] = data; + break; + + case RS_AS_OF: /* RSAS */ + rs_clr_as (data); + break; + + case RS_MR_OF: /* RSMR */ + rsmr[drv] = data; + break; + + case RS_ER_OF: /* RSER */ + case RS_DS_OF: /* RSDS */ + case RS_LA_OF: /* RSLA */ + case RS_DT_OF: /* RSDT */ + break; /* read only */ + + default: /* all others */ + return MBE_NXR; + } /* end switch */ + +rs_update_ds (0, drv); /* update status */ +return SCPE_OK; +} + +/* Initiate operation - unit not busy, function set */ + +t_stat rs_go (int32 drv) +{ +int32 fnc, dtype, t; +UNIT *uptr; + +fnc = GET_FNC (rscs1[drv]); /* get function */ +if (DEBUG_PRS (rs_dev)) + fprintf (sim_deb, ">>RS%d STRT: fnc=%s, ds=%o, da=%o, er=%o\n", + drv, rs_fname[fnc], rsds[drv], rsda[drv], rser[drv]); +uptr = rs_dev.units + drv; /* get unit */ +rs_clr_as (AS_U0 << drv); /* clear attention */ +dtype = GET_DTYPE (uptr->flags); /* get drive type */ +if ((fnc != FNC_DCLR) && (rsds[drv] & DS_ERR)) { /* err & ~clear? */ + rs_set_er (ER_ILF, drv); /* not allowed */ + rs_update_ds (DS_ATA, drv); /* set attention */ + return MBE_GOE; + } + +switch (fnc) { /* case on function */ + + case FNC_DCLR: /* drive clear */ + rser[drv] = 0; /* clear errors */ + case FNC_NOP: /* no operation */ + return SCPE_OK; + + case FNC_SEARCH: /* search */ + case FNC_WRITE: /* write */ + case FNC_WCHK: /* write check */ + case FNC_READ: /* read */ + if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ + rs_set_er (ER_UNS, drv); /* unsafe */ + break; + } + if (rsda[drv] & DA_INV) { /* bad address? */ + rs_set_er (ER_IAE, drv); + break; + } + rsds[drv] = rsds[drv] & ~DS_RDY; /* clr drive rdy */ + if (fnc == FNC_SEARCH) /* search? */ + rsds[drv] = rsds[drv] | DS_PIP; /* set PIP */ + t = abs (rsda[drv] - GET_POS (rs_wait)); /* pos diff */ + if (t < 1) /* min time */ + t = 1; + sim_activate (uptr, rs_wait * t); /* schedule */ + return SCPE_OK; + + default: /* all others */ + rs_set_er (ER_ILF, drv); /* not supported */ + break; + } + +rs_update_ds (DS_ATA, drv); /* set attn, req int */ +return MBE_GOE; +} + +/* Abort opertion - there is a data transfer in progress */ + +int32 rs_abort (void) +{ +return rs_reset (&rs_dev); +} + +/* Service unit timeout + + Complete search or data transfer command + Unit must exist - can't remove an active unit + Drives are buffered in memory - no IO errors +*/ + +t_stat rs_svc (UNIT *uptr) +{ +int32 i, fnc, dtype, drv; +int32 wc, abc, awc, mbc, da; +uint16 *fbuf = (uint16 *)uptr->filebuf; + +dtype = GET_DTYPE (uptr->flags); /* get drive type */ +drv = (int32) (uptr - rs_dev.units); /* get drv number */ +da = rsda[drv] * RS_NUMWD (dtype); /* get disk addr */ +fnc = GET_FNC (rscs1[drv]); /* get function */ + +if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ + rs_set_er (ER_UNS, drv); /* set drive error */ + if (fnc >= FNC_XFR) /* xfr? set done */ + mba_set_don (rs_dib.ba); + rs_update_ds (DS_ATA, drv); /* set attn */ + return (rs_stopioe? SCPE_UNATT: SCPE_OK); + } +rsds[drv] = (rsds[drv] & ~DS_PIP) | DS_RDY; /* change drive status */ + +switch (fnc) { /* case on function */ + + case FNC_SEARCH: /* search */ + rs_update_ds (DS_ATA, drv); + break; + + case FNC_WRITE: /* write */ + if ((uptr->flags & UNIT_WLK) && /* write locked? */ + (GET_TK (rsda[drv]) <= (int32) rswlk[drv])) { + rs_set_er (ER_WLE, drv); /* set drive error */ + mba_set_exc (rs_dib.ba); /* set exception */ + rs_update_ds (DS_ATA, drv); /* set attn */ + return SCPE_OK; + } + case FNC_WCHK: /* write check */ + case FNC_READ: /* read */ + if (rsda[drv] & DA_INV) { /* bad addr? */ + rs_set_er (ER_IAE, drv); /* set error */ + mba_set_exc (rs_dib.ba); /* set exception */ + rs_update_ds (DS_ATA, drv); /* set attn */ + break; + } + fbuf = fbuf + da; /* ptr into buffer */ + mbc = mba_get_bc (rs_dib.ba); /* get byte count */ + wc = (mbc + 1) >> 1; /* convert to words */ + if ((da + wc) > RS_SIZE (dtype)) { /* disk overrun? */ + rs_set_er (ER_AOE, drv); /* set err */ + wc = RS_SIZE (dtype) - da; /* trim xfer */ + mbc = wc << 1; /* trim mb count */ + } + if (fnc == FNC_WRITE) { /* write? */ + abc = mba_rdbufW (rs_dib.ba, mbc, fbuf); /* rd mem to buf */ + wc = (abc + 1) >> 1; /* actual # wds */ + awc = (wc + (RS_NUMWD (dtype) - 1)) & ~(RS_NUMWD (dtype) - 1); + for (i = wc; i < awc; i++) /* fill buf */ + fbuf[i] = 0; + if ((da + awc) > (int32) uptr->hwmark) /* update hw mark*/ + uptr->hwmark = da + awc; + } /* end if wr */ + else if (fnc == FNC_READ) /* read */ + mba_wrbufW (rs_dib.ba, mbc, fbuf); /* wri buf to mem */ + else mba_chbufW (rs_dib.ba, mbc, fbuf); /* check vs mem */ + + da = da + wc + (RS_NUMWD (dtype) - 1); + if (da >= RS_SIZE (dtype)) + rsds[drv] = rsds[drv] | DS_LST; + rsda[drv] = da / RS_NUMWD (dtype); + mba_set_don (rs_dib.ba); /* set done */ + rs_update_ds (0, drv); /* update ds */ + break; + } /* end case func */ + +if (DEBUG_PRS (rs_dev)) + fprintf (sim_deb, ">>RS%d DONE: fnc=%s, ds=%o, da=%o, er=%d\n", + drv, rs_fname[fnc], rsds[drv], rsda[drv], rser[drv]); +return SCPE_OK; +} + +/* Set drive error */ + +void rs_set_er (int32 flag, int32 drv) +{ +rser[drv] = rser[drv] | flag; +rsds[drv] = rsds[drv] | DS_ATA; +mba_upd_ata (rs_dib.ba, 1); +return; +} + +/* Clear attention flags */ + +void rs_clr_as (int32 mask) +{ +uint32 i, as; + +for (i = as = 0; i < RS_NUMDR; i++) { + if (mask & (AS_U0 << i)) + rsds[i] &= ~DS_ATA; + if (rsds[i] & DS_ATA) + as = 1; + } +mba_upd_ata (rs_dib.ba, as); +return; +} + +/* Drive status update */ + +void rs_update_ds (int32 flag, int32 drv) +{ +if (flag & DS_ATA) + mba_upd_ata (rs_dib.ba, 1); +if (rs_unit[drv].flags & UNIT_DIS) { + rsds[drv] = rser[drv] = 0; + return; + } +else rsds[drv] = (rsds[drv] | DS_DPR) & ~(DS_ERR | DS_WLK); +if (rs_unit[drv].flags & UNIT_ATT) { + rsds[drv] = rsds[drv] | DS_MOL; + if ((rs_unit[drv].flags & UNIT_WLK) && + (GET_TK (rsda[drv]) <= (int32) rswlk[drv])) + rsds[drv] = rsds[drv] | DS_WLK; + } +if (rser[drv]) + rsds[drv] = rsds[drv] | DS_ERR; +rsds[drv] = rsds[drv] | flag; +return; +} + +/* Device reset */ + +t_stat rs_reset (DEVICE *dptr) +{ +int32 i; +UNIT *uptr; + +mba_set_enbdis (MBA_RS, rs_dev.flags & DEV_DIS); +for (i = 0; i < RS_NUMDR; i++) { + uptr = rs_dev.units + i; + sim_cancel (uptr); + rscs1[i] = 0; + rser[i] = 0; + rsda[i] = 0; + rsmr[i] = 0; + rsds[i] = DS_RDY; + rs_update_ds (0, i); /* upd drive status */ + } +return SCPE_OK; +} + +/* Device attach */ + +t_stat rs_attach (UNIT *uptr, char *cptr) +{ +int32 drv, p; +t_stat r; + +uptr->capac = RS_SIZE (GET_DTYPE (uptr->flags)); +r = attach_unit (uptr, cptr); /* attach unit */ +if (r != SCPE_OK) /* error? */ + return r; +drv = (int32) (uptr - rs_dev.units); /* get drv number */ +rsds[drv] = DS_MOL | DS_RDY | DS_DPR; /* upd drv status */ +rser[drv] = 0; +rs_update_ds (DS_ATA, drv); /* upd drive status */ + +if ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */ + return SCPE_OK; +p = sim_fsize (uptr->fileref); /* get file size */ +if (((p + 1) >> 1) <= RS03_SIZE) { + uptr->flags &= ~UNIT_DTYPE; + uptr->capac = RS03_SIZE; + } +else { + uptr->flags |= UNIT_DTYPE; + uptr->capac = RS04_SIZE; + } +return SCPE_OK; +} + +/* Device detach */ + +t_stat rs_detach (UNIT *uptr) +{ +int32 drv; +extern int32 sim_is_running; + +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; +drv = (int32) (uptr - rs_dev.units); /* get drv number */ +rsds[drv] = 0; +if (!sim_is_running) /* from console? */ + rs_update_ds (DS_ATA, drv); /* request intr */ +return detach_unit (uptr); +} + +/* Set size command validation routine */ + +t_stat rs_set_size (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 dtype = GET_DTYPE (val); + +if (uptr->flags & UNIT_ATT) + return SCPE_ALATT; +uptr->capac = RS_SIZE (dtype); +return SCPE_OK; +} + +/* Set bad block routine */ + +/* Boot routine */ + +#define BOOT_START 02000 /* start */ +#define BOOT_ENTRY (BOOT_START + 002) /* entry */ +#define BOOT_UNIT (BOOT_START + 010) /* unit number */ +#define BOOT_CSR (BOOT_START + 014) /* CSR */ +#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint16)) + +static const uint16 boot_rom[] = { + 0042123, /* "SD" */ + 0012706, BOOT_START, /* mov #boot_start, sp */ + 0012700, 0000000, /* mov #unit, r0 */ + 0012701, 0172040, /* mov #RSCS1, r1 */ + 0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */ + 0010061, 0000010, /* mov r0, 10(r1) ; set unit */ + 0012761, 0177000, 0000002, /* mov #-512., 2(r1) ; set wc */ + 0005061, 0000004, /* clr 4(r1) ; clr ba */ + 0005061, 0000006, /* clr 6(r1) ; clr da */ + 0012711, 0000071, /* mov #READ+GO, (r1) ; read */ + 0105711, /* tstb (r1) ; wait */ + 0100376, /* bpl .-2 */ + 0005002, /* clr R2 */ + 0005003, /* clr R3 */ + 0012704, BOOT_START+020, /* mov #start+020, r4 */ + 0005005, /* clr R5 */ + 0105011, /* clrb (r1) */ + 0005007 /* clr PC */ + }; + +t_stat rs_boot (int32 unitno, DEVICE *dptr) +{ +int32 i; +extern int32 saved_PC; +extern uint16 *M; +UNIT *uptr = rs_dev.units + unitno; + +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; +M[BOOT_UNIT >> 1] = unitno & (RS_NUMDR - 1); +M[BOOT_CSR >> 1] = mba_get_csr (rs_dib.ba) & DMASK; +saved_PC = BOOT_ENTRY; +return SCPE_OK; +} + diff --git a/PDP11/pdp11_rx.c b/PDP11/pdp11_rx.c index f4267b61..511635d8 100644 --- a/PDP11/pdp11_rx.c +++ b/PDP11/pdp11_rx.c @@ -1,6 +1,6 @@ /* pdp11_rx.c: RX11/RX01 floppy disk simulator - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ rx RX11/RX01 floppy disk + 03-Sep-13 RMS Added explicit void * cast 07-Jul-05 RMS Removed extraneous externs 12-Oct-02 RMS Added autoconfigure support 08-Oct-02 RMS Added variable address support to bootstrap @@ -330,7 +331,7 @@ t_stat rx_svc (UNIT *uptr) { int32 i, func; uint32 da; -int8 *fbuf = uptr->filebuf; +int8 *fbuf = (int8 *) uptr->filebuf; func = RXCS_GETFNC (rx_csr); /* get function */ switch (rx_state) { /* case on state */ diff --git a/PDP11/pdp11_ry.c b/PDP11/pdp11_ry.c index a973e2e0..2fc9f50b 100644 --- a/PDP11/pdp11_ry.c +++ b/PDP11/pdp11_ry.c @@ -1,6 +1,6 @@ /* pdp11_ry.c: RX211/RXV21/RX02 floppy disk simulator - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ ry RX211/RXV21/RX02 floppy disk + 03-Sep-13 RMS Added explicit void * cast 15-May-06 RMS Fixed bug in autosize attach (David Gesswein) 07-Jul-05 RMS Removed extraneous externs 18-Feb-05 RMS Fixed bug in boot code (Graham Toal) @@ -374,7 +375,7 @@ t_stat ry_svc (UNIT *uptr) int32 i, t, func, bps; static uint8 estat[8]; uint32 ba, da; -int8 *fbuf = uptr->filebuf; +int8 *fbuf = (int8 *) uptr->filebuf; func = RYCS_GETFNC (ry_csr); /* get function */ bps = (ry_csr & RYCS_DEN)? RY_NUMBY: RX_NUMBY; /* get sector size */ diff --git a/PDP11/pdp11_sys.c b/PDP11/pdp11_sys.c index b0b358cf..085dde21 100644 --- a/PDP11/pdp11_sys.c +++ b/PDP11/pdp11_sys.c @@ -1,6 +1,6 @@ /* pdp11_sys.c: PDP-11 simulator interface - Copyright (c) 1993-2012, Robert M Supnik + Copyright (c) 1993-2013, 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,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. + 02-Sep-13 RMS Added third Massbus, RS03/RS04 29-Apr-12 RMS Fixed compiler warning (Mark Pizzolato) 19-Nov-08 RMS Moved I/O support routines to I/O library 15-May-08 RMS Added KE11-A, DC11 support @@ -92,6 +93,7 @@ extern DEVICE rx_dev; extern DEVICE ry_dev; extern DEVICE mba_dev[]; extern DEVICE rp_dev; +extern DEVICE rs_dev; extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev; extern DEVICE tm_dev; extern DEVICE tq_dev; @@ -128,6 +130,7 @@ DEVICE *sim_devices[] = { &sys_dev, &mba_dev[0], &mba_dev[1], + &mba_dev[2], &clk_dev, &pclk_dev, &ptr_dev, @@ -150,6 +153,7 @@ DEVICE *sim_devices[] = { &rx_dev, &ry_dev, &rp_dev, + &rs_dev, &rq_dev, &rqb_dev, &rqc_dev, diff --git a/PDP11/pdp11_ta.c b/PDP11/pdp11_ta.c index 822a2a30..225e3249 100644 --- a/PDP11/pdp11_ta.c +++ b/PDP11/pdp11_ta.c @@ -1,6 +1,6 @@ /* pdp11_ta.c: PDP-11 cassette tape simulator - Copyright (c) 2007-2008, Robert M Supnik + Copyright (c) 2007-2013, 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"), @@ -24,7 +24,9 @@ in this Software without prior written authorization from Robert M Supnik. ta TA11/TU60 cassette tape - + + 06-Jun-13 RMS Reset must set RDY (Ian Hammond) + Added CAPS-11 bootstrap (Ian Hammond) 06-Aug-07 RMS Foward op at BOT skips initial file gap Magnetic tapes are represented as a series of variable records @@ -130,6 +132,7 @@ t_stat ta_svc (UNIT *uptr); t_stat ta_reset (DEVICE *dptr); t_stat ta_attach (UNIT *uptr, char *cptr); t_stat ta_detach (UNIT *uptr); +t_stat ta_boot (int32 unitno, DEVICE *dptr); void ta_go (void); t_stat ta_map_err (UNIT *uptr, t_stat st); UNIT *ta_busy (void); @@ -196,8 +199,8 @@ DEVICE ta_dev = { "TA", ta_unit, ta_reg, ta_mod, TA_NUMDR, 10, 31, 1, 8, 8, NULL, NULL, &ta_reset, - NULL, &ta_attach, &ta_detach, - &ta_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG + &ta_boot, &ta_attach, &ta_detach, + &ta_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_UBUS }; /* I/O dispatch routines, I/O addresses 17777500 - 17777503 @@ -444,8 +447,8 @@ switch (uptr->FNC) { /* case on function */ ta_cs |= TACS_RDY; /* set ready */ ta_updsta (uptr); /* update status */ if (DEBUG_PRS (ta_dev)) - fprintf (sim_deb, ">>TA done: op=%o, status = %o, pos=%d\n", - uptr->FNC, ta_cs, uptr->pos); + fprintf (sim_deb, ">>TA done: op=%o, status = %o, dstatus = %o, pos=%d\n", + uptr->FNC, ta_cs, uptr->UST, uptr->pos); return r; } @@ -564,7 +567,7 @@ t_stat ta_reset (DEVICE *dptr) uint32 u; UNIT *uptr; -ta_cs = 0; +ta_cs = TACS_RDY; /* init sets RDY */ ta_idb = 0; ta_odb = 0; ta_write = 0; @@ -610,3 +613,54 @@ ta_updsta (NULL); uptr->UST = 0; return r; } + +/* Bootstrap routine */ + +#define BOOT_START 01000 /* start */ +#define BOOT_ENTRY (BOOT_START) +#define BOOT_CSR (BOOT_START + 002) /* CSR */ +#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint16)) + +static const uint16 boot_rom[] = { +0012700, /* mov #tacs,r0 */ +0177500, +0005010, /* clr (r0) */ +0010701, /* 3$: mov pc,r1 */ +0062701, /* add #20-here,r1 */ +0000052, +0012702, /* mov #375,r2 */ +0000375, +0112103, /* movb (r1)+,r3 */ +0112110, /* 5$: movb (r1)+,(r0) */ +0100413, /* bmi 15$ */ +0130310, /* 10$: bitb r3,(r0) */ +0001776, /* beq 10$ */ +0105202, /* incb r2 */ +0100772, /* bmi 5$ */ +0116012, /* movb 2(r0),r2 */ +0000002, +0120337, /* cmpb r3,@#0 */ +0000000, +0001767, /* beq 10$ */ +0000000, /* 12$: halt */ +0000755, /* br 3$ */ +0005710, /* 15$: tst (r0) */ +0100774, /* bmi 12$ */ +0005007, /* clr pc */ +0017640, /* $20: (data) */ +0002415, +0112024 +}; + +t_stat ta_boot (int32 unitno, DEVICE *dptr) +{ +int32 i; +extern int32 saved_PC; +extern uint16 *M; + +for (i = 0; i < BOOT_LEN; i++) + M[(BOOT_START >> 1) + i] = boot_rom[i]; +M[BOOT_CSR >> 1] = ta_dib.ba & DMASK; +saved_PC = BOOT_ENTRY; +return SCPE_OK; +} \ No newline at end of file diff --git a/PDP11/pdp11_tq.c b/PDP11/pdp11_tq.c index 9ac8840e..8e632060 100644 --- a/PDP11/pdp11_tq.c +++ b/PDP11/pdp11_tq.c @@ -1,6 +1,6 @@ /* pdp11_tq.c: TMSCP tape controller simulator - Copyright (c) 2002-2011, Robert M Supnik + Copyright (c) 2002-2013, 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 @@ tq TQK50 tape controller + 17-Mar-13 RMS Fixed bug in ABORT link walk loop (Dave Bryan) 17-Aug-11 RMS Added CAPACITY modifier 14-Jan-11 MP Various fixes discovered while exploring Ultrix issue: - Set UNIT_SXC flag when a tape mark is encountered @@ -877,6 +878,7 @@ if (uptr = tq_getucb (lu)) { /* get unit */ tq_pkt[prv].link = tq_pkt[tpkt].link; /* unlink */ break; } + prv = tpkt; /* no match, next */ } } if (tpkt) { /* found target? */ diff --git a/PDP18B/pdp18b_drm.c b/PDP18B/pdp18b_drm.c index c65990b1..dd5a0912 100644 --- a/PDP18B/pdp18b_drm.c +++ b/PDP18B/pdp18b_drm.c @@ -1,6 +1,6 @@ /* pdp18b_drm.c: drum/fixed head disk simulator - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ drm (PDP-4,PDP-7) Type 24 serial drum + 03-Sep-13 RMS Added explicit void * cast 14-Jan-04 RMS Revised IO device call interface 26-Oct-03 RMS Cleaned up buffer copy code 05-Dec-02 RMS Updated from Type 24 documentation @@ -181,7 +182,7 @@ t_stat drm_svc (UNIT *uptr) { int32 i; uint32 da; -int32 *fbuf = uptr->filebuf; +int32 *fbuf = (int32 *) uptr->filebuf; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ drm_err = 1; /* set error */ diff --git a/PDP18B/pdp18b_dt.c b/PDP18B/pdp18b_dt.c index 9b422fec..844c15f8 100644 --- a/PDP18B/pdp18b_dt.c +++ b/PDP18B/pdp18b_dt.c @@ -859,11 +859,11 @@ if (mot & DTS_DIR) /* update pos */ else uptr->pos = uptr->pos + delta; if (((int32) uptr->pos < 0) || ((int32) uptr->pos > (DTU_FWDEZ (uptr) + DT_EZLIN))) { - detach_unit (uptr); /* off reel? */ + detach_unit (uptr); /* off reel? */ uptr->STATE = uptr->pos = 0; unum = (int32) (uptr - dt_dev.units); - if (unum == DTA_GETUNIT (dtsa)) /* if selected, */ - dt_seterr (uptr, DTB_SEL); /* error */ + if (unum == DTA_GETUNIT (dtsa)) /* if selected, */ + dt_seterr (uptr, DTB_SEL); /* error */ return TRUE; } return FALSE; diff --git a/PDP18B/pdp18b_rb.c b/PDP18B/pdp18b_rb.c index 1079fe8c..ff2fec5e 100644 --- a/PDP18B/pdp18b_rb.c +++ b/PDP18B/pdp18b_rb.c @@ -1,6 +1,6 @@ /* pdp18b_rb.c: RB09 fixed head disk simulator - Copyright (c) 2003-2008, Robert M Supnik + Copyright (c) 2003-2013, 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 @@ rb RB09 fixed head disk + 03-Sep-13 RMS Added explicit void * cast 14-Jan-04 RMS Revised IO device call interface 26-Oct-03 RMS Cleaned up buffer copy code @@ -240,7 +241,7 @@ return r; t_stat rb_svc (UNIT *uptr) { int32 t, sw; -int32 *fbuf = uptr->filebuf; +int32 *fbuf = (int32 *) uptr->filebuf; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ rb_updsta (RBS_NRY | RBS_DON); /* set nxd, done */ diff --git a/PDP18B/pdp18b_rf.c b/PDP18B/pdp18b_rf.c index 51e6ecd9..a075c4a0 100644 --- a/PDP18B/pdp18b_rf.c +++ b/PDP18B/pdp18b_rf.c @@ -1,6 +1,6 @@ /* pdp18b_rf.c: fixed head disk simulator - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2013, 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,7 @@ rf (PDP-9) RF09/RF09 (PDP-15) RF15/RS09 + 03-Sep-13 RMS Added explicit void * cast 04-Oct-06 RMS Fixed bug, DSCD does not clear function register 15-May-06 RMS Fixed bug in autosize attach (David Gesswein) 14-Jan-04 RMS Revised IO device call interface @@ -265,7 +266,7 @@ return dat; t_stat rf_svc (UNIT *uptr) { int32 f, pa, d, t; -int32 *fbuf = uptr->filebuf; +int32 *fbuf = (int32 *) uptr->filebuf; if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ rf_updsta (RFS_NED | RFS_DON); /* set nxd, done */ diff --git a/PDP18B/pdp18b_tt1.c b/PDP18B/pdp18b_tt1.c index fdc5ac22..1e60bb79 100644 --- a/PDP18B/pdp18b_tt1.c +++ b/PDP18B/pdp18b_tt1.c @@ -1,6 +1,6 @@ /* pdp18b_ttx.c: PDP-9/15 additional terminals simulator - Copyright (c) 1993-2012, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ ttix,ttox LT15/LT19 terminal input/output + 11-Oct-13 RMS Poll TTIX immediately to pick up initial connect 18-Apr-12 RMS Revised to use clock coscheduling 19-Nov-08 RMS Revised for common TMXR show routines 18-Jun-07 RMS Added UNIT_IDLE flag @@ -396,7 +397,7 @@ t_stat r; r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */ if (r != SCPE_OK) /* error */ return r; -sim_activate (uptr, tmxr_poll); /* start poll */ +sim_activate (uptr, 0); /* start poll at once */ return SCPE_OK; } diff --git a/PDP8/pdp8_cpu.c b/PDP8/pdp8_cpu.c index c327c41a..5da8b55e 100644 --- a/PDP8/pdp8_cpu.c +++ b/PDP8/pdp8_cpu.c @@ -1,6 +1,6 @@ /* pdp8_cpu.c: PDP-8 CPU simulator - Copyright (c) 1993-2011, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ cpu central processor + 17-Sep-13 RMS Fixed boot in wrong field problem (Dave Gesswein) 28-Apr-07 RMS Removed clock initialization 30-Oct-06 RMS Added idle and infinite loop detection 30-Sep-06 RMS Fixed SC value after DVI overflow (Don North) @@ -330,7 +331,8 @@ t_stat reason; /* Restore register state */ -if (build_dev_tab ()) return SCPE_STOP; /* build dev_tab */ +if (build_dev_tab ()) /* build dev_tab */ + return SCPE_STOP; PC = saved_PC & 007777; /* load local copies */ IF = saved_PC & 070000; DF = saved_DF & 070000; @@ -1373,6 +1375,15 @@ sim_brk_types = sim_brk_dflt = SWMASK ('E'); return SCPE_OK; } +/* Set PC for boot (PC<14:12> will typically be 0) */ + +void cpu_set_bootpc (int32 pc) +{ +saved_PC = pc; /* set PC, IF */ +saved_DF = IB = pc & 070000; /* set IB, DF */ +return; +} + /* Memory examine */ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw) diff --git a/PDP8/pdp8_ct.c b/PDP8/pdp8_ct.c index 9f5f1e27..abef6ec6 100644 --- a/PDP8/pdp8_ct.c +++ b/PDP8/pdp8_ct.c @@ -1,6 +1,6 @@ /* pdp8_ct.c: PDP-8 cassette tape simulator - Copyright (c) 2006-2011, Robert M Supnik + Copyright (c) 2006-2013, 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,9 +25,10 @@ ct TA8E/TU60 cassette tape + 17-Sep-07 RMS Changed to use central set_bootpc routine 13-Aug-07 RMS Fixed handling of BEOT 06-Aug-07 RMS Foward op at BOT skips initial file gap - 30-May-2007 RMS Fixed typo (Norm Lastovica) + 30-May007 RMS Fixed typo (Norm Lastovica) Magnetic tapes are represented as a series of variable records of the form: @@ -719,13 +720,12 @@ static const uint16 boot_rom[] = { t_stat ct_boot (int32 unitno, DEVICE *dptr) { int32 i; -extern int32 saved_PC; extern uint16 M[]; if ((ct_dib.dev != DEV_CT) || unitno) /* only std devno */ return STOP_NOTSTD; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; +cpu_set_bootpc (BOOT_START); return SCPE_OK; } diff --git a/PDP8/pdp8_defs.h b/PDP8/pdp8_defs.h index 5d2ee547..2aee89e8 100644 --- a/PDP8/pdp8_defs.h +++ b/PDP8/pdp8_defs.h @@ -1,6 +1,6 @@ /* pdp8_defs.h: PDP-8 simulator definitions - Copyright (c) 1993-2012, Robert M Supnik + Copyright (c) 1993-2013, 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,8 +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-Sep-13 RMS Added set_bootpc prototype 18-Apr-12 RMS Removed separate timer for additional terminals; - added clock_cosched prototype + Added clock_cosched prototype 22-May-10 RMS Added check for 64b definitions 21-Aug-07 RMS Added FPP8 support 13-Dec-06 RMS Added TA8E support @@ -211,5 +212,6 @@ t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc); int32 clk_cosched (int32 wait); +void cpu_set_bootpc (int32 pc); #endif diff --git a/PDP8/pdp8_df.c b/PDP8/pdp8_df.c index a802e6e0..ede45928 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-2011, Robert M Supnik + Copyright (c) 1993-2013, 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,8 @@ df DF32 fixed head disk + 17-Sep-13 RMS Changed to use central set_bootpc routine + 03-Sep-13 RMS Added explicit void * cast 15-May-06 RMS Fixed bug in autosize attach (Dave Gesswein) 07-Jan-06 RMS Fixed unaligned register access bug (Doug Carman) 04-Jan-04 RMS Changed sim_fsize calling sequence @@ -249,7 +251,7 @@ t_stat df_svc (UNIT *uptr) { int32 pa, t, mex; uint32 da; -int16 *fbuf = uptr->filebuf; +int16 *fbuf = (int16 *) uptr->filebuf; UPDATE_PCELL; /* update photocell */ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ @@ -340,12 +342,12 @@ extern int32 sim_switches, saved_PC; if (sim_switches & SWMASK ('D')) { for (i = 0; i < DM4_LEN; i = i + 2) M[dm4_rom[i]] = dm4_rom[i + 1]; - saved_PC = DM4_START; + cpu_set_bootpc (DM4_START); } else { for (i = 0; i < OS8_LEN; i++) M[OS8_START + i] = os8_rom[i]; - saved_PC = OS8_START; + cpu_set_bootpc (OS8_START); } return SCPE_OK; } diff --git a/PDP8/pdp8_dt.c b/PDP8/pdp8_dt.c index 8c452eae..e6b88a15 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-2011, Robert M Supnik + Copyright (c) 1993-2013, 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 + 17-Sep-13 RMS Changed to use central set_bootpc routine 23-Jun-06 RMS Fixed switch conflict in ATTACH 07-Jan-06 RMS Fixed unaligned register access bug (Doug Carman) 16-Aug-05 RMS Fixed C++ declaration and cast problems @@ -383,7 +384,8 @@ int32 pulse = IR & 07; int32 old_dtsa = dtsa, fnc; UNIT *uptr; -if (pulse & 01) AC = AC | dtsa; /* DTRA */ +if (pulse & 01) /* DTRA */ + AC = AC | dtsa; if (pulse & 06) { /* select */ if (pulse & 02) /* DTCA */ dtsa = 0; @@ -1014,7 +1016,8 @@ return SCPE_OK; int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos, int32 dir) { -if (relpos >= DT_HTLIN) relpos = relpos - (DT_WSIZE * DTU_BSIZE (uptr)); +if (relpos >= DT_HTLIN) + relpos = relpos - (DT_WSIZE * DTU_BSIZE (uptr)); if (dir) { /* reverse */ switch (relpos / DT_WSIZE) { case 6: /* rev csm */ @@ -1188,7 +1191,7 @@ if (dt_dib.dev != DEV_DTA) /* only std devno */ dt_unit[unitno].pos = DT_EZLIN; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; +cpu_set_bootpc (BOOT_START); return SCPE_OK; } diff --git a/PDP8/pdp8_pt.c b/PDP8/pdp8_pt.c index f2b1352a..6ec915bc 100644 --- a/PDP8/pdp8_pt.c +++ b/PDP8/pdp8_pt.c @@ -1,6 +1,6 @@ /* pdp8_pt.c: PDP-8 paper tape reader/punch simulator - Copyright (c) 1993-2011, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ ptr,ptp PC8E paper tape reader/punch + 17-Mar-13 RMS Modified to use central set_bootpc routine 25-Apr-03 RMS Revised for extended file support 04-Oct-02 RMS Added DIBs 30-May-02 RMS Widened POS to 32b @@ -286,6 +287,6 @@ if (ptr_dib.dev != DEV_PTR) /* only std devno */ return STOP_NOTSTD; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; +cpu_set_bootpc (BOOT_START); return SCPE_OK; } diff --git a/PDP8/pdp8_rf.c b/PDP8/pdp8_rf.c index aef1c76d..170954d0 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-2011, Robert M Supnik + Copyright (c) 1993-2013, 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,8 @@ rf RF08 fixed head disk + 17-Sep-13 RMS Changed to use central set_bootpc routine + 03-Sep-13 RMS Added explicit void * cast 15-May-06 RMS Fixed bug in autosize attach (Dave Gesswein) 07-Jan-06 RMS Fixed unaligned register access bug (Doug Carman) 04-Jan-04 RMS Changed sim_fsize calling sequence @@ -302,7 +304,7 @@ return AC; t_stat rf_svc (UNIT *uptr) { int32 pa, t, mex; -int16 *fbuf = uptr->filebuf; +int16 *fbuf = (int16 *) uptr->filebuf; UPDATE_PCELL; /* update photocell */ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */ @@ -406,12 +408,12 @@ if (rf_dib.dev != DEV_RF) /* only std devno */ if (sim_switches & SWMASK ('D')) { for (i = 0; i < DM4_LEN; i = i + 2) M[dm4_rom[i]] = dm4_rom[i + 1]; - saved_PC = DM4_START; + cpu_set_bootpc (DM4_START); } else { for (i = 0; i < OS8_LEN; i++) M[OS8_START + i] = os8_rom[i]; - saved_PC = OS8_START; + cpu_set_bootpc (OS8_START); } return SCPE_OK; } diff --git a/PDP8/pdp8_rk.c b/PDP8/pdp8_rk.c index 10b0e5ad..f68057f0 100644 --- a/PDP8/pdp8_rk.c +++ b/PDP8/pdp8_rk.c @@ -1,6 +1,6 @@ /* pdp8_rk.c: RK8E cartridge disk simulator - Copyright (c) 1993-2011, Robert M Supnik + Copyright (c) 1993-2013, 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,8 @@ rk RK8E/RK05 cartridge disk + 17-Sep-13 RMS Changed to use central set_bootpc routine + 18-Mar-13 RMS Raised RK_MIN so that RKLFMT will work (Mark Pizzolato) 25-Apr-03 RMS Revised for extended file support 04-Oct-02 RMS Added DIB, device number support 06-Jan-02 RMS Changed enable/disable support @@ -121,7 +123,7 @@ ((rk_cmd & RKC_IE) != 0)) \ int_req = int_req | INT_RK; \ else int_req = int_req & ~INT_RK -#define RK_MIN 10 +#define RK_MIN 50 #define MAX(x,y) (((x) > (y))? (x): (y)) extern uint16 M[]; @@ -458,6 +460,6 @@ if (rk_dib.dev != DEV_RK) /* only std devno */ for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; M[BOOT_UNIT] = (unitno & RK_M_NUMDR) << 1; -saved_PC = BOOT_START; +cpu_set_bootpc (BOOT_START); return SCPE_OK; } diff --git a/PDP8/pdp8_rl.c b/PDP8/pdp8_rl.c index 22beb05a..8efe79cb 100644 --- a/PDP8/pdp8_rl.c +++ b/PDP8/pdp8_rl.c @@ -1,6 +1,6 @@ /* pdp8_rl.c: RL8A cartridge disk simulator - Copyright (c) 1993-2011, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ rl RL8A cartridge disk + 17-Sep-13 RMS Changed to use central set_bootpc routine 25-Oct-05 RMS Fixed IOT 61 decode bug (David Gesswein) 16-Aug-05 RMS Fixed C++ declaration and cast problems 04-Jan-04 RMS Changed attach routine to use sim_fsize @@ -699,6 +700,6 @@ if (rl_dib.dev != DEV_RL) /* only std devno */ rl_unit[unitno].TRK = 0; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; +cpu_set_bootpc (BOOT_START); return SCPE_OK; } diff --git a/PDP8/pdp8_rx.c b/PDP8/pdp8_rx.c index 7a51df0d..efa3f06e 100644 --- a/PDP8/pdp8_rx.c +++ b/PDP8/pdp8_rx.c @@ -1,6 +1,6 @@ /* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator - Copyright (c) 1993-2011, Robert M Supnik + Copyright (c) 1993-2013, 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,8 @@ rx RX8E/RX01, RX28/RX02 floppy disk + 17-Sep-13 RMS Changed to use central set_bootpc routine + 03-Sep-13 RMS Added explicit void * cast 15-May-06 RMS Fixed bug in autosize attach (Dave Gesswein) 04-Jan-04 RMS Changed sim_fsize calling sequence 05-Nov-03 RMS Fixed bug in RX28 read status (Charles Dickman) @@ -366,7 +368,7 @@ return; t_stat rx_svc (UNIT *uptr) { int32 i, func, byptr, bps, wps; -int8 *fbuf = uptr->filebuf; +int8 *fbuf = (int8 *) uptr->filebuf; uint32 da; #define PTR12(x) (((x) + (x) + (x)) >> 1) @@ -742,13 +744,13 @@ if (rx_dib.dev != DEV_RX) /* only std devno */ if (rx_28) { for (i = 0; i < BOOT2_LEN; i++) M[BOOT2_START + i] = boot2_rom[i]; - saved_PC = BOOT2_ENTRY; + cpu_set_bootpc (BOOT2_ENTRY); } else { for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; M[BOOT_INST] = unitno? 07024: 07004; - saved_PC = BOOT_ENTRY; + cpu_set_bootpc (BOOT_ENTRY); } return SCPE_OK; } diff --git a/PDP8/pdp8_sys.c b/PDP8/pdp8_sys.c index ed7ff85b..b12a16ff 100644 --- a/PDP8/pdp8_sys.c +++ b/PDP8/pdp8_sys.c @@ -1,6 +1,6 @@ /* pdp8_sys.c: PDP-8 simulator interface - Copyright (c) 1993-2011, Robert M Supnik + Copyright (c) 1993-2013, 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,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-Sep-13 RMS Fixed recognition of initial field change (Dave Gesswein) 24-Mar-09 RMS Added link to FPP 24-Jun-08 RMS Fixed bug in new rim loader (Don North) 24-May-08 RMS Fixed signed/unsigned declaration inconsistency @@ -191,11 +192,11 @@ t_stat sim_load_bin (FILE *fi) int32 hi, lo, wd, csum, t; uint32 field, newf, origin; +csum = origin = field = newf = 0; /* init */ do { /* skip leader */ if ((hi = sim_bin_getc (fi, &newf)) == EOF) return SCPE_FMT; } while ((hi == 0) || (hi >= 0200)); -csum = origin = field = newf = 0; /* init */ for (;;) { /* data blocks */ if ((lo = sim_bin_getc (fi, &newf)) == EOF) /* low char */ return SCPE_FMT; diff --git a/PDP8/pdp8_td.c b/PDP8/pdp8_td.c index 46703def..48fdf7cb 100644 --- a/PDP8/pdp8_td.c +++ b/PDP8/pdp8_td.c @@ -1,6 +1,6 @@ /* pdp8_td.c: PDP-8 simple DECtape controller (TD8E) simulator - Copyright (c) 1993-2011, Robert M Supnik + Copyright (c) 1993-2013, 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"), @@ -28,6 +28,7 @@ td TD8E/TU56 DECtape + 17-Sep-13 RMS Changed to use central set_bootpc routine 23-Mar-11 RMS Fixed SDLC to clear AC (from Dave Gesswein) 23-Jun-06 RMS Fixed switch conflict in ATTACH 16-Aug-05 RMS Fixed C++ declaration and cast problems @@ -100,7 +101,7 @@ /* 16b, 18b, 36b DECtape constants */ -#define D18_WSIZE 6 /* word sizein lines */ +#define D18_WSIZE 6 /* word size in lines */ #define D18_BSIZE 384 /* block size in 12b */ #define D18_TSIZE 578 /* tape size */ #define D18_LPERB (DT_HTLIN + (D18_BSIZE * DT_WSIZE) + DT_HTLIN) @@ -752,7 +753,7 @@ if (td_dib.dev != DEV_TD8E) td_unit[unitno].pos = DT_EZLIN; for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i]; -saved_PC = BOOT_START; +cpu_set_bootpc (BOOT_START); return SCPE_OK; } @@ -912,7 +913,8 @@ int32 td_set_mtk (int32 code, int32 u, int32 k) { int32 i; -for (i = 5; i >= 0; i--) tdb_mtk[u][k++] = (code >> i) & 1; +for (i = 5; i >= 0; i--) + tdb_mtk[u][k++] = (code >> i) & 1; return k; } diff --git a/PDP8/pdp8_ttx.c b/PDP8/pdp8_ttx.c index 0956178c..ffac280a 100644 --- a/PDP8/pdp8_ttx.c +++ b/PDP8/pdp8_ttx.c @@ -1,6 +1,6 @@ /* pdp8_ttx.c: PDP-8 additional terminals simulator - Copyright (c) 1993-2012, Robert M Supnik + Copyright (c) 1993-2013, 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 @@ ttix,ttox PT08/KL8JA terminal input/output + 11-Oct-13 RMS Poll TTIX immediately to pick up initial connect (Mark Pizzolato) 18-Apr-12 RMS Revised to use clock coscheduling 19-Nov-08 RMS Revised for common TMXR show routines 07-Jun-06 RMS Added UNIT_IDLE flag @@ -360,7 +361,7 @@ t_stat r; r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */ if (r != SCPE_OK) /* error */ return r; -sim_activate (uptr, tmxr_poll); /* start poll */ +sim_activate (uptr, 0); /* start poll at once */ return SCPE_OK; } diff --git a/SDS/sds_drm.c b/SDS/sds_drm.c index 1e0bfc42..0a8648ff 100644 --- a/SDS/sds_drm.c +++ b/SDS/sds_drm.c @@ -1,6 +1,6 @@ /* sds_drm.c: SDS 940 Project Genie drum simulator - Copyright (c) 2002-2008, Robert M. Supnik + Copyright (c) 2002-2013, 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,8 @@ drm drum + 03-Sep-13 RMS Added explicit void * cast + The drum is buffered in memory. Note: the Project Genie documentation and the actual monitor sources disagree @@ -191,7 +193,7 @@ t_stat drm_svc (UNIT *uptr) { int32 t, rda; uint32 dpc, dwd; -uint32 *fbuf = uptr->filebuf; +uint32 *fbuf = (uint32 *) uptr->filebuf; if (drm_sta != DRM_SXFR) { /* fetch drum prog? */ dpc = M[DRM_PC]; /* get drum PC */ diff --git a/VAX/vax780_defs.h b/VAX/vax780_defs.h index f7086268..6f509643 100644 --- a/VAX/vax780_defs.h +++ b/VAX/vax780_defs.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. + 12-Dec-12 RMS Fixed IO base address for RQB, RQC, RQD 05-Nov-11 RMS Added VEC_QMODE definition 19-Nov-08 RMS Moved I/O support routines to I/O library 29-Apr-07 RMS Modified model-specific reserved operand check macros @@ -277,9 +278,9 @@ typedef struct { #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 IOBA_RQC (IOBA_RQB + IOLN_RQB) #define IOLN_RQC 004 -#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC) +#define IOBA_RQD (IOBA_RQC + IOLN_RQC) #define IOLN_RQD 004 #define IOBA_RQ (IOPAGEBASE + 012150) /* UDA50 */ #define IOLN_RQ 004 diff --git a/VAX/vax780_mba.c b/VAX/vax780_mba.c index afe264c4..1b0abdec 100644 --- a/VAX/vax780_mba.c +++ b/VAX/vax780_mba.c @@ -1,6 +1,6 @@ /* vax780_mba.c: VAX 11/780 Massbus adapter - Copyright (c) 2004-2008, Robert M Supnik + Copyright (c) 2004-2012, 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 @@ mba0, mba1 RH780 Massbus adapter + 08-Dec-12 RMS Block interrupt if data transfer in progress (Mark Pizzolato) 28-May-08 RMS Inlined physical memory routines */ @@ -695,7 +696,7 @@ if (set & MBASR_ABORTS) 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)) +if ((set & MBASR_INTR) && (mba_cr[mb] & MBACR_IE) && !(mba_sr[mb] & MBASR_DTBUSY)) 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]); diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index 85e9459d..3b1ad070 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -1,6 +1,6 @@ /* vaxmod_defs.h: VAX model-specific definitions file - Copyright (c) 1998-2011, Robert M Supnik + Copyright (c) 1998-2012, 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,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. + 12-Dec-12 RMS Fixed IO base address for RQB, RQC, RQD 11-Dec-11 RMS Moved all Qbus devices to BR4; deleted RP definitions 25-Nov-11 RMS Added VEC_QBUS definition 29-Apr-07 RMS Separated checks for PxBR and SBR @@ -280,9 +281,9 @@ typedef struct { #define IOLN_DZ 010 #define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2))) #define IOLN_RQB 004 -#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB) +#define IOBA_RQC (IOBA_RQB + IOLN_RQB) #define IOLN_RQC 004 -#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC) +#define IOBA_RQD (IOBA_RQC + IOLN_RQC) #define IOLN_RQD 004 #define IOBA_VH (IOPAGEBASE + 000440) /* DHQ11 */ #define IOLN_VH 020 diff --git a/scp.c b/scp.c index bbbefe6e..afe333ac 100644 --- a/scp.c +++ b/scp.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. + 08-May-12 RMS Fixed memory leaks in save/restore (Peter Schorn) 20-Mar-12 MP Fixes to "SHOW SHOW" commands 06-Jan-12 JDB Fixed "SHOW DEVICE" with only one enabled unit (Dave Bryan) 13-Jan-11 MP Added "SHOW SHOW" and "SHOW SHOW" commands @@ -2344,8 +2345,10 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru devices */ for (l = 0; (l < SRBSIZ) && (k < high); l++, k = k + (dptr->aincr)) { /* check for 0 block */ r = dptr->examine (&val, k, uptr, SIM_SW_REST); - if (r != SCPE_OK) + if (r != SCPE_OK) { + free (mbuf); return r; + } if (val) zeroflg = FALSE; SZ_STORE (sz, val, mbuf, l); } /* end for l */ @@ -2549,19 +2552,26 @@ for ( ;; ) { /* device loop */ if ((mbuf = calloc (SRBSIZ, sz)) == NULL) return SCPE_MEM; for (k = 0; k < high; ) { /* loop thru mem */ - READ_I (blkcnt); /* block count */ + if (sim_fread (&blkcnt, sizeof (blkcnt), 1, rfile) == 0) { + free (mbuf); /* read blk cnt */ + return SCPE_IOERR; + } if (blkcnt < 0) /* compressed? */ limit = -blkcnt; else limit = sim_fread (mbuf, sz, blkcnt, rfile); - if (limit <= 0) /* invalid or err? */ + if (limit <= 0) { /* invalid or err? */ + free (mbuf); return SCPE_IOERR; + } for (j = 0; j < limit; j++, k = k + (dptr->aincr)) { if (blkcnt < 0) /* compressed? */ val = 0; else SZ_LOAD (sz, val, mbuf, j); /* saved value */ r = dptr->deposit (val, k, uptr, SIM_SW_REST); - if (r != SCPE_OK) + if (r != SCPE_OK) { + free (mbuf); return r; + } } /* end for j */ } /* end for k */ free (mbuf); /* dealloc buffer */ diff --git a/sim_rev.h b/sim_rev.h index 1104d399..36b91dfb 100644 --- a/sim_rev.h +++ b/sim_rev.h @@ -36,6 +36,103 @@ patch date module(s) and fix(es) + 1 tbd h316_stddev.c: + - fixed TTY output behavior (Bob Armstrong) + + h316_sys.c: + - added symbolic names for IO devices + - fixed handling of SMK and OTK + + i1401_lp.c: + - fixed printer chain selection + + id_pas.c: + - poll PAS immediately after attach to pick up connect + + nova_cpu.c: + - added clarifying braces (Dave Bryan) + + pdp1_dcs.c: + - poll DCS immediately after attach to pick up connect + + pdp10_rp.c: + - fixed incorrect copy/paste from pdp11_rp.c + + pdp10_tu.c: + - fixed bug in read/write check reverse (Dave Bryan) + + pdp11_defs.h: + - fixed base address for RQB, RQC, RQD + - added address and IPL data for RS03/RS04 + + pdp11_cpu.c: + - MMR1 does not track PC changes (Johnny Billquist) + + pdp11_cpumod.c: + - fixed model change to set memory size as last step + + pdp11_dc.c, pdp11_dl.c" + - poll input immediately after attach to pick up connect + + pdp11_fp.c: + - MMR1 does not track PC changes (Johnny Billquist) + + pdp11_hk.c: + - rewrote error handling + - rewrote interrupt handling + + pdp11_rh.c: + - added third Massbus adapter, debug printouts + + pdp11_rk.c: + - fixed behavior of RKDS with non-existant drives (Mark Pizzolato) + + pdp11_rp.c: + - UNLOAD shouldn't set ATTN (Mark Pizzolato) + + pdp11_rs.c: + - first release + + pdp11_rq.c: + - fixed bug in ABORT link walk loop (Dave Bryan) + + pdp11_sys.c: + - added third Massbus adapter, RS03/RS04 + + pdp11_ta.c: + - fixed bug to set RDY on reset (Ian Hammond) + - added CAPS-11 bootstrap (Ian Hammond) + + pdp11_tq.c: + - fixed bug in ABORT link walk loop (Dave Bryan) + + pdp15_tt1.c: + - poll TTIX immediately after attach to pick up connect + + pdp8_cpu.c: + - fixed "boot in wrong field" bug (Dave Gesswein) + + pdp8_ct.c, pdp8_df.c, pdp8_dt.c, pdp8_rf.c, pdp8_rk.c, + pdp8_rl.c, pdp8_rx.c, pdp8_td.c: + - changed to use central cpu_setboot routine + + pdp8_rk.c: + - raised RK_MIN so that RKLFMT will work (Mark Pizzolato) + - changed to use central cpu_setboot routine + + pdp8_sys.c: + - fixed recognition of initial field change (Dave Gesswein) + + pdp8_ttx.c: + - poll TTIX immediately after attach to pick up connect (Mark Pizzolato) + + vax780_defs.h, vaxmod_defs.h: + - fixed base address for RQB, RQC, RQD + + vax780_mba.c: + - block interrupt if data transfer in progress (Mark Pizzolato) + + 0 01-May-2012 scp.c: - added *nix READLINE support (Mark Pizzolato) - fixed handling of DO with no arguments (Dave Bryan) @@ -208,7 +305,7 @@ patch date module(s) and fix(es) pdp11_io.c: - fixed Qbus interrupts to treat all IO devices (except clock) as BR4 - - fixed order of int_internal (Jordi Guillaumes i Pons) + - fixed order of int_internal (Jordi Guillaumes i Pons) ppd11_rf.c - fixed bug in updating mem addr extension (Peter Schorn) diff --git a/swtp6800/common/m6800.c b/swtp6800/common/m6800.c index b87617a8..7ffbe217 100644 --- a/swtp6800/common/m6800.c +++ b/swtp6800/common/m6800.c @@ -120,7 +120,7 @@ int32 int_req = 0; /* Interrupt request */ int32 mem_fault = 0; /* memory fault flag */ extern int32 sim_int_char; -extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ +extern uint32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */ /* function prototypes */