From 0289368e1490279d7c15936ce010c8e7b4d678f7 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 3 Sep 2019 22:25:42 -0400 Subject: [PATCH 01/98] KA10: Added support for KL10. --- PDP10/kl10_fe.c | 1705 +++++++++++++++++++++++++ PDP10/kx10_cpu.c | 3067 ++++++++++++++++++++++++++++++++++++++++++--- PDP10/kx10_defs.h | 57 +- PDP10/kx10_rp.c | 26 +- PDP10/kx10_rs.c | 2 - PDP10/kx10_sys.c | 51 +- PDP10/kx10_tu.c | 2 - makefile | 20 +- 8 files changed, 4723 insertions(+), 207 deletions(-) create mode 100644 PDP10/kl10_fe.c diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c new file mode 100644 index 0000000..315abf2 --- /dev/null +++ b/PDP10/kl10_fe.c @@ -0,0 +1,1705 @@ +/* kl10_fe.c: KL-10 front end (console terminal) simulator + + Copyright (c) 2013-2019, Richard Cornwell + + 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 + RICHARD CORNWELL 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 Richard Cornwell shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Richard Cornwell + +*/ + +#include "kx10_defs.h" +#include "sim_sock.h" +#include "sim_tmxr.h" +#include + +#if KL +#define UNIT_DUMMY (1 << UNIT_V_UF) + +#define DTE_DEVNUM 0200 + +/* DTE10 CONI bits */ + +#define DTE_RM 00100000 /* Restricted mode */ +#define DTE_D11 00040000 /* Dead-11 */ +#define DTE_11DB 00020000 /* TO11 Door bell request */ +#define DTE_10DB 00001000 /* TO10 Door bell request */ +#define DTE_11ER 00000400 /* Error during TO11 transfer */ +#define DTE_11DN 00000100 /* TO 11 transfer done */ +#define DTE_10DN 00000040 /* TO 10 transfer done */ +#define DTE_10ER 00000020 /* Error during TO10 transfer */ +#define DTE_PIE 00000010 /* DTE PI enabled */ +#define DTE_PIA 00000007 /* PI channel assigment */ + +/* internal flags */ +#define DTE_11RELD 01000000 /* Reload 11. */ +#define DTE_TO11 02000000 /* Transfer to 11 */ +#define DTE_SEC 04000000 /* In secondary protocol */ +#define DTE_IND 010000000 /* Next transfer will be indirect */ +#define DTE_SIND 020000000 /* Send indirect data next */ + +/* DTE CONO bits */ +#define DTE_CO11DB 0020000 /* Set TO11 Door bell */ +#define DTE_CO11CR 0010000 /* Clear reload 11 button */ +#define DTE_CO11SR 0004000 /* Set reload 11 button */ +#define DTE_CO10DB 0001000 /* Clear TO10 Door bell */ +#define DTE_CO11CL 0000100 /* Clear TO11 done and error */ +#define DTE_CO10CL 0000040 /* Clear TO10 done and error */ +#define DTE_PIENB 0000020 /* Load PI and enable bit */ + +/* DTE DATAO */ +#define DTE_TO10IB 010000 /* Interrupt after transfer */ +#define DTE_TO10BC 007777 /* Byte count for transfer */ + +/* Secondary protocol addresses */ +#define SEC_DTFLG 0444 /* Operation complete flag */ +#define SEC_DTCLK 0445 /* Clock interrupt flag */ +#define SEC_DTCI 0446 /* Clock interrupt instruction */ +#define SEC_DTT11 0447 /* 10 to 11 argument */ +#define SEC_DTF11 0450 /* 10 from 11 argument */ +#define SEC_DTCMD 0451 /* To 11 command word */ +#define SEC_DTSEQ 0452 /* Operation sequence number */ +#define SEC_DTOPR 0453 /* Operational DTE # */ +#define SEC_DTCHR 0454 /* Last typed character */ +#define SEC_DTMTD 0455 /* Monitor tty output complete flag */ +#define SEC_DTMTI 0456 /* Monitor tty input flag */ +#define SEC_DTSWR 0457 /* 10 switch register */ + +#define SEC_PGMCTL 00400 +#define SEC_ENDPASS 00404 +#define SEC_LOOKUP 00406 +#define SEC_RDWRD 00407 +#define SEC_RDBYT 00414 +#define SEC_ESEC 00440 +#define SEC_EPRI 00500 +#define SEC_ERTM 00540 +#define SEC_CLKCTL 01000 +#define SEC_CLKOFF 01000 +#define SEC_CLKON 01001 +#define SEC_CLKWT 01002 +#define SEC_CLKRD 01003 +#define SEC_RDSW 01400 +#define SEC_CLRDDT 03000 +#define SEC_SETDDT 03400 +#define SEC_MONO 04000 +#define SEC_MONON 04400 +#define SEC_SETPRI 05000 +#define SEC_RTM 05400 +#define SEC_CMDMSK 07400 +#define DTE_MON 00000001 /* Save in unit1 STATUS */ +#define SEC_CLK 00000001 /* Clock enabled */ +#define DTE_ACK_CTY 00000002 /* Send CTY Ack */ + +/* Primary or Queued protocol addresses */ +#define PRI_CMTW_0 0 +#define PRI_CMTW_PPT 1 /* Pointer to com region */ +#define PRI_CMTW_STS 2 /* Status word */ +#define PRI_CMT_PWF SMASK /* Power failure */ +#define PRI_CMT_L11 BIT1 /* Load 11 */ +#define PRI_CMT_INI BIT2 /* Init */ +#define PRI_CMT_TST BIT3 /* Valid examine bit */ +#define PRI_CMT_QP 020000000LL /* Do Queued protocol */ +#define PRI_CMT_FWD 001000000LL /* Do full word transfers */ +#define PRI_CMT_IP RSIGN /* Indirect transfer */ +#define PRI_CMT_TOT 0200000LL /* TOIT bit */ +#define PRI_CMT_10IC 0177400LL /* TO10 IC for queued transfers */ +#define PRI_CMT_11IC 0000377LL /* TO11 IC for queued transfers */ +#define PRI_CMTW_CNT 3 /* Queue Count */ +#define PRI_CMTW_KAC 5 /* Keep alive count */ + +#define PRI_EM2EI 001 /* Initial message to 11 */ +#define PRI_EM2TI 002 /* Replay to initial message. */ +#define PRI_EMSTR 003 /* String data */ +#define PRI_EMLNC 004 /* Line-Char */ +#define PRI_EMRDS 005 /* Request device status */ +#define PRI_EMHDS 007 /* Here is device status */ +#define PRI_EMRDT 011 /* Request Date/Time */ +#define PRI_EMHDR 012 /* Here is date and time */ +#define PRI_EMFLO 013 /* Flush output */ +#define PRI_EMSNA 014 /* Send all (ttys) */ +#define PRI_EMDSC 015 /* Dataset connect */ +#define PRI_EMHUD 016 /* Hang up dataset */ +#define PRI_EMACK 017 /* Acknowledge line */ +#define PRI_EMXOF 020 /* XOFF line */ +#define PRI_EMXON 021 /* XON line */ +#define PRI_EMHLS 022 /* Here is line speeds */ +#define PRI_EMHLA 023 /* Here is line allocation */ +#define PRI_EMRBI 024 /* Reboot information */ +#define PRI_EMAKA 025 /* Ack ALL */ +#define PRI_EMTDO 026 /* Turn device On/Off */ +#define PRI_EMEDR 027 /* Enable/Disable line */ +#define PRI_EMLDR 030 /* Load LP RAM */ +#define PRI_EMLDV 031 /* Load LP VFU */ + +#define PRI_EMCTY 001 /* Device code for CTY */ +#define PRI_EMDL1 002 /* DL11 */ +#define PRI_EMDH1 003 /* DH11 #1 */ +#define PRI_EMDLS 004 /* DLS (all ttys combined) */ +#define PRI_EMLPT 005 /* Front end LPT */ +#define PRI_EMCDR 006 /* CDR */ +#define PRI_EMCLK 007 /* Clock */ +#define PRI_EMFED 010 /* Front end device */ + +#define TMR_RTC 2 + +extern int32 tmxr_poll; +t_stat dte_devio(uint32 dev, uint64 *data); +int dte_devirq(uint32 dev, int addr); +void dte_second(UNIT *uptr); +void dte_primary(UNIT *uptr); +void dte_transfer(UNIT *uptr); +void dte_function(UNIT *uptr); +int dte_start(UNIT *uptr); +int dte_queue(UNIT *uptr, int func, int dev, int dcnt, uint16 *data); +t_stat dtei_svc (UNIT *uptr); +t_stat dteo_svc (UNIT *uptr); +t_stat dtertc_srv(UNIT * uptr); +t_stat dte_reset (DEVICE *dptr); +t_stat dte_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *dte_description (DEVICE *dptr); +extern uint64 SW; /* Switch register */ + + +#define STATUS u3 +#define CNT u4 +#define CHHOLD u5 + +extern uint32 eb_ptr; +static int32 rtc_tps = 60; +uint16 rtc_tick; +uint16 rtc_wait = 0; + +struct _dte_queue { + int dptr; /* Pointer to working item */ + uint16 cnt; /* Number of bytes in packet */ + uint16 func; /* Function code */ + uint16 dev; /* Dev code */ + uint16 spare; /* Dev code */ + uint16 dcnt; /* Data count */ + uint16 data[256]; /* Data packet */ + uint16 sdev; /* Secondary device code */ +} dte_in[32], dte_out[32]; + +int dte_in_ptr; +int dte_in_cmd; +int dte_out_ptr; +int dte_out_res; +int dte_base; /* Base */ +int dte_off; /* Our offset */ +int dte_dt10_off; /* Offset to 10 deposit region */ +int dte_et10_off; /* Offset to 10 examine region */ +int dte_et11_off; /* Offset to 11 examine region */ +int dte_proc_num; /* Our processor number */ + +struct _buffer { + int in_ptr; /* Insert pointer */ + int out_ptr; /* Remove pointer */ + char buff[256]; /* Buffer */ +} cty_in, cty_out; + +DIB dte_dib[] = { + { DTE_DEVNUM|000, 1, dte_devio, dte_devirq}, +}; + +MTAB dte_mod[] = { + { UNIT_DUMMY, 0, NULL, "STOP", &dte_stop_os }, + { TT_MODE, TT_MODE_UC, "UC", "UC", &tty_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, + { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode }, + { 0 } + }; + +UNIT dte_unit[] = { + { UDATA (&dteo_svc, TT_MODE_7B, 0), 10000 }, + { UDATA (&dtei_svc, TT_MODE_7B|UNIT_DIS, 0), 10000 }, + { UDATA (&dtertc_srv, UNIT_IDLE|UNIT_DIS, 0), 1000 } + }; + + +DEVICE dte_dev = { + "CTY", dte_unit, NULL, dte_mod, + 3, 10, 31, 1, 8, 8, + NULL, NULL, &dte_reset, + NULL, NULL, NULL, &dte_dib, DEV_DEBUG, 0, dev_debug, + NULL, NULL, &dte_help, NULL, NULL, &dte_description + }; + + + +#ifndef NUM_DEVS_LP +#define NUM_DEVS_LP 0 +#endif + +#if (NUM_DEVS_LP > 0) + +#define COL u4 +#define POS u5 +#define LINE u6 + +#define MARGIN 6 + +#define UNIT_V_CT (UNIT_V_UF + 0) +#define UNIT_UC (1 << UNIT_V_CT) +#define UNIT_CT (3 << UNIT_V_CT) + + + +t_stat lpt_svc (UNIT *uptr); +t_stat lpt_reset (DEVICE *dptr); +t_stat lpt_attach (UNIT *uptr, CONST char *cptr); +t_stat lpt_detach (UNIT *uptr); +t_stat lpt_setlpp(UNIT *, int32, CONST char *, void *); +t_stat lpt_getlpp(FILE *, UNIT *, int32, CONST void *); +t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, + const char *cptr); +const char *lpt_description (DEVICE *dptr); + +char lpt_buffer[134 * 3]; + +struct _buffer lpt_queue; + +/* LPT data structures + + lpt_dev LPT device descriptor + lpt_unit LPT unit descriptor + lpt_reg LPT register list +*/ + +UNIT lpt_unit = { + UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 66), 100 + }; + +REG lpt_reg[] = { + { BRDATA(BUFF, lpt_buffer, 16, 8, sizeof(lpt_buffer)), REG_HRO}, + { NULL } +}; + +MTAB lpt_mod[] = { + {UNIT_CT, 0, "Lower case", "LC", NULL}, + {UNIT_CT, UNIT_UC, "Upper case", "UC", NULL}, + {MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LINESPERPAGE", "LINESPERPAGE", + &lpt_setlpp, &lpt_getlpp, NULL, "Number of lines per page"}, + { 0 } +}; + +DEVICE lpt_dev = { + "LPT", &lpt_unit, lpt_reg, lpt_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &lpt_reset, + NULL, &lpt_attach, &lpt_detach, + NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug, + NULL, NULL, &lpt_help, NULL, NULL, &lpt_description +}; +#endif + +#ifndef NUM_DEVS_TTY +#define NUM_DEVS_TTY 0 +#endif + +#if (NUM_DEVS_TTY > 0) + +struct _buffer tty_out[NUM_LINES_TTY], tty_in[NUM_LINES_TTY]; +TMLN tty_ldsc[NUM_LINES_TTY] = { 0 }; /* Line descriptors */ +TMXR tty_desc = { NUM_LINES_TTY, 0, 0, tty_ldsc }; +int tty_connect[NUM_LINES_TTY];; +int tty_enable = 0; +extern int32 tmxr_poll; + +t_stat ttyi_svc (UNIT *uptr); +t_stat ttyo_svc (UNIT *uptr); +t_stat tty_reset (DEVICE *dptr); +t_stat tty_set_modem (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat tty_show_modem (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat tty_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat tty_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat tty_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat tty_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat tty_attach (UNIT *uptr, CONST char *cptr); +t_stat tty_detach (UNIT *uptr); +t_stat tty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, + const char *cptr); +const char *tty_description (DEVICE *dptr); + +/* TTY data structures + + tty_dev TTY device descriptor + tty_unit TTY unit descriptor + tty_reg TTY register list +*/ + +UNIT tty_unit[] = { + { UDATA (&ttyi_svc, TT_MODE_7B+UNIT_IDLE+UNIT_DISABLE+UNIT_ATTABLE, 0), KBD_POLL_WAIT}, + { UDATA (&ttyo_svc, TT_MODE_7B+UNIT_IDLE+UNIT_DIS, 0), KBD_POLL_WAIT}, + }; + +REG tty_reg[] = { + { DRDATA (TIME, tty_unit[0].wait, 24), REG_NZ + PV_LEFT }, + { NULL } + }; + +MTAB tty_mod[] = { + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", NULL }, + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 1, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &tty_desc, "Disconnect a specific line" }, + { UNIT_ATT, UNIT_ATT, "SUMMARY", NULL, + NULL, &tmxr_show_summ, (void *) &tty_desc, "Display a summary of line states" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 1, "CONNECTIONS", NULL, + NULL, &tmxr_show_cstat, (void *) &tty_desc, "Display current connections" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "STATISTICS", NULL, + NULL, &tmxr_show_cstat, (void *) &tty_desc, "Display multiplexer statistics" }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "LINES", "LINES=n", + &tty_setnl, &tmxr_show_lines, (void *) &tty_desc, "Set number of lines" }, + { MTAB_XTD|MTAB_VDV|MTAB_NC, 0, NULL, "LOG=n=file", + &tty_set_log, NULL, (void *)&tty_desc }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, NULL, "NOLOG", + &tty_set_nolog, NULL, (void *)&tty_desc, "Disable logging on designated line" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "LOG", NULL, + NULL, &tty_show_log, (void *)&tty_desc, "Display logging for all lines" }, + { 0 } + }; + +DEVICE tty_dev = { + "TTY", tty_unit, tty_reg, tty_mod, + 2, 10, 31, 1, 8, 8, + &tmxr_ex, &tmxr_dep, &tty_reset, + NULL, &tty_attach, &tty_detach, + NULL, DEV_NET | DEV_DISABLE | DEV_DEBUG, 0, dev_debug, + NULL, NULL, &tty_help, NULL, NULL, &tty_description + }; +#endif + + +t_stat dte_devio(uint32 dev, uint64 *data) { + uint32 res; + switch(dev & 3) { + case CONI: + *data = (uint64)(dte_unit[0].STATUS) & RMASK; + sim_debug(DEBUG_CONI, &dte_dev, "CTY %03o CONI %06o\n", dev, (uint32)*data); + break; + case CONO: + res = (uint32)(*data & RMASK); + clr_interrupt(dev); + if (res & DTE_PIENB) { + dte_unit[0].STATUS &= ~(DTE_PIA|DTE_PIE); + dte_unit[0].STATUS |= res & (DTE_PIA|DTE_PIE); + } + if (res & DTE_CO11CL) + dte_unit[0].STATUS &= ~(DTE_11DN|DTE_11ER); + if (res & DTE_CO10CL) + dte_unit[0].STATUS &= ~(DTE_10DN|DTE_10ER); + if (res & DTE_CO10DB) + dte_unit[0].STATUS &= ~(DTE_10DB); + if (res & DTE_CO11CR) + dte_unit[0].STATUS &= ~(DTE_11RELD); + if (res & DTE_CO11SR) + dte_unit[0].STATUS |= (DTE_11RELD); + if (res & DTE_CO11DB) { +sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n"); + dte_unit[0].STATUS |= DTE_11DB; + sim_activate(&dte_unit[0], 200); + } + if (dte_unit[0].STATUS & DTE_PIE && + dte_unit[0].STATUS & (DTE_10DB|DTE_11DN|DTE_10DN|DTE_11ER|DTE_10ER)) + set_interrupt(dev, dte_unit[0].STATUS); + sim_debug(DEBUG_CONO, &dte_dev, "CTY %03o CONO %06o %06o\n", dev, (uint32)*data, PC); + break; + case DATAI: + sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAI %06o\n", dev, (uint32)*data); + break; + case DATAO: + dte_unit[0].CNT = (*data & (DTE_TO10IB|DTE_TO10BC)); + dte_unit[0].STATUS |= DTE_TO11; + sim_activate(&dte_unit[0], 10); + sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAO %06o\n", dev, (uint32)*data); + break; + } + return SCPE_OK; +} + +/* Handle KL style interrupt vectors */ +int +dte_devirq(uint32 dev, int addr) { + return 0142; +} + +/* Handle TO11 interrupts */ +t_stat dteo_svc (UNIT *uptr) +{ + t_stat r; + + /* Did the 10 knock? */ + if (uptr->STATUS & DTE_11DB) { + /* If in secondary mode, do that protocol */ + if (uptr->STATUS & DTE_SEC) + dte_second(uptr); + else + dte_primary(uptr); /* Retrieve data */ + } else if (uptr->STATUS & DTE_TO11) { + /* Does 10 want us to send it what we have? */ + dte_transfer(uptr); + } + return SCPE_OK; +} + +/* Handle secondary protocol */ +void dte_second(UNIT *uptr) { + uint64 word; + int32 ch; + uint32 base = 0; + t_stat r; + +#if KI_22BIT +#if ITS_KL + if ((cpu_unit[0].flags & UNIT_ITSPAGE) == 0) +#endif + base = eb_ptr; +#endif + /* read command */ + word = M[SEC_DTCMD + base]; + /* Do it */ + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY secondary %012llo\n", word); + switch(word & SEC_CMDMSK) { + default: + case SEC_MONO: /* Ouput character in monitor mode */ + ch = (int32)(word & 0177); + M[SEC_DTCHR + base] = ch; + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + if ((r = sim_putchar_s (ch)) != SCPE_OK) { /* Output errors */ + sim_activate(uptr, 1000); + return; + } + M[SEC_DTMTD + base] = FMASK ^ 1; + M[SEC_DTF11 + base] = 0; + break; + case SEC_SETPRI: +enter_pri: + if (Mem_examine_word(0, 0, &word)) + break; + dte_proc_num = (word >> 24) & 037; + dte_base = dte_proc_num + 1; + dte_off = dte_base + (word & 0177777); + dte_dt10_off = 16; + dte_et10_off = dte_dt10_off + 16; + dte_et11_off = dte_base + 16; + uptr->STATUS &= ~DTE_SEC; + dte_unit[1].STATUS &= ~DTE_SEC; + dte_in_ptr = dte_out_ptr = 0; + dte_in_cmd = dte_out_res = 0; + /* Start input process */ + break; + case SEC_SETDDT: /* Read character from console */ + if ((ch = dte_unit[1].CHHOLD) == 0) { + sim_activate(uptr, 100); + return; + } + M[SEC_DTF11 + base] = 0177 & ch; + M[SEC_DTMTI + base] = FMASK; + dte_unit[1].CHHOLD = 0; + break; + case SEC_CLRDDT: /* Clear DDT input mode */ + uptr->STATUS &= ~DTE_MON; + sim_cancel(&dte_unit[1]); + break; + case SEC_MONON: + uptr->STATUS |= DTE_MON; + sim_activate(&dte_unit[1], 100); + break; + case SEC_RDSW: /* Read switch register */ + M[SEC_DTSWR + base] = SW; + M[SEC_DTF11 + base] = SW; + break; + + case SEC_PGMCTL: /* Program control: Used by KLDCP */ + switch(word) { + case SEC_ENDPASS: + case SEC_LOOKUP: + case SEC_RDWRD: + case SEC_RDBYT: + break; + case SEC_ESEC: + goto enter_pri; + case SEC_EPRI: + case SEC_ERTM: + break; + } + break; + case SEC_CLKCTL: /* Clock control: Used by KLDCP */ + switch(word) { + case SEC_CLKOFF: + dte_unit[2].STATUS &= ~SEC_CLK; + break; + case SEC_CLKWT: + rtc_wait = (uint16)(M[SEC_DTT11 + base] & 0177777); + case SEC_CLKON: + dte_unit[2].STATUS |= SEC_CLK; + rtc_tick = 0; + break; + case SEC_CLKRD: + M[SEC_DTF11+base] = rtc_tick; + break; + } + break; + } + /* Acknowledge command */ + M[SEC_DTFLG + base] = FMASK; + uptr->STATUS |= DTE_10DB; + uptr->STATUS &= ~DTE_11DB; +} + +/* Handle primary protocol */ +void dte_primary(UNIT *uptr) { + uint64 word, iword; + int s; + int cnt; + struct _dte_queue *in; + uint16 data1, data2, *dp; + + if ((uptr->STATUS & DTE_11DB) == 0) + return; + + /* Check if there is room for another packet */ + if (((dte_in_ptr + 1) & 0x1f) == dte_in_cmd) { + /* If not reschedule ourselves */ + sim_activate(uptr, 100); + return; + } + uptr->STATUS &= ~(DTE_11DB); + clr_interrupt(DTE_DEVNUM); + /* Check status word to see if valid */ + if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word)) { +error: + /* If we can't read it, go back to secondary */ + uptr->STATUS |= DTE_SEC; + return; + } + sim_debug(DEBUG_EXP, &dte_dev, "DTE: Read status: %012llo\n", word); + + if ((word & PRI_CMT_QP) == 0) { + uptr->STATUS |= DTE_SEC; + } + in = &dte_in[dte_in_ptr]; + /* Check if indirect */ + if ((word & PRI_CMT_IP) != 0) { + /* Transfer from 10 */ + if ((uptr->STATUS & DTE_IND) == 0) { + fprintf(stderr, "DTE out of sync\n\r"); + return; + } + word = M[0140 + eb_ptr]; + sim_debug(DEBUG_EXP, &dte_dev, "DTE: Read pointer: %012llo\n", word); + word = M[0141 + eb_ptr]; + sim_debug(DEBUG_EXP, &dte_dev, "DTE: write pointer: %012llo\n", word); + /* Get size of transfer */ + if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_CNT, &iword)) + goto error; + sim_debug(DEBUG_EXP, &dte_dev, "DTE: count: %012llo\n", iword); + in->dcnt = (uint16)(iword & 0177777); + /* Read in data */ + dp = &in->data[0]; + for (cnt = in->dcnt; cnt >= 0; cnt -=2) { + /* Read in data */ + if (!Mem_read_byte(0, dp)) + goto error; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o\n", + *dp, *dp >> 8, *dp & 0377); + dp++; + } + uptr->STATUS &= ~DTE_IND; + dte_in_ptr = (dte_in_ptr + 1) & 0x1f; + } else { + /* Transfer from 10 */ + in->dptr = 0; + /* Read in count */ + if (!Mem_read_byte(0, &data1)) + goto error; + in->cnt = data1; + cnt = in->cnt-2; + if (!Mem_read_byte(0, &data1)) + goto error; + in->func = data1; + cnt -= 2; + if (!Mem_read_byte(0, &data1)) + goto error; + in->dev = data1; + cnt -= 2; + if (!Mem_read_byte(0, &data1)) + goto error; + in->spare = data1; + cnt -= 2; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read CMD: %o %o %o\n", + in->cnt, in->func, in->dev); + dp = &in->data[0]; + for (; cnt > 0; cnt -=2) { + /* Read in data */ + if (!Mem_read_byte(0, dp)) + goto error; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read data: %06o %03o %03o\n", + *dp, *dp >> 8, *dp & 0377); + dp++; + } + if (in->func & 0100000) { + uptr->STATUS |= DTE_IND; + in->sdev = in->dcnt = in->data[0]; + word |= PRI_CMT_TOT; + if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) + goto error; + } else { + dte_in_ptr = (dte_in_ptr + 1) & 0x1f; + } + } +done: + word &= ~PRI_CMT_TOT; + if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) + goto error; + uptr->STATUS |= DTE_11DN; + if (uptr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, uptr->STATUS); +} + +void +dte_function(UNIT *uptr) +{ + uint16 data1[32]; + int32 ch; + struct _dte_queue *cmd; + t_stat r; + + + /* Check if queue is empty */ + while (dte_in_cmd != dte_in_ptr) { + if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n", + dte_out_res, dte_out_ptr); + return; + } + cmd = &dte_in[dte_in_cmd]; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: func %02o %o %d %d\n", cmd->func & 0377, + cmd->dev, cmd->dcnt, cmd->dptr ); + switch (cmd->func & 0377) { + case PRI_EM2EI: /* Initial message to 11 */ + data1[0] = 0; + if (dte_queue(uptr, PRI_EM2TI, PRI_EMCTY, 1, data1) == 0) + return; +#if (NUM_DEVS_LP > 0) + data1[0] = 140; + if (dte_queue(uptr, PRI_EMHLA, PRI_EMLPT, 1, data1) == 0) + return; +#endif + +// data1[0] = ((ln + 1) << 8) | 32; + // (void)dte_queue(uptr, PRI_EMHLA, PRI_EMDL1, 1, data1); + if (dte_queue(uptr, PRI_EMAKA, PRI_EMDH1, 0, data1) == 0) + return; + break; + + case PRI_EM2TI: /* Replay to initial message. */ + case PRI_EMACK: /* Acknowledge line */ + /* Should never get these */ + break; + + case PRI_EMSTR: /* String data */ + + /* Handle printer data */ + if (cmd->dev == PRI_EMLPT) { + if (!sim_is_active(&lpt_unit)) + sim_activate(&lpt_unit, 1000); + while (cmd->dptr < cmd->dcnt) { + if (((lpt_queue.in_ptr + 1) & 0xff) == lpt_queue.out_ptr) + return; + ch = (int32)(cmd->data[cmd->dptr >> 1]); + if ((cmd->dptr & 1) == 0) + ch >>= 8; + ch &= 0177; + lpt_queue.buff[lpt_queue.in_ptr] = ch; + lpt_queue.in_ptr = (lpt_queue.in_ptr + 1) & 0xff; + cmd->dptr++; + } + if (cmd->dptr != cmd->dcnt) + return; + break; + } + + /* Handle terminal data */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 1; + if (ln < 0) + goto cty; + if (ln >= tty_desc.lines) + break; + while (cmd->dptr < cmd->dcnt) { + if (((tty_out[ln].in_ptr + 1) & 0xff) == tty_out[ln].out_ptr) + return; + ch = (int32)(cmd->data[cmd->dptr >> 1]); + if ((cmd->dptr & 1) == 0) + ch >>= 8; + ch &= 0177; + sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln); + tty_out[ln].buff[tty_out[ln].in_ptr] = ch; + tty_out[ln].in_ptr = (tty_out[ln].in_ptr + 1) & 0xff; + cmd->dptr++; + } + if (cmd->dptr != cmd->dcnt) + return; + break; + } + /* Fall through */ + case PRI_EMSNA: /* Send all (ttys) */ + if (cmd->dev != PRI_EMCTY) + break; +cty: + data1[0] = 0; + while (cmd->dptr < cmd->dcnt) { + ch = (int32)(cmd->data[cmd->dptr >> 1]); + if ((cmd->dptr & 1) == 0) + ch >>= 8; + ch &= 0177; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY type %x\n", ch); + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + if ((r = sim_putchar_s (ch)) != SCPE_OK) /* Output errors */ + return; + cmd->dptr++; + } + if (cmd->dptr != cmd->dcnt) + return; + if (dte_queue(uptr, PRI_EMACK, PRI_EMCTY, 1, data1) == 0) + return; + break; + + case PRI_EMLNC: /* Line-Char */ + /* Send by DTE only? */ +#if 0 + data1[0] = 0; + while (cmd->dptr < cmd->dcnt) { + ch = (int32)(cmd->data[cmd->dptr >> 1]); + if ((ch >> 8) == PRI_EMCTY) { + ch &= 0177; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ltype %x\n", ch); + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + if ((r = sim_putchar_s (ch)) != SCPE_OK) /* Output errors */ + return; + data1[0] = (PRI_EMCTY << 8); + } + cmd->dptr+=2; + } + if (cmd->dptr != cmd->dcnt) + return; + if (dte_queue(uptr, PRI_EMACK, PRI_EMCTY, 1, data1) == 0) + return; +#endif + break; + case PRI_EMRDS: /* Request device status */ + case PRI_EMHDS: /* Here is device status */ + case PRI_EMRDT: /* Request Date/Time */ + case PRI_EMHDR: /* Here is date and time */ + break; + case PRI_EMFLO: /* Flush output */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 1;; + tty_out[ln].in_ptr = tty_out[ln].out_ptr = 0; + } + break; + case PRI_EMDSC: /* Dataset connect */ + break; + case PRI_EMHUD: /* Hang up dataset */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 1; + TMLN *lp = &tty_ldsc[ln]; + tmxr_linemsg (lp, "\r\nLine Hangup\r\n"); + tmxr_reset_ln(lp); + tty_connect[ln] = 0; + } + break; + case PRI_EMXOF: /* XOFF line */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 1; + tty_ldsc[ln].rcve = 0; + } + break; + case PRI_EMXON: /* XON line */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 1; + tty_ldsc[ln].rcve = 1; + } + break; + case PRI_EMHLS: /* Here is line speeds */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 1; + } + break; + case PRI_EMHLA: /* Here is line allocation */ + case PRI_EMRBI: /* Reboot information */ + case PRI_EMAKA: /* Ack ALL */ + case PRI_EMTDO: /* Turn device On/Off */ + break; + case PRI_EMEDR: /* Enable/Disable line */ + if (cmd->dev == PRI_EMDH1) { + /* Zero means enable, no-zero means disable */ + tty_enable = !cmd->data[0]; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY enable %x\n", tty_enable); + if (tty_enable) { + sim_activate(&tty_unit[0], 1000); + sim_activate(&tty_unit[1], 1000); + } else { + sim_cancel(&tty_unit[0]); + sim_cancel(&tty_unit[1]); + } + } + break; + case PRI_EMLDR: /* Load LP RAM */ + case PRI_EMLDV: /* Load LP VFU */ + default: + break; + } + /* Mark command as finished */ + cmd->cnt = 0; + dte_in_cmd = (dte_in_cmd + 1) & 0x1F; + } +} + +/* + * Handle primary protocol, + * Send to 10 when requested. + */ +void dte_transfer(UNIT *uptr) { + uint64 word; + int s; + uint16 cnt; + uint16 scnt; + struct _dte_queue *out; + uint16 data1, data2, *dp; + + /* Check if Queue empty */ + if (dte_out_res == dte_out_ptr) + return; + + out = &dte_out[dte_out_ptr]; + uptr->STATUS &= ~DTE_TO11; + clr_interrupt(DTE_DEVNUM); + + /* Compute how much 10 wants us to send */ + scnt = ((uptr->CNT ^ DTE_TO10BC) + 1) & DTE_TO10BC; + /* Check if indirect */ + if ((uptr->STATUS & DTE_SIND) != 0) { + /* Transfer indirect */ + cnt = out->dcnt+2; + dp = &out->data[0]; + if (cnt > scnt) /* Only send as much as we are allowed */ + cnt = scnt; + for (; cnt > 0; cnt -= 2) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Send Idata: %06o %03o %03o\n", + *dp, *dp >> 8, *dp & 0377); + if (Mem_write_byte(0, dp) == 0) + goto error; + } + uptr->STATUS &= ~DTE_SIND; + } else { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d send CMD: %o %o %o\n", + dte_out_ptr, dte_out_res, out->cnt, out->func, out->dev); + /* Get size of packet */ + cnt = out->cnt + out->dcnt; + /* If it will not fit, request indirect */ + if (cnt > scnt) { /* If not enough space request indirect */ + out->func |= 0100000; + cnt = scnt; + } + /* Write out header */ + if (!Mem_write_byte(0, &cnt)) + goto error; + if (!Mem_write_byte(0, &out->func)) + goto error; + cnt -= 2; + if (!Mem_write_byte(0, &out->dev)) + goto error; + cnt -= 2; + if (!Mem_write_byte(0, &out->spare)) + goto error; + cnt -= 2; + if (out->func & 0100000) { + if (!Mem_write_byte(0, &out->dcnt)) + goto error; + uptr->STATUS |= DTE_SIND; + goto done; + } + cnt -= 2; + dp = &out->data[0]; + for (; cnt > 0; cnt -= 2) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Send data: %06o %03o %03o\n", + *dp, *dp >> 8, *dp & 0377); + if (!Mem_write_byte(0, dp)) + goto error; + dp++; + } + } + out->cnt = 0; + dte_out_ptr = (dte_out_ptr + 1) & 0x1f; +done: + uptr->STATUS |= DTE_10DN; +//fprintf(stderr, "Xfer done %06o\n\r", uptr->CNT ); + if (uptr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, uptr->STATUS); +error: + return; +} + +/* + * Queue up a packet to send to 10. + */ +int +dte_queue(UNIT *uptr, int func, int dev, int dcnt, uint16 *data) +{ + uint64 word; + uint16 *dp; + UNIT *optr = &dte_unit[0]; + struct _dte_queue *out; + + /* Check if room in queue for this packet. */ + if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d out full\n", dte_out_res, dte_out_ptr); + return 0; + } + out = &dte_out[dte_out_res]; + out->cnt = 10; + out->func = func; + out->dev = dev; + out->dcnt = (dcnt-1)*2; + out->spare = 0; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d queue resp: %o %o %o\n", + dte_out_ptr, dte_out_res, out->cnt, out->func, out->dev); + for (dp = &out->data[0]; dcnt > 0; dcnt--) { + *dp++ = *data++; + } + /* Advance pointer to next function */ + dte_out_res = (dte_out_res + 1) & 0x1f; + return 1; +} + + +/* + * If anything in queue, start a transfer, if one is not already + * pending. + */ +int +dte_start(UNIT *uptr) +{ + uint64 word; + int dcnt; + + /* Check if queue empty */ + if (dte_out_ptr == dte_out_res) + return 1; + + /* If there is interrupt pending, just return */ + if ((uptr->STATUS & (DTE_IND|DTE_10DB|DTE_11DB)) != 0) + return 1; + if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word)) { +error: + /* If we can't read it, go back to secondary */ + uptr->STATUS |= DTE_SEC|DTE_10ER; + if (uptr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, uptr->STATUS); + return 0; + } + /* If in middle of transfer hold off */ + if (word & PRI_CMT_TOT) + return 1; + /* Bump count of messages sent */ + word = (word & ~(PRI_CMT_10IC|PRI_CMT_IP)) | ((word + 0400) & PRI_CMT_10IC); + if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) + goto error; + word = (uint64)(dte_out[dte_out_ptr].cnt + dte_out[dte_out_ptr].dcnt); + if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_CNT, &word)) + goto error; + /* Tell 10 something is ready */ + uptr->STATUS |= DTE_10DB; + if (uptr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, uptr->STATUS); + return 1; +} + + +/* Handle TO10 traffic */ +t_stat dtei_svc (UNIT *uptr) +{ + int32 ch; + uint32 base = 0; + UNIT *optr = &dte_unit[0]; + uint16 data1; + +#if KI_22BIT + base = eb_ptr; +#endif + + sim_clock_coschedule (uptr, 1000); + if ((uptr->STATUS & DTE_SEC) == 0) { + dte_function(uptr); /* Process queue */ + dte_start(optr); + } + /* continue poll */ + if ((ch = uptr->CHHOLD) == 0) { + if ((ch = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ + return ch; + if (ch & SCPE_BREAK) /* ignore break */ + return SCPE_OK; + ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (uptr->flags)); + uptr->CHHOLD = ch; + } + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %x\n", ch); + if (optr->STATUS & DTE_SEC) { + if (optr->STATUS & DTE_MON && M[SEC_DTMTI + base] == 0) { + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %x\n", ch & 0177); + M[SEC_DTF11 + base] = ch; + M[SEC_DTMTI + base] = FMASK; + optr->STATUS |= DTE_10DB; + if (optr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, optr->STATUS); + uptr->CHHOLD = 0; + } + } else { + data1 = (PRI_EMCTY << 8) | ch; + if (dte_queue(uptr, PRI_EMLNC, PRI_EMCTY, 1, &data1) != 0) + uptr->CHHOLD = 0; + } + return SCPE_OK; +} + +t_stat +dtertc_srv(UNIT * uptr) +{ + int32 t; + UNIT *optr = &dte_unit[0]; + + t = sim_rtcn_calb (rtc_tps, TMR_RTC); + sim_activate_after(uptr, 1000000/rtc_tps); + if (uptr->STATUS & SEC_CLK) { + rtc_tick++; + if (rtc_wait != 0) { + rtc_wait--; + } else { + UNIT *optr = &dte_unit[0]; + uint32 base = 0; +#if KI_22BIT + base = eb_ptr; +#endif + /* Set timer flag */ + M[SEC_DTCLK + base] = FMASK; + optr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, optr->STATUS); + sim_debug(DEBUG_EXP, &dte_dev, "CTY tick %x %x %06o\n", + rtc_tick, rtc_wait, optr->STATUS); + } + } + if ((optr->STATUS & DTE_SEC) == 0) { + int addr = 0144 + eb_ptr; + uint64 word; + + (void)Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word); +//fprintf(stderr, "Timer %06o %012llo\n\r", optr->STATUS, word); + addr = (M[addr+1] + dte_off + PRI_CMTW_KAC) & RMASK; + word = M[addr]; + word = (word + 1) & FMASK; + M[addr] = word; + sim_debug(DEBUG_EXP, &dte_dev, "CTY keepalive %06o %012llo %06o\n", + addr, word, optr->STATUS); + } + + return SCPE_OK; +} + + +t_stat dte_reset (DEVICE *dptr) +{ + dte_unit[0].STATUS = DTE_SEC; + dte_unit[1].STATUS = DTE_SEC; + dte_unit[1].CHHOLD = 0; + dte_unit[2].STATUS = 0; + dte_in_ptr = dte_in_cmd = dte_out_ptr = dte_out_res = 0; + cty_in.in_ptr = 0; + cty_in.out_ptr = 0; + cty_out.in_ptr = 0; + cty_out.out_ptr = 0; + sim_rtcn_init_unit (&dte_unit[2], dte_unit[2].wait, TMR_RTC); + sim_activate(&dte_unit[1], 100); + sim_activate(&dte_unit[2], 100); + return SCPE_OK; +} + +/* Stop operating system */ + +t_stat dte_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + M[CTY_SWITCH] = 1; /* tell OS to stop */ + return SCPE_OK; +} + +t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + dte_unit[0].flags = (dte_unit[0].flags & ~TT_MODE) | val; + return SCPE_OK; +} + +t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "To stop the cpu use the command:\n\n"); +fprintf (st, " sim> SET CTY STOP\n\n"); +fprintf (st, "This will write a 1 to location %03o, causing TOPS10 to stop\n\n", CTY_SWITCH); +fprintf (st, "The additional terminals can be set to one of four modes: UC, 7P, 7B, or 8B.\n\n"); +fprintf (st, " mode input characters output characters\n\n"); +fprintf (st, " UC lower case converted lower case converted to upper case,\n"); +fprintf (st, " to upper case, high-order bit cleared,\n"); +fprintf (st, " high-order bit cleared non-printing characters suppressed\n"); +fprintf (st, " 7P high-order bit cleared high-order bit cleared,\n"); +fprintf (st, " non-printing characters suppressed\n"); +fprintf (st, " 7B high-order bit cleared high-order bit cleared\n"); +fprintf (st, " 8B no changes no changes\n\n"); +fprintf (st, "The default mode is 7P. In addition, each line can be configured to\n"); +fprintf (st, "behave as though it was attached to a dataset, or hardwired to a terminal:\n\n"); +fprint_reg_help (st, &dte_dev); +return SCPE_OK; +} + +const char *dte_description (DEVICE *dptr) +{ + return "Console TTY Line"; +} + + +#if (NUM_DEVS_LP > 0) + +void +lpt_printline(UNIT *uptr, int nl) { + int trim = 0; + uint16 data1 = 1; + /* Trim off trailing blanks */ + while (uptr->COL >= 0 && lpt_buffer[uptr->POS - 1] == ' ') { + uptr->COL--; + uptr->POS--; + trim = 1; + } + lpt_buffer[uptr->POS] = '\0'; + sim_debug(DEBUG_DETAIL, &lpt_dev, "LP output %d %d [%s]\n", uptr->COL, nl, lpt_buffer); + /* Stick a carraige return and linefeed as needed */ + if (uptr->COL != 0 || trim) + lpt_buffer[uptr->POS++] = '\r'; + if (nl != 0) { + lpt_buffer[uptr->POS++] = '\n'; + uptr->LINE++; + } + if (nl > 0 && uptr->LINE >= ((int32)uptr->capac - MARGIN)) { + lpt_buffer[uptr->POS++] = '\f'; + uptr->LINE = 0; + } else if (nl < 0 && uptr->LINE >= (int32)uptr->capac) { + uptr->LINE = 0; + } + + sim_fwrite(&lpt_buffer, 1, uptr->POS, uptr->fileref); + uptr->pos += uptr->POS; + uptr->COL = 0; + uptr->POS = 0; +// if (uptr->LINE == 0) + // (void)dte_queue(&dte_unit[0], PRI_EMHDS, PRI_EMLPT, 1, &data1); + return; +} + + +/* Unit service */ +void +lpt_output(UNIT *uptr, char c) { + + if (c == 0) + return; + if (uptr->COL == 132) + lpt_printline(uptr, 1); + if ((uptr->flags & UNIT_UC) && (c & 0140) == 0140) + c &= 0137; + else if (c >= 040 && c < 0177) { + lpt_buffer[uptr->POS++] = c; + uptr->COL++; + } + return; +} + +t_stat lpt_svc (UNIT *uptr) +{ + char c; + int pos; + int cpos; + uint16 data1 = 0; + + if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_OK; + + while (((lpt_queue.out_ptr + 1) & 0xff) != lpt_queue.in_ptr) { + c = lpt_queue.buff[lpt_queue.out_ptr]; + lpt_queue.out_ptr = (lpt_queue.out_ptr + 1) & 0xff; + if (c < 040) { /* Control character */ + switch(c) { + case 011: /* Horizontal tab, space to 8'th column */ + lpt_output(uptr, ' '); + while ((uptr->COL & 07) != 0) + lpt_output(uptr, ' '); + break; + case 015: /* Carriage return, print line */ + lpt_printline(uptr, 0); + break; + case 012: /* Line feed, print line, space one line */ + lpt_printline(uptr, 1); + break; + case 014: /* Form feed, skip to top of page */ + lpt_printline(uptr, 0); + sim_fwrite("\014", 1, 1, uptr->fileref); + uptr->pos++; + uptr->LINE = 0; + break; + case 013: /* Vertical tab, Skip mod 20 */ + lpt_printline(uptr, 1); + while((uptr->LINE % 20) != 0) { + sim_fwrite("\r\n", 1, 2, uptr->fileref); + uptr->pos+=2; + uptr->LINE++; + } + break; + case 020: /* Skip half page */ + lpt_printline(uptr, 1); + while((uptr->LINE % 30) != 0) { + sim_fwrite("\r\n", 1, 2, uptr->fileref); + uptr->pos+=2; + uptr->LINE++; + } + break; + case 021: /* Skip even lines */ + lpt_printline(uptr, 1); + while((uptr->LINE % 2) != 0) { + sim_fwrite("\r\n", 1, 2, uptr->fileref); + uptr->pos+=2; + uptr->LINE++; + } + break; + case 022: /* Skip triple lines */ + lpt_printline(uptr, 1); + while((uptr->LINE % 3) != 0) { + sim_fwrite("\r\n", 1, 2, uptr->fileref); + uptr->pos+=2; + uptr->LINE++; + } + break; + case 023: /* Skip one line */ + lpt_printline(uptr, -1); + break; + default: /* Ignore */ + break; + } + } else { + sim_debug(DEBUG_DETAIL, &lpt_dev, "LP deque %02x '%c'\n", c, c); + lpt_output(uptr, c); + } + } + if (dte_queue(&dte_unit[0], PRI_EMACK, PRI_EMLPT, 1, &data1) == 0) + sim_activate(uptr, 1000); + return SCPE_OK; +} + +/* Reset routine */ + +t_stat lpt_reset (DEVICE *dptr) +{ + UNIT *uptr = &lpt_unit; + uptr->POS = 0; + uptr->COL = 0; + uptr->LINE = 1; + sim_cancel (&lpt_unit); /* deactivate unit */ + return SCPE_OK; +} + +/* Attach routine */ + +t_stat lpt_attach (UNIT *uptr, CONST char *cptr) +{ + t_stat reason; + + return attach_unit (uptr, cptr); +} + +/* Detach routine */ + +t_stat lpt_detach (UNIT *uptr) +{ + return detach_unit (uptr); +} + +/* + * Line printer routines + */ + +t_stat +lpt_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + t_value i; + t_stat r; + if (cptr == NULL) + return SCPE_ARG; + if (uptr == NULL) + return SCPE_IERR; + i = get_uint (cptr, 10, 100, &r); + if (r != SCPE_OK) + return SCPE_ARG; + uptr->capac = (t_addr)i; + uptr->LINE = 0; + return SCPE_OK; +} + +t_stat +lpt_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc) +{ + if (uptr == NULL) + return SCPE_IERR; + fprintf(st, "linesperpage=%d", uptr->capac); + return SCPE_OK; +} + +t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "Line Printer (LPT)\n\n"); +fprintf (st, "The line printer (LPT) writes data to a disk file. The POS register specifies\n"); +fprintf (st, "the number of the next data item to be written. Thus, by changing POS, the\n"); +fprintf (st, "user can backspace or advance the printer.\n"); +fprintf (st, "The Line printer can be configured to any number of lines per page with the:\n"); +fprintf (st, " sim> SET %s0 LINESPERPAGE=n\n\n", dptr->name); +fprintf (st, "The default is 66 lines per page.\n\n"); +fprintf (st, "The device address of the Line printer can be changed\n"); +fprintf (st, " sim> SET %s0 DEV=n\n\n", dptr->name); +fprint_set_help (st, dptr); +fprint_show_help (st, dptr); +fprint_reg_help (st, dptr); +return SCPE_OK; +} + +const char *lpt_description (DEVICE *dptr) +{ + return "LPT0 line printer" ; +} + +#endif + +#if (NUM_DEVS_TTY > 0) + +/* Unit service */ +t_stat ttyi_svc (UNIT *uptr) +{ + int32 ln; + int n = 0; + TMLN *lp; + uint16 data1[32]; + int flg; + + if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; + + sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */ + + /* Check if room in queue for at least one packet */ + if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n", + dte_out_res, dte_out_ptr); + return SCPE_OK; + } + + ln = tmxr_poll_conn (&tty_desc); /* look for connect */ + if (ln >= 0) { /* got one? rcv enb*/ + tty_ldsc[ln].rcve = 1; + tty_ldsc[ln].xmte = 1; + data1[0] = ((ln + 1) << 8) | (ln + 1); + tty_connect[ln] = 1; + (void)dte_queue(&dte_unit[0], PRI_EMDSC, PRI_EMDLS, 1, data1); +// data1[0] = (ln + 1) << 8; + // /* Send out any data we got */ + // (void)dte_queue(&dte_unit[0], PRI_EMACK, PRI_EMDLS, 1, data1); + sim_debug(DEBUG_DETAIL, &tty_dev, "TTY line connect %d\n", ln); + } + tmxr_poll_tx(&tty_desc); + tmxr_poll_rx(&tty_desc); + + /* Check if room in queue for at least one packet */ + if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n", + dte_out_res, dte_out_ptr); + return SCPE_OK; + } + ln = uptr->CNT; + do { + flg = 0; + lp = &tty_ldsc[ln]; + /* Check to see if any pending data for this line */ + if (lp->rcve && tmxr_input_pending_ln(lp) > 0) { + int32 ch = tmxr_getc_ln (lp); + sim_debug(DEBUG_DETAIL, &tty_dev, "TTY recieve %d: %02x\n", ln, ch); + if ((ch & SCPE_BREAK) == 0) { /* break? */ + ch = sim_tt_inpcvt (ch, TT_GET_MODE(tty_unit[0].flags) | TTUF_KSR); + data1[n++] = ((ln + 1) << 8) | ch; + } + flg = 1; + } + if (++ln >= tty_desc.lines) + ln = 0; + } while (flg && n < 32); + uptr->CNT = ln; + + /* Send out any data we got */ + if (n > 0) + (void)dte_queue(&dte_unit[0], PRI_EMLNC, PRI_EMDLS, n, data1); + + /* Look for lines that have been disconnected */ + for (ln = 0; ln < tty_desc.lines; ln++) { + if (tty_connect[ln] == 1 && tty_ldsc[ln].conn == 0) { + data1[0] = (ln + 1) << 8; + if (dte_queue(&dte_unit[0], PRI_EMHUD, PRI_EMDLS, 1, data1) != 0) { + /* Check if disconnect */ + tty_connect[ln] = 0; + sim_debug(DEBUG_DETAIL, &tty_dev, "TTY line disconnect %d\n", ln); + } + } + } + + return SCPE_OK; +} + +/* Output whatever we can */ +t_stat ttyo_svc (UNIT *uptr) +{ + t_stat r; + int32 ln; + int n = 0; + TMLN *lp; + uint16 data1[32]; + + if ((tty_unit[0].flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; + + sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */ + + for (ln = 0; ln < tty_desc.lines; ln++) { + lp = &tty_ldsc[ln]; + if (lp->conn == 0) + continue; + if (tty_out[ln].out_ptr == tty_out[ln].in_ptr) + continue; + /* Check if room in queue for at least one packet */ + if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n", + dte_out_res, dte_out_ptr); + return SCPE_OK; + } + while (tty_out[ln].out_ptr != tty_out[ln].in_ptr) { + int32 ch = tty_out[ln].buff[tty_out[ln].out_ptr]; + ch = sim_tt_outcvt(ch, TT_GET_MODE (tty_unit[0].flags) | TTUF_KSR); + sim_debug(DEBUG_DATA, &tty_dev, "TTY: %d output %02x\n", ln, ch); + r = tmxr_putc_ln (lp, ch); + if (r == SCPE_OK) + tty_out[ln].out_ptr = (tty_out[ln].out_ptr + 1) & 0xff; + else if (r == SCPE_LOST) { + tty_out[ln].out_ptr = tty_out[ln].in_ptr = 0; + continue; + } + } + data1[n++] = (ln + 1) << 8; + /* Send out any data we got */ + if (n > 32) { + (void)dte_queue(&dte_unit[0], PRI_EMACK, PRI_EMDLS, n, data1); + n = 0; + } + } + + /* Send out any data we got */ + if (n > 0) + (void)dte_queue(&dte_unit[0], PRI_EMACK, PRI_EMDLS, n, data1); + + return SCPE_OK; +} + +/* Reset routine */ + +t_stat tty_reset (DEVICE *dptr) +{ + return SCPE_OK; +} + + +/* SET LINES processor */ + +t_stat tty_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + int32 newln, i, t; + t_stat r; + + if (cptr == NULL) + return SCPE_ARG; + newln = (int32) get_uint (cptr, 10, NUM_LINES_TTY, &r); + if ((r != SCPE_OK) || (newln == tty_desc.lines)) + return r; + if ((newln == 0) || (newln >= NUM_LINES_TTY) || (newln % 16) != 0) + return SCPE_ARG; + if (newln < tty_desc.lines) { + for (i = newln, t = 0; i < tty_desc.lines; i++) + t = t | tty_ldsc[i].conn; + if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) + return SCPE_OK; + for (i = newln; i < tty_desc.lines; i++) { + if (tty_ldsc[i].conn) { + tmxr_linemsg (&tty_ldsc[i], "\r\nOperator disconnected line\r\n"); + tmxr_send_buffered_data (&tty_ldsc[i]); + } + tmxr_detach_ln (&tty_ldsc[i]); /* completely reset line */ + } + } + if (tty_desc.lines < newln) + memset (tty_ldsc + tty_desc.lines, 0, sizeof(*tty_ldsc)*(newln-tty_desc.lines)); + tty_desc.lines = newln; + return tty_reset (&tty_dev); /* setup lines and auto config */ +} + +/* SET LOG processor */ + +t_stat tty_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + t_stat r; + char gbuf[CBUFSIZE]; + int32 ln; + + if (cptr == NULL) + return SCPE_ARG; + cptr = get_glyph (cptr, gbuf, '='); + if ((cptr == NULL) || (*cptr == 0) || (gbuf[0] == 0)) + return SCPE_ARG; + ln = (int32) get_uint (gbuf, 10, tty_desc.lines, &r); + if ((r != SCPE_OK) || (ln >= tty_desc.lines)) + return SCPE_ARG; + return tmxr_set_log (NULL, ln, cptr, desc); +} + +/* SET NOLOG processor */ + +t_stat tty_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + t_stat r; + int32 ln; + + if (cptr == NULL) + return SCPE_ARG; + ln = (int32) get_uint (cptr, 10, tty_desc.lines, &r); + if ((r != SCPE_OK) || (ln >= tty_desc.lines)) + return SCPE_ARG; + return tmxr_set_nolog (NULL, ln, NULL, desc); +} + +/* SHOW LOG processor */ + +t_stat tty_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + int32 i; + + for (i = 0; i < tty_desc.lines; i++) { + fprintf (st, "line %d: ", i); + tmxr_show_log (st, NULL, i, desc); + fprintf (st, "\n"); + } + return SCPE_OK; +} + + +/* Attach routine */ + +t_stat tty_attach (UNIT *uptr, CONST char *cptr) +{ +t_stat reason; + +reason = tmxr_attach (&tty_desc, uptr, cptr); +if (reason != SCPE_OK) + return reason; +sim_activate (uptr, tmxr_poll); +return SCPE_OK; +} + +/* Detach routine */ + +t_stat tty_detach (UNIT *uptr) +{ + int32 i; + t_stat reason; +reason = tmxr_detach (&tty_desc, uptr); +for (i = 0; i < tty_desc.lines; i++) + tty_ldsc[i].rcve = 0; +sim_cancel (uptr); +return reason; +} + +t_stat tty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "DC10E Terminal Interfaces\n\n"); +fprintf (st, "The DC10 supported up to 8 blocks of 8 lines. Modem control was on a seperate\n"); +fprintf (st, "line. The simulator supports this by setting modem control to a fixed offset\n"); +fprintf (st, "from the given line. The number of lines is specified with a SET command:\n\n"); +fprintf (st, " sim> SET DC LINES=n set number of additional lines to n [8-32]\n\n"); +fprintf (st, "Lines must be set in multiples of 8.\n"); +fprintf (st, "The default offset for modem lines is 32. This can be changed with\n\n"); +fprintf (st, " sim> SET DC MODEM=n set offset for modem control to n [8-32]\n\n"); +fprintf (st, "Modem control must be set larger then the number of lines\n"); +fprintf (st, "The ATTACH command specifies the port to be used:\n\n"); +tmxr_attach_help (st, dptr, uptr, flag, cptr); +fprintf (st, "The additional terminals can be set to one of four modes: UC, 7P, 7B, or 8B.\n\n"); +fprintf (st, " mode input characters output characters\n\n"); +fprintf (st, " UC lower case converted lower case converted to upper case,\n"); +fprintf (st, " to upper case, high-order bit cleared,\n"); +fprintf (st, " high-order bit cleared non-printing characters suppressed\n"); +fprintf (st, " 7P high-order bit cleared high-order bit cleared,\n"); +fprintf (st, " non-printing characters suppressed\n"); +fprintf (st, " 7B high-order bit cleared high-order bit cleared\n"); +fprintf (st, " 8B no changes no changes\n\n"); +fprintf (st, "The default mode is 7P.\n"); +fprintf (st, "Finally, each line supports output logging. The SET DCn LOG command enables\n"); +fprintf (st, "logging on a line:\n\n"); +fprintf (st, " sim> SET DCn LOG=filename log output of line n to filename\n\n"); +fprintf (st, "The SET DCn NOLOG command disables logging and closes the open log file,\n"); +fprintf (st, "if any.\n\n"); +fprintf (st, "Once DC is attached and the simulator is running, the terminals listen for\n"); +fprintf (st, "connections on the specified port. They assume that the incoming connections\n"); +fprintf (st, "are Telnet connections. The connections remain open until disconnected either\n"); +fprintf (st, "by the Telnet client, a SET DC DISCONNECT command, or a DETACH DC command.\n\n"); +fprintf (st, "Other special commands:\n\n"); +fprintf (st, " sim> SHOW DC CONNECTIONS show current connections\n"); +fprintf (st, " sim> SHOW DC STATISTICS show statistics for active connections\n"); +fprintf (st, " sim> SET DCn DISCONNECT disconnects the specified line.\n"); +fprint_reg_help (st, &tty_dev); +fprintf (st, "\nThe additional terminals do not support save and restore. All open connections\n"); +fprintf (st, "are lost when the simulator shuts down or DC is detached.\n"); +return SCPE_OK; +} + +const char *tty_description (DEVICE *dptr) +{ +return "DC10E asynchronous line interface"; +} + +#endif +#endif diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 1104236..2ede924 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -100,6 +100,7 @@ #define HIST_PC 0x40000000 #define HIST_PC2 0x80000000 +#define HIST_PCE 0x20000000 #define HIST_MIN 64 #define HIST_MAX 500000 #define TMR_RTC 0 @@ -107,11 +108,15 @@ uint64 M[MAXMEMSIZE]; /* Memory */ +#if KL +uint64 FM[128]; /* Fast memory register */ +#else #if KI uint64 FM[64]; /* Fast memory register */ #else uint64 FM[16]; /* Fast memory register */ #endif +#endif uint64 AR; /* Primary work register */ uint64 MQ; /* Extension to AR */ uint64 BR; /* Secondary operand */ @@ -159,7 +164,7 @@ int pi_restore; /* Restore previous level */ int pi_hold; /* Hold onto interrupt */ int modify; /* Modify cycle */ int xct_flag; /* XCT flags */ -#if KI +#if KI | KL uint64 ARX; /* Extension to AR */ uint64 BRX; /* Extension to BR */ uint64 ADX; /* Extension to AD */ @@ -168,10 +173,26 @@ uint32 eb_ptr; /* Executive base pointer */ uint8 fm_sel; /* User fast memory block */ int32 apr_serial = -1; /* CPU Serial number */ int inout_fail; /* In out fail flag */ +#if KL +int ext_ac; /* Extended instruction AC */ +uint8 prev_ctx; /* Previous AC context */ +uint16 irq_enable; /* Apr IRQ enable bits */ +uint16 irq_flags; /* Apr IRQ bits */ +int mtr_irq; /* Timer IRQ */ +int mtr_enable; /* Enable Timer */ +int mtr_flags; /* Flags for accounting */ +int tim_per; /* Timer period */ +int tim_val; /* Current timer value */ +uint32 brk_addr; /* Address break */ +int brk_flags; /* Break flags */ +int t20_page; /* Tops 20 paging selected */ +int ptr_flg; /* Access to pointer value */ +#else int small_user; /* Small user flag */ +#endif int user_addr_cmp; /* User address compare flag */ #endif -#if KI | ITS | BBN +#if KI | KL | ITS | BBN uint32 e_tlb[512]; /* Executive TLB */ uint32 u_tlb[546]; /* User TLB */ int page_enable; /* Enable paging */ @@ -204,6 +225,16 @@ uint64 opc; /* Saved PC and Flags */ uint64 mar; /* Memory address compare */ uint32 qua_time; /* Quantum clock value */ #endif +#if KL_ITS +#define dbr1 FM[(6<<4)|1] +#define dbr2 FM[(6<<4)|2] +#define dbr3 FM[(6<<4)|3] +#define dbr4 FM[(6<<4)|4] +#define jpc FM[(6<<4)|7] +#define opc FM[(6<<4)|6] +#define mar brk_addr; +#endif + int watch_stop; /* Stop at memory watch point */ int maoff = 0; /* Offset for traps */ @@ -216,13 +247,15 @@ int32 rtc_tps = 60; t_stat qua_srv(UNIT * uptr); int32 qua_tps = 125000; #endif +#if KL +t_stat tim_srv(UNIT * uptr); +#endif int32 tmxr_poll = 10000; /* Physical address range for Rubin 10-11 interface. */ #define T11RANGE(addr) ((addr) >= 03040000) /* Physical address range for auxiliary PDP-6. */ -extern int auxcpu_base; -#define AUXCPURANGE(addr) ((addr) >= auxcpu_base && (addr) < (auxcpu_base + 040000)) +#define AUXCPURANGE(addr) ((addr) >= 03000000 && (addr) < 03040000) DEVICE *rh_devs[] = { #if (NUM_DEVS_RS > 0) @@ -272,13 +305,16 @@ InstHistory *hst = NULL; /* instruction history */ /* Forward and external declarations */ +#if KL +int do_extend(uint32 IA); +#endif t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_reset (DEVICE *dptr); t_stat cpu_set_size (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat cpu_set_hist (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, CONST void *desc); -#if KI +#if KI | KL t_stat cpu_set_serial (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat cpu_show_serial (FILE *st, UNIT *uptr, int32 val, CONST void *desc); #endif @@ -300,6 +336,9 @@ t_bool build_dev_tab (void); UNIT cpu_unit[] = { { UDATA (&rtc_srv, UNIT_IDLE|UNIT_FIX|UNIT_BINK|UNIT_TWOSEG, 256 * 1024) }, #if ITS { UDATA (&qua_srv, UNIT_IDLE|UNIT_DIS, 0) } +#endif +#if KL + { UDATA (&tim_srv, UNIT_IDLE|UNIT_DIS, 0) } #endif }; @@ -322,10 +361,14 @@ REG cpu_reg[] = { { ORDATA (FM15, FM[015], 36) }, { ORDATA (FM16, FM[016], 36) }, { ORDATA (FM17, FM[017], 36) }, +#if KL + { BRDATA (FM, &FM[0], 8, 36, 128)}, +#else #if KI { BRDATA (FM, &FM[0], 8, 36, 64)}, #else { BRDATA (FM, &FM[0], 8, 36, 16)}, +#endif #endif { ORDATAD (PIR, PIR, 8, "Priority Interrupt Request") }, { ORDATAD (PIH, PIH, 8, "Priority Interrupt Hold") }, @@ -365,24 +408,28 @@ REG cpu_reg[] = { #endif { FLDATA (PIHOLD, pi_hold, 0), REG_HRO}, { FLDATA (PIREST, pi_restore, 0), REG_HRO}, -#if KI +#if KI | KL { ORDATAD (UB, ub_ptr, 18, "User Base Pointer") }, { ORDATAD (EB, eb_ptr, 18, "Executive Base Pointer") }, { ORDATAD (FMSEL, fm_sel, 8, "Register set select") }, { ORDATAD (SERIAL, apr_serial, 10, "System Serial Number") }, { FLDATA (INOUT, inout_fail, 0), REG_RO}, +#if KI { FLDATA (SMALL, small_user, 0), REG_RO}, +#endif { FLDATA (ADRCMP, user_addr_cmp, 0), REG_HRO}, #endif -#if KI | ITS | BBN +#if KL | KI | ITS | BBN { FLDATAD (PAGE_ENABLE, page_enable, 0, "Paging enabled")}, { FLDATAD (PAGE_FAULT, page_fault, 0, "Page fault"), REG_RO}, { ORDATAD (AC_STACK, ac_stack, 18, "AC Stack"), REG_RO}, { ORDATAD (PAGE_RELOAD, pag_reload, 18, "Page reload"), REG_HRO}, { ORDATAD (FAULT_DATA, fault_data, 36, "Page fault data"), REG_RO}, { FLDATAD (TRP_FLG, trap_flag, 0, "Trap flag"), REG_HRO}, +#if !KL { ORDATAD (LST_PAGE, last_page, 9, "Last page"), REG_HRO}, #endif +#endif #if BBN { FLDATAD (EXEC_MAP, exec_map, 0, "Executive mapping"), REG_RO}, { FLDATAD (NXT_WR, next_write, 0, "Map next write"), REG_RO}, @@ -434,7 +481,7 @@ MTAB cpu_mod[] = { "One Relocation Register"}, { UNIT_M_PAGE, UNIT_TWOSEG, "TWOSEG", "TWOSEG", NULL, NULL, NULL, "Two Relocation Registers"}, -#if ITS +#if ITS | KL_ITS { UNIT_M_PAGE, UNIT_ITSPAGE, "ITS", "ITS", NULL, NULL, NULL, "Paging hardware for ITS"}, #endif @@ -539,7 +586,7 @@ int opflags[] = { /* Double precsision math */ /* UJEN */ /* UUO101 */ /* GFAD */ /* GFSB */ 0, 0, 0, 0, - /* JSYS */ /* ADJSP */ /* GFMP */ /*GFDV */ + /* JSYS */ /* ADJSP */ /* GFMP */ /* GFDV */ 0, 0, 0, 0, /* DFAD */ /* DFSB */ /* DFMP */ /* DFDV */ 0, 0, 0, 0, @@ -781,7 +828,7 @@ int opflags[] = { #define SMEAR_SIGN(x) x = ((x) & SMASK) ? (x) | EXPO : (x) & MANT #define GET_EXPO(x) ((((x) & SMASK) ? 0377 : 0 ) \ ^ (((x) >> 27) & 0377)) -#if KI +#if KI | KL #define AOB(x) ((x + 1) & RMASK) | ((x + 01000000LL) & (C1|LMASK)) #define SOB(x) ((x + RMASK) & RMASK) | ((x + LMASK) & (C1|LMASK)); #else @@ -793,8 +840,12 @@ int opflags[] = { #define QTEN11 (ten11_unit[0].flags & UNIT_ATT) #define QAUXCPU (auxcpu_unit[0].flags & UNIT_ATT) #else +#if KL_ITS +#define QITS (cpu_unit[0].flags & UNIT_ITSPAGE) +#else #define QITS 0 #endif +#endif #if BBN #define QBBN (cpu_unit[0].flags & UNIT_BBNPAGE) #else @@ -1013,8 +1064,9 @@ t_stat dev_pi(uint32 dev, uint64 *data) { } if (res & 0400) /* Bit 27 */ pi_enable = 0; - if (res & 01000) /* Bit 26 */ + if (res & 01000) { /* Bit 26 */ PIE &= ~(*data & 0177); + } if (res & 02000) /* Bit 25 */ PIE |= (*data & 0177); if (res & 04000) { /* Bit 24 */ @@ -1025,15 +1077,17 @@ t_stat dev_pi(uint32 dev, uint64 *data) { if (res & 020000 && cpu_unit[0].flags & UNIT_MPX) mpx_enable = 1; #endif -#if KI +#if KI | KL if (res & 020000) { /* Bit 22 */ PIR &= ~(*data & 0177); } #endif +#if !KL if (res & 040000) /* Bit 21 */ parity_irq = 1; if (res & 0100000) /* Bit 20 */ parity_irq = 0; +#endif check_apr_irq(); sim_debug(DEBUG_CONO, &cpu_dev, "CONO PI %012llo\n", *data); break; @@ -1042,19 +1096,28 @@ t_stat dev_pi(uint32 dev, uint64 *data) { res = PIE; res |= (pi_enable << 7); res |= (PIH << 8); -#if KI +#if KI | KL res |= ((uint64)(PIR) << 18); #endif +#if !KL res |= (parity_irq << 15); +#endif *data = res; sim_debug(DEBUG_CONI, &cpu_dev, "CONI PI %012llo\n", *data); break; case DATAO: +#if KL + if (dev & 040) { /* SDIAG */ +// fprintf(stderr, "SDIAG %012llo\n\r", *data); + break; + } +#else MI = *data; #ifdef PANDA_LIGHTS /* Set lights */ ka10_lights_main (*data); +#endif #endif break; @@ -1081,6 +1144,340 @@ t_stat null_dev(uint32 dev, uint64 *data) { return SCPE_OK; } +#if KL +static int timer_irq, timer_flg; + +/* + * Page device for KL10. + */ +t_stat dev_pag(uint32 dev, uint64 *data) { + uint64 res = 0; + int i; + switch(dev & 03) { + case CONI: + res = (eb_ptr >> 9); + if (page_enable) + res |= 020000; + if (t20_page) + res |= 040000; + *data = res; + sim_debug(DEBUG_CONI, &cpu_dev, "CONI PAG %012llo\n", *data); + break; + + case CONO: + eb_ptr = (*data & 017777) << 9; + for (i = 0; i < 512; i++) + e_tlb[i] = 0; + for (;i < 546; i++) + u_tlb[i] = 0; + page_enable = (*data & 020000) != 0; + t20_page = (*data & 040000) != 0; + sim_debug(DEBUG_CONO, &cpu_dev, "CONO PAG %012llo\n", *data); + break; + + case DATAO: + if (dev & 040) { /* CLRPT */ + int upmp = 0; + int page = (RMASK & AB) >> 9; + int uf = (FLAGS & USER) != 0; + int i; + + page &= ~7; + /* Map the page */ +// if (uf || upmp) { + for(i = 0; i < 8; i++) + u_tlb[page+i] = 0; + // } else { + for(i = 0; i < 8; i++) + e_tlb[page+i] = 0; + // } + /* If not user do exec mappping */ + if (/*!uf && !t20_page &&*/ (page & 0740) == 0340) { + /* Pages 340-377 via UBT */ + page += 01000 - 0340; + upmp = 1; + for(i = 0; i < 8; i++) + u_tlb[page+i] = 0; + } + break; + } + res = *data; + if (res & SMASK) { + fm_sel = (uint8)(res >> 23) & 0160; + prev_ctx = (res >> 20) & 0160; + } + if (res & BIT1) { + /* Load previous section */ + } + if (res & BIT2) { + ub_ptr = (res & 017777) << 9; + for (i = 0; i < 512; i++) + u_tlb[i] = 0; + for (;i < 546; i++) + u_tlb[i] = 0; + } + sim_debug(DEBUG_DATAIO, &cpu_dev, + "DATAO PAG %012llo ebr=%06o ubr=%06o\n", + *data, eb_ptr, ub_ptr); + break; + + case DATAI: + if (dev & 040) { + /* Convert to MMU */ + } + res = (ub_ptr >> 9); + /* Set previous section */ + res |= ((uint64)(prev_ctx & 0160)) << 20; + res |= ((uint64)(fm_sel & 0160)) << 23; + res |= SMASK|BIT1|BIT2; + *data = res; + sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI PAG %012llo\n", *data); + break; + } + return SCPE_OK; +} + +/* + * Cache control. + * All operations set sweep done. + */ +t_stat dev_cca(uint32 dev, uint64 *data) { + irq_flags |= 020; + check_apr_irq(); + return SCPE_OK; +} + + +/* + * Check if the last operation caused a APR IRQ to be generated. + */ +void check_apr_irq() { + if (pi_enable && apr_irq) { + int flg = 0; + clr_interrupt(0); + flg = irq_enable & irq_flags; + if (flg) + set_interrupt(0, apr_irq); + } +} + +int Mem_write(int flag, int cur_context); + +/* + * APR device for KL10. + */ +t_stat dev_apr(uint32 dev, uint64 *data) { + uint64 res = 0; + + switch(dev & 03) { + case CONI: + /* Read trap conditions */ + res = irq_flags | apr_irq; + res |= ((uint64)irq_enable) << 18; + if (irq_flags & irq_enable) + res |= 010; + *data = res; + sim_debug(DEBUG_CONI, &cpu_dev, "CONI APR %012llo\n", *data); + break; + + case CONO: + /* Set trap conditions */ + res = *data; + apr_irq = res & 07; + clr_interrupt(0); + if (res & 0200000) + reset_all(1); + if (res & 0100000) { /* Enable interrupts */ + irq_enable |= 07760 & res; + } + if (res & 0040000) { /* Disable interrupts */ + irq_enable &= ~(07760 & res); + } + if (res & 0020000) { /* Clear interrupt */ + irq_flags &= ~(07760 & res); + } + if (res & 0010000) { /* Set interrupt */ + irq_flags |= (07760 & res); + } + check_apr_irq(); + sim_debug(DEBUG_CONO, &cpu_dev, "CONO APR %012llo\n", *data); + break; + + case DATAO: + brk_addr = *data & RMASK; + brk_flags = 017 & (*data >> 23); + sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAO APR %012llo\n", *data); + break; + + case DATAI: + if (dev & 040) { + /* APRID */ + AR = SMASK| (500LL << 18); + /* Bit 0 for TOPS-20 paging */ + /* Bit 1 for extended addressing */ + /* Bit 2 Exotic microcode */ + /* Bit 4 for ITS Style Paging */ +#if KL_ITS + AR |= 00020000000000LL; +#endif + /* Bit 18 50hz 4 */ + /* Bit 19 Cache 2 */ + /* Bit 20 Channel? 1*/ + /* Bit 21 Extended KL10 */ + /* Bit 22 Master Osc */ + AR |= (uint64)((apr_serial == -1) ? DEF_SERIAL : apr_serial); + MB = AR; + (void)Mem_write(0, 0); + sim_debug(DEBUG_DATAIO, &cpu_dev, "APRID %012llo\n", MB); + break; + } + *data = ((uint64)brk_flags) << 23; + *data |= (uint64)brk_addr; + sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI APR %012llo\n", *data); + break; + } + return SCPE_OK; +} + +/* + * MTR device for KL10. + */ +t_stat dev_mtr(uint32 dev, uint64 *data) { + uint64 res = 0; + + switch(dev & 03) { + case CONI: + /* Reader meters */ + *data = mtr_irq; + if (mtr_enable) + *data |= 02000; + *data |= (uint64)(mtr_flags << 12); + sim_debug(DEBUG_CONI, &cpu_dev, "CONI MTR %012llo\n", *data); + break; + + case CONO: + /* WRTIME */ + mtr_irq = *data & 07; + if (*data & 02000) + mtr_enable = 1; + if (*data & 04000) + mtr_enable = 0; + if (*data & RSIGN) + mtr_flags = (*data >> 12) & 07; + clr_interrupt(4 << 2); + if (tim_val & 030000) + set_interrupt(4 << 2, mtr_irq); + sim_debug(DEBUG_CONO, &cpu_dev, "CONO MTR %012llo\n", *data); + break; + + case DATAO: + if (dev & 040) { + sim_debug(DEBUG_DATAIO, &cpu_dev, "BLKO MTR %012llo\n", *data); + } else { + sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAO MTR %012llo\n", *data); + } + break; + + case DATAI: + if (dev & 040) { + /* Read memory accounting */ + sim_debug(DEBUG_DATAIO, &cpu_dev, "BLKI MTR %012llo\n", *data); + } else { + /* Read executive accounting */ + sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI MTR %012llo\n", *data); + } + break; + } + return SCPE_OK; +} + +/* + * TIM device for KL10. + */ +t_stat dev_tim(uint32 dev, uint64 *data) { + uint64 res; + double us; + UNIT *uptr = &cpu_unit[1 + ITS]; + + /* Update current timer count */ + if (sim_is_active(uptr)) { + us = sim_activate_time_usecs (uptr) / 10; + /* Check if going to period or overflow */ + if (tim_val & 0100000) + tim_val = (tim_val & 0070000) + tim_per - (int)us; + else + tim_val = (tim_val & 0070000) + 010000 - (int)us; + } + clr_interrupt(4 << 2); + switch(dev & 03) { + case CONI: + /* Interval counter */ + res = tim_per; + res |= tim_val & 070000; + res |= ((uint64)(tim_val & 07777)) << 18; + *data = res; + sim_debug(DEBUG_CONI, &cpu_dev, "CONI TIM %012llo\n", *data); + return SCPE_OK; + + case CONO: + /* Interval counter */ + sim_cancel(uptr); + tim_val &= 037777; /* Clear run bit */ + tim_per = *data & 07777; + if (*data & 020000) /* Clear overflow and done */ + tim_val &= 07777; + if (*data & 0400000) /* Clear counter */ + tim_val = 0; + if (*data & 040000) /* Enable counter */ + tim_val |= 040000; + sim_debug(DEBUG_CONO, &cpu_dev, "CONO TIM %012llo\n", *data); + break; + + case DATAO: + if (dev & 040) { + /* Write performance */ + sim_debug(DEBUG_DATAIO, &cpu_dev, "BLKO TIM %012llo\n", *data); + } else { + sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAO TIM %012llo\n", *data); + } + return SCPE_OK; + + case DATAI: + if (dev & 040) { + /* Read perfomance */ + sim_debug(DEBUG_DATAIO, &cpu_dev, "BLKI TIM %012llo\n", *data); + } else { + /* RDTIME */ + *data = M[eb_ptr + 0510]; + BR = M[eb_ptr + 0511]; + sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI TIM %012llo\n", *data); + } + return SCPE_OK; + } + /* If timer is on, figure out when it will go off */ + if (tim_val & 040000) { + /* If we have already passed time, schedule to overflow */ + if ((tim_val & 07777) >= tim_per) { + us = (float)((010000 - (tim_val & 07777)) * 10); + tim_val &= 0077777; + } else { + us = (float)((tim_per - (tim_val & 07777)) * 10); + tim_val |= 0100000; + } + (void)sim_activate_after_d(uptr, us); + } + if (tim_val & 030000) + set_interrupt(4 << 2, mtr_irq); + return SCPE_OK; +} + +int +tim_irq(uint32 dev, int addr) +{ + return 0514; +} + +#endif #if KI static int timer_irq, timer_flg; @@ -1417,10 +1814,255 @@ sim_debug(DEBUG_DATAIO, &cpu_dev, "Rl=%06o Pl=%06o, Rh=%06o, Ph=%06o\n", Rl, Pl, } #endif +#if KL +int +load_tlb(int uf, int page, int upmp, int wr, int trap) +{ + uint64 data; + +#if KL_ITS + if (QITS && t20_page) { + int dbr; + int pg; + + dbr = (uf)? + ((page & 0400)?FM[(06<<4)|4]:FM[(06<<4)|3]) : + ((page & 0400)?FM[(06<<4)|2]:FM[(06<<4)|1]); + pg = (page & 0377) >> 2; /* 2 1024 word page entries */ + data = M[dbr + pg]; + if ((page & 02) == 0) + data >>= 18; + data &= RMASK; + switch(data >> 16) { + case 0: pg = 0; break; /* No access */ + case 1: /* Read Only */ + case 2: pg = RSIGN; break; /* R/W First */ + case 3: pg = RSIGN|0100000; break; /* R/W */ + } + pg |= data & 01777; + /* Create 2 page table entries. */ + if (uf) { + u_tlb[page & 0776] = pg; + u_tlb[(page & 0776)|1] = pg+1; + } else { + e_tlb[page & 0776] = pg; + e_tlb[(page & 0776)|1] = pg+1; + } + } else +#endif +#define PG_PUB 0040000 +#define PG_WRT 0020000 +#define PG_CAC 0004000 +#define PG_STG 0000037 +#define PG_IDX 0000377 + +#define PG_MASK 0000003777777LL +#define PG_AGE 0770000000000LL +#define PG_PAG 0007777 +//fprintf(stderr, "Lookup Page %03o %0o %o %o\r\n", page, t20_page, upmp, uf); + if (t20_page) { /* Start with full access */ + int acc_bits = PG_PUB|PG_WRT|PG_CAC; + uint64 spt = FM[(06<<4)|3] & PG_MASK; + uint64 cst = FM[(06<<4)|2] & PG_MASK; + uint64 cst_msk = FM[(06<<4)|0]; + uint64 cst_dat = FM[(06<<4)|1]; + int index; + int match = 0; + int pg; + + /* Get segment pointer */ + /* And save it */ + if (uf) + data = M[ub_ptr + 0440]; + else + data = M[eb_ptr + 0440]; +fprintf(stderr, "Map %012llo %012llo %012llo\n\r", data, spt, cst); + /* Find correct page table */ + do { + switch ((data >> 33) & 07) { + default: /* Invalid page */ + fault_data = 0; + page_fault = 1; + return 0; + case 1: /* Direct page */ + /* Bit 4 = execute */ + /* Bit 3 = Write */ + /* Bit 2 = Read */ + acc_bits &= (data >> 18) & RMASK; + match = 1; + break; + + case 2: /* Shared page */ + acc_bits &= (data >> 18) & RMASK; + data = M[(data & RMASK) + spt]; + match = 1; + break; + + case 3: /* Indirect page */ + acc_bits &= (data >> 18) & RMASK; + index = (data >> 18) & PG_IDX; + data = M[(data & RMASK) + spt]; + if ((data >> 18) & PG_STG) { + if (trap) { + fault_data = 0; + page_fault = 1; + } + return 0; + } + data = M[(data & RMASK) + index]; + break; + + } + } while (!match); +fprintf(stderr, "XMap %012llo\n\r", data); + + match = 0; + /* Now look up address of final table entry */ + do { + if ((data >> 18) & PG_STG) { +fprintf(stderr, "ZMap %012llo not in stg\n\r", data); + if (trap) { + fault_data = 0; + page_fault = 1; + } + return 0; + } + pg = data & PG_PAG; + /* Check outside of memory */ + /* Update CST entry if needed */ + if (cst) { + uint64 c = M[cst + pg]; + if ((c & PG_AGE) == 0) { +fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); + if (trap) { + fault_data = 0; + page_fault = 1; + } + return 0; + } + M[cst + pg] = (c & cst_msk) | cst_dat; + } + + /* Get address of page */ + data = M[(pg << 9) + page]; +fprintf(stderr, "YMap %012llo\n\r", data); + + /* Decode map pointer */ + switch ((data >> 33) & 07) { + default: /* Invalid page */ + if (trap) { + fault_data = 0; + page_fault = 1; + } + return 0; + case 1: /* Direct page */ + /* Bit 4 = execute */ + /* Bit 3 = Write */ + /* Bit 2 = Read */ + acc_bits &= (data >> 18) & RMASK; + match = 1; + break; + + case 2: /* Shared page */ + acc_bits &= (data >> 18) & RMASK; + data = M[(data & RMASK) + spt]; + match = 1; + break; + + case 3: /* Indirect page */ + acc_bits &= (data >> 18) & RMASK; + index = (data >> 18) & PG_IDX; + data = M[(data & RMASK) + spt]; + if ((data >> 18) & PG_STG) { + if (trap) { + fault_data = 0; + page_fault = 1; + } + return 0; + } + data = M[(data & RMASK) + index]; + break; + + } + } while (!match); + + /* Now have final page */ + if ((data >> 18) & PG_STG) { + fault_data = 0; + page_fault = 1; + return 0; + } + pg = data & PG_PAG; + /* Check outside of memory */ + /* Update CST entry if needed */ + if (cst) { + uint64 c = M[cst + pg]; + if ((c & PG_AGE) == 0) { + if (trap) { + fault_data = 0; + page_fault = 1; + } + return 0; + } + if (acc_bits & PG_WRT) { + if (wr) + c |= 1; + acc_bits |= 1; + } else if (wr) { /* Trying to write and not writable */ + if (trap) { + fault_data = 0 /* Write fault */; + page_fault = 1; + } + return 0; + } + M[cst + pg] = (c & cst_msk) | cst_dat; + } else { + if (acc_bits & PG_WRT) + acc_bits |= 1; + } + /* Now construct a TBL entry */ +/* A = accessable */ +/* P = public */ +/* W = writable */ +/* S = user */ +/* C = cache */ + data = pg | RSIGN; + if (acc_bits & PG_PUB) + data |= 0200000; + if (acc_bits & PG_WRT) + data |= 0100000; + if (acc_bits & 1) + data |= 0040000; /* Set M bit (S) */ + if (acc_bits & PG_CAC) + data |= 0020000; + /* And save it */ + if (uf) + u_tlb[page] = data; + else + e_tlb[page] = data; + } else { + /* Map the page */ + if (uf | upmp) { + data = M[ub_ptr + (page >> 1)]; + u_tlb[page & 01776] = (uint32)(RMASK & (data >> 18)); + u_tlb[page | 1] = (uint32)(RMASK & data); + data = u_tlb[page]; + } else { + if (page & 0400) + data = M[eb_ptr + (page >> 1)]; + else + data = M[eb_ptr + (page >> 1) + 0600]; + e_tlb[page & 01776] = (uint32)(RMASK & (data >> 18)); + e_tlb[page | 1] = (uint32)(RMASK & data); + data = e_tlb[page]; + } + } +//fprintf(stderr, "Page %03o %06o %o\r\n", page, (data & RMASK), uf); + return (int)(data & RMASK); +} -#if KI /* - * Handle page lookup on KI10 + * Handle page lookup on KL10 * * addr is address to look up. * flag is set for pi cycle and user overide. @@ -1430,10 +2072,11 @@ sim_debug(DEBUG_DATAIO, &cpu_dev, "Rl=%06o Pl=%06o, Rh=%06o, Ph=%06o\n", Rl, Pl, * fetch is set for instruction fetches. */ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch) { - uint64 data; + int data; int base = 0; int page = (RMASK & addr) >> 9; int uf = (FLAGS & USER) != 0; + int pub = (FLAGS & PUBLIC) != 0; int upmp = 0; if (page_fault) @@ -1445,31 +2088,395 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch return 1; } - /* If fetching byte data, use write access */ - if (BYF5 && (IR & 06) == 6) - wr = 1; - + /* Handle address breaks */ + if (addr == brk_addr && uf == (brk_flags & 1) && (FLAGS & ADRFLT) == 0) { + if ((fetch && (brk_flags & 010) != 0) || + (!fetch && !wr && (brk_flags & 04) != 0) || + (wr && (brk_flags & 02) != 0)) { + fault_data = ((uint64)addr) | 023LL << 30 |((uf)?SMASK:0); + page_fault = 1; + return 0; + } + } + /* If this is modify instruction use write access */ wr |= modify; /* Figure out if this is a user space access */ + + /* AC = 1 use BYF5 */ + /* AC = 2 use ptr_flg */ + /* AC = 4 all general access */ + /* AC = 8 only in cur_context EA calculations */ if (flag) uf = 0; - else if (xct_flag != 0 && !cur_context && !uf) { - if (((xct_flag & 2) != 0 && wr != 0) || - ((xct_flag & 1) != 0 && (wr == 0 || modify))) { - uf = (FLAGS & USERIO) != 0; - } + else if (xct_flag != 0 && !uf && !fetch) { +fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); + if (((xct_flag & 8) != 0 && cur_context) || + ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || + ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || + ((xct_flag & 1) != 0 && !cur_context && BYF5 )) { + uf = (FLAGS & USERIO) != 0; + pub = (FLAGS & PRV_PUB) != 0; + } +fprintf(stderr, "%o %o\n\r", uf, pub); } - /* If user, check if small user enabled */ - if (uf) { - if (small_user && (page & 0340) != 0) { - fault_data = (((uint64)(page))<<18) | ((uint64)(uf) << 27) | 020LL; - page_fault = 1; + /* Handle KI paging odditiy */ + if (!uf && !t20_page && (page & 0740) == 0340) { + /* Pages 340-377 via UBT */ + page += 01000 - 0340; + upmp = 1; + } + + /* Map the page */ + if (uf || upmp) + data = u_tlb[page]; + else + data = e_tlb[page]; + + /* If not valid, go refill it */ + if (data == 0) { + data = load_tlb(uf, page, upmp, wr, 1); + if (data == 0 && page_fault) return 0; + } + *loc = ((data & 017777) << 9) + (addr & 0777); + + /* If PUBLIC and private page, make sure we are fetching a Portal */ + if ((data & RSIGN) && !flag && pub && ((data & 0200000) == 0) && + (!fetch || (M[*loc] & 00777740000000LL) != 0254040000000LL)) { + /* Handle public violation */ + fault_data = ((uint64)addr) | 021LL << 30 | BIT8 |((uf)?SMASK:0); +fprintf(stderr, "Public fault %012llo %06o\n\r", fault_data, FLAGS << 5); + page_fault = 1; + return 0; + } + + /* Check for access error */ + if ((data & RSIGN) == 0 || (wr & ((data & 0100000) == 0))) { +fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); + fault_data = BIT8 | (uint64)addr; + /* Remap the flag bits */ + if (uf) { /* U */ + fault_data |= SMASK; /* BIT0 */ + u_tlb[page] = 0; + } else { + e_tlb[page] = 0; } + if (data & 0400000LL) /* A */ + fault_data |= 00100000000000LL; /* BIT2 */ + if (data & 0200000LL) /* P */ + fault_data |= 00004000000000LL; /* BIT6 */ + if (data & 0100000LL) /* W */ + fault_data |= 00040000000000LL; /* BIT3 */ + if (data & 0040000LL) /* S */ + fault_data |= 00020000000000LL; /* BIT4 */ + if (wr) /* T */ + fault_data |= 00010000000000LL; /* BIT5 */ + if (data & 0020000LL) /* C */ + fault_data |= 00002000000000LL; /* BIT7 */ + page_fault = 1; + return 0; + } + + + /* If fetching from public page, set public flag */ + if (fetch && ((data & 0200000) != 0)) + FLAGS |= PUBLIC; + return 1; +} + +/* + * Register access on KL 10 + */ +uint64 get_reg(int reg) { + return FM[fm_sel|(reg & 017)]; +} + +void set_reg(int reg, uint64 value) { + FM[fm_sel|(reg & 017)] = value; +} + +/* + * Read a location directly from memory. + * + * Return of 0 if successful, 1 if there was an error. + */ +int Mem_read_nopage() { + if (AB < 020) { + MB = FM[fm_sel|AB]; } else { + sim_interval--; + if (AB >= (int)MEMSIZE) { + irq_flags |= 02000; + return 1; + } + MB = M[AB]; + } + return 0; +} + +/* + * Write a directly to a location in memory. + * + * Return of 0 if successful, 1 if there was an error. + */ +int Mem_write_nopage() { + + if (AB < 020) { + FM[fm_sel|AB] = MB; + } else { + sim_interval--; + if (AB >= (int)MEMSIZE) { + irq_flags |= 02000; + return 1; + } + M[AB] = MB; + } + return 0; +} + +int Mem_read(int flag, int cur_context, int fetch) { + int addr; + + if (AB < 020) { + if (xct_flag != 0 && !fetch && (FLAGS & USER) == 0) { +fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgr ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); + if (((xct_flag & 8) != 0 && cur_context) || + ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || + ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || + ((xct_flag & 1) != 0 && !cur_context && BYF5)) { + MB = FM[prev_ctx|AB]; +fprintf(stderr, "prev \n\r"); + return 0; + } +fprintf(stderr, "\n\r"); + } + MB = get_reg(AB); + } else { + sim_interval--; + if (!page_lookup(AB, flag, &addr, 0, cur_context, fetch)) + return 1; + if (addr >= (int)MEMSIZE) { + irq_flags |= 02000; + return 1; + } + if (sim_brk_summ && sim_brk_test(AB, SWMASK('R'))) + watch_stop = 1; + MB = M[addr]; + } + return 0; +} + +int Mem_write(int flag, int cur_context) { + int addr; + + if (AB < 020) { + if (xct_flag != 0 && (FLAGS & USER) == 0) { +fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgw ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); + if (((xct_flag & 8) != 0 && cur_context) || + ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || + ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || + ((xct_flag & 1) != 0 && !cur_context && BYF5)) { +fprintf(stderr, "prev \n\r"); + FM[prev_ctx|AB] = MB; + return 0; + } +fprintf(stderr, "\n\r"); + } + set_reg(AB, MB); + } else { + sim_interval--; + if (!page_lookup(AB, flag, &addr, 1, cur_context, 0)) + return 1; + if (addr >= (int)MEMSIZE) { + irq_flags |= 02000; + return 1; + } + if (sim_brk_summ && sim_brk_test(AB, SWMASK('W'))) + watch_stop = 1; + M[addr] = MB; + } + return 0; +} + +/* executive page table lookup */ +int exec_page_lookup(int addr, int wr, int *loc) +{ + int data; + int page = (RMASK & addr) >> 9; + int upmp = 0; + + /* If paging is not enabled, address is direct */ + if (!page_enable) { + *loc = addr; + return 0; + } + + /* Handle KI paging odditiy */ + if (!t20_page && (page & 0740) == 0340) { + /* Pages 340-377 via UBT */ + page += 01000 - 0340; + upmp = 1; + } + + /* Map the page */ + if (upmp) + data = u_tlb[page]; + else + data = e_tlb[page]; + + /* If not valid, go refill it */ + if (data == 0) { + data = load_tlb(0, page, upmp, wr, 0); + if (data == 0) + return 1; + } + *loc = ((data & 017777) << 9) + (addr & 0777); + return 0; +} + +int Mem_examine_word(int n, int wrd, uint64 *data) { + int addr = 0144 + (8 * n) + eb_ptr; + int base = 0; + + if (addr >= MEMSIZE) + return 1; + if (M[addr] == 0 || wrd > M[addr]) + return 1; + addr = (M[addr+1] + wrd) & RMASK; + if (exec_page_lookup(addr, 0, &addr)) + return 1; +//fprintf(stderr, "Examine: %06o %012llo\n\r", addr, M[addr]); + *data = M[addr]; + return 0; +} + +int Mem_deposit_word(int n, int wrd, uint64 *data) { + int addr = 0146 + (8 * n) + eb_ptr; + int base = 0; + + if (addr >= MEMSIZE) + return 1; + if (M[addr] == 0 || wrd > M[addr]) + return 1; + addr = (M[addr+1] + wrd) & RMASK; + if (exec_page_lookup(addr, 1, &addr)) + return 1; +//fprintf(stderr, "Deposit: %06o %012llo -> %012llo\n\r", addr, M[addr], *data); + M[addr] = *data; + return 0; +} + +/* + * Read in 16 bits of data from a byte pointer. + */ +int Mem_read_byte(int n, uint16 *data) { + int addr; + uint64 val; + uint64 msk; + int p, s, np; + int need = 16; + + *data = 0; + while (need > 0) { + addr = 0140 + (8 * n) + eb_ptr; + if (addr >= MEMSIZE) + return 0; + val = M[addr]; +// fprintf(stderr, "Read: %06o %012llo -> ", addr, val); + s = (val >> 24) & 077; + p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; + if (p & 0400) { + p = np = (36 + (0777 ^ s) + 1) & 0777; + val = (val & LMASK) | ((val + 1) & RMASK); + } else + np = p; + np &= 077; + val &= PMASK; + val |= (uint64)(np) << 30; +// fprintf(stderr, " %012llo %d %d %d\n\r", val, s, p, np); + M[addr] = val; + addr = val & RMASK; + if (exec_page_lookup((int)(val & RMASK), 0, &addr)) + return 0; + /* Generate mask for given size */ + msk = (uint64)(1) << s; + msk--; + val = M[addr]; +// fprintf(stderr, "Byte: %06o %012llo %012llo %012llo %d %d %d -> ", addr, val, msk, val >> p, s, p, need); + val = (val >> p) & msk; + if (s > 8) + need -= 16; + else + need -= 8; + *data |= val << need; +// fprintf(stderr, " %012llo %06o \n\r", val, *data); + } + return 1; +} + +int Mem_write_byte(int n, uint16 *data) { + int addr; + uint64 val; + uint64 msk; + int p, s, np; + int need = 16; + uint16 dat = *data; + + dat = ((dat >> 8) & 0377) | ((dat & 0377) << 8); + while (need > 0) { + addr = 0141 + (8 * n) + eb_ptr; + if (addr >= MEMSIZE) + return 0; + val = M[addr]; +// fprintf(stderr, "Write: %06o %012llo -> ", addr, val); + s = (val >> 24) & 077; + p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; + if (p & 0400) { + p = np = (36 + (0777 ^ s) + 1) & 0777; + val = (val & LMASK) | ((val + 1) & RMASK); + } else + np = p; + np &= 077; + val &= PMASK; + val |= (uint64)(np) << 30; +// fprintf(stderr, "%06o %012llo %d %d %d\n\r", addr, val, s, p, np); + M[addr] = val; + addr = val & RMASK; + if (exec_page_lookup((int)(val & RMASK), 1, &addr)) + return 0; + /* Generate mask for given size */ + msk = (uint64)(1) << s; + msk--; + msk <<= p; + val = M[addr]; +// fprintf(stderr, "Byte: %06o %012llo %012llo %o %o %o -> ", addr, val, msk, s, p, need); + val &= CM(msk); + val |= msk & (((uint64)(dat >> (need - s))) << p); + M[addr] = val; +// fprintf(stderr, " %012llo %06o \n\r", val, dat); + need -= s; + } + return 1; +} + +#endif + +#if KI +/* + * Load the TLB entry, used for both page_lookup and MAP. + * Do not call this for direct map executive pages. + */ +int +load_tlb(int uf, int page) +{ + uint64 data; + int base = 0; + int upmp = 0; + + if (!uf) { /* Handle system mapping */ /* Pages 340-377 via UBR */ if ((page & 0740) == 0340) { @@ -1480,18 +2487,8 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch base = 1; /* Pages 000-037 direct map */ } else { - /* Check if supervisory mode */ - *loc = addr; - /* If PUBLIC and private page, make sure we are fetching a Portal */ - if (!flag && ((FLAGS & PUBLIC) != 0) && - (!fetch || (M[addr] & 00777040000000LL) != 0254040000000LL)) { - /* Handle public violation */ - fault_data = (((uint64)(page))<<18) | ((uint64)(uf) << 27) - | 021LL; - page_fault = 1; - return !wr; - } - return 1; + /* Return what MAP wants to see */ + return (RSIGN | 020000 | page); } } /* Map the page */ @@ -1519,6 +2516,78 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch else last_page = ((page ^ 0777) << 1); } + return (int)(data & RMASK); +} + +/* + * Handle page lookup on KI10 + * + * addr is address to look up. + * flag is set for pi cycle and user overide. + * loc is final address. + * wr indicates whether cycle is read or write. + * cur_context is set when access should ignore xct_flag + * fetch is set for instruction fetches. + */ +int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch) { + int data; + int base = 0; + int page = (RMASK & addr) >> 9; + int uf = (FLAGS & USER) != 0; + int pub = (FLAGS & PUBLIC) != 0; + + if (page_fault) + return 0; + + /* If paging is not enabled, address is direct */ + if (!page_enable) { + *loc = addr; + return 1; + } + + /* If fetching byte data, use write access */ + if (BYF5 && (IR & 06) == 6) + wr = 1; + + /* If this is modify instruction use write access */ + wr |= modify; + + /* Figure out if this is a user space access */ + if (flag) + uf = 0; + else if (xct_flag != 0 && !cur_context && !uf) { + if (((xct_flag & 2) != 0 && wr != 0) || + ((xct_flag & 1) != 0 && (wr == 0 || modify))) { + uf = (FLAGS & USERIO) != 0; + pub = (FLAGS & PRV_PUB) != 0; + } + } + + /* If user, check if small user enabled */ + if (uf) { + if (small_user && (page & 0340) != 0) { + fault_data = (((uint64)(page))<<18) | ((uint64)(uf) << 27) | 020LL; + page_fault = 1; + return 0; + } + } + + /* Handle direct pages */ + if (!uf && page < 0340) { + /* Check if supervisory mode */ + *loc = addr; + /* If PUBLIC and private page, make sure we are fetching a Portal */ + if (!flag && pub && + (!fetch || (M[addr] & 00777040000000LL) != 0254040000000LL)) { + /* Handle public violation */ + fault_data = (((uint64)(page))<<18) | ((uint64)(uf) << 27) + | 021LL; + page_fault = 1; + return !wr; + } + return 1; + } + data = load_tlb(uf, page); *loc = ((data & 017777) << 9) + (addr & 0777); /* Check for access error */ @@ -1533,8 +2602,9 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch return 0; } +pub: /* If PUBLIC and private page, make sure we are fetching a Portal */ - if (!flag && ((FLAGS & PUBLIC) != 0) && ((data & 0200000) == 0) && + if (!flag && pub && ((data & 0200000) == 0) && (!fetch || (M[*loc] & 00777040000000LL) != 0254040000000LL)) { /* Handle public violation */ fault_data = (((uint64)(page))<<18) | ((uint64)(uf) << 27) | 021LL; @@ -2614,9 +3684,12 @@ int flag1; int flag3; int instr_count = 0; /* Number of instructions to execute */ uint32 IA; -#if ITS +#if ITS | KL_ITS char one_p_arm = 0; /* One proceed arm */ #endif +#if KL +int extend = 0; /* Process extended instruction */ +#endif if (sim_step != 0) { instr_count = sim_step; @@ -2639,18 +3712,22 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ BYF5 = 0; #if KI | KL page_fault = 0; +#if KL + ptr_flg = 0; #endif -#if ITS +#endif +#if ITS | KL_ITS if (QITS) { one_p_arm = 0; +#if !KL_ITS set_quantum(); +#endif } #endif watch_stop = 0; while ( reason == 0) { /* loop until ABORT */ - AIO_CHECK_EVENT; /* queue async events */ - if (sim_interval <= 0) { /* check clock queue */ + if (sim_interval <= 0) { /* check clock queue */ if ((reason = sim_process_event()) != SCPE_OK) {/* error? stop sim */ #if ITS if (QITS) @@ -2677,6 +3754,10 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ xct_flag = 0; #if KI | KL trap_flag = 0; +#if KL + extend = 0; + ptr_flg = 0; +#endif #endif AB = PC; uuo_cycle = 0; @@ -2701,6 +3782,10 @@ fetch: pi_rq = check_irq_level(); if (pi_rq) goto st_pi; +#if KL + if ((FLAGS & (TRP1|TRP2)) == 0) + PC = (PC + 1) & RMASK; +#endif goto last; } @@ -2740,7 +3825,15 @@ no_fetch: AR = MB; AB = MB & RMASK; if (MB & 017000000) { +#if 0 + if (xct_flag != 0 && (FLAGS & USER) == 0 && (xct_flag & 8) != 0) + AR = FM[prev_ctx|((MB >> 18) & 017)]; + else + AR = get_reg((MB >> 18) & 017); + AR = MB = (AR + AB) & FMASK; +#else AR = MB = (AB + get_reg((MB >> 18) & 017)) & FMASK; +#endif AB = MB & RMASK; } if (IR != 0254) @@ -2749,7 +3842,6 @@ no_fetch: if (Mem_read(pi_cycle | uuo_cycle, 1, 0)) goto last; /* Handle events during a indirect loop */ - AIO_CHECK_EVENT; /* queue async events */ if (sim_interval-- <= 0) { if ((reason = sim_process_event()) != SCPE_OK) { return reason; @@ -2770,11 +3862,17 @@ st_pi: AB = 040 | (pi_enc << 1) | maoff; #if KI | KL xct_flag = 0; +#if KL + extend = 0; +#endif /* * Scan through the devices and allow KI devices to have first * hit at a given level. */ for (f = 0; f < 128; f++) { + if (dev_irqv[f] != 0) + sim_debug(DEBUG_IRQ, &cpu_dev, "vect irq %o %03o \n", + pi_enc, dev_irq[f]); if (dev_irqv[f] != 0 && dev_irq[f] & (0200 >> pi_enc)) { AB = dev_irqv[f](f << 2, AB); break; @@ -2798,28 +3896,39 @@ st_pi: #endif /* Check if possible idle loop */ - if (sim_idle_enab && + if (sim_idle_enab && (((FLAGS & USER) != 0 && PC < 020 && AB < 020 && (IR & 0760) == 0340) || (uuo_cycle && (IR & 0740) == 0 && IA == 041))) { sim_idle (TMR_RTC, FALSE); } /* Update history */ - if (hst_lnt) { + if (hst_lnt && PC >= 020) { hst_p = hst_p + 1; if (hst_p >= hst_lnt) { hst_p = 0; } hst[hst_p].pc = HIST_PC | ((BYF5)? (HIST_PC2|PC) : IA); +#if KL + if (extend) + hst[hst_p].pc |= HIST_PCE; +#endif hst[hst_p].ea = AB; hst[hst_p].ir = AD; - hst[hst_p].flags = (FLAGS << 5) |(clk_flg << 2) | (nxm_flag << 1) + hst[hst_p].flags = (FLAGS << 5) +#if KA | KI | PDP6 + |(clk_flg << 2) | (nxm_flag << 1) #if KA | PDP6 | (mem_prot << 4) | (push_ovf << 3) #endif #if PDP6 | ill_op #endif +#endif +#if KL + | (fm_sel >> 4) +#endif + ; hst[hst_p].ac = get_reg(AC); } @@ -2833,7 +3942,16 @@ st_pi: sac_inh = 0; modify = 0; f_pc_inh = 0; - +#if KL + if (extend) { + extend = 0; + if (IR == 0 || IR > 031 || AC != 0) + goto muuo; + if (do_extend(IA)) + goto muuo; + goto last; + } +#endif /* Load pseudo registers based on flags */ if (i_flags & (FCEPSE|FCE)) { if (i_flags & FCEPSE) @@ -2852,7 +3970,7 @@ st_pi: BR = get_reg(AC); } - if (hst_lnt) { + if (hst_lnt && PC >= 020) { hst[hst_p].mb = AR; } @@ -2877,26 +3995,43 @@ muuo: case 0060: case 0061: case 0062: case 0063: case 0064: case 0065: case 0066: case 0067: case 0070: case 0071: case 0072: case 0073: +#if !KL_ITS case 0074: case 0075: case 0076: case 0077: +#endif /* MUUO */ #if KI | KL - case 0100: case 0101: case 0102: case 0103: - case 0104: case 0105: case 0106: case 0107: - case 0123: + case 0100: /* UJEN */ + case 0101: case 0102: case 0103: + case 0104: /* JSYS */ + case 0106: + case 0107: +#if !KL_ITS case 0247: /* UUO */ +#endif unasign: + /* Save Opcode */ MB = ((uint64)(IR) << 27) | ((uint64)(AC) << 23) | (uint64)(AB); AB = ub_ptr | 0424; Mem_write_nopage(); - AB |= 1; + /* Save flags */ + AB++; MB = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + (trap_flag == 0)) & RMASK); if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; } Mem_write_nopage(); +#if KL + /* Save context */ + AB ++; + MB = (ub_ptr >> 9) | ((uint64)(prev_ctx & 0160)) << 20 | + ((uint64)(fm_sel & 0160)) << 23 | SMASK|BIT1|BIT2; + Mem_write_nopage(); + prev_ctx = fm_sel; +#endif + /* Read in new PC and flags */ FLAGS &= ~ (PRV_PUB|BYTI|ADRFLT|TRP1|TRP2); AB = ub_ptr | 0430; if (trap_flag != 0) @@ -2906,6 +4041,7 @@ unasign: if (FLAGS & USER) AB |= 4; Mem_read_nopage(); + FLAGS = (MB >> 23) & 017777; /* If transistioning from user to executive adjust flags */ if ((FLAGS & USER) != 0 && (AB & 4) != 0) @@ -2933,7 +4069,7 @@ unasign: ex_uuo_sync = 1; #endif MB = ((uint64)(IR) << 27) | ((uint64)(AC) << 23) | (uint64)(AB); -#if KI | KL +#if KI if ((FLAGS & USER) == 0) { AB = eb_ptr + 040; Mem_write_nopage(); @@ -2949,7 +4085,7 @@ unasign: Mem_write(uuo_cycle, 1); AB += 1; f_load_pc = 0; -#if ITS +#if ITS | KL_ITS if (QITS && one_p_arm) { FLAGS |= ONEP; one_p_arm = 0; @@ -2957,8 +4093,96 @@ unasign: #endif f_pc_inh = 1; break; +#if KL_ITS + case 0074: /* XCTR */ + case 0075: /* XCTRI */ + if (QITS && (FLAGS & USER) == 0) { + f_load_pc = 0; + f_pc_inh = 1; + xct_flag = AC | ((IR & 1) << 4); + break; + } + goto unasign; + + case 0076: + if (QITS && (FLAGS & USER) == 0) { + /* Load store ITS pager info */ + if ((AB + 8) > MEMSIZE) { + break; + } + MB = M[AB]; /* WD 0 */ + jpc = (MB & RMASK); + AB = (AB + 1) & RMASK; + MB = M[AB]; + opc = MB; + AB = (AB + 1) & RMASK; + MB = M[AB]; /* WD 2 */ + brk_addr = /*03777777 &*/ MB; + AB = (AB + 1) & RMASK; + MB = M[AB]; /* WD 3 */ + fault_data = (MB >> 18) & RMASK; + AB = (AB + 1) & RMASK; + MB = M[AB]; /* WD 4 */ + FM[(06<<4)|1] = ((0377 << 18) | RMASK) & MB; + AB = (AB + 1) & RMASK; + MB = M[AB]; /* WD 5 */ + FM[(06<<4)|2] = ((0377 << 18) | RMASK) & MB; + AB = (AB + 1) & RMASK; + MB = M[AB]; /* WD 6 */ + FM[(06<<4)|3] = ((0377 << 18) | RMASK) & MB; + AB = (AB + 1) & RMASK; + MB = M[AB]; /* WD 7 */ + page_enable = 1; + for (f = 0; f < 512; f++) + e_tlb[f] = u_tlb[f] = 0; + break; + } + goto unasign; + case 0077: + if (QITS && (FLAGS & USER) == 0) { + if ((AB + 8) > MEMSIZE) { + break; + } + MB = ((uint64)fault_data) << 18 | + (uint64)jpc; + M[AB] = MB; + AB = (AB + 1) & RMASK; + MB = opc; + M[AB] = MB; + AB = (AB + 1) & RMASK; + MB = (brk_addr); + M[AB] = MB; + AB = (AB + 1) & RMASK; + MB = ((uint64)fault_data) << 18; + M[AB] = MB; + AB = (AB + 1) & RMASK; + MB = (uint64)FM[(06<<4)|1]; + M[AB] = MB; + AB = (AB + 1) & RMASK; + MB = (uint64)FM[(06<<4)|2]; + M[AB] = MB; + AB = (AB + 1) & RMASK; + MB = (uint64)FM[(06<<4)|3]; + M[AB] = MB; + AB = (AB + 1) & RMASK; + M[AB] = MB; + } + goto unasign; +#endif + #if KI | KL +#if KL + case 0105: /* ADJSP */ + BR = get_reg(AC); + AD = (BR + AR) & RMASK; + AD |= (BR & LMASK) + ((AR << 18) & LMASK); + if (((BR ^ AD) & SMASK) != 0) + FLAGS |= TRP2; + set_reg(AC, AD & FMASK); + break; +#endif + case 0110: /* DFAD */ case 0111: /* DFSB */ /* On Load AR,MQ has memory operand */ @@ -3155,8 +4379,13 @@ dpnorm: if ((AR & 0777) == 0777) AR &= (FPFMASK << 8); } +#if KL + while (((AR & (FPSBIT|FPNBIT)) == (FPSBIT|FPNBIT)) || + ((AR & (FPSBIT|FPNBIT)) == 0)) { +#else if (((AR & (FPSBIT|FPNBIT)) == (FPSBIT|FPNBIT)) || ((AR & (FPSBIT|FPNBIT)) == 0)) { +#endif SC --; AR <<= 1; if (MQ & BIT1) @@ -3165,6 +4394,16 @@ dpnorm: MQ &= FMASK; nrf = 1; } +#if KL + /* Handle special minus case */ + if (AR == (FPHBIT|FPSBIT)) { + SC += 1; + if (AR & 1) + MQ |= SMASK; + MQ >>= 1; + AR = (AR & FPHBIT) | (AR >> 1); + } +#endif } else { AR = MQ = 0; SC = 0; @@ -3216,13 +4455,18 @@ dpnorm: SMEAR_SIGN(BR); BR <<= 35; BR |= MB & CMASK; +#if KL + /* One extra bit for KL */ + AR <<= 1; + BR <<= 1; +#endif /* Make both positive */ flag1 = 0; - if (AR & FPSBIT) { + if (AR & FPHBIT) { AR = (FPFMASK ^ AR) + 1; flag1 = 1; } - if (BR & FPSBIT) { + if (BR & FPHBIT) { BR = (FPFMASK ^ BR) + 1; flag1 = !flag1; } @@ -3250,7 +4494,7 @@ dpnorm: FLAGS |= FLTUND|OVR|FLTOVR|TRP1; /* Do divide */ AD = 0; - for (FE = 0; FE < 62; FE++) { + for (FE = 0; FE < (62 + KL); FE++) { AD <<= 1; if (AR >= BR) { AR = AR - BR; @@ -3259,15 +4503,24 @@ dpnorm: AR <<= 1; } AR = AD; + /* Fix sign of result */ if (flag1) { AR = (AR ^ FPFMASK) + 1; - } + } +#if KL + else + AR++; /* Round on KL */ + AR = (AR & FPHBIT) | (AR >> 1); /* Remove extra bit */ +#endif + /* Check potential overflow */ if (((SC & 0400) != 0) ^ ((SC & 0200) != 0) || SC == 0600) fxu_hold_set = 1; + /* Normalize */ while (((AR & FPHBIT) != 0) != ((AR & FPSBIT) != 0)) { SC += 1; AR = (AR & FPHBIT) | (AR >> 1); } + /* Extract halfs from 64bit word */ MQ = (AR & CMASK); AR >>= 35; AR &= MMASK; @@ -3279,6 +4532,7 @@ dpnorm: FLAGS |= FLTUND; } } + /* Add in exponent */ SCAD = SC ^ ((AR & SMASK) ? 0377 : 0); AR &= SMASK|MMASK; if (AR != 0 || MQ != 0) @@ -3288,11 +4542,275 @@ dpnorm: set_reg(AC+1, MQ); break; +#if KL + case 0114: /* DADD */ + flag1 = flag3 = 0; + /* AR,ARX = AC BR,BX = mem */ + /* AR High */ + if (Mem_read(0, 0, 0)) + goto last; + BR = MB; + AB = (AB + 1) & RMASK; + if (Mem_read(0, 0, 0)) + goto last; + BRX = MB; + AR = get_reg(AC); + ARX = get_reg(AC + 1); + /* Add numbers */ + ARX = (ARX & CMASK) + (BRX & CMASK); + f = (ARX & SMASK) != 0; + if (((AR & CMASK) + (BR & CMASK) + f) & SMASK) { + FLAGS |= CRY1; + flag1 = 1; + } + AR = AR + BR + f; + if (AR & C1) { + if (!pi_cycle) + FLAGS |= CRY0; + flag3 = 1; + } + AR &= FMASK; + if (flag1 != flag3) { + if (!pi_cycle) + FLAGS |= OVR|TRP1; + check_apr_irq(); + } + ARX &= CMASK; + ARX |= AR & SMASK; + set_reg(AC, AR); + set_reg(AC+1, ARX); + break; + + case 0115: /* DSUB */ + flag1 = flag3 = 0; + /* AR,AX = AC BR,BX = mem */ + /* AR High */ + if (Mem_read(0, 0, 0)) + goto last; + BR = MB; + AB = (AB + 1) & RMASK; + if (Mem_read(0, 0, 0)) + goto last; + BRX = MB; + AR = get_reg(AC); + ARX = get_reg(AC + 1); + /* Add numbers */ + ARX = (ARX & CMASK) + CCM(BRX) + 1; + f = (ARX & SMASK) != 0; + if (((AR & CMASK) + CCM(BR) + f) & SMASK) { + FLAGS |= CRY1; + flag1 = 1; + } + AR = AR + CM(BR) + f; + if (AR & C1) { + if (!pi_cycle) + FLAGS |= CRY0; + flag3 = 1; + } + AR &= FMASK; + if (flag1 != flag3) { + if (!pi_cycle) + FLAGS |= OVR|TRP1; + check_apr_irq(); + } + ARX &= CMASK; + ARX |= AR & SMASK; + set_reg(AC, AR); + set_reg(AC+1, ARX); + break; + + case 0116: /* DMUL */ + flag1 = flag3 = 0; + /* AR,ARX = AC BR,BRX = mem */ + /* AR High */ + if (Mem_read(0, 0, 0)) + goto last; + BR = MB; + AB = (AB + 1) & RMASK; + if (Mem_read(0, 0, 0)) + goto last; + BRX = MB; + AR = get_reg(AC); + ARX = get_reg(AC + 1); + /* Make BR,BRX positive */ + if (BR & SMASK) { + /* Low */ + BRX = CCM(BRX) + 1; /* Low */ + /* High */ + BR = (CM(BR) + ((BRX & SMASK) != 0)) & FMASK; + flag1 = 1; + /* Can only occur if 2**-70 */ + if (BR & SMASK) + FLAGS |= OVR|TRP1; + } + /* Make AR,ARX positive */ + if (AR & SMASK) { + /* Low */ + ARX = CCM(ARX) + 1; /* Low */ + /* High */ + AR = (CM(AR) + ((ARX & SMASK) != 0)) & FMASK; + flag1 ^= 1; + /* Can only occur if 2**-70 */ + if (AR & SMASK) + FLAGS |= OVR|TRP1; + } + /* Form product in AD,ADX,BR,BX */ + AD = ADX = 0; + BRX &= CMASK; /* Clear sign of BX */ + ARX &= CMASK; + /* Compute product */ + for (SC = 70; SC >= 0; SC--) { + /* Shift MQ,MB,BR,BX right one */ + f = (BRX & 1); + if (BR & 1) + BRX |= SMASK; + if (ADX & 1) + BR |= SMASK; + if (AD & 1) + ADX |= SMASK; + BRX >>= 1; + BR >>= 1; + ADX >>= 1; + AD >>= 1; + if (f) { /* Add AR,ARX to AD,ADX */ + ADX = ADX + ARX; + AD = AD + AR + ((ADX & SMASK) != 0); + ADX &= CMASK; + } + } + /* If minus, negate whole thing */ + if (flag1) { + BRX = CCM(BRX) + 1; /* Low */ + BR = CCM(BR) + ((BRX & SMASK) != 0); + ADX = CCM(ADX) + ((BR & SMASK) != 0); + AD = CM(AD) + ((ADX & SMASK) != 0); + } + /* Copy signs */ + BRX &= CMASK; + BR &= CMASK; + ADX &= CMASK; + AD &= FMASK; + BRX |= AD & SMASK; + BR |= AD & SMASK; + ADX |= AD & SMASK; + /* Save results */ + set_reg(AC, AD); + set_reg(AC+1, ADX); + set_reg(AC+2, BR); + set_reg(AC+3, BRX); + break; + + case 0117: /* DDIV */ + flag1 = flag3 = 0; + /* AR,ARX = AC BR,BRX = mem */ + /* AR High */ + if (Mem_read(0, 0, 0)) + goto last; + BR = MB; + AB = (AB + 1) & RMASK; + if (Mem_read(0, 0, 0)) + goto last; + BRX = MB; + /* Make BR,BX positive */ + if (BR & SMASK) { + /* Low */ + BRX = CCM(BRX) + 1; /* Low */ + /* High */ + BR = (CM(BR) + ((BRX & SMASK) != 0)) & FMASK; + flag1 = 1; + /* Can only occur if 2**-70 */ + if (BR & SMASK) { + FLAGS |= OVR|TRP1; + } + } + if ((BR | BRX) == 0) { + FLAGS |= NODIV; + break; + } + /* Get dividend */ + AR = get_reg(AC); + ARX = get_reg(AC + 1); + MB = get_reg(AC + 2); + MQ = get_reg(AC + 3); + + /* Make MQ,MB,AR,ARX positive */ + if (AR & SMASK) { + /* Low */ + MQ = CCM(MQ) + 1; + MB = CCM(MB) + ((MQ & SMASK) != 0); + ARX = CCM(ARX) + ((MB & SMASK) != 0); + AR = (CM(AR) + ((ARX & SMASK) != 0)) & FMASK; + flag1 ^= 1; + flag3 = 1; + if (AR & SMASK) { + FLAGS |= OVR|TRP1; + } + } + MQ &= CMASK; + MB &= CMASK; + ARX &= CMASK; + /* Precheck divide ok */ + ADX = ARX + CCM(BRX) + 1; + AD = AR + CM(BR) + ((ADX & SMASK) != 0); + if ((AD & C1) != 0) { + FLAGS |= OVR|TRP1|NODIV; + break; + } + /* Do divide */ + for (SC = 70; SC > 0; SC--) { + AR <<= 1; + ARX <<= 1; + MB <<= 1; + MQ <<= 1; + if (ARX & SMASK) + AR |= 1; + if (MB & SMASK) + ARX |= 1; + if (MQ & SMASK) + MB |= 1; + ARX &= CMASK; + MB &= CMASK; + MQ &= CMASK; + ADX = ARX + CCM(BRX) + 1; + AD = AR + CM(BR) + ((ADX & SMASK) != 0); + if ((AD & SMASK) == 0) { + ARX = ADX; + AR = AD & CMASK; + MQ |= 1; + } + } + BRX &= CMASK; /* Clear sign of BX */ + ARX &= CMASK; + /* Set sign of quotent */ + if (flag1) { + MQ = CCM(MQ) + 1; + MB = CM(MB) + ((MQ & SMASK) != 0); + MQ &= CMASK; + MB &= FMASK; + } + /* Set sign or remainder */ + if (flag3) { + ARX = CCM(ARX) + 1; /* Low */ + AR = CM(AR) + ((ARX & SMASK) != 0); + ARX &= CMASK; + AR &= FMASK; + } + MQ |= MB & SMASK; + ARX |= AR & SMASK; + /* Save results */ + set_reg(AC, MB); + set_reg(AC+1, MQ); + set_reg(AC+2, AR); + set_reg(AC+3, ARX); + break; + +#else case 0114: /* DADD */ case 0115: /* DSUB */ case 0116: /* DMUL */ case 0117: /* DDIV */ goto unasign; +#endif case 0120: /* DMOVE */ if (Mem_read(0, 0, 0)) @@ -3313,16 +4831,53 @@ dpnorm: AB = (AB + 1) & RMASK; if (Mem_read(0, 0, 0)) goto last; - MQ = ((MB & CMASK) ^ CMASK) + 1; /* Low */ + MQ = CCM(MB) + 1; /* Low */ /* High */ - AR = (CM(AR) + ((MQ & SMASK) != 0)) & FMASK; +#if KL + if ((CCM(AR) + ((MQ & SMASK) != 0)) & SMASK) { + FLAGS |= CRY1; + flag1 = 1; + } +#endif + AR = (CM(AR) + ((MQ & SMASK) != 0)); MQ &= CMASK; +#if KL + if (AR & C1) { + FLAGS |= CRY0; + flag3 = 1; + } + if (flag1 != flag3 && !pi_cycle) { + FLAGS |= OVR|TRP1; + check_apr_irq(); + } + if ((AR == SMASK && MQ == 0) && !pi_cycle) + FLAGS |= TRP1; +#endif + AR &= FMASK; set_reg(AC, AR); set_reg(AC+1, MQ); break; + case 0123: /* Extend */ +#if KL + /* Handle like xct */ + f_load_pc = 0; + f_pc_inh = 1; + extend = 1; + ext_ac = AC; + BR = AB; /* Save address of instruction */ + if (Mem_read(0, 1, 0)) + goto last; + goto no_fetch; +#else + goto unasign; +#endif + case 0124: /* DMOVEM */ AR = get_reg(AC); +#if KL + MQ = get_reg(AC + 1); +#endif /* Handle each half as seperate instruction */ if ((FLAGS & BYTI) == 0) { MB = AR; @@ -3330,13 +4885,15 @@ dpnorm: goto last; FLAGS |= BYTI; } +#if !KL MQ = get_reg(AC + 1); +#endif if ((FLAGS & BYTI)) { AB = (AB + 1) & RMASK; MB = MQ; + FLAGS &= ~BYTI; if (Mem_write(0, 0)) goto last; - FLAGS &= ~BYTI; } break; @@ -3346,15 +4903,42 @@ dpnorm: /* Handle each half as seperate instruction */ if ((FLAGS & BYTI) == 0) { BR = AR = CM(AR); - BR = (BR + 1); - MQ = (((MQ & CMASK) ^ CMASK) + 1); - if (MQ & SMASK) + BR = BR + 1; + MQ = CCM(MQ) + 1; + if (MQ & SMASK) { +#if KL + if ((CCM(get_reg(AC)) + 1) & SMASK) { + FLAGS |= CRY1; + flag1 = 1; + } +#endif AR = BR; +#if KL + if (AR & C1) { + FLAGS |= CRY0; + flag3 = 1; + } + if (flag1 != flag3 && !pi_cycle) { + FLAGS |= OVR|TRP1; + check_apr_irq(); + } + if ((AR == SMASK && MQ == 0) && !pi_cycle) + FLAGS |= TRP1; +#endif + } AR &= FMASK; MB = AR; if (Mem_write(0, 0)) goto last; FLAGS |= BYTI; +#if KL + AB = (AB + 1) & RMASK; + MB = MQ & CMASK; + if (Mem_write(0, 0)) + goto last; + FLAGS &= ~BYTI; + break; +#endif } if ((FLAGS & BYTI)) { MQ = get_reg(AC + 1); @@ -3498,10 +5082,9 @@ dpnorm: AB = (AB + 1) & RMASK; MB = M[AB]; /* WD 3 */ /* Store Quantum */ - qua_time = MB & (RMASK|BIT17); + qua_time = MB & RMASK; set_quantum(); fault_data = (MB >> 18) & RMASK; - fault_data &= ~1; /* Clear high quantum bit */ mem_prot = 0; if ((fault_data & 0777772) != 0) mem_prot = 1; @@ -3611,7 +5194,7 @@ dpnorm: goto unasign; case 0247: /* UUO or ITS CIRC instruction */ -#if ITS +#if ITS | KL_ITS if (QITS) { BR = AR; AR = get_reg(AC); @@ -3669,7 +5252,7 @@ unasign: uuo_cycle = 1; Mem_write(uuo_cycle, 0); AB += 1; -#if ITS +#if ITS | KL_ITS if (QITS && one_p_arm) { FLAGS |= ONEP; one_p_arm = 0; @@ -3681,10 +5264,54 @@ unasign: #endif case 0133: /* IBP/ADJBP */ +#if KL + if (AC != 0) { /* ADJBP */ + modify = 1; + if (Mem_read(0, !QITS, 0)) { + goto last; + } + AR = MB; + SC = (AR >> 24) & 077; /* S */ + if (SC) { + int bpw, left, newb, adjw, adjb, c; + + FE = (AR >> 30) & 077; /* P */ + AB = AR & RMASK; /* Address */ + left = (36 - FE) / SC; /* Number bytes left (36 - P)/S */ + bpw = left + (FE / SC); /* Bytes per word */ + if (bpw == 0) { + FLAGS |= OVR|NODIV|TRP1; + break; + } + BR = get_reg(AC); /* Grab amount to move */ + /* Make BR into native integer */ + if (BR & RSIGN) + adjw = -((int)(CM(BR) + 1) & RMASK); + else + adjw = (int)(BR & RMASK); + newb = adjw + left; /* Adjust to word boundry */ + adjw = newb / bpw; /* Number of words to move */ + adjb = (newb >= 0)? newb % bpw: -((-newb) % bpw); + if (adjb <= 0) { + adjb += bpw; /* Move forward */ + adjw--; + } + FE = 36 - (adjb * SC) - ((36 - FE) % SC); /* New P */ + AR = (((uint64)(FE & 077)) << 30) | /* Make new BP */ + (AR & 00777777000000LL) | /* S,IX,I */ + ((AR + adjw) & RMASK); + } + set_reg(AC, AR); + break; + } +#endif case 0134: /* ILDB */ case 0136: /* IDPB */ if ((FLAGS & BYTI) == 0) { /* BYF6 */ modify = 1; +#if KL + ptr_flg = 1; +#endif if (Mem_read(0, !QITS, 0)) { #if PDP6 FLAGS |= BYTI; @@ -3717,6 +5344,9 @@ unasign: case 0135:/* LDB */ case 0137:/* DPB */ if ((FLAGS & BYTI) == 0 || !BYF5) { +#if KL + ptr_flg = 1; +#endif if (Mem_read(0, !QITS, 0)) goto last; AR = MB; @@ -3735,6 +5365,9 @@ ldb_ptr: } #endif } else { +#if KL + ptr_flg = 0; +#endif AB = AR & RMASK; if ((IR & 06) == 6) modify = 1; @@ -3780,16 +5413,18 @@ ldb_ptr: case 0132:/* FSC */ SC = ((AB & RSIGN) ? 0400 : 0) | (AB & 0377); SCAD = GET_EXPO(AR); +#if KL + SC |= (SC & 0400) ? 0777000 : 0; + SCAD |= (SC & 0400) ? 0777000 : 0; + SC = SCAD + SC; +#else SC = (SCAD + SC) & 0777; +#endif flag1 = 0; if (AR & SMASK) flag1 = 1; -#if !PDP6 - SMEAR_SIGN(AR); - AR <<= 34; - goto fnorm; -#else +#if PDP6 if (((SC & 0400) != 0) ^ ((SC & 0200) != 0)) fxu_hold_set = 1; if ((SC & 0400) != 0 && !pi_cycle) { @@ -3805,6 +5440,10 @@ ldb_ptr: AR &= SMASK|MMASK; AR |= ((uint64)((SC) & 0377)) << 27; break; +#else + SMEAR_SIGN(AR); + AR <<= 34; + goto fnorm; #endif @@ -3860,6 +5499,9 @@ ufa: /* Get exponent */ SC = GET_EXPO(AR); +#if KL + SC |= (SC & 0400) ? 0777000 : 0; /* Extend sign */ +#endif /* Smear the signs */ SMEAR_SIGN(AR); SMEAR_SIGN(BR); @@ -3898,8 +5540,10 @@ fnorm: #if !PDP6 AR &= ~077; /* Save one extra bit */ #endif +#if !KL if (((SC & 0400) != 0) ^ ((SC & 0200) != 0)) fxu_hold_set = 1; +#endif if (IR != 0130) { /* !UFA */ fnormx: while (AR != 0 && ((AR & FPSBIT) != 0) == ((AR & FPNBIT) != 0) && @@ -3913,14 +5557,14 @@ fnormx: } /* Handle edge case of a - and overflow bit */ if ((AR & 000777777777600000000000LL) == (FPSBIT|FPNBIT)) { - SC += 1; + SC ++; AR = (AR & FPHBIT) | (AR >> 1); } if (!nrf && ((IR & 04) != 0)) { f = (AR & FP1BIT) != 0; if ((AR & FPRBIT2) != 0) { #if !PDP6 - /* FADR & FSBR do not rount if negative and equal round */ + /* FADR & FSBR do not round if negative and equal round */ /* FMPR does not round if result negative and equal round */ if (((IR & 070) != 070 && (AR & FPSBIT) != 0 && @@ -3952,6 +5596,13 @@ fnormx: AR = MQ = 0; SC = 0; } +#if KL + if (!pi_cycle && (SC & 0400) != 0) { + FLAGS |= OVR|FLTOVR|TRP1; + if ((SC & RSIGN) != 0) + FLAGS |= FLTUND; + } +#else if (((SC & 0400) != 0) && !pi_cycle) { FLAGS |= OVR|FLTOVR|TRP1; #if !PDP6 @@ -3962,6 +5613,7 @@ fnormx: #endif check_apr_irq(); } +#endif SCAD = SC ^ ((AR & SMASK) ? 0377 : 0); AR &= SMASK|MMASK; AR |= ((uint64)(SCAD & 0377)) << 27; @@ -4008,7 +5660,11 @@ fnormx: SC = (((BR & SMASK) ? 0777 : 0) ^ (BR >> 27)) & 0777; SC += (((AR & SMASK) ? 0777 : 0) ^ (AR >> 27)) & 0777; SC += 0600; +#if KL + SC |= (SC & 0400) ? 0777000 : 0; /* Extend sign */ +#else SC &= 0777; +#endif /* Make positive and compute result sign */ flag1 = 0; flag3 = 0; @@ -4067,7 +5723,6 @@ fnormx: if (BR & SMASK) { BR = CM(BR) + 1; flag1 = 1; - flag3 = 1; } if (AR & SMASK) { if ((AR & MMASK) == 0) { @@ -4077,7 +5732,11 @@ fnormx: AR = CM(AR) + 1; flag1 = !flag1; } +#if KL + SC = (SC + ((0777 ^ SCAD) + 1) + 0201); +#else SC = (SC + ((0777 ^ SCAD) + 1) + 0201) & 0777; +#endif /* Clear exponents */ AR &= MMASK; BR &= MMASK; @@ -4094,6 +5753,32 @@ fnormx: AR = BR / AR; if (AR != 0) { #if !PDP6 +#if KL + if (flag1) { + AR = ((AR ^ FMASK) + 1) & FMASK; + } + AR = (AR >> 1) | (AR & SMASK); + if (IR & 04) { + AR++; + flag3 = AR & 1; + } + AR = (AR >> 1) | (AR & SMASK); + while (AR != 0 && ((AR & SMASK) != 0) == ((AR & BIT8) != 0) && + ((AR & BIT8) != 0) == ((AR & BIT9) != 0)) { + AR <<= 1; + AR |= flag3; + flag3 = 0; + SC--; + } + AR &= FMASK; + if ((SC & 01600) != 1600) + fxu_hold_set = 1; + if (AR == (SMASK|EXPO)) { + AR = (AR >> 1) | (AR & SMASK); + SC ++; + } + AR &= SMASK|MMASK; +#else if ((AR & BIT7) != 0) { AR >>= 1; } else { @@ -4109,6 +5794,7 @@ fnormx: AR <<= 1; SC--; } +#endif #else if (flag1) { AR = ((AR ^ FMASK) + 1) & FMASK; @@ -4152,7 +5838,7 @@ fnormx: } check_apr_irq(); } -#if !PDP6 +#if !PDP6 & !KL if (flag1) { AR = ((AR ^ MMASK) + 1) & MMASK; AR |= SMASK; @@ -4398,7 +6084,7 @@ left: case 0213: /* MOVNS */ flag1 = flag3 = 0; AD = CM(AR) + 1; - if ((((AR & CMASK) ^ CMASK) + 1) & SMASK) { + if ((CCM(AR) + 1) & SMASK) { #if !PDP6 FLAGS |= CRY1; #endif @@ -4654,7 +6340,7 @@ left: #if !PDP6 SC = 0; if (AR != 0) { -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -4768,7 +6454,6 @@ left: case 0251: /* BLT */ BR = AB; do { - AIO_CHECK_EVENT; /* queue async events */ if (sim_interval <= 0) { sim_process_event(); } @@ -4784,7 +6469,13 @@ left: } } AB = (AR >> 18) & RMASK; +#if KL + BYF5 = 1; +#endif if (Mem_read(0, 0, 0)) { +#if KL + BYF5 = 0; +#endif #if ITS /* On ITS if access error, allow for skip */ if (QITS && (xct_flag & 04) != 0) @@ -4795,7 +6486,7 @@ left: AR = AOB(AR) & FMASK; #endif f_pc_inh = 1; -#if KA & ITS +#if ITS if (QITS) set_reg(AC, AR); #else @@ -4804,6 +6495,10 @@ left: goto last; } AB = (AR & RMASK); +#if KL + BYF5 = 0; + set_reg(AC, AOB(AR)); +#endif if (Mem_write(0, 0)) { #if ITS /* On ITS if access error, allow for skip */ @@ -4815,7 +6510,7 @@ left: AR = AOB(AR) & FMASK; #endif f_pc_inh = 1; -#if KA & ITS +#if ITS if (QITS) set_reg(AC, AR); #else @@ -4831,7 +6526,7 @@ left: case 0252: /* AOBJP */ AR = AOB(AR); if ((AR & SMASK) == 0) { -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -4845,7 +6540,7 @@ left: case 0253: /* AOBJN */ AR = AOB(AR); if ((AR & SMASK) != 0) { -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -4859,16 +6554,107 @@ left: case 0254: /* JRST */ /* AR Frm PC */ if (uuo_cycle | pi_cycle) { FLAGS &= ~USER; /* Clear USER */ -#if ITS +#if ITS | KL_ITS if (QITS && one_p_arm) { FLAGS |= ONEP; one_p_arm = 0; } #endif } +#if KL + switch (AC) { + case 000: /* JRST */ + break; + case 001: /* PORTAL */ + FLAGS &= ~(PUBLIC|PRV_PUB); + break; + case 005: /* XJRSTF */ +xjrstf: + if (Mem_read(0, 0, 0)) + goto last; + BR = MB >> 32; /* Move flags into position */ +fprintf(stderr, "Xjrst %012llo - ", MB); + AB = (AB + 1) & RMASK; + if (Mem_read(0, 0, 0)) + goto last; + AR = MB; /* Get PC. */ +fprintf(stderr, " %012llo\n\r", MB); + goto jrstf; + + case 006: /* XJEN */ + case 012: /* JEN */ + /* Restore interrupt level. */ + if ((FLAGS & (USER|USERIO)) == USER || + (FLAGS & (USER|PUBLIC)) == PUBLIC) { + goto muuo; + } else { + pi_restore = 1; + } + if ((AC & 010) == 0) + goto xjrstf; + /* Fall through */ + + + case 002: /* JRSTF */ + BR = AR >> 23; /* Move into position */ +jrstf: + FLAGS &= ~(OVR|NODIV|FLTUND|BYTI|FLTOVR|CRY1|CRY0|TRP1|TRP2|PCHNG); + /* If executive mode, copy USER and UIO */ + if ((FLAGS & (PUBLIC|USER)) == 0) + FLAGS |= BR & (USER|USERIO|PUBLIC); + /* Can always clear UIO */ + if ((BR & USERIO) == 0) + FLAGS &= ~USERIO; + FLAGS |= BR & (OVR|NODIV|FLTUND|BYTI|FLTOVR|CRY1|CRY0|\ + TRP1|TRP2|PUBLIC|PCHNG); +#if KL_ITS + if (QITS) + FLAGS |= BR & (PURE|ONEP); +#endif + FLAGS &= ~PRV_PUB; + if ((FLAGS & USER) == 0) + FLAGS |= (BR & OVR) ? PRV_PUB : 0; + check_apr_irq(); + break; + + case 003: /* Invalid */ + case 007: /* XPCW */ + case 011: /* Invalid */ + case 013: /* Invalid */ + case 014: /* SFM */ + case 015: /* Invalid */ + case 016: /* Invalid */ + case 017: /* Invalid */ + goto muuo; + + case 004: /* HALT */ + if ((FLAGS & (USER|USERIO)) == USER || + (FLAGS & (USER|PUBLIC)) == PUBLIC) { + goto muuo; + } else { + reason = STOP_HALT; + } + break; + case 010: /* JEN */ + /* Restore interrupt level. */ + if ((FLAGS & (USER|USERIO)) == USER || + (FLAGS & (USER|PUBLIC)) == PUBLIC) { + goto muuo; + } else { + pi_restore = 1; + } + break; + } +#if KL_ITS + if ((FLAGS & USER) && QITS) { + jpc = PC; + } +#endif + PC = AR & RMASK; +#else /* JEN */ if (AC & 010) { /* Restore interrupt level. */ -#if KI | KL +#if KI if ((FLAGS & (USER|USERIO)) == USER || (FLAGS & (USER|PUBLIC)) == PUBLIC) { #else @@ -4881,7 +6667,7 @@ left: } /* HALT */ if (AC & 04) { -#if KI | KL +#if KI if ((FLAGS & (USER|USERIO)) == USER || (FLAGS & (USER|PUBLIC)) == PUBLIC) { #else @@ -4928,18 +6714,19 @@ left: } if (AC & 01) { /* Enter User Mode */ -#if KI | KL +#if KI FLAGS &= ~(PUBLIC|PRV_PUB); #else FLAGS |= USER; #endif } +#endif f_pc_inh = 1; break; case 0255: /* JFCL */ if ((FLAGS >> 9) & AC) { -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -4966,7 +6753,7 @@ left: if (QWAITS && (FLAGS & USER) == 0) xct_flag = AC; #endif -#if ITS +#if ITS | KL_ITS if (QITS && one_p_arm) { FLAGS |= ONEP; one_p_arm = 0; @@ -4977,14 +6764,57 @@ left: case 0257: /* MAP */ #if KI | KL f = AB >> 9; + flag1 = (FLAGS & USER) != 0; + flag3 = 0; +#if KI /* Check if Paging Enabled */ if (!page_enable || AB < 020) { AR = 0020000LL + f; /* direct map */ +#else + /* Check if Paging Enabled */ + if (!page_enable || AB < 020) { + AR = AB; /* direct map */ +#endif set_reg(AC, AR); break; } - flag1 = (FLAGS & USER) != 0; +#if KL + /* Invalid in user unless USERIO set, or not in supervisor mode */ + if ((FLAGS & (USER|USERIO)) == USER || (FLAGS & (USER|PUBLIC)) == PUBLIC) + goto muuo; + /* Figure out if this is a user space access */ + if (xct_flag & 4) + flag1 = (FLAGS & USERIO) != 0; + + /* Handle KI paging odditiy */ + if (!flag1 && !t20_page && (f & 0740) == 0340) { + /* Pages 340-377 via UBT */ + f += 01000 - 0340; + flag3 = 1; + } + + AR = load_tlb(flag1, f, flag3, 0, 0); + page_fault = 0; /* Incase error during lookup */ + BR = AR; + /* Remap the flag bits */ + if (BR & 0400000LL) { /* A */ + AR = ((AR & 017777LL) << 9) + (AB & 0777); + if (flag1) /* U */ + AR |= SMASK; /* BIT8 */ + AR |= 00100000000000LL; /* BIT2 */ + if (BR & 0200000LL) /* P */ + AR |= 00004000000000LL; /* BIT6 */ + if (BR & 0100000LL) /* W */ + AR |= 00040000000000LL; /* BIT3 */ + if (BR & 0040000LL) /* S */ + AR |= 00020000000000LL; /* BIT4 */ + if (BR & 0020000LL) /* C */ + AR |= 00002000000000LL; /* BIT7 */ + } else + AR = (f & 01740) ? 0 : 0377777LL; + AR |= BIT8; +#else /* Figure out if this is a user space access */ if (xct_flag != 0 && !flag1) { if ((xct_flag & 2) != 0) { @@ -4992,7 +6822,6 @@ left: } } - flag3 = 0; /* If user, check if small user enabled */ if (flag1) { if (small_user && (f & 0340) != 0) { @@ -5000,60 +6829,18 @@ left: set_reg(AC, AR); break; } - } else { - /* Handle system mapping */ - /* Pages 340-377 via UBR */ - if ((f & 0740) == 0340) { - f += 01000 - 0340; - flag3 = 2; - /* Pages 400-777 via EBR */ - } else if (f & 0400) { - flag3 = 1; - /* Pages 000-037 direct map */ - } else { - AR = 0020000LL + f; /* direct map */ - set_reg(AC, AR); - break; - } } - /* Map the page */ - if (flag3&1) { - AR = e_tlb[f]; - if (AR == 0) { - AR = M[eb_ptr + (f >> 1)]; - e_tlb[f & 0776] = RMASK & (AR >> 18); - e_tlb[f | 1] = RMASK & AR; - AR = e_tlb[f]; - if (AR == 0) { - AR = 0437777; - set_reg(AC, AR); - break; - } - pag_reload = ((pag_reload + 1) & 037) | 040; - } - last_page = ((f ^ 0777) << 1) | 1; + + /* Get translation */ + AR = load_tlb(flag1, f); + if (AR == 0) { + AR = 0437777LL; } else { - AR = u_tlb[f]; - if (AR == 0) { - AR = M[ub_ptr + (f >> 1)]; - u_tlb[f & 01776] = RMASK & (AR >> 18); - u_tlb[f | 1] = RMASK & AR; - AR = u_tlb[f]; - if (AR == 0) { - AR = 0437777; - set_reg(AC, AR); - break; - } - pag_reload = ((pag_reload + 1) & 037) | 040; - } - if (flag3 & 2) - last_page = (((f-0440) ^ 0777) << 1) | 1; - else - last_page = ((f ^ 0777) << 1); + if ((AR & 0400000LL) == 0) + AR &= 0437777LL; /* Return valid entry for page */ + AR ^= 0400000LL; /* Flip access status. */ } - if ((AR & 0400000LL) == 0) - AR &= 0437777LL; /* Return valid entry for page */ - AR ^= 0400000LL; /* Flip access status. */ +#endif set_reg(AC, AR); #endif break; @@ -5061,7 +6848,7 @@ left: /* Stack, JUMP */ case 0260: /* PUSHJ */ /* AR Frm PC */ MB = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + !pi_cycle) & RMASK); -#if KI +#if KI | KL if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; @@ -5070,6 +6857,9 @@ left: BR = AB; AR = AOB(AR); AB = AR & RMASK; +#if KL + BYF5 = 1; +#endif if (Mem_write(uuo_cycle | pi_cycle, 0)) goto last; FLAGS &= ~ (BYTI|ADRFLT|TRP1|TRP2); @@ -5085,7 +6875,7 @@ left: #if !PDP6 if (uuo_cycle | pi_cycle) { FLAGS &= ~(USER|PUBLIC); /* Clear USER */ -#if ITS +#if ITS | KL_ITS if (QITS && one_p_arm) { FLAGS |= ONEP; one_p_arm = 0; @@ -5093,7 +6883,7 @@ left: #endif } #endif -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -5116,6 +6906,9 @@ left: #endif } MB = BR; +#if KL + BYF5 = 1; +#endif if (Mem_write(0, 0)) goto last; break; @@ -5126,6 +6919,9 @@ left: goto last; AR = SOB(AR); AB = BR & RMASK; +#if KL + BYF5 = 1; /* Tell PXCT that this is stack */ +#endif if (Mem_write(0, 0)) goto last; if ((AR & C1) == 0) { @@ -5143,7 +6939,7 @@ left: AB = AR & RMASK; if (Mem_read(0, 0, 0)) goto last; -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -5165,7 +6961,7 @@ left: case 0264: /* JSR */ /* AR Frm PC */ MB = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + !pi_cycle) & RMASK); -#if KI +#if KI | KL if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; @@ -5183,7 +6979,7 @@ left: if (Mem_write(0, 0)) goto last; FLAGS &= ~ (BYTI|ADRFLT|TRP1|TRP2); -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -5197,7 +6993,7 @@ left: AD = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + !pi_cycle) & RMASK); FLAGS &= ~ (BYTI|ADRFLT|TRP1|TRP2); -#if KI +#if KI | KL if ((FLAGS & USER) == 0) { AD &= ~SMASK; AD |= (FLAGS & PRV_PUB) ? SMASK : 0; @@ -5208,7 +7004,7 @@ left: FLAGS &= ~(USER|PUBLIC); /* Clear USER */ } #endif -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -5226,7 +7022,7 @@ left: FLAGS &= ~(USER|PUBLIC); /* Clear USER */ } #endif -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -5242,7 +7038,7 @@ left: if (Mem_read(uuo_cycle | pi_cycle, 0, 0)) goto last; set_reg(AC, MB); -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -5279,7 +7075,7 @@ left: case 0276: /* SUBM */ case 0277: /* SUBB */ flag1 = flag3 = 0; - if ((((AR & CMASK) ^ CMASK) + (BR & CMASK) + 1) & SMASK) { + if ((CCM(AR) + (BR & CMASK) + 1) & SMASK) { FLAGS |= CRY1; flag1 = 1; } @@ -5397,7 +7193,7 @@ jump_op: f |= ((AD == 0) << 1); f = f & IR; if (((IR & 04) != 0) == (f == 0)) { -#if ITS +#if ITS | KL_ITS if ((FLAGS & USER) && QITS) { jpc = PC; } @@ -5770,7 +7566,7 @@ test_op: case 0764: case 0765: case 0766: case 0767: case 0770: case 0771: case 0772: case 0773: case 0774: case 0775: case 0776: case 0777: -#if KI +#if KI | KL if (!pi_cycle && ((((FLAGS & (USER|USERIO)) == USER) && (IR & 040) == 0) || ((FLAGS & (USER|PUBLIC)) == PUBLIC))) { @@ -5787,6 +7583,22 @@ fetch_opr: switch(AC & 07) { case 0: /* 00 BLKI */ case 2: /* 10 BLKO */ +#if KL + if (d <= 05) { + if (AC & 02) { +// if (Mem_read(pi_cycle, 0, 0)) + // goto last; + // AR = MB; + dev_tab[d](040|DATAO|(d<<2), &AR); + } else { + dev_tab[d](040|DATAI|(d<<2), &AR); + // MB = AR; + // if (Mem_write(pi_cycle, 0)) + // goto last; + } + break; + } +#endif if (Mem_read(pi_cycle, 0, 0)) goto last; AR = MB; @@ -5812,6 +7624,14 @@ fetch_opr: MB = AR; if (Mem_write(pi_cycle, 0)) goto last; +#if KL + if (d == 5) { /* DATAI TIM is two words */ + AB = (AB + 1) & RMASK; + MB = BR; + if (Mem_write(pi_cycle, 0)) + goto last; + } +#endif break; case 3: /* 14 DATAO */ if (Mem_read(pi_cycle, 0, 0)) @@ -5860,7 +7680,7 @@ fetch_opr: set_reg(AC+1, MQ); } - if (hst_lnt) { + if (hst_lnt && PC >= 020) { hst[hst_p].fmb = AR; } @@ -5874,7 +7694,46 @@ last: goto fetch; } #endif -#if KI | KL +#if KL + /* Handle page fault and traps */ + if (page_enable && page_fault) { + page_fault = 0; + if (pi_cycle) { + pi_cycle = 0; + set_pi_hold(); /* Hold off all lower interrupts */ + } +fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); + BYF5 = 0; + AB = ub_ptr + 0500; + MB = fault_data; + Mem_write_nopage(); + AB++; + FLAGS |= trap_flag & (TRP1|TRP2); + trap_flag = (TRP1|TRP2); + MB = (((uint64)(FLAGS) << 23) & LMASK) | (PC & RMASK); + if ((FLAGS & USER) == 0) { + MB &= ~SMASK; + MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + } + Mem_write_nopage(); + AB++; + flag1 = flag3 = 0; + if (FLAGS & PUBLIC) + flag3 = 1; + if (FLAGS & USER) + flag1 = 1; + Mem_read_nopage(); + FLAGS = (MB >> 23) & 017777; + /* If transistioning from user to executive adjust flags */ + if ((FLAGS & USER) != 0 && flag1) + FLAGS |= USERIO; + if ((FLAGS & USER) == 0 && (flag3 || (FLAGS & OVR) != 0)) + FLAGS |= PRV_PUB|OVR; + PC = MB & RMASK; + f_pc_inh = 1; + } +#endif +#if KI /* Handle page fault and traps */ if (page_enable && page_fault) { page_fault = 0; @@ -5893,6 +7752,7 @@ last: #if KI | KL if (!f_pc_inh && (trap_flag == 0) && !pi_cycle) { + FLAGS &= ~ADRFLT; #else if (!f_pc_inh && !pi_cycle) { #endif @@ -5910,10 +7770,20 @@ last: /* Dismiss an interrupt */ if (pi_cycle) { #if KI | KL - if (page_enable && page_fault) { + if (page_enable && page_fault) { page_fault = 0; +fprintf(stderr, "Page fault trap %06o\n\r", PC); + pi_cycle = 0; +#if KI inout_fail = 1; - } +#else + irq_flags |= 01000; + FM[(7 << 4) | 2] = fault_data; +#endif + check_apr_irq(); + pi_rq = check_irq_level(); + goto st_pi; + } #endif if ((IR & 0700) == 0700 && ((AC & 04) == 0)) { @@ -5975,6 +7845,9 @@ last: #endif return SCPE_STEP; } +#if KL + FLAGS &= ~ADRFLT; +#endif } /* Should never get here */ #if ITS @@ -5985,6 +7858,811 @@ if (QITS) return reason; } +#if KL + +/* Get data from pointer */ +int +load_byte(int n, uint64 *data, uint64 fill, int cnt) +{ + uint64 val, msk; + int s, p, addr, ind, np; + + /* Check if should return fill */ + val = get_reg(n); + if (cnt && (val & MANT) == 0) { + *data = fill; + return 1; + } + /* Get pointer */ + val = get_reg(n+1); + /* Extract index */ + s = (val >> 24) & 077; + p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; + /* Advance pointer */ + if (p & 0400) { + np = p = ((0777 ^ s) + 044 + 1) & 0777; + val = (val & LMASK) | ((val + 1) & RMASK); + } else + np = p; + np &= 077; + /* Update pointer */ + val &= PMASK; + val |= (uint64)(np) << 30; + AB = val & RMASK; + MB = val; + + /* Handle indirection repeat until no longer indirect */ + do { + ind = (MB & 020000000) != 0; + if (MB & 017000000) { + AB = (AB + get_reg((MB >> 18) & 017)) & RMASK; + } + if (ind) { + if (Mem_read(0, 1, 0)) + goto back; + AB = MB & RMASK; + } + if (sim_interval <= 0) { + sim_process_event(); + } + } while (ind & pi_pending); + + /* Save pointer */ + set_reg(n+1, val); + + /* Read final value */ + if (Mem_read(0, 0, 0)) + goto back; + + /* Generate mask for given size */ + msk = (uint64)(1) << s; + msk--; + *data = (MB >> p) & msk; + if (cnt) { + /* Decrement count */ + val = get_reg(n); + val--; + set_reg(n, val); + } + + return 1; + +back: + val = get_reg(n+1); + val &= PMASK; + val |= (uint64)(p + s) << 30; + set_reg(n+1, val); + return 0; +} + +/* Store data into pointer */ +int +store_byte(int n, uint64 data, int cnt) +{ + uint64 val, msk; + int s, p, addr, ind, np; + + /* Get pointer */ + val = get_reg(n+1); + /* Extract index */ + s = (val >> 24) & 077; + p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; + /* Advance pointer */ + if (p & 0400) { + np = p = ((0777 ^ s) + 044 + 1) & 0777; + val = (val & LMASK) | ((val + 1) & RMASK); + } else + np = p; + np &= 077; + /* Update pointer */ + val &= PMASK; + val |= (uint64)(np) << 30; + AB = val & RMASK; + MB = val; + + /* Handle indirection repeat until no longer indirect */ + do { + ind = (MB & 020000000) != 0; + if (MB & 017000000) { + AB = (AB + get_reg((MB >> 18) & 017)) & RMASK; + } + if (ind) { + if (Mem_read(0, 1, 0)) + goto back; + AB = MB & RMASK; + } + if (sim_interval <= 0) { + sim_process_event(); + } + } while (ind & pi_pending); + + /* Save pointer */ + set_reg(n+1, val); + + + /* Generate mask for given size */ + msk = (uint64)(1) << s; + msk--; + + /* Read final value */ + modify = 1; + if (Mem_read(0, 0, 0)) + goto back; + + msk <<= p; + MB &= CM(msk); + MB |= msk & ((uint64)(data) << p); + if (Mem_write(0, 0)) + goto back; + + if (cnt) { + /* Decrement count */ + val = get_reg(n); + val--; + set_reg(n, val); + } + + return 1; + +back: + val = get_reg(n+1); + val &= PMASK; + val |= (uint64)(p + s) << 30; + set_reg(n+1, val); + return 0; +} + +void +get_mask(int n, uint64 *msk) +{ + uint64 val; + int s; + /* Get pointer */ + val = get_reg(n+1); + /* Extract index */ + s = (val >> 24) & 077; + + /* Generate mask for given size */ + *msk = ((uint64)(1) << s) - 1; +} + +/* Advance a pointer by 1 */ +void +adv_byte(int n) +{ + uint64 val; + int s, p, np; + + /* Check if should return fill */ + val = get_reg(n); + if ((val & MANT) == 0) + return; + /* Decrement count */ + val--; + set_reg(n, val); + + /* Get pointer */ + val = get_reg(n+1); + /* Extract index */ + s = (val >> 24) & 077; + p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; + /* Advance pointer */ + if (p & 0400) { + p = np = (36 + (0777 ^ s) + 1) & 0777; + val = (val & LMASK) | ((val + 1) & RMASK); + } else + np = p; + np &= 077; + /* Update pointer */ + val &= PMASK; + val |= (uint64)(np) << 30; + MB = val; + + /* Save pointer */ + set_reg(n+1, val); +} + +/* back a pointer by 1 */ +void +bak_byte(int n, int cnt) +{ + uint64 val, msk; + int s, p, addr, ind, np; + + /* Increment count */ + if (cnt) { + val = get_reg(n); + val++; + set_reg(n, val); + } + + /* Get pointer */ + val = get_reg(n+1); + /* Extract index */ + s = (val >> 24) & 077; + p = (((val >> 30) & 077) + (s)) & 0777; + /* Advance pointer */ + /* Update pointer */ + val &= PMASK; + val |= (uint64)(p) << 30; + MB = val; + + /* Save pointer */ + set_reg(n+1, val); +} + +/* Preform a table lookup operation */ +int +do_xlate(uint32 tbl, uint64 val, int mask) +{ + uint64 reg; + int f; + + AB = (tbl + (val >> 1)) & RMASK; + if (Mem_read(0, 0, 0)) { + /* Backup ext_ac */ + return -2; + } + if ((val & 1) == 0) + MB >>= 18; + val = MB & mask; + reg = get_reg(ext_ac); + f = 1; + switch ((MB >> 15) & 07) { + case 0: + if ((reg & SMASK) == 0) /* If S */ + f = 0; + break; + case 1: f = -1; /* Terminate */ + break; + case 2: + if ((reg & SMASK) == 0) /* If S, clear M */ + f = 0; + reg &= ~BIT2; + break; + case 3: + if ((reg & SMASK) == 0) /* If S, set M */ + f = 0; + reg |= BIT2; + break; + case 4: + reg |= SMASK|BIT1; /* Set S & N */ + break; + case 5: + f = -1; /* Terminate, set N */ + reg |= BIT1; + break; + case 6: + reg |= SMASK|BIT1; /* Set S, N, Clear M */ + reg &= ~BIT2; + break; + case 7: + reg |= SMASK|BIT1|BIT2; /* Set S, N, M */ + break; + } + set_reg(ext_ac, reg); + return f; +} + +/* Table of powers of 10 for CVTBD opcodes */ +uint64 pow10_tab[22][2] = { + /* 0: */ 0000000000000LL, 0000000000001LL, + /* 1: */ 0000000000000LL, 0000000000012LL, + /* 2: */ 0000000000000LL, 0000000000144LL, + /* 3: */ 0000000000000LL, 0000000001750LL, + /* 4: */ 0000000000000LL, 0000000023420LL, + /* 5: */ 0000000000000LL, 0000000303240LL, + /* 6: */ 0000000000000LL, 0000003641100LL, + /* 7: */ 0000000000000LL, 0000046113200LL, + /* 8: */ 0000000000000LL, 0000575360400LL, + /* 9: */ 0000000000000LL, 0007346545000LL, + /* 10: */ 0000000000000LL, 0112402762000LL, + /* 11: */ 0000000000002LL, 0351035564000LL, + /* 12: */ 0000000000035LL, 0032451210000LL, + /* 13: */ 0000000000443LL, 0011634520000LL, + /* 14: */ 0000000005536LL, 0142036440000LL, + /* 15: */ 0000000070657LL, 0324461500000LL, + /* 16: */ 0000001070336LL, 0115760200000LL, + /* 17: */ 0000013064257LL, 0013542400000LL, + /* 18: */ 0000157013326LL, 0164731000000LL, + /* 19: */ 0002126162140LL, 0221172000000LL, + /* 20: */ 0025536165705LL, 0254304000000LL, + /* 21: */ 0330656232670LL, 0273650000000LL +}; + +/* + * Process extended instruction. + * + * On entry BR = address of instruction. + * AB = value of E0. + * IR = opcode. + */ +int +do_extend(uint32 ia) +{ + uint64 fill1, fill2; + uint64 val1, val2; + uint64 msk; + uint64 reg; + int f, i; + + + switch(IR) { + case 001: /* CMPSL */ + case 002: /* CMPSE */ + case 003: /* CMPSLE */ + case 005: /* CMPSGE */ + case 006: /* CMPSN */ + case 007: /* CMPSG */ + if (((get_reg(ext_ac) | get_reg(ext_ac+3)) & EMASK) != 0) + return 1; + /* Fetch filler values */ + AB = (ia + 1) & RMASK; + if (Mem_read(0, 1, 0)) + return 0; + fill1 = MB; + AB = (AB + 1) & RMASK; + if (Mem_read(0, 1, 0)) + return 0; + fill2 = MB; + + /* Compare the strings */ + f = 2; + while (((get_reg(ext_ac) | get_reg(ext_ac+3)) & MANT) != 0) { + if (!load_byte(ext_ac, &val1, fill1, 1)) { + return 0; + } + if (!load_byte(ext_ac+3, &val2, fill2, 1)) { + /* Backup ext_ac */ + bak_byte(ext_ac, 1); + return 0; + } + if (val1 != val2) { + f = (val1 < val2) ? 1: 0; + break; + } + } + /* Check if we should skip */ + switch (IR & 7) { + case 1: f = (f == 1); break; + case 2: f = (f == 2); break; + case 3: f = (f != 0); break; + case 5: f = (f != 1); break; + case 6: f = (f != 2); break; + case 7: f = (f == 0); break; + default: f = 0; break; + } + /* Skip if conditions match */ + if (f) + PC = (PC + 1) & RMASK; + return 0; + + case 004: /* EDIT */ + val2 = MB; /* Save address of translate table */ + /* Fetch filler values */ + AB = (ia + 1) & RMASK; + if (Mem_read(0, 1, 0)) + return 0; + fill1 = MB; + /* Get floating character */ + AB = (AB + 1) & RMASK; + if (Mem_read(0, 1, 0)) + return 0; + fill2 = MB; + f = 1; + while (f) { + int a; + + /* Read in pattern control */ + reg = get_reg(ext_ac); + AB = reg & RMASK; + if (Mem_read(0, 0, 0)) + return 0; + i = (reg >> 30) & 03; + reg &= ~(3LL << 30); /* Clear byte number */ + val1 = (MB >> ((3 - i) * 9)) & 0777; + i++; + if (i > 3) { + reg++; + i = 0; + } + reg |= ((uint64)i) << 30; + i = 0; + a = 0; + switch ((val1 >> 6) & 07) { + case 0: /* Individual options */ + switch (val1 & 077) { + case 0: /* Stop */ + f = 0; + break; + case 1: + if (!load_byte(ext_ac, &val1, 0, 0)) + return 0; + a = 1; + AB = (val2 + (val1 >> 1)) & RMASK; + if (Mem_read(0, 0, 0)) + return 0; + if ((val1 & 1) == 0) + MB >>= 18; + val1 = MB & 07777; + switch ((MB >> 15) & 07) { + case 0: + func0: + if ((reg & SMASK) != 0) { /* If S */ + i = 1; + } else if (fill1 != 0) { + val1 = fill1; + i = 1; + } + break; + case 1: + set_reg(ext_ac, reg); + return 0; /* Next */ + case 2: + reg &= ~BIT2; /* If S, clear M */ + goto func0; + case 3: + reg |= BIT2; /* If S, set M */ + goto func0; + case 4: + func4: + if ((reg & SMASK) == 0) { + AB = get_reg(ext_ac+3) & RMASK; + MB = get_reg(ext_ac+4); + if (Mem_write(0, 0)) + return 0; + if (fill2 != 0) { + val1 = fill2; + i = 1; + } + } else + i = 1; + reg |= SMASK|BIT1; /* Set S & N */ + break; + case 5: + reg |= BIT1; + break; + case 6: + reg &= ~BIT2; /* Clear M */ + goto func4; + case 7: + reg |= BIT2; /* Set M */ + goto func4; + } + break; + case 2: /* Set signifigance */ + if ((reg & SMASK) == 0) { + AB = get_reg(ext_ac+3) & RMASK; + MB = get_reg(ext_ac+4); + if (Mem_write(0, 0)) + return 0; + if (fill2 != 0) { + val1 = fill2; + i = 1; + } + } + reg |= SMASK; + break; + case 3: /* Field separater */ + reg &= ~(SMASK|BIT1|BIT2); /* Clear S & N */ + break; + case 4: /* Exchange Mark */ + AB = get_reg(ext_ac+3) & RMASK; + if (Mem_read(0, 0, 0)) + return 0; + AR = MB; + MB = get_reg(ext_ac+4); + if (Mem_write(0, 0)) + return 0; + set_reg(ext_ac+4, AR); + AB = (AB + 1) & RMASK; + if (Mem_read(0, 0, 0)) + return 0; + AR = MB; + MB = get_reg(ext_ac+5); + if (Mem_write(0, 0)) + return 0; + set_reg(ext_ac+5, AR); + break; + case 5: + i = 0; + break; + } + break; + case 1: /* Insert Message char */ + if ((reg & SMASK) != 0) { + AB = (ia + (val1 & 077) + 1) & RMASK; + if (Mem_read(0, 0, 0)) + return 0; + i = 1; + val1 = MB; + } else if (fill1 != 0) { + i = 1; + val1 = fill1; + } + break; + case 5: /* Skip on M */ + if ((reg & BIT2) != 0) + goto skipa; + break; + case 6: /* Skip on N */ + if ((reg & BIT1) == 0) + break; + case 7: /* Skip allways */ + skipa: + /* Compute new byte number */ + val1 = (val1 & 077) + 1; + val2 = ((reg >> 30) & 03) + val1; + reg &= ~(3LL << 30); /* Clear byte number */ + reg += (val2 >> 2); + reg |= (val2 & 3) << 30; + i = 0; + default: + break; + } + if (i) { + if (!store_byte(ext_ac+3, val1, 0)) { + if (a) + bak_byte(ext_ac, 0); + return 0; + } + } + set_reg(ext_ac, reg); + } + PC = (PC + 1) & RMASK; + break; + + case 010: /* CVTDBO */ + case 011: /* CVTDBT */ + val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); + /* Check if conversion started */ + if ((get_reg(ext_ac) & SMASK) == 0) { + set_reg(ext_ac+3, 0); + set_reg(ext_ac+4, 0); + } + AR = get_reg(ext_ac + 3); + ARX = get_reg(ext_ac + 4); + if (IR == 010) { + fill2 = get_reg(ext_ac); + fill2 |= SMASK; + set_reg(ext_ac, fill2); + } + while ((get_reg(ext_ac) & MANT) != 0) { + f = 1; + if (!load_byte(ext_ac, &val1, 0, 1)) { + set_reg(ext_ac+3, ARX); + set_reg(ext_ac+4, AR); + return 0; + } + if (IR == 010) + val1 = (val1 + val2) & FMASK; + else + f = do_xlate((uint32)(val2 & RMASK), val1, 017); + if (f < 0) + break; + if (f) { + if ((val1 & RSIGN) != 0 || val1 > 9) { + ARX = (ARX & CMASK) | (AR & SMASK); + set_reg(ext_ac+3, AR); + set_reg(ext_ac+4, ARX); + return 0; + } + /* Multiply by 2 */ + AR <<= 1; + ARX <<= 1; + if (ARX & SMASK) + AR |= 1; + ARX &= CMASK; + /* Compute times 4 */ + BR = (AR << 2) | ((ARX >> 33) & 03); + BRX = (ARX << 2) & CMASK; + ARX = (ARX & CMASK) + (BRX & CMASK) + val1; + f = (ARX >> 35); + AR = AR + BR + f; + ARX &= CMASK; + AR &= FMASK; + } + } + ARX &= CMASK; + if ((get_reg(ext_ac) & MANT) == 0) { + PC = (PC + 1) & RMASK; + if (get_reg(ext_ac) & BIT2) { + ARX = CCM(ARX) + 1; + AR = CM(AR) + ((ARX & SMASK) != 0); + } + } + ARX = (ARX & CMASK) | (AR & SMASK); + AR &= FMASK; + set_reg(ext_ac+3, AR); + set_reg(ext_ac+4, ARX); + break; + case 012: /* CVTBDO */ + case 013: /* CVTBDT */ + /* Save E1 */ + if (IR == 012) + val2 = AB; + else + val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); + /* Get fill */ + AB = (ia + 1) & RMASK; + if (Mem_read(0, 1, 0)) + return 0; + fill1 = MB; + AR = get_reg(ext_ac); + ARX = get_reg(ext_ac + 1); + reg = get_reg(ext_ac + 3); + /* Set M bit if minus */ + if ((AR & SMASK) != 0 && (reg & BIT2) == 0) { + reg |= BIT2; + ARX = CCM(ARX) + 1; + AR = CM(AR) + ((ARX & SMASK) != 0); + } + ARX &= CMASK; + /* Set N bit if non-zero number */ + if ((AR | ARX) != 0) + reg |= BIT1; + set_reg(ext_ac+3, reg); + /* Compute number of digits needed for value */ + for (f = 0; f < 22; f++) { + BRX = ARX + CCM(pow10_tab[f][1]) + 1; + BR = AR + CM(pow10_tab[f][0]) + ((BRX & SMASK) != 0); + if ((BR & C1) == 0) + break; + } + if (f == 0) + f = 1; + /* Check if room to save it */ + if (f > (reg & MANT)) + return 0; + /* Fill out left justify */ + /* If L, fill leading zeros with fill char */ + while ((reg & SMASK) != 0 && (reg & MANT) != f) { + if (!store_byte(ext_ac + 3, fill1, 1)) + return 0; + reg = get_reg(ext_ac + 3); + } + /* Insert correct digit */ + for (f--; f >= 0; f--) { + /* Subtract closest power of 10 */ + for (i = 0; i < 10; i++) { + BRX = ARX + CCM(pow10_tab[f][1]) + 1; + BR = AR + CM(pow10_tab[f][0]) + ((BRX & SMASK) != 0); + if ((BR & C1) == 0) + break; + ARX = BRX & CMASK; + AR = BR & FMASK; + } + val1 = (uint64)i; + if (IR == 013) { + /* Read first translation entry */ + AB = (val1 + val2) & RMASK; + if (Mem_read(0, 0, 0)) { + set_reg(ext_ac + 3, (reg & (SMASK|EXPO)) | (f+1)); + return 0; + } + val1 = MB; + if (f == 0 && (get_reg(ext_ac + 3) & BIT2) != 0) + val1 >>= 12; + val1 &= 07777; + } else + val1 += val2; + if (!store_byte(ext_ac + 3, val1, 1)) { + set_reg(ext_ac + 3, (reg & (SMASK|EXPO)) | (f+1)); + return 0; + } + set_reg(ext_ac, AR); + set_reg(ext_ac+1, ARX); + } + reg = get_reg(ext_ac+3); + reg &= SMASK|EXPO; + set_reg(ext_ac+3, reg); + set_reg(ext_ac, 0); + set_reg(ext_ac+1, 0); + PC = (PC + 1) & RMASK; + break; + case 014: /* MOVSO */ + case 015: /* MOVST */ + case 016: /* MOVSLJ */ + get_mask(ext_ac+3, &msk); + if ((((get_reg(ext_ac) & (077LL << 26))| get_reg(ext_ac+3)) & EMASK) != 0) + return 1; + if (IR == 014) + val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); + else if (IR == 015) { + AB = ia; + if (Mem_read(0, 1, 0)) + return 0; + val2 = MB; + } else { + val2 = AB; + } + /* Fetch filler values */ + AB = (ia + 1) & RMASK; + if (Mem_read(0, 1, 0)) + return 0; + fill1 = MB; + f = 1; + while ((get_reg(ext_ac) & MANT) != 0) { + if ((get_reg(ext_ac+3) & MANT) == 0) + return 0; + f = 1; + if (!load_byte(ext_ac, &val1, fill1, 1)) { + return 0; + } + if (IR == 014) + val1 = (val1 + val2) & FMASK; + else if (IR == 015) + f = do_xlate((uint32)(val2), val1, 07777); + if (f < 0) + return 0; + if (f) { + /* Check if in range */ + if (IR == 014 && (val1 & ~msk) != 0) + return 0; + if (!store_byte(ext_ac+3, val1, 1)) { + bak_byte(ext_ac, 1); + return 0; + } + } else { + adv_byte(ext_ac+3); + } + } + while ((get_reg(ext_ac+3) & MANT) != 0) { + if (!store_byte(ext_ac+3, fill1, 1)) + return 0; + } + PC = (PC + 1) & RMASK; + break; + + case 017: /* MOVSRJ */ + /* Fetch filler values */ + if (((get_reg(ext_ac) | get_reg(ext_ac+3)) & EMASK) != 0) + return 1; + AB = (ia + 1) & RMASK; + if (Mem_read(0, 1, 0)) + return 0; + fill1 = MB; + /* While source is larger, skip source */ + while ((get_reg(ext_ac+3) & MANT) != 0 && + (get_reg(ext_ac) & MANT) > (get_reg(ext_ac+3) & MANT)) { + adv_byte(ext_ac); + } + /* While destination is larger, fill destination */ + while ((get_reg(ext_ac+3) & MANT) != 0 && + (get_reg(ext_ac) & MANT) < (get_reg(ext_ac+3) & MANT)) { + if (!store_byte(ext_ac+3, fill1, 1)) { + return 0; + } + } + /* Copy rest of string */ + while ((get_reg(ext_ac+3) & MANT) != 0) { + if (!load_byte(ext_ac, &val1, fill1, 1)) + return 0; + if (!store_byte(ext_ac+3, val1, 1)) { + /* Backup ext_ac */ + bak_byte(ext_ac, 1); + return 0; + } + } + PC = (PC + 1) & RMASK; + break; + + case 020: /* XBLT */ + case 021: /* GSNGL */ + case 022: /* GDBLE */ + case 023: /* GDFIX */ + case 024: /* GFIX */ + case 025: /* GDFIXR */ + case 026: /* GFIXR */ + case 027: /* DGFLTR */ + case 030: /* GFLTR */ + case 031: /* GFSC */ + return 1; + } + return 0; +} +#endif + t_stat rtc_srv(UNIT * uptr) { @@ -6012,25 +8690,32 @@ qua_srv(UNIT * uptr) } #endif - -/* - * This sequence of instructions is a mix that hopefully - * represents a resonable instruction set that is a close - * estimate to the normal calibrated result. - */ - -static const char *pdp10_clock_precalibrate_commands[] = { - "-m 100 ADDM 0,110", - "-m 101 ADDI 0,1", - "-m 102 JRST 100", - "PC 100", - NULL}; +#if KL +t_stat +tim_srv(UNIT * uptr) +{ + double us; + + /* See if we are counting to overflow or period */ + if (tim_val & 0100000) { + tim_val = 020000 | tim_per; + us = (double)((010000 - tim_per) * 10); + } else { + tim_val = 0130000; + us = (double)(tim_per * 10); + } + set_interrupt(4 << 2, mtr_irq); + (void)sim_activate_after_d(uptr, us); + return SCPE_OK; +} +#endif /* Reset routine */ t_stat cpu_reset (DEVICE *dptr) { int i; +sim_debug(DEBUG_CONO, dptr, "CPU reset\n"); BYF5 = uuo_cycle = 0; #if KA | PDP6 Pl = Ph = 01777; @@ -6051,7 +8736,11 @@ pi_restore = pi_hold = 0; #if KI | KL ub_ptr = eb_ptr = 0; pag_reload = ac_stack = 0; +#if KI fm_sel = small_user = user_addr_cmp = page_enable = 0; +#else +fm_sel = prev_ctx = user_addr_cmp = page_enable = 0; +#endif #endif #if BBN exec_map = 0; @@ -6060,9 +8749,13 @@ exec_map = 0; for(i=0; i < 128; dev_irq[i++] = 0); sim_brk_types = SWMASK('E') | SWMASK('W') | SWMASK('R'); sim_brk_dflt = SWMASK ('E'); -sim_clock_precalibrate_commands = pdp10_clock_precalibrate_commands; sim_rtcn_init_unit (&cpu_unit[0], cpu_unit[0].wait, TMR_RTC); sim_activate(&cpu_unit[0], 10000); +#if ITS +if (QITS) { + sim_rtcn_init_unit (&cpu_unit[1], cpu_unit[1].wait, TMR_RTC); +} +#endif #if MPX_DEV mpx_enable = 0; #endif @@ -6139,6 +8832,7 @@ t_bool build_dev_tab (void) DEVICE *dptr; DIB *dibp; uint32 i, j, d; +int rh20 = 0540; /* Set trap offset based on MAOFF flag */ maoff = (cpu_unit[0].flags & UNIT_MAOFF)? 0100 : 0; @@ -6180,6 +8874,12 @@ dev_tab[0] = &dev_apr; dev_tab[1] = &dev_pi; #if KI | KL dev_tab[2] = &dev_pag; +#if KL +dev_tab[3] = &dev_cca; +dev_tab[4] = &dev_tim; +dev_irqv[4] = &tim_irq; +dev_tab[5] = &dev_mtr; +#endif #endif #if BBN if (QBBN) @@ -6215,6 +8915,10 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { d = dibp->dev_num; if (d & RH10_DEV) /* Skip RH10 devices */ continue; + if (d & RH20_DEV) { /* RH20, grab next device */ + d = rh20; + rh20 += 4; + } if (dev_tab[(d >> 2) + j] != &null_dev) { /* already filled? */ sim_printf ("%s device number conflict at %02o\n", @@ -6330,7 +9034,10 @@ for (k = 0; k < lnt; k++) { /* print specified */ #else fprintf (st, "%06o ", h->flags); #endif - if ((h->pc & HIST_PC2) == 0) { + if ((h->pc & HIST_PCE) != 0) { + sim_eval = h->ir; + fprint_val (st, sim_eval, 8, 36, PV_RZRO); + } else if ((h->pc & HIST_PC2) == 0) { sim_eval = h->ir; fprint_val (st, sim_eval, 8, 36, PV_RZRO); fputs (" ", st); diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 13c453c..500e413 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -46,6 +46,14 @@ #define KI 0 #endif +#ifndef KL +#define KL 0 +#endif + +#if KL +#define KLA 1 +#endif + #ifndef KLA #define KLA 0 #endif @@ -54,10 +62,6 @@ #define KLB 0 #endif -#ifndef KL /* Either KL10A or KL10B */ -#define KL (KLA+KLB) -#endif - #if (PDP6 + KA + KI + KL) != 1 #error "Please define only one type of CPU" #endif @@ -81,6 +85,11 @@ #define WAITS KA #endif +/* Support for ITS on KL */ +#ifndef KL_ITS +#define KL_ITS KL +#endif + #ifndef PDP6_DEV /* Include PDP6 devices */ #define PDP6_DEV PDP6|WAITS #endif @@ -162,6 +171,8 @@ extern DEBTAB crd_debug[]; #define EMASK 00777000000000LL #define MMASK 00000777777777LL #define BIT1 00200000000000LL +#define BIT2 00100000000000LL +#define BIT3 00040000000000LL #define BIT7 00002000000000LL #define BIT8 00001000000000LL #define BIT9 00000400000000LL @@ -181,6 +192,7 @@ extern DEBTAB crd_debug[]; #define FPRBIT1 00000000000200000000000LL #define CM(x) (FMASK ^ (x)) +#define CCM(x) ((CMASK ^ (x)) & CMASK) #define INST_V_OP 27 /* opcode */ #define INST_M_OP 0777 @@ -205,6 +217,7 @@ extern DEBTAB crd_debug[]; #define LRZ(x) (((x) >> 18) & RMASK) #define JRST1 (((uint64)OP_JRST << 27) + 1) + #if PDP6 #define NODIV 000000 #define FLTUND 000000 @@ -290,6 +303,10 @@ extern DEBTAB crd_debug[]; #define DEF_SERIAL 514 /* Default DEC test machine */ #endif +#if KL +#define DEF_SERIAL 1025 /* Default DEC test machine */ +#endif + #if BBN #define BBN_PAGE 0000017777777LL #define BBN_TRPPG 0000017000000LL @@ -322,6 +339,9 @@ extern DEBTAB crd_debug[]; #define UNIT_V_MPX (UNIT_V_WAITS + 1) #define UNIT_M_MPX (1 << UNIT_V_MPX) #define UNIT_MPX (UNIT_M_MPX) /* MPX Device for ITS */ +#define DEV_V_RH (DEV_V_UF + 8) /* Type RH20 */ +#define TYPE_RH10 (0 << DEV_V_RH) +#define TYPE_RH20 (1 << DEV_V_RH) #if MPX_DEV @@ -338,8 +358,18 @@ extern void set_pi_hold(); extern UNIT cpu_unit[]; extern UNIT ten11_unit[]; extern UNIT auxcpu_unit[]; -extern DEVICE cpu_dev; +#if KL +/* DTE memory access functions, n = DTE# */ +extern int Mem_examine_word(int n, int wrd, uint64 *data); +extern int Mem_deposit_word(int n, int wrd, uint64 *data); +extern int Mem_read_byte(int n, uint16 *data); +extern int Mem_write_byte(int n, uint16 *data); +extern DEVICE dte_dev; +extern DEVICE tty_dev; +#else extern DEVICE cty_dev; +#endif +extern DEVICE cpu_dev; extern DEVICE mt_dev; extern DEVICE dpa_dev; extern DEVICE dpb_dev; @@ -396,6 +426,7 @@ struct pdp_dib { }; #define RH10_DEV 01000 +#define RH20_DEV 02000 struct rh_dev { uint32 dev_num; DEVICE *dev; @@ -446,9 +477,15 @@ int auxcpu_write (int addr, t_uint64); /* I/O system parameters */ #define NUM_DEVS_LP 1 +#if KL +#define NUM_DEVS_PT 0 +#define NUM_DEVS_CR 0 +#define NUM_DEVS_CP 0 +#else #define NUM_DEVS_PT 1 #define NUM_DEVS_CR 1 #define NUM_DEVS_CP 1 +#endif #define NUM_DEVS_DPY USE_DISPLAY #define NUM_DEVS_WCNSLS USE_DISPLAY #if PDP6_DEV @@ -461,10 +498,20 @@ int auxcpu_write (int addr, t_uint64); #if !PDP6 #define NUM_DEVS_DC 1 #define NUM_DEVS_MT 1 +#if KL +#define NUM_DEVS_RC 0 +#define NUM_DEVS_DT 0 +#define NUM_DEVS_DK 0 +#define NUM_DEVS_DP 0 +#define NUM_DEVS_TTY 1 +#define NUM_LINES_TTY 16 +#else #define NUM_DEVS_RC 1 #define NUM_DEVS_DT 1 #define NUM_DEVS_DK 1 #define NUM_DEVS_DP 2 +#define NUM_DEVS_TTY 0 +#endif #define NUM_DEVS_RP 4 #define NUM_DEVS_RS 1 #define NUM_DEVS_TU 1 diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index 29ec6b4..37eb5e9 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -89,6 +89,14 @@ #define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */ #define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */ +/* RH20 CONO Flags */ +#define RH20_DELETE_SCR 0000000000100LL /* Clear SCR */ +#define RH20_RCLP 0000000000200LL /* Reset command list */ +#define RH20_MASS_EN 0000000000400LL /* Mass bus enable */ +#define RH20_XFER_CLR 0000000001000LL /* Clear XFER error */ +#define RH20_CLR_MBC 0000000002000LL /* Clear MBC */ +#define RH20_CLR_RAE 0000000004000LL /* Clear RAE error */ + /* DATAO/DATAI */ #define CR_REG 0770000000000LL /* Register number */ #define LOAD_REG 0004000000000LL /* Load register */ @@ -292,7 +300,6 @@ int rp_imode[NUM_DEVS_RP]; int rp_drive[NUM_DEVS_RP]; int rp_rae[NUM_DEVS_RP]; int rp_attn[NUM_DEVS_RP]; -extern int readin_flag; t_stat rp_devio(uint32 dev, uint64 *data); int rp_devirq(uint32 dev, int addr); @@ -410,7 +417,6 @@ REG rpa_reg[] = { {ORDATA(REG, rp_reg[0], 6), REG_RO}, {ORDATA(RAE, rp_rae[0], 8), REG_RO}, {ORDATA(ATTN, rp_attn[0], 8), REG_RO}, - {FLDATA(READIN, readin_flag, 0), REG_HRO}, {ORDATA(STATUS, rp_df10[0].status, 18), REG_RO}, {ORDATA(CIA, rp_df10[0].cia, 18)}, {ORDATA(CCW, rp_df10[0].ccw, 18)}, @@ -1259,6 +1265,21 @@ rp_boot(int32 unit_num, DEVICE * rptr) uint64 word; int wc; +#if KL + int sect; + /* KL does not support readin, so fake it by reading in sectors 4 to 7 */ + /* Possible in future fine boot loader in FE file system */ + addr = (MEMSIZE - 512) & RMASK; + for (sect = 4; sect <= 7; sect++) { + (void)sim_fseek(uptr->fileref, (sect * RP_NUMWD) * sizeof(uint64), SEEK_SET); + (void)sim_fread (&rp_buf[0][0], sizeof(uint64), RP_NUMWD, uptr->fileref); + ptr = 0; + for(wc = RP_NUMWD; wc > 0; wc--) { + M[addr++] = rp_buf[0][ptr++]; + } + } + PC = (MEMSIZE - 512) & RMASK; +#else df = &rp_df10[ctlr]; dptr = rp_devs[ctlr]; (void)sim_fseek(uptr->fileref, 0, SEEK_SET); @@ -1283,6 +1304,7 @@ rp_boot(int32 unit_num, DEVICE * rptr) rp_drive[ctlr] = uptr - dptr->units; df->status |= CCW_COMP_1|PI_ENABLE; PC = word & RMASK; +#endif return SCPE_OK; } diff --git a/PDP10/kx10_rs.c b/PDP10/kx10_rs.c index d550c27..81fae05 100644 --- a/PDP10/kx10_rs.c +++ b/PDP10/kx10_rs.c @@ -237,7 +237,6 @@ int rs_imode[NUM_DEVS_RS]; int rs_drive[NUM_DEVS_RS]; int rs_rae[NUM_DEVS_RS]; int rs_attn[NUM_DEVS_RS]; -extern int readin_flag; t_stat rs_devio(uint32 dev, uint64 *data); int rs_devirq(uint32 dev, int addr); @@ -295,7 +294,6 @@ REG rsa_reg[] = { {ORDATA(REG, rs_reg[0], 6), REG_RO}, {ORDATA(RAE, rs_rae[0], 8), REG_RO}, {ORDATA(ATTN, rs_attn[0], 8), REG_RO}, - {FLDATA(READIN, readin_flag, 0), REG_HRO}, {ORDATA(STATUS, rs_df10[0].status, 18), REG_RO}, {ORDATA(CIA, rs_df10[0].cia, 18)}, {ORDATA(CCW, rs_df10[0].ccw, 18)}, diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index d9e0faf..6febd27 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -68,6 +68,9 @@ DEVICE *sim_devices[] = { #if PDP6 | KA | KI &cty_dev, #endif +#if KL + &dte_dev, +#endif #if (NUM_DEVS_PT > 0) &ptp_dev, &ptr_dev, @@ -141,6 +144,9 @@ DEVICE *sim_devices[] = { #if (NUM_DEVS_DC > 0) &dc_dev, #endif +#if (NUM_DEVS_TTY > 0) + &tty_dev, +#endif #if (NUM_DEVS_DCS > 0) &dcs_dev, #endif @@ -550,7 +556,6 @@ t_stat load_sav (FILE *fileref) wc = (int32)(data >> 18); pa = (uint32) (data & RMASK); if (wc == (OP_JRST << 9)) { - printf("Start addr=%06o\n", pa); PC = pa; return SCPE_OK; } @@ -604,8 +609,10 @@ uint32 ma; ndir = entvec = 0; /* no dir, entvec */ cont = 1; do { - wc = sim_fread (&data, sizeof (uint64), 1, fileref);/* read blk hdr */ - if (wc == 0) /* error? */ + + wc = get_word(fileref, &data); +// wc = sim_fread (&data, sizeof (uint64), 1, fileref);/* read blk hdr */ + if (wc != 0) /* error? */ return SCPE_FMT; bsz = (int32) ((data & RMASK) - 1); /* get count */ if (bsz < 0) /* zero? */ @@ -616,9 +623,14 @@ do { case EXE_DIR: /* directory */ if (ndir != 0) /* got one */ return SCPE_FMT; - ndir = sim_fread (dirbuf, sizeof (uint64), bsz, fileref); - if (ndir < bsz) /* error */ - return SCPE_FMT; + for (i = 0; i < bsz; i++) { + if (get_word(fileref, &dirbuf[i])) + return SCPE_FMT; + } + ndir = bsz; +// ndir = sim_fread (dirbuf, sizeof (uint64), bsz, fileref); + // if (ndir < bsz) /* error */ + // return SCPE_FMT; break; case EXE_PDV: /* optional */ @@ -628,9 +640,14 @@ do { case EXE_VEC: /* entry vec */ if (bsz != 2) /* must be 2 wds */ return SCPE_FMT; - entvec = sim_fread (entbuf, sizeof (uint64), bsz, fileref); - if (entvec < 2) /* error? */ - return SCPE_FMT; + for (i = 0; i < bsz; i++) { + if (get_word(fileref, &entbuf[i])) + return SCPE_FMT; + } +// entvec = sim_fread (entbuf, sizeof (uint64), bsz, fileref); + // if (entvec < 2) /* error? */ + // return SCPE_FMT; + entvec = bsz; cont = 0; /* stop */ break; @@ -651,10 +668,11 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */ rpt = ((int32) ((dirbuf[i + 1] >> 27) + 1)) & 0777; /* repeat count */ for (j = 0; j < rpt; j++, mpage++) { /* loop thru rpts */ if (fpage) { /* file pages? */ - (void)sim_fseek (fileref, (fpage << PAG_V_PN) * sizeof (uint64), SEEK_SET); - wc = sim_fread (pagbuf, sizeof (uint64), PAG_SIZE, fileref); - if (wc < PAG_SIZE) - return SCPE_FMT; + (void)sim_fseek (fileref, (fpage << PAG_V_PN) * 5, SEEK_SET); + for (k = 0; k < PAG_SIZE; k++) { + if (get_word(fileref, &pagbuf[k])) + return SCPE_FMT; + } fpage++; } ma = mpage << PAG_V_PN; /* mem addr */ @@ -764,8 +782,13 @@ static const char *opcode[] = { "MUUO60", "MUUO61", "MUUO62", "MUUO63", "MUUO64", "MUUO65", "MUUO66", "MUUO67", "MUUO70", "MUUO71", "MUUO72", "MUUO73", "MUUO74", "MUUO75", "MUUO76", "MUUO77", -"UJEN", "MUUO101", "MUUO102", "JSYS", "MUUO104", "MUUO105", "MUUO106", +#if KL +"UJEN", "GFAD", "GFSB", "JSYS", "ADJSP", "GFMP", "GFDV ", "DFAD", "DFSB", "DFMP", "DFDV", "DADD", "DSUB", "DMUL", "DDIV", +#else +"UJEN", "MUUO101", "MUUO102", "JSYS", "MUUO104", "MUUO105", "MUUO106", +"DFAD", "DFSB", "DFMP", "DFDV", "MUUO114", "MUUO115", "MUUO116", "MUUO117", +#endif "DMOVE", "DMOVN", "FIX", "EXTEND", "DMOVEM", "DMOVNM", "FIXR", "FLTR", "UFA", "DFN", "FSC", "ADJBP", "ILDB", "LDB", "IDPB", "DPB", "FAD", "FADL", "FADM", "FADB", "FADR", "FADRL", "FADRM", "FADRB", diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index ae7d1de..2870106 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -224,7 +224,6 @@ int tu_rae[NUM_DEVS_TU]; int tu_attn[NUM_DEVS_TU]; uint16 tu_frame[NUM_DEVS_TU]; uint16 tu_tcr[NUM_DEVS_TU]; -extern int readin_flag; static uint64 tu_boot_buffer; t_stat tu_devio(uint32 dev, uint64 *data); @@ -280,7 +279,6 @@ REG tua_reg[] = { {ORDATA(REG, tu_reg[0], 6), REG_RO}, {ORDATA(RAE, tu_rae[0], 8), REG_RO}, {ORDATA(ATTN, tu_attn[0], 8), REG_RO}, - {FLDATA(READIN, readin_flag, 0), REG_HRO}, {ORDATA(STATUS, tu_df10[0].status, 18), REG_RO}, {ORDATA(CIA, tu_df10[0].cia, 18)}, {ORDATA(CCW, tu_df10[0].ccw, 18)}, diff --git a/makefile b/makefile index dfd1e30..90f0364 100644 --- a/makefile +++ b/makefile @@ -111,7 +111,7 @@ endif ifneq (,$(or $(findstring pdp6,$(MAKECMDGOALS)),$(findstring pdp10-ka,$(MAKECMDGOALS)),$(findstring pdp10-ki,$(MAKECMDGOALS)))) VIDEO_USEFUL = true endif -ifneq (,$(or $(findstring pdp10-ka,$(MAKECMDGOALS)),$(findstring pdp10-ki,$(MAKECMDGOALS)))) +ifneq (,$(or $(findstring pdp10-ka,$(MAKECMDGOALS)),$(findstring pdp10-ki,$(MAKECMDGOALS),$(findstring pdp10-kl,$MAKECMDGOALS)))) NETWORK_USEFUL = true endif # building the pdp11, pdp10, or any vax simulator could use networking support @@ -1265,6 +1265,13 @@ KI10 += ${KA10D}/ka10_lights.c KI10_LDFLAGS = -lusb-1.0 endif +KL10D = PDP10 +KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \ + ${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rp.c \ + ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c ${KL10D}/kx10_imp.c \ + ${KL10D}/kl10_fe.c +KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT} + PDP1D = PDP1 ifneq (,$(DISPLAY_OPT)) PDP1_DISPLAY_OPT = -DDISPLAY_TYPE=DIS_TYPE30 -DPIX_SCALE=RES_HALF @@ -1885,7 +1892,7 @@ ATT3B2_OPT = -I ${ATT3B2D} -DUSE_INT64 -DUSE_ADDR64 # # Build everything (not the unsupported/incomplete or experimental simulators) # -ALL = b5500 i701 i704 i7010 i7070 i7080 i7090 pdp10-ka pdp10-ki ibm360 ibm360_32 icl1900 pdp6 sel32 +ALL = b5500 i701 i704 i7010 i7070 i7080 i7090 pdp10-ka pdp10-ki pdp10-kl ibm360 ibm360_32 icl1900 pdp6 sel32 all : ${ALL} @@ -2012,6 +2019,15 @@ ifneq (,$(call find_test,${PDP10D},ki10)) $@ $(call find_test,${PDP10D},ki10) $(TEST_ARG) endif +pdp10-kl : ${BIN}pdp10-kl${EXE} + +${BIN}pdp10-kl${EXE} : ${KL10} ${SIM} + ${MKDIRBIN} + ${CC} ${KL10} ${SIM} ${KL10_OPT} $(CC_OUTSPEC) ${LDFLAGS} ${KL10_LDFLAGS} +ifneq (,$(call find_test,${PDP10D},kl10)) + $@ $(call find_test,${PDP10D},kl10) $(TEST_ARG) +endif + pdp11 : ${BIN}BuildROMs${EXE} ${BIN}pdp11${EXE} ${BIN}pdp11${EXE} : ${PDP11} ${SIM} From 257c5b7a3203b7b358a4d45fc945c8989c372b78 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 4 Sep 2019 22:43:02 -0400 Subject: [PATCH 02/98] KA10: Updated so ITS can be selected. --- PDP10/kx10_cpu.c | 236 +++++++++++++++++++++++++++------------------- PDP10/kx10_defs.h | 10 ++ 2 files changed, 150 insertions(+), 96 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 2ede924..2903606 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -187,6 +187,11 @@ uint32 brk_addr; /* Address break */ int brk_flags; /* Break flags */ int t20_page; /* Tops 20 paging selected */ int ptr_flg; /* Access to pointer value */ +#if KLB +int cur_sect; /* Current section */ +int prv_sect; /* Previous section */ +int pc_sect; /* Program counter section */ +#endif #else int small_user; /* Small user flag */ #endif @@ -475,13 +480,23 @@ MTAB cpu_mod[] = { #if KI|KL { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SERIAL", "SERIAL", &cpu_set_serial, &cpu_show_serial, NULL, "CPU Serial Number" }, +#if KLB + { UNIT_M_PAGE, 0, "KL10A", "KL10A", NULL, NULL, NULL, + "Base KL10"}, + { UNIT_M_PAGE, UNIT_KL10B, "KL10B", "KL10B", NULL, NULL, NULL, + "Extended addressing support for KL10"}, +#endif +#if KL_ITS + { UNIT_M_PAGE, UNIT_ITSPAGE, "ITS", "ITS", NULL, NULL, NULL, + "Paging hardware for ITS"}, +#endif #endif #if KA { UNIT_M_PAGE, 0, "ONESEG", "ONESEG", NULL, NULL, NULL, "One Relocation Register"}, { UNIT_M_PAGE, UNIT_TWOSEG, "TWOSEG", "TWOSEG", NULL, NULL, NULL, "Two Relocation Registers"}, -#if ITS | KL_ITS +#if ITS { UNIT_M_PAGE, UNIT_ITSPAGE, "ITS", "ITS", NULL, NULL, NULL, "Paging hardware for ITS"}, #endif @@ -856,6 +871,11 @@ int opflags[] = { #else #define QWAITS 0 #endif +#if KLB +#define QKLB (cpu_unit[0].flags & UNIT_KL10B) +#else +#define QKLB 0 +#endif #if ITS /* @@ -1200,7 +1220,7 @@ t_stat dev_pag(uint32 dev, uint64 *data) { u_tlb[page+i] = 0; } break; - } + } res = *data; if (res & SMASK) { fm_sel = (uint8)(res >> 23) & 0160; @@ -1246,8 +1266,7 @@ t_stat dev_cca(uint32 dev, uint64 *data) { check_apr_irq(); return SCPE_OK; } - - + /* * Check if the last operation caused a APR IRQ to be generated. */ @@ -1312,7 +1331,7 @@ t_stat dev_apr(uint32 dev, uint64 *data) { case DATAI: if (dev & 040) { /* APRID */ - AR = SMASK| (500LL << 18); + AR = SMASK| (500LL << 18); /* Bit 0 for TOPS-20 paging */ /* Bit 1 for extended addressing */ /* Bit 2 Exotic microcode */ @@ -1330,7 +1349,7 @@ t_stat dev_apr(uint32 dev, uint64 *data) { (void)Mem_write(0, 0); sim_debug(DEBUG_DATAIO, &cpu_dev, "APRID %012llo\n", MB); break; - } + } *data = ((uint64)brk_flags) << 23; *data |= (uint64)brk_addr; sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI APR %012llo\n", *data); @@ -1373,7 +1392,7 @@ t_stat dev_mtr(uint32 dev, uint64 *data) { case DATAO: if (dev & 040) { sim_debug(DEBUG_DATAIO, &cpu_dev, "BLKO MTR %012llo\n", *data); - } else { + } else { sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAO MTR %012llo\n", *data); } break; @@ -1437,7 +1456,7 @@ t_stat dev_tim(uint32 dev, uint64 *data) { if (dev & 040) { /* Write performance */ sim_debug(DEBUG_DATAIO, &cpu_dev, "BLKO TIM %012llo\n", *data); - } else { + } else { sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAO TIM %012llo\n", *data); } return SCPE_OK; @@ -1459,10 +1478,10 @@ t_stat dev_tim(uint32 dev, uint64 *data) { /* If we have already passed time, schedule to overflow */ if ((tim_val & 07777) >= tim_per) { us = (float)((010000 - (tim_val & 07777)) * 10); - tim_val &= 0077777; + tim_val &= 0077777; } else { us = (float)((tim_per - (tim_val & 07777)) * 10); - tim_val |= 0100000; + tim_val |= 0100000; } (void)sim_activate_after_d(uptr, us); } @@ -1816,7 +1835,7 @@ sim_debug(DEBUG_DATAIO, &cpu_dev, "Rl=%06o Pl=%06o, Rh=%06o, Ph=%06o\n", Rl, Pl, #if KL int -load_tlb(int uf, int page, int upmp, int wr, int trap) +load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) { uint64 data; @@ -1825,7 +1844,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap) int dbr; int pg; - dbr = (uf)? + dbr = (uf)? ((page & 0400)?FM[(06<<4)|4]:FM[(06<<4)|3]) : ((page & 0400)?FM[(06<<4)|2]:FM[(06<<4)|1]); pg = (page & 0377) >> 2; /* 2 1024 word page entries */ @@ -1869,13 +1888,21 @@ load_tlb(int uf, int page, int upmp, int wr, int trap) int index; int match = 0; int pg; + int base = 0440; /* Get segment pointer */ /* And save it */ +#if KLB + if (QKLB) { + base = 0540; + if (!flag) + base += (cur_sect & 037); + } +#endif if (uf) - data = M[ub_ptr + 0440]; + data = M[ub_ptr + base]; else - data = M[eb_ptr + 0440]; + data = M[eb_ptr + base]; fprintf(stderr, "Map %012llo %012llo %012llo\n\r", data, spt, cst); /* Find correct page table */ do { @@ -2035,6 +2062,10 @@ fprintf(stderr, "YMap %012llo\n\r", data); data |= 0040000; /* Set M bit (S) */ if (acc_bits & PG_CAC) data |= 0020000; +#if KLB + if (QKLB) + data |= (((flag) ? 0: cur_sect) & 037) << 18; +#endif /* And save it */ if (uf) u_tlb[page] = data; @@ -2098,7 +2129,7 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch return 0; } } - + /* If this is modify instruction use write access */ wr |= modify; @@ -2113,7 +2144,7 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch else if (xct_flag != 0 && !uf && !fetch) { fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); if (((xct_flag & 8) != 0 && cur_context) || - ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || + ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || ((xct_flag & 1) != 0 && !cur_context && BYF5 )) { uf = (FLAGS & USERIO) != 0; @@ -2135,9 +2166,13 @@ fprintf(stderr, "%o %o\n\r", uf, pub); else data = e_tlb[page]; +#if KLB + if (QKLB && t20_page && ((data >> 18) & 037) != ((flag) ? 0 : cur_sect)) + data = 0; +#endif /* If not valid, go refill it */ if (data == 0) { - data = load_tlb(uf, page, upmp, wr, 1); + data = load_tlb(uf, page, upmp, wr, 1, flag); if (data == 0 && page_fault) return 0; } @@ -2204,10 +2239,10 @@ void set_reg(int reg, uint64 value) { * Return of 0 if successful, 1 if there was an error. */ int Mem_read_nopage() { + sim_interval--; if (AB < 020) { MB = FM[fm_sel|AB]; } else { - sim_interval--; if (AB >= (int)MEMSIZE) { irq_flags |= 02000; return 1; @@ -2223,11 +2258,10 @@ int Mem_read_nopage() { * Return of 0 if successful, 1 if there was an error. */ int Mem_write_nopage() { - + sim_interval--; if (AB < 020) { FM[fm_sel|AB] = MB; } else { - sim_interval--; if (AB >= (int)MEMSIZE) { irq_flags |= 02000; return 1; @@ -2240,11 +2274,12 @@ int Mem_write_nopage() { int Mem_read(int flag, int cur_context, int fetch) { int addr; + sim_interval--; if (AB < 020) { if (xct_flag != 0 && !fetch && (FLAGS & USER) == 0) { fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgr ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context) || - ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || + ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || ((xct_flag & 1) != 0 && !cur_context && BYF5)) { MB = FM[prev_ctx|AB]; @@ -2255,7 +2290,6 @@ fprintf(stderr, "\n\r"); } MB = get_reg(AB); } else { - sim_interval--; if (!page_lookup(AB, flag, &addr, 0, cur_context, fetch)) return 1; if (addr >= (int)MEMSIZE) { @@ -2272,11 +2306,12 @@ fprintf(stderr, "\n\r"); int Mem_write(int flag, int cur_context) { int addr; + sim_interval--; if (AB < 020) { if (xct_flag != 0 && (FLAGS & USER) == 0) { fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgw ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context) || - ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || + ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || ((xct_flag & 1) != 0 && !cur_context && BYF5)) { fprintf(stderr, "prev \n\r"); @@ -2287,7 +2322,6 @@ fprintf(stderr, "\n\r"); } set_reg(AB, MB); } else { - sim_interval--; if (!page_lookup(AB, flag, &addr, 1, cur_context, 0)) return 1; if (addr >= (int)MEMSIZE) { @@ -2328,8 +2362,8 @@ int exec_page_lookup(int addr, int wr, int *loc) data = e_tlb[page]; /* If not valid, go refill it */ - if (data == 0) { - data = load_tlb(0, page, upmp, wr, 0); + if (data == 0 || (data & LMASK) != 0) { + data = load_tlb(0, page, upmp, wr, 0, 1); if (data == 0) return 1; } @@ -2343,7 +2377,7 @@ int Mem_examine_word(int n, int wrd, uint64 *data) { if (addr >= MEMSIZE) return 1; - if (M[addr] == 0 || wrd > M[addr]) + if (M[addr] == 0 || wrd > M[addr]) return 1; addr = (M[addr+1] + wrd) & RMASK; if (exec_page_lookup(addr, 0, &addr)) @@ -2359,7 +2393,7 @@ int Mem_deposit_word(int n, int wrd, uint64 *data) { if (addr >= MEMSIZE) return 1; - if (M[addr] == 0 || wrd > M[addr]) + if (M[addr] == 0 || wrd > M[addr]) return 1; addr = (M[addr+1] + wrd) & RMASK; if (exec_page_lookup(addr, 1, &addr)) @@ -2391,7 +2425,7 @@ int Mem_read_byte(int n, uint16 *data) { if (p & 0400) { p = np = (36 + (0777 ^ s) + 1) & 0777; val = (val & LMASK) | ((val + 1) & RMASK); - } else + } else np = p; np &= 077; val &= PMASK; @@ -2492,6 +2526,7 @@ load_tlb(int uf, int page) } } /* Map the page */ + sim_interval--; if (base) { data = e_tlb[page]; if (data == 0) { @@ -2641,10 +2676,10 @@ void set_reg(int reg, uint64 value) { * Return of 0 if successful, 1 if there was an error. */ int Mem_read_nopage() { + sim_interval--; if (AB < 020) { MB = FM[AB]; } else { - sim_interval--; if (AB >= (int)MEMSIZE) { nxm_flag = 1; return 1; @@ -2660,11 +2695,10 @@ int Mem_read_nopage() { * Return of 0 if successful, 1 if there was an error. */ int Mem_write_nopage() { - + sim_interval--; if (AB < 020) { FM[AB] = MB; } else { - sim_interval--; if (AB >= (int)MEMSIZE) { nxm_flag = 1; return 1; @@ -2677,6 +2711,7 @@ int Mem_write_nopage() { int Mem_read(int flag, int cur_context, int fetch) { int addr; + sim_interval--; if (AB < 020) { if (FLAGS & USER) { MB = get_reg(AB); @@ -2696,7 +2731,6 @@ int Mem_read(int flag, int cur_context, int fetch) { MB = get_reg(AB); } else { read: - sim_interval--; if (!page_lookup(AB, flag, &addr, 0, cur_context, fetch)) return 1; if (addr >= (int)MEMSIZE) { @@ -2713,6 +2747,7 @@ read: int Mem_write(int flag, int cur_context) { int addr; + sim_interval--; if (AB < 020) { if (FLAGS & USER) { set_reg(AB, MB); @@ -2735,7 +2770,6 @@ int Mem_write(int flag, int cur_context) { set_reg(AB, MB); } else { write: - sim_interval--; if (!page_lookup(AB, flag, &addr, 1, cur_context, 0)) return 1; if (addr >= (int)MEMSIZE) { @@ -2773,6 +2807,7 @@ int its_load_tlb(uint32 reg, int page, uint32 *tlb) { fault_data |= 0400; return 1; } + sim_interval--; data = M[entry]; if (page & 1) { data &= ~036000LL; @@ -2928,6 +2963,7 @@ fault: int Mem_read_its(int flag, int cur_context, int fetch) { int addr; + sim_interval--; if (AB < 020) { if ((xct_flag & 1) != 0 && !cur_context && (FLAGS & USER) == 0) { MB = M[(ac_stack & 01777777) + AB]; @@ -2935,7 +2971,6 @@ int Mem_read_its(int flag, int cur_context, int fetch) { } MB = get_reg(AB); } else { - sim_interval--; if (!page_lookup_its(AB, flag, &addr, 0, cur_context, fetch)) return 1; #if NUM_DEVS_TEN11 > 0 @@ -2975,6 +3010,7 @@ int Mem_read_its(int flag, int cur_context, int fetch) { int Mem_write_its(int flag, int cur_context) { int addr; + sim_interval--; if (AB < 020) { if ((xct_flag & 2) != 0 && !cur_context && (FLAGS & USER) == 0) { M[(ac_stack & 01777777) + AB] = MB; @@ -2982,7 +3018,6 @@ int Mem_write_its(int flag, int cur_context) { } set_reg(AB, MB); } else { - sim_interval--; if (!page_lookup_its(AB, flag, &addr, 1, cur_context, 0)) return 1; #if NUM_DEVS_TEN11 > 0 @@ -3120,6 +3155,7 @@ lookup: goto fault_bbn; } base = user_base_reg; + sim_interval--; tlb_data = u_tlb[page]; } else { /* 000 - 077 resident map */ @@ -3134,6 +3170,7 @@ lookup: base = mon_base_reg; else base = 03000; + sim_interval--; tlb_data = e_tlb[page]; } if (tlb_data != 0) { @@ -3156,6 +3193,7 @@ access: /* Map the page */ match = 0; while (!match) { + sim_interval--; data = M[base + map]; switch ((data >> 34) & 03) { @@ -3220,6 +3258,7 @@ access: goto fault_bbn; } /* Update CST */ + sim_interval--; data = M[04000 + (tlb_data & 03777)]; if ((data & 00700000000000LL) == 0) { fault_data = 0100000 >> ((data >> 31) & 03); @@ -3276,12 +3315,12 @@ fault_bbn: int Mem_read_bbn(int flag, int cur_context, int fetch) { int addr; + sim_interval--; /* If not doing any special access, just access register */ if (AB < 020 && ((xct_flag == 0 || fetch || cur_context || (FLAGS & USER) != 0))) { MB = get_reg(AB); return 0; } - sim_interval--; if (!page_lookup_bbn(AB, flag, &addr, 0, cur_context, fetch)) return 1; if (addr < 020) { @@ -3306,12 +3345,12 @@ int Mem_read_bbn(int flag, int cur_context, int fetch) { int Mem_write_bbn(int flag, int cur_context) { int addr; + sim_interval--; /* If not doing any special access, just access register */ if (AB < 020 && ((xct_flag == 0 || cur_context || (FLAGS & USER) != 0))) { set_reg(AB, MB); return 0; } - sim_interval--; if (!page_lookup_bbn(AB, flag, &addr, 1, cur_context, 0)) return 1; if (addr < 020) { @@ -3370,11 +3409,11 @@ int page_lookup_waits(int addr, int flag, int *loc, int wr, int cur_context, int int Mem_read_waits(int flag, int cur_context, int fetch) { int addr; + sim_interval--; if (AB < 020 && ((xct_flag == 0 || fetch || cur_context || (FLAGS & USER) != 0))) { MB = get_reg(AB); return 0; } - sim_interval--; if (!page_lookup_waits(AB, flag, &addr, 0, cur_context, fetch)) return 1; if (addr >= (int)MEMSIZE) { @@ -3396,13 +3435,12 @@ int Mem_read_waits(int flag, int cur_context, int fetch) { int Mem_write_waits(int flag, int cur_context) { int addr; - + sim_interval--; /* If not doing any special access, just access register */ if (AB < 020 && ((xct_flag == 0 || cur_context || (FLAGS & USER) != 0))) { set_reg(AB, MB); return 0; } - sim_interval--; if (!page_lookup_waits(AB, flag, &addr, 1, cur_context, 0)) return 1; if (addr >= (int)MEMSIZE) { @@ -3440,10 +3478,10 @@ int page_lookup_ka(int addr, int flag, int *loc, int wr, int cur_context, int fe int Mem_read_ka(int flag, int cur_context, int fetch) { int addr; + sim_interval--; if (AB < 020) { MB = get_reg(AB); } else { - sim_interval--; if (!page_lookup_ka(AB, flag, &addr, 0, cur_context, fetch)) return 1; if (addr >= (int)MEMSIZE) { @@ -3466,10 +3504,10 @@ int Mem_read_ka(int flag, int cur_context, int fetch) { int Mem_write_ka(int flag, int cur_context) { int addr; + sim_interval--; if (AB < 020) { set_reg(AB, MB); } else { - sim_interval--; if (!page_lookup_ka(AB, flag, &addr, 1, cur_context, 0)) return 1; if (addr >= (int)MEMSIZE) { @@ -3606,10 +3644,10 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch int Mem_read(int flag, int cur_context, int fetch) { int addr; + sim_interval--; if (AB < 020) { MB = get_reg(AB); } else { - sim_interval--; if (!page_lookup(AB, flag, &addr, 0, cur_context, fetch)) return 1; if (addr >= (int)MEMSIZE) { @@ -3632,10 +3670,10 @@ int Mem_read(int flag, int cur_context, int fetch) { int Mem_write(int flag, int cur_context) { int addr; + sim_interval--; if (AB < 020) { set_reg(AB, MB); } else { - sim_interval--; if (!page_lookup(AB, flag, &addr, 1, cur_context, 0)) return 1; if (addr >= (int)MEMSIZE) { @@ -3760,6 +3798,12 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ #endif #endif AB = PC; +#if KLB + if (QKLB) + cur_sect = pc_sect; + else + cur_sect = 0; +#endif uuo_cycle = 0; f_pc_inh = 0; } @@ -3826,9 +3870,9 @@ no_fetch: AB = MB & RMASK; if (MB & 017000000) { #if 0 - if (xct_flag != 0 && (FLAGS & USER) == 0 && (xct_flag & 8) != 0) + if (xct_flag != 0 && (FLAGS & USER) == 0 && (xct_flag & 8) != 0) AR = FM[prev_ctx|((MB >> 18) & 017)]; - else + else AR = get_reg((MB >> 18) & 017); AR = MB = (AR + AB) & FMASK; #else @@ -4003,7 +4047,7 @@ muuo: #if KI | KL case 0100: /* UJEN */ - case 0101: case 0102: case 0103: + case 0101: case 0102: case 0103: case 0104: /* JSYS */ case 0106: case 0107: @@ -4041,10 +4085,10 @@ unasign: if (FLAGS & USER) AB |= 4; Mem_read_nopage(); - + FLAGS = (MB >> 23) & 017777; /* If transistioning from user to executive adjust flags */ - if ((FLAGS & USER) != 0 && (AB & 4) != 0) + if ((FLAGS & USER) != 0 && (AB & 4) != 0) FLAGS |= USERIO; if ((FLAGS & USER) == 0 && (AB & 2 || (FLAGS & OVR) != 0)) FLAGS |= PRV_PUB|OVR; @@ -4104,7 +4148,7 @@ unasign: } goto unasign; - case 0076: + case 0076: if (QITS && (FLAGS & USER) == 0) { /* Load store ITS pager info */ if ((AB + 8) > MEMSIZE) { @@ -4506,7 +4550,7 @@ dpnorm: /* Fix sign of result */ if (flag1) { AR = (AR ^ FPFMASK) + 1; - } + } #if KL else AR++; /* Round on KL */ @@ -4638,7 +4682,7 @@ dpnorm: BRX = CCM(BRX) + 1; /* Low */ /* High */ BR = (CM(BR) + ((BRX & SMASK) != 0)) & FMASK; - flag1 = 1; + flag1 = 1; /* Can only occur if 2**-70 */ if (BR & SMASK) FLAGS |= OVR|TRP1; @@ -4649,7 +4693,7 @@ dpnorm: ARX = CCM(ARX) + 1; /* Low */ /* High */ AR = (CM(AR) + ((ARX & SMASK) != 0)) & FMASK; - flag1 ^= 1; + flag1 ^= 1; /* Can only occur if 2**-70 */ if (AR & SMASK) FLAGS |= OVR|TRP1; @@ -4717,7 +4761,7 @@ dpnorm: BRX = CCM(BRX) + 1; /* Low */ /* High */ BR = (CM(BR) + ((BRX & SMASK) != 0)) & FMASK; - flag1 = 1; + flag1 = 1; /* Can only occur if 2**-70 */ if (BR & SMASK) { FLAGS |= OVR|TRP1; @@ -4740,7 +4784,7 @@ dpnorm: MB = CCM(MB) + ((MQ & SMASK) != 0); ARX = CCM(ARX) + ((MB & SMASK) != 0); AR = (CM(AR) + ((ARX & SMASK) != 0)) & FMASK; - flag1 ^= 1; + flag1 ^= 1; flag3 = 1; if (AR & SMASK) { FLAGS |= OVR|TRP1; @@ -5234,9 +5278,9 @@ dpnorm: goto ufa; } #endif - + /* UUO */ - case 0105: case 0106: case 0107: + case 0105: case 0106: case 0107: case 0110: case 0111: case 0112: case 0113: case 0114: case 0115: case 0116: case 0117: case 0120: case 0121: case 0122: case 0123: @@ -5285,7 +5329,7 @@ unasign: } BR = get_reg(AC); /* Grab amount to move */ /* Make BR into native integer */ - if (BR & RSIGN) + if (BR & RSIGN) adjw = -((int)(CM(BR) + 1) & RMASK); else adjw = (int)(BR & RMASK); @@ -5599,10 +5643,10 @@ fnormx: #if KL if (!pi_cycle && (SC & 0400) != 0) { FLAGS |= OVR|FLTOVR|TRP1; - if ((SC & RSIGN) != 0) + if ((SC & RSIGN) != 0) FLAGS |= FLTUND; } -#else +#else if (((SC & 0400) != 0) && !pi_cycle) { FLAGS |= OVR|FLTOVR|TRP1; #if !PDP6 @@ -5756,7 +5800,7 @@ fnormx: #if KL if (flag1) { AR = ((AR ^ FMASK) + 1) & FMASK; - } + } AR = (AR >> 1) | (AR & SMASK); if (IR & 04) { AR++; @@ -6191,7 +6235,7 @@ left: break; /* Done */ } -#if !PDP6 +#if !PDP6 if (AR == SMASK && BR == 1) { FLAGS |= OVR|NODIV; /* Overflow and No Divide */ sac_inh=1; /* Don't touch AC */ @@ -6714,7 +6758,7 @@ jrstf: } if (AC & 01) { /* Enter User Mode */ -#if KI +#if KI FLAGS &= ~(PUBLIC|PRV_PUB); #else FLAGS |= USER; @@ -6794,7 +6838,7 @@ jrstf: flag3 = 1; } - AR = load_tlb(flag1, f, flag3, 0, 0); + AR = load_tlb(flag1, f, flag3, 0, 0, 0); page_fault = 0; /* Incase error during lookup */ BR = AR; /* Remap the flag bits */ @@ -6811,7 +6855,7 @@ jrstf: AR |= 00020000000000LL; /* BIT4 */ if (BR & 0020000LL) /* C */ AR |= 00002000000000LL; /* BIT7 */ - } else + } else AR = (f & 01740) ? 0 : 0377777LL; AR |= BIT8; #else @@ -7725,7 +7769,7 @@ fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); Mem_read_nopage(); FLAGS = (MB >> 23) & 017777; /* If transistioning from user to executive adjust flags */ - if ((FLAGS & USER) != 0 && flag1) + if ((FLAGS & USER) != 0 && flag1) FLAGS |= USERIO; if ((FLAGS & USER) == 0 && (flag3 || (FLAGS & OVR) != 0)) FLAGS |= PRV_PUB|OVR; @@ -7882,7 +7926,7 @@ load_byte(int n, uint64 *data, uint64 fill, int cnt) if (p & 0400) { np = p = ((0777 ^ s) + 044 + 1) & 0777; val = (val & LMASK) | ((val + 1) & RMASK); - } else + } else np = p; np &= 077; /* Update pointer */ @@ -7898,7 +7942,7 @@ load_byte(int n, uint64 *data, uint64 fill, int cnt) AB = (AB + get_reg((MB >> 18) & 017)) & RMASK; } if (ind) { - if (Mem_read(0, 1, 0)) + if (Mem_read(0, 1, 0)) goto back; AB = MB & RMASK; } @@ -7911,7 +7955,7 @@ load_byte(int n, uint64 *data, uint64 fill, int cnt) set_reg(n+1, val); /* Read final value */ - if (Mem_read(0, 0, 0)) + if (Mem_read(0, 0, 0)) goto back; /* Generate mask for given size */ @@ -7951,7 +7995,7 @@ store_byte(int n, uint64 data, int cnt) if (p & 0400) { np = p = ((0777 ^ s) + 044 + 1) & 0777; val = (val & LMASK) | ((val + 1) & RMASK); - } else + } else np = p; np &= 077; /* Update pointer */ @@ -8025,7 +8069,7 @@ get_mask(int n, uint64 *msk) /* Generate mask for given size */ *msk = ((uint64)(1) << s) - 1; } - + /* Advance a pointer by 1 */ void adv_byte(int n) @@ -8035,7 +8079,7 @@ adv_byte(int n) /* Check if should return fill */ val = get_reg(n); - if ((val & MANT) == 0) + if ((val & MANT) == 0) return; /* Decrement count */ val--; @@ -8050,7 +8094,7 @@ adv_byte(int n) if (p & 0400) { p = np = (36 + (0777 ^ s) + 1) & 0777; val = (val & LMASK) | ((val + 1) & RMASK); - } else + } else np = p; np &= 077; /* Update pointer */ @@ -8136,7 +8180,7 @@ do_xlate(uint32 tbl, uint64 val, int mask) reg |= SMASK|BIT1; /* Set S, N, Clear M */ reg &= ~BIT2; break; - case 7: + case 7: reg |= SMASK|BIT1|BIT2; /* Set S, N, M */ break; } @@ -8205,7 +8249,7 @@ do_extend(uint32 ia) if (Mem_read(0, 1, 0)) return 0; fill2 = MB; - + /* Compare the strings */ f = 2; while (((get_reg(ext_ac) | get_reg(ext_ac+3)) & MANT) != 0) { @@ -8265,7 +8309,7 @@ do_extend(uint32 ia) if (i > 3) { reg++; i = 0; - } + } reg |= ((uint64)i) << 30; i = 0; a = 0; @@ -8287,7 +8331,7 @@ do_extend(uint32 ia) val1 = MB & 07777; switch ((MB >> 15) & 07) { case 0: - func0: + func0: if ((reg & SMASK) != 0) { /* If S */ i = 1; } else if (fill1 != 0) { @@ -8295,7 +8339,7 @@ do_extend(uint32 ia) i = 1; } break; - case 1: + case 1: set_reg(ext_ac, reg); return 0; /* Next */ case 2: @@ -8305,7 +8349,7 @@ do_extend(uint32 ia) reg |= BIT2; /* If S, set M */ goto func0; case 4: - func4: + func4: if ((reg & SMASK) == 0) { AB = get_reg(ext_ac+3) & RMASK; MB = get_reg(ext_ac+4); @@ -8324,8 +8368,8 @@ do_extend(uint32 ia) break; case 6: reg &= ~BIT2; /* Clear M */ - goto func4; - case 7: + goto func4; + case 7: reg |= BIT2; /* Set M */ goto func4; } @@ -8341,7 +8385,7 @@ do_extend(uint32 ia) i = 1; } } - reg |= SMASK; + reg |= SMASK; break; case 3: /* Field separater */ reg &= ~(SMASK|BIT1|BIT2); /* Clear S & N */ @@ -8365,7 +8409,7 @@ do_extend(uint32 ia) set_reg(ext_ac+5, AR); break; case 5: - i = 0; + i = 0; break; } break; @@ -8392,7 +8436,7 @@ do_extend(uint32 ia) skipa: /* Compute new byte number */ val1 = (val1 & 077) + 1; - val2 = ((reg >> 30) & 03) + val1; + val2 = ((reg >> 30) & 03) + val1; reg &= ~(3LL << 30); /* Clear byte number */ reg += (val2 >> 2); reg |= (val2 & 3) << 30; @@ -8408,7 +8452,7 @@ do_extend(uint32 ia) } } set_reg(ext_ac, reg); - } + } PC = (PC + 1) & RMASK; break; @@ -8434,9 +8478,9 @@ do_extend(uint32 ia) set_reg(ext_ac+4, AR); return 0; } - if (IR == 010) + if (IR == 010) val1 = (val1 + val2) & FMASK; - else + else f = do_xlate((uint32)(val2 & RMASK), val1, 017); if (f < 0) break; @@ -8482,7 +8526,7 @@ do_extend(uint32 ia) if (IR == 012) val2 = AB; else - val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); + val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); /* Get fill */ AB = (ia + 1) & RMASK; if (Mem_read(0, 1, 0)) @@ -8544,7 +8588,7 @@ do_extend(uint32 ia) if (f == 0 && (get_reg(ext_ac + 3) & BIT2) != 0) val1 >>= 12; val1 &= 07777; - } else + } else val1 += val2; if (!store_byte(ext_ac + 3, val1, 1)) { set_reg(ext_ac + 3, (reg & (SMASK|EXPO)) | (f+1)); @@ -8566,7 +8610,7 @@ do_extend(uint32 ia) get_mask(ext_ac+3, &msk); if ((((get_reg(ext_ac) & (077LL << 26))| get_reg(ext_ac+3)) & EMASK) != 0) return 1; - if (IR == 014) + if (IR == 014) val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); else if (IR == 015) { AB = ia; @@ -8583,7 +8627,7 @@ do_extend(uint32 ia) fill1 = MB; f = 1; while ((get_reg(ext_ac) & MANT) != 0) { - if ((get_reg(ext_ac+3) & MANT) == 0) + if ((get_reg(ext_ac+3) & MANT) == 0) return 0; f = 1; if (!load_byte(ext_ac, &val1, fill1, 1)) { @@ -8646,7 +8690,7 @@ do_extend(uint32 ia) } PC = (PC + 1) & RMASK; break; - + case 020: /* XBLT */ case 021: /* GSNGL */ case 022: /* GDBLE */ @@ -8695,7 +8739,7 @@ t_stat tim_srv(UNIT * uptr) { double us; - + /* See if we are counting to overflow or period */ if (tim_val & 0100000) { tim_val = 020000 | tim_per; @@ -8875,7 +8919,7 @@ dev_tab[1] = &dev_pi; #if KI | KL dev_tab[2] = &dev_pag; #if KL -dev_tab[3] = &dev_cca; +dev_tab[3] = &dev_cca; dev_tab[4] = &dev_tim; dev_irqv[4] = &tim_irq; dev_tab[5] = &dev_mtr; @@ -9068,7 +9112,7 @@ const char * cpu_description (DEVICE *dptr) { #if KL - return "KL10A CPU"; + return "KL10 CPU"; #endif #if KI return "KI10 CPU"; diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 500e413..be42f9a 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -52,6 +52,7 @@ #if KL #define KLA 1 +#define KLB 0 #endif #ifndef KLA @@ -329,7 +330,16 @@ extern DEBTAB crd_debug[]; #define UNIT_V_MAOFF (UNIT_V_MSIZE + 8) #define UNIT_V_PAGE (UNIT_V_MAOFF + 1) #define UNIT_MAOFF (1 << UNIT_V_MAOFF) +#if KL +#if KLB +#define UNIT_KL10B (1 << UNIT_V_PAGE) +#else +#define UNIT_KL10B (0) +#endif +#define UNIT_TWOSEG (0) +#else #define UNIT_TWOSEG (1 << UNIT_V_PAGE) +#endif #define UNIT_ITSPAGE (2 << UNIT_V_PAGE) #define UNIT_BBNPAGE (4 << UNIT_V_PAGE) #define UNIT_M_PAGE (007 << UNIT_V_PAGE) From 84821f2db4b4e37f0fec373fb5754f8313ee3381 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 5 Sep 2019 21:17:12 -0400 Subject: [PATCH 03/98] KA10: Fixed typo in kl10_fe.c --- PDP10/kl10_fe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 315abf2..0f7f4c3 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -472,7 +472,7 @@ void dte_second(UNIT *uptr) { t_stat r; #if KI_22BIT -#if ITS_KL +#if KL_ITS if ((cpu_unit[0].flags & UNIT_ITSPAGE) == 0) #endif base = eb_ptr; From 8377dad75c5074415c1ee2c2a272e0a217d41630 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sat, 7 Sep 2019 14:55:49 -0400 Subject: [PATCH 04/98] KA10: Fixes to allow ITS Paging to start to work. --- PDP10/kx10_cpu.c | 84 +++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 2903606..44c5f10 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -189,7 +189,7 @@ int t20_page; /* Tops 20 paging selected */ int ptr_flg; /* Access to pointer value */ #if KLB int cur_sect; /* Current section */ -int prv_sect; /* Previous section */ +int prev_sect; /* Previous section */ int pc_sect; /* Program counter section */ #endif #else @@ -1228,6 +1228,7 @@ t_stat dev_pag(uint32 dev, uint64 *data) { } if (res & BIT1) { /* Load previous section */ + prev_sect = (res >> 18) & 077; } if (res & BIT2) { ub_ptr = (res & 017777) << 9; @@ -1267,6 +1268,7 @@ t_stat dev_cca(uint32 dev, uint64 *data) { return SCPE_OK; } + /* * Check if the last operation caused a APR IRQ to be generated. */ @@ -1331,19 +1333,24 @@ t_stat dev_apr(uint32 dev, uint64 *data) { case DATAI: if (dev & 040) { /* APRID */ - AR = SMASK| (500LL << 18); + AR = SMASK| (500LL << 18); /* MC level 500 */ /* Bit 0 for TOPS-20 paging */ /* Bit 1 for extended addressing */ /* Bit 2 Exotic microcode */ /* Bit 4 for ITS Style Paging */ #if KL_ITS - AR |= 00020000000000LL; + if (QITS) + AR |= 00020000000000LL; #endif - /* Bit 18 50hz 4 */ - /* Bit 19 Cache 2 */ - /* Bit 20 Channel? 1*/ + /* Bit 18 50hz */ + /* Bit 19 Cache */ + /* Bit 20 Channel? */ /* Bit 21 Extended KL10 */ /* Bit 22 Master Osc */ +#if KLB + if (QKLB) + AR |= BIT1|040000; +#endif AR |= (uint64)((apr_serial == -1) ? DEF_SERIAL : apr_serial); MB = AR; (void)Mem_write(0, 0); @@ -1844,12 +1851,11 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) int dbr; int pg; - dbr = (uf)? - ((page & 0400)?FM[(06<<4)|4]:FM[(06<<4)|3]) : - ((page & 0400)?FM[(06<<4)|2]:FM[(06<<4)|1]); + dbr = (uf)? ((page & 0400) ? dbr1 : dbr2) : + ((page & 0400) ? dbr3 : dbr4) ; pg = (page & 0377) >> 2; /* 2 1024 word page entries */ data = M[dbr + pg]; - if ((page & 02) == 0) + if ((page & 01) != 0) data >>= 18; data &= RMASK; switch(data >> 16) { @@ -1858,14 +1864,16 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) case 2: pg = RSIGN; break; /* R/W First */ case 3: pg = RSIGN|0100000; break; /* R/W */ } - pg |= data & 01777; + pg |= (data & 00377) << 1; /* Create 2 page table entries. */ if (uf) { u_tlb[page & 0776] = pg; - u_tlb[(page & 0776)|1] = pg+1; + u_tlb[(page & 0776)|1] = pg|1; + data = u_tlb[page]; } else { e_tlb[page & 0776] = pg; - e_tlb[(page & 0776)|1] = pg+1; + e_tlb[(page & 0776)|1] = pg|1; + data = e_tlb[page]; } } else #endif @@ -2072,6 +2080,7 @@ fprintf(stderr, "YMap %012llo\n\r", data); else e_tlb[page] = data; } else { + /* Map the page */ if (uf | upmp) { data = M[ub_ptr + (page >> 1)]; @@ -3869,15 +3878,12 @@ no_fetch: AR = MB; AB = MB & RMASK; if (MB & 017000000) { -#if 0 - if (xct_flag != 0 && (FLAGS & USER) == 0 && (xct_flag & 8) != 0) - AR = FM[prev_ctx|((MB >> 18) & 017)]; +#if KL + if ((xct_flag & 8) != 0 && (FLAGS & USER) == 0) + AR = MB = (AB + FM[prev_ctx|((MB >> 18) & 017)]) & FMASK; else - AR = get_reg((MB >> 18) & 017); - AR = MB = (AR + AB) & FMASK; -#else - AR = MB = (AB + get_reg((MB >> 18) & 017)) & FMASK; #endif + AR = MB = (AB + get_reg((MB >> 18) & 017)) & FMASK; AB = MB & RMASK; } if (IR != 0254) @@ -4073,7 +4079,7 @@ unasign: MB = (ub_ptr >> 9) | ((uint64)(prev_ctx & 0160)) << 20 | ((uint64)(fm_sel & 0160)) << 23 | SMASK|BIT1|BIT2; Mem_write_nopage(); - prev_ctx = fm_sel; +// prev_ctx = fm_sel; #endif /* Read in new PC and flags */ FLAGS &= ~ (PRV_PUB|BYTI|ADRFLT|TRP1|TRP2); @@ -4167,18 +4173,13 @@ unasign: fault_data = (MB >> 18) & RMASK; AB = (AB + 1) & RMASK; MB = M[AB]; /* WD 4 */ - FM[(06<<4)|1] = ((0377 << 18) | RMASK) & MB; + dbr1 = ((0377 << 18) | RMASK) & MB; AB = (AB + 1) & RMASK; MB = M[AB]; /* WD 5 */ - FM[(06<<4)|2] = ((0377 << 18) | RMASK) & MB; + dbr2 = ((0377 << 18) | RMASK) & MB; AB = (AB + 1) & RMASK; - MB = M[AB]; /* WD 6 */ - FM[(06<<4)|3] = ((0377 << 18) | RMASK) & MB; - AB = (AB + 1) & RMASK; - MB = M[AB]; /* WD 7 */ - page_enable = 1; for (f = 0; f < 512; f++) - e_tlb[f] = u_tlb[f] = 0; + u_tlb[f] = 0; break; } goto unasign; @@ -4200,15 +4201,10 @@ unasign: MB = ((uint64)fault_data) << 18; M[AB] = MB; AB = (AB + 1) & RMASK; - MB = (uint64)FM[(06<<4)|1]; - M[AB] = MB; - AB = (AB + 1) & RMASK; - MB = (uint64)FM[(06<<4)|2]; - M[AB] = MB; - AB = (AB + 1) & RMASK; - MB = (uint64)FM[(06<<4)|3]; + MB = dbr1; M[AB] = MB; AB = (AB + 1) & RMASK; + MB = dbr2; M[AB] = MB; } goto unasign; @@ -6814,14 +6810,10 @@ jrstf: /* Check if Paging Enabled */ if (!page_enable || AB < 020) { AR = 0020000LL + f; /* direct map */ -#else - /* Check if Paging Enabled */ - if (!page_enable || AB < 020) { - AR = AB; /* direct map */ -#endif set_reg(AC, AR); break; } +#endif #if KL /* Invalid in user unless USERIO set, or not in supervisor mode */ if ((FLAGS & (USER|USERIO)) == USER || (FLAGS & (USER|PUBLIC)) == PUBLIC) @@ -6831,6 +6823,16 @@ jrstf: if (xct_flag & 4) flag1 = (FLAGS & USERIO) != 0; + /* Check if Paging Enabled */ + if (!page_enable || AB < 020) { + AR = AB; /* direct map */ + if (flag1) /* U */ + AR |= SMASK; /* BIT8 */ + AR |= BIT8|BIT2|00040000000000LL; /* BIT3 */ + set_reg(AC, AR); + break; + } + /* Handle KI paging odditiy */ if (!flag1 && !t20_page && (f & 0740) == 0340) { /* Pages 340-377 via UBT */ From 3553ba523fccc104e0e699b32115bfa259c8d95c Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sat, 7 Sep 2019 22:48:49 -0400 Subject: [PATCH 05/98] KA10: More ITS and KLB changes. --- PDP10/kx10_cpu.c | 91 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 9 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 44c5f10..fa7a6e7 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -191,6 +191,7 @@ int ptr_flg; /* Access to pointer value */ int cur_sect; /* Current section */ int prev_sect; /* Previous section */ int pc_sect; /* Program counter section */ +int glb_sect; /* Global section access */ #endif #else int small_user; /* Small user flag */ @@ -1226,10 +1227,12 @@ t_stat dev_pag(uint32 dev, uint64 *data) { fm_sel = (uint8)(res >> 23) & 0160; prev_ctx = (res >> 20) & 0160; } - if (res & BIT1) { +#if KLB + if (QKLB && res & BIT1) { /* Load previous section */ prev_sect = (res >> 18) & 077; } +#endif if (res & BIT2) { ub_ptr = (res & 017777) << 9; for (i = 0; i < 512; i++) @@ -1851,7 +1854,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) int dbr; int pg; - dbr = (uf)? ((page & 0400) ? dbr1 : dbr2) : + dbr = (uf)? ((page & 0400) ? dbr2 : dbr1) : ((page & 0400) ? dbr3 : dbr4) ; pg = (page & 0377) >> 2; /* 2 1024 word page entries */ data = M[dbr + pg]; @@ -2220,6 +2223,11 @@ fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) fault_data |= 00010000000000LL; /* BIT5 */ if (data & 0020000LL) /* C */ fault_data |= 00002000000000LL; /* BIT7 */ +#if KL_ITS + if (QITS && (xct_flag & 020) != 0) + PC = (PC + 1) & AMASK; + else +#endif page_fault = 1; return 0; } @@ -3812,6 +3820,7 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ cur_sect = pc_sect; else cur_sect = 0; + glb_sect = 0; #endif uuo_cycle = 0; f_pc_inh = 0; @@ -6619,6 +6628,10 @@ fprintf(stderr, "Xjrst %012llo - ", MB); goto last; AR = MB; /* Get PC. */ fprintf(stderr, " %012llo\n\r", MB); +#if KLB + if (QKLB) + pc_sect = (MB >> 18) & 017; +#endif goto jrstf; case 006: /* XJEN */ @@ -6657,11 +6670,32 @@ jrstf: check_apr_irq(); break; - case 003: /* Invalid */ case 007: /* XPCW */ +#if KLB + if (QKLB) { + MB = ((uint64)FLAGS) << 23; + if (Mem_write(0, 0)) + goto last; + AB = (AB + 1) & RMASK; + MB = (((uint64)pc_sect) << 18) | PC; + if (Mem_write(0, 0)) + goto last; + AB = (AB + 1) & RMASK; + goto xjrstf; + } +#endif + case 014: /* SFM */ +#if KLB + if (QKLB) { + MB = ((uint64)FLAGS) << 23; + MB |= prev_sect; + (void)Mem_write(0, 0); + goto last; + } +#endif + case 003: /* Invalid */ case 011: /* Invalid */ case 013: /* Invalid */ - case 014: /* SFM */ case 015: /* Invalid */ case 016: /* Invalid */ case 017: /* Invalid */ @@ -8820,14 +8854,34 @@ if (vptr == NULL) if (ea < 020) *vptr = FM[ea] & FMASK; else { +#if KL | KI if (sw & SWMASK ('V')) { - if (ea >= MAXMEMSIZE) - return SCPE_REL; + int uf = ((sw & SWMASK('U')) != 0); + int page = ea >> 9; + uint32 tlb; +#if KL + if (!uf && !t20_page && (page & 0740) == 0340) { +#else + if (!uf && (page & 0740) == 0340) { +#endif + /* Pages 340-377 via UBT */ + page += 01000 - 0340; + uf = 1; } + if (uf) + tlb = u_tlb[page]; + else + tlb = e_tlb[page]; + if ((tlb & RSIGN) == 0) + return 4; + ea = ((tlb & 017777) << 9) + (ea & 0777); + } +#endif + if (ea >= MEMSIZE) return SCPE_NXM; *vptr = M[ea] & FMASK; - } +} return SCPE_OK; } @@ -8838,10 +8892,29 @@ t_stat cpu_dep (t_value val, t_addr ea, UNIT *uptr, int32 sw) if (ea < 020) FM[ea] = val & FMASK; else { +#if KL | KI if (sw & SWMASK ('V')) { - if (ea >= MAXMEMSIZE) - return SCPE_REL; + int uf = ((sw & SWMASK('U')) != 0); + int page = ea >> 9; + uint32 tlb; +#if KL + if (!uf && !t20_page && (page & 0740) == 0340) { +#else + if (!uf && (page & 0740) == 0340) { +#endif + /* Pages 340-377 via UBT */ + page += 01000 - 0340; + uf = 1; } + if (uf) + tlb = u_tlb[page]; + else + tlb = e_tlb[page]; + if ((tlb & RSIGN) == 0) + return 4; + ea = ((tlb & 017777) << 9) + (ea & 0777); + } +#endif if (ea >= MEMSIZE) return SCPE_NXM; M[ea] = val & FMASK; From ac2ad23138867653c5f9d056a04f980b22cb23a2 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 8 Sep 2019 21:36:59 -0400 Subject: [PATCH 06/98] KA10: More ITS fixes. --- PDP10/kx10_cpu.c | 61 +++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index fa7a6e7..4a7e21e 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -236,8 +236,7 @@ uint32 qua_time; /* Quantum clock value */ #define dbr2 FM[(6<<4)|2] #define dbr3 FM[(6<<4)|3] #define dbr4 FM[(6<<4)|4] -#define jpc FM[(6<<4)|7] -#define opc FM[(6<<4)|6] +#define jpc FM[(6<<4)|15] #define mar brk_addr; #endif @@ -1227,12 +1226,10 @@ t_stat dev_pag(uint32 dev, uint64 *data) { fm_sel = (uint8)(res >> 23) & 0160; prev_ctx = (res >> 20) & 0160; } -#if KLB - if (QKLB && res & BIT1) { + if (res & BIT1) { /* Load previous section */ prev_sect = (res >> 18) & 077; } -#endif if (res & BIT2) { ub_ptr = (res & 017777) << 9; for (i = 0; i < 512; i++) @@ -1851,23 +1848,25 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) #if KL_ITS if (QITS && t20_page) { - int dbr; + uint64 dbr; int pg; dbr = (uf)? ((page & 0400) ? dbr2 : dbr1) : ((page & 0400) ? dbr3 : dbr4) ; pg = (page & 0377) >> 2; /* 2 1024 word page entries */ data = M[dbr + pg]; - if ((page & 01) != 0) +fprintf(stderr, "Load page %06o dbr%012llo pg%06o data=%012llo -> ", page, dbr, pg, data); + if ((page & 02) == 0) data >>= 18; data &= RMASK; + pg = 0; switch(data >> 16) { - case 0: pg = 0; break; /* No access */ + case 0: break; /* No access */ case 1: /* Read Only */ case 2: pg = RSIGN; break; /* R/W First */ case 3: pg = RSIGN|0100000; break; /* R/W */ } - pg |= (data & 00377) << 1; + pg |= (data & 017777) << 1; /* Create 2 page table entries. */ if (uf) { u_tlb[page & 0776] = pg; @@ -1878,6 +1877,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) e_tlb[(page & 0776)|1] = pg|1; data = e_tlb[page]; } +fprintf(stderr, " %06o %06o\n\r", pg, pg | 1); } else #endif #define PG_PUB 0040000 @@ -3832,7 +3832,9 @@ fetch: #endif #if ITS if (QITS && pi_cycle == 0 && mem_prot == 0) { +#if !KL_ITS opc = PC | (FLAGS << 18); +#endif if ((FLAGS & ONEP) != 0) { one_p_arm = 1; FLAGS &= ~ONEP; @@ -4163,7 +4165,7 @@ unasign: } goto unasign; - case 0076: + case 0076: /* LMR */ if (QITS && (FLAGS & USER) == 0) { /* Load store ITS pager info */ if ((AB + 8) > MEMSIZE) { @@ -4172,49 +4174,44 @@ unasign: MB = M[AB]; /* WD 0 */ jpc = (MB & RMASK); AB = (AB + 1) & RMASK; - MB = M[AB]; - opc = MB; + MB = M[AB]; /* WD 1 */ + brk_addr = MB & RMASK; + brk_flags = 017 & (MB >> 23); AB = (AB + 1) & RMASK; MB = M[AB]; /* WD 2 */ - brk_addr = /*03777777 &*/ MB; + fault_data = MB; AB = (AB + 1) & RMASK; MB = M[AB]; /* WD 3 */ - fault_data = (MB >> 18) & RMASK; + dbr1 = MB; AB = (AB + 1) & RMASK; MB = M[AB]; /* WD 4 */ - dbr1 = ((0377 << 18) | RMASK) & MB; - AB = (AB + 1) & RMASK; - MB = M[AB]; /* WD 5 */ - dbr2 = ((0377 << 18) | RMASK) & MB; - AB = (AB + 1) & RMASK; + dbr2 = MB; for (f = 0; f < 512; f++) u_tlb[f] = 0; break; } goto unasign; - case 0077: + case 0077: /* SPM */ if (QITS && (FLAGS & USER) == 0) { if ((AB + 8) > MEMSIZE) { break; } - MB = ((uint64)fault_data) << 18 | - (uint64)jpc; - M[AB] = MB; + MB = (uint64)jpc; + M[AB] = MB; /* WD 0 */ AB = (AB + 1) & RMASK; - MB = opc; - M[AB] = MB; + MB = (uint64)brk_addr; + MB |= ((uint64)brk_flags) << 23; + M[AB] = MB; /* WD 1 */ AB = (AB + 1) & RMASK; - MB = (brk_addr); - M[AB] = MB; - AB = (AB + 1) & RMASK; - MB = ((uint64)fault_data) << 18; - M[AB] = MB; + MB = fault_data; + M[AB] = MB; /* WD 2 */ AB = (AB + 1) & RMASK; MB = dbr1; - M[AB] = MB; + M[AB] = MB; /* WD 3 */ AB = (AB + 1) & RMASK; MB = dbr2; - M[AB] = MB; + M[AB] = MB; /* WD 4 */ + break; } goto unasign; #endif From efcf0c33e1a6f69fab0faabe4ef969d7af82d816 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 8 Sep 2019 23:39:38 -0400 Subject: [PATCH 07/98] KA10: Fixed compile error. --- PDP10/kx10_cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 4a7e21e..757bf23 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1228,7 +1228,9 @@ t_stat dev_pag(uint32 dev, uint64 *data) { } if (res & BIT1) { /* Load previous section */ +#if KLB prev_sect = (res >> 18) & 077; +#endif } if (res & BIT2) { ub_ptr = (res & 017777) << 9; From 38d6a0a58a18f5cff97060f48586a41aaf5516bb Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 10 Sep 2019 21:16:20 -0400 Subject: [PATCH 08/98] KA10: More fixes to get ITS to work, added performance metering. --- PDP10/kx10_cpu.c | 252 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 171 insertions(+), 81 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 757bf23..d8666c6 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -183,6 +183,8 @@ int mtr_enable; /* Enable Timer */ int mtr_flags; /* Flags for accounting */ int tim_per; /* Timer period */ int tim_val; /* Current timer value */ +int mem_cnt; /* Number of memory cycles */ +int rtc_tim; /* Time till next 60hz clock */ uint32 brk_addr; /* Address break */ int brk_flags; /* Break flags */ int t20_page; /* Tops 20 paging selected */ @@ -1167,6 +1169,24 @@ t_stat null_dev(uint32 dev, uint64 *data) { #if KL static int timer_irq, timer_flg; +void +update_times(int tim) +{ + uint64 temp; + if (page_enable) { + temp = (M[eb_ptr + 0511] & CMASK) + (tim << 12); + if (temp & SMASK) + M[eb_ptr + 0510] = (M[eb_ptr+0510] + 1) & FMASK; + M[eb_ptr + 0511] = temp & CMASK; + if (FLAGS & USER) { + temp = (M[ub_ptr + 0506] & CMASK) + (tim << 12); + if (temp & SMASK) + M[ub_ptr + 0505] = (M[ub_ptr+0505] + 1) & FMASK; + M[ub_ptr + 0506] = temp & CMASK; + } + } +} + /* * Page device for KL10. */ @@ -1204,13 +1224,10 @@ t_stat dev_pag(uint32 dev, uint64 *data) { page &= ~7; /* Map the page */ -// if (uf || upmp) { - for(i = 0; i < 8; i++) - u_tlb[page+i] = 0; - // } else { - for(i = 0; i < 8; i++) - e_tlb[page+i] = 0; - // } + for(i = 0; i < 8; i++) + u_tlb[page+i] = 0; + for(i = 0; i < 8; i++) + e_tlb[page+i] = 0; /* If not user do exec mappping */ if (/*!uf && !t20_page &&*/ (page & 0740) == 0340) { /* Pages 340-377 via UBT */ @@ -1219,29 +1236,36 @@ t_stat dev_pag(uint32 dev, uint64 *data) { for(i = 0; i < 8; i++) u_tlb[page+i] = 0; } - break; - } - res = *data; - if (res & SMASK) { - fm_sel = (uint8)(res >> 23) & 0160; - prev_ctx = (res >> 20) & 0160; - } - if (res & BIT1) { - /* Load previous section */ + } else { + res = *data; + if (res & SMASK) { + fm_sel = (uint8)(res >> 23) & 0160; + prev_ctx = (res >> 20) & 0160; + } + if (res & BIT1) { + /* Load previous section */ #if KLB - prev_sect = (res >> 18) & 077; + prev_sect = (res >> 18) & 077; #endif - } - if (res & BIT2) { - ub_ptr = (res & 017777) << 9; - for (i = 0; i < 512; i++) - u_tlb[i] = 0; - for (;i < 546; i++) - u_tlb[i] = 0; - } - sim_debug(DEBUG_DATAIO, &cpu_dev, + } + if ((res & RSIGN) == 0) { + int t; + double us = sim_activate_time_usecs (&cpu_unit[0]); + t = rtc_tim - ((int)us); + update_times(t); + rtc_tim = ((int)us); + } + if (res & BIT2) { + ub_ptr = (res & 017777) << 9; + for (i = 0; i < 512; i++) + u_tlb[i] = 0; + for (;i < 546; i++) + u_tlb[i] = 0; + } + sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAO PAG %012llo ebr=%06o ubr=%06o\n", *data, eb_ptr, ub_ptr); + } break; case DATAI: @@ -1334,34 +1358,32 @@ t_stat dev_apr(uint32 dev, uint64 *data) { case DATAI: if (dev & 040) { - /* APRID */ - AR = SMASK| (500LL << 18); /* MC level 500 */ - /* Bit 0 for TOPS-20 paging */ - /* Bit 1 for extended addressing */ - /* Bit 2 Exotic microcode */ - /* Bit 4 for ITS Style Paging */ + /* APRID */ + AR = SMASK| (500LL << 18); /* MC level 500 */ + /* Bit 0 for TOPS-20 paging */ + /* Bit 1 for extended addressing */ + /* Bit 2 Exotic microcode */ + /* Bit 4 for ITS Style Paging */ #if KL_ITS - if (QITS) - AR |= 00020000000000LL; -#endif - /* Bit 18 50hz */ - /* Bit 19 Cache */ - /* Bit 20 Channel? */ - /* Bit 21 Extended KL10 */ - /* Bit 22 Master Osc */ -#if KLB - if (QKLB) - AR |= BIT1|040000; -#endif - AR |= (uint64)((apr_serial == -1) ? DEF_SERIAL : apr_serial); - MB = AR; - (void)Mem_write(0, 0); - sim_debug(DEBUG_DATAIO, &cpu_dev, "APRID %012llo\n", MB); - break; + if (QITS) + AR |= 00020000000000LL; +#endif + /* Bit 18 50hz */ + /* Bit 19 Cache */ + /* Bit 20 Channel? */ + /* Bit 21 Extended KL10 */ + /* Bit 22 Master Osc */ +#if KLB + if (QKLB) + AR |= BIT1|040000; +#endif + AR |= (uint64)((apr_serial == -1) ? DEF_SERIAL : apr_serial); + sim_debug(DEBUG_DATAIO, &cpu_dev, "APRID BLKI %012llo\n", MB); + } else { + *data = ((uint64)brk_flags) << 23; + *data |= (uint64)brk_addr; + sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI APR %012llo\n", *data); } - *data = ((uint64)brk_flags) << 23; - *data |= (uint64)brk_addr; - sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI APR %012llo\n", *data); break; } return SCPE_OK; @@ -1399,6 +1421,7 @@ t_stat dev_mtr(uint32 dev, uint64 *data) { break; case DATAO: + /* MUUO */ if (dev & 040) { sim_debug(DEBUG_DATAIO, &cpu_dev, "BLKO MTR %012llo\n", *data); } else { @@ -1408,12 +1431,34 @@ t_stat dev_mtr(uint32 dev, uint64 *data) { case DATAI: if (dev & 040) { + /* RDMACT */ /* Read memory accounting */ + if (page_enable) { + res = (M[ub_ptr + 0507] & CMASK); + BR = M[ub_ptr + 0506]; + } else { + res = 0 << 12; + BR = 0; + } sim_debug(DEBUG_DATAIO, &cpu_dev, "BLKI MTR %012llo\n", *data); } else { + /* RDEACT */ /* Read executive accounting */ + int t; + double us = sim_activate_time_usecs (&cpu_unit[0]); + t = rtc_tim - ((int)us); + update_times(t); + rtc_tim = ((int)us); + if (page_enable) { + res = (M[ub_ptr + 0505] & CMASK); + BR = M[ub_ptr + 0504]; + } else { + res = t << 12; + BR = 0; + } sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI MTR %012llo\n", *data); } + *data = res; break; } return SCPE_OK; @@ -1463,7 +1508,8 @@ t_stat dev_tim(uint32 dev, uint64 *data) { case DATAO: if (dev & 040) { - /* Write performance */ + /* WRPAE */ + /* Write performance enables */ sim_debug(DEBUG_DATAIO, &cpu_dev, "BLKO TIM %012llo\n", *data); } else { sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAO TIM %012llo\n", *data); @@ -1472,14 +1518,38 @@ t_stat dev_tim(uint32 dev, uint64 *data) { case DATAI: if (dev & 040) { - /* Read perfomance */ + /* RDPERF */ + /* Read process execution time */ + int t; + us = sim_activate_time_usecs (&cpu_unit[0]); + t = rtc_tim - ((int)us); + update_times(t); + rtc_tim = ((int)us); + if (page_enable) { + res = (M[ub_ptr + 0505]); + BR = M[ub_ptr + 0504]; + } else { + res = 0 << 12; + BR = t; + } sim_debug(DEBUG_DATAIO, &cpu_dev, "BLKI TIM %012llo\n", *data); } else { /* RDTIME */ - *data = M[eb_ptr + 0510]; - BR = M[eb_ptr + 0511]; + int t; + us = sim_activate_time_usecs (&cpu_unit[0]); + t = rtc_tim - ((int)us); + update_times(t); + rtc_tim = ((int)us); + if (page_enable) { + res = (M[eb_ptr + 0511]); + BR = M[eb_ptr + 0510]; + } else { + res = t << 12; + BR = 0; + } sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI TIM %012llo\n", *data); } + *data = res; return SCPE_OK; } /* If timer is on, figure out when it will go off */ @@ -1857,7 +1927,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) ((page & 0400) ? dbr3 : dbr4) ; pg = (page & 0377) >> 2; /* 2 1024 word page entries */ data = M[dbr + pg]; -fprintf(stderr, "Load page %06o dbr%012llo pg%06o data=%012llo -> ", page, dbr, pg, data); +//fprintf(stderr, "Load page %06o dbr%012llo pg%06o data=%012llo -> ", page, dbr, pg, data); if ((page & 02) == 0) data >>= 18; data &= RMASK; @@ -1879,7 +1949,7 @@ fprintf(stderr, "Load page %06o dbr%012llo pg%06o data=%012llo -> ", page, dbr, e_tlb[(page & 0776)|1] = pg|1; data = e_tlb[page]; } -fprintf(stderr, " %06o %06o\n\r", pg, pg | 1); +//fprintf(stderr, " %06o %06o\n\r", pg, pg | 1); } else #endif #define PG_PUB 0040000 @@ -2156,7 +2226,7 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch if (flag) uf = 0; else if (xct_flag != 0 && !uf && !fetch) { -fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); +//fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); if (((xct_flag & 8) != 0 && cur_context) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || @@ -2164,7 +2234,7 @@ fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, P uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; } -fprintf(stderr, "%o %o\n\r", uf, pub); +//fprintf(stderr, "%o %o\n\r", uf, pub); } /* Handle KI paging odditiy */ @@ -2197,7 +2267,7 @@ fprintf(stderr, "%o %o\n\r", uf, pub); (!fetch || (M[*loc] & 00777740000000LL) != 0254040000000LL)) { /* Handle public violation */ fault_data = ((uint64)addr) | 021LL << 30 | BIT8 |((uf)?SMASK:0); -fprintf(stderr, "Public fault %012llo %06o\n\r", fault_data, FLAGS << 5); +//fprintf(stderr, "Public fault %012llo %06o\n\r", fault_data, FLAGS << 5); page_fault = 1; return 0; } @@ -2296,16 +2366,16 @@ int Mem_read(int flag, int cur_context, int fetch) { sim_interval--; if (AB < 020) { if (xct_flag != 0 && !fetch && (FLAGS & USER) == 0) { -fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgr ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); +//fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgr ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || ((xct_flag & 1) != 0 && !cur_context && BYF5)) { MB = FM[prev_ctx|AB]; -fprintf(stderr, "prev \n\r"); +//fprintf(stderr, "prev \n\r"); return 0; } -fprintf(stderr, "\n\r"); +//fprintf(stderr, "\n\r"); } MB = get_reg(AB); } else { @@ -2328,16 +2398,16 @@ int Mem_write(int flag, int cur_context) { sim_interval--; if (AB < 020) { if (xct_flag != 0 && (FLAGS & USER) == 0) { -fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgw ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); +//fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgw ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || ((xct_flag & 1) != 0 && !cur_context && BYF5)) { -fprintf(stderr, "prev \n\r"); +//fprintf(stderr, "prev \n\r"); FM[prev_ctx|AB] = MB; return 0; } -fprintf(stderr, "\n\r"); +//fprintf(stderr, "\n\r"); } set_reg(AB, MB); } else { @@ -3880,6 +3950,7 @@ no_fetch: /* Handle indirection repeat until no longer indirect */ do { + int ix; if ((!pi_cycle) & pi_pending #if KI | KL & (!trap_flag) @@ -3887,16 +3958,19 @@ no_fetch: ) { pi_rq = check_irq_level(); } - ind = (MB & 020000000) != 0; + ind = TST_IND(MB) != 0; AR = MB; AB = MB & RMASK; - if (MB & 017000000) { + ix = GET_XR(MB); + if (ix) { #if KL +// if (xct_flag != 0) +//fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o m=%012llo\n\r", IR, PC, AB, xct_flag, MB); if ((xct_flag & 8) != 0 && (FLAGS & USER) == 0) - AR = MB = (AB + FM[prev_ctx|((MB >> 18) & 017)]) & FMASK; + AR = MB = (AB + FM[prev_ctx|ix]) & FMASK; else #endif - AR = MB = (AB + get_reg((MB >> 18) & 017)) & FMASK; + AR = MB = (AB + get_reg(ix)) & FMASK; AB = MB & RMASK; } if (IR != 0254) @@ -6621,12 +6695,10 @@ xjrstf: if (Mem_read(0, 0, 0)) goto last; BR = MB >> 32; /* Move flags into position */ -fprintf(stderr, "Xjrst %012llo - ", MB); AB = (AB + 1) & RMASK; if (Mem_read(0, 0, 0)) goto last; AR = MB; /* Get PC. */ -fprintf(stderr, " %012llo\n\r", MB); #if KLB if (QKLB) pc_sect = (MB >> 18) & 017; @@ -7330,7 +7402,7 @@ skip_op: PC_CHANGE PC = (PC + 1) & RMASK; #if KI | KL - } else if (pi_cycle) { + } else if (trap_flag == 0 && pi_cycle) { pi_ov = pi_hold = 1; #endif } @@ -7663,17 +7735,26 @@ fetch_opr: case 0: /* 00 BLKI */ case 2: /* 10 BLKO */ #if KL + /* For KL10 special devices treat like DATAI/DATAO */ if (d <= 05) { if (AC & 02) { -// if (Mem_read(pi_cycle, 0, 0)) - // goto last; - // AR = MB; + if (d == 1 || d == 4) { + if (Mem_read(pi_cycle, 0, 0)) + goto last; + AR = MB; + } dev_tab[d](040|DATAO|(d<<2), &AR); } else { dev_tab[d](040|DATAI|(d<<2), &AR); - // MB = AR; - // if (Mem_write(pi_cycle, 0)) - // goto last; + MB = AR; + if (Mem_write(pi_cycle, 0)) + goto last; + if (d == 4 || d == 5) { + AB = (AB + 1) & RMASK; + MB = BR; + if (Mem_write(pi_cycle, 0)) + goto last; + } } break; } @@ -7704,7 +7785,7 @@ fetch_opr: if (Mem_write(pi_cycle, 0)) goto last; #if KL - if (d == 5) { /* DATAI TIM is two words */ + if (d == 4 || d == 5) { /* DATAI TIM, MTR is two words */ AB = (AB + 1) & RMASK; MB = BR; if (Mem_write(pi_cycle, 0)) @@ -8746,14 +8827,23 @@ t_stat rtc_srv(UNIT * uptr) { int32 t; +#if KL + uint64 temp; +#endif t = sim_rtcn_calb (rtc_tps, TMR_RTC); sim_activate_after(uptr, 1000000/rtc_tps); tmxr_poll = t/2; +#if PDP6 | KA | KI clk_flg = 1; if (clk_en) { sim_debug(DEBUG_CONO, &cpu_dev, "CONO timmer\n"); set_interrupt(4, clk_irq); } +#endif +#if KL + update_times(rtc_tim); + rtc_tim = (1000000/rtc_tps); +#endif return SCPE_OK; } From 65dd4f6d2c6b2904a68b13f7e3408bc0e2ef231c Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 10 Sep 2019 21:20:47 -0400 Subject: [PATCH 09/98] KA10: Added interrupt for PD to KL. --- PDP10/ka10_pd.c | 44 +++++++++++++++++++++++++++++++++++++++++++- PDP10/kx10_defs.h | 2 +- makefile | 2 +- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/PDP10/ka10_pd.c b/PDP10/ka10_pd.c index 2aeaeed..d428cec 100644 --- a/PDP10/ka10_pd.c +++ b/PDP10/ka10_pd.c @@ -42,14 +42,24 @@ #define PD_DEVNUM 0500 #define PD_OFF (1 << DEV_V_UF) +#define PIA_CH u3 + +#define PIA_FLG 07 +#define CLK_IRQ 010 + +#define TMR_PD 3 + +int pd_tps = 60; + t_stat pd_devio(uint32 dev, uint64 *data); const char *pd_description (DEVICE *dptr); +t_stat pd_srv(UNIT *uptr); t_stat pd_set_on(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat pd_set_off(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat pd_show_on(FILE *st, UNIT *uptr, int32 val, CONST void *desc); UNIT pd_unit[] = { - {UDATA(NULL, UNIT_DISABLE, 0)}, /* 0 */ + {UDATA(pd_srv, UNIT_IDLE|UNIT_DISABLE, 0)}, /* 0 */ }; DIB pd_dib = {PD_DEVNUM, 1, &pd_devio, NULL}; @@ -91,6 +101,21 @@ t_stat pd_devio(uint32 dev, uint64 *data) else *data = pd_ticks(); break; + case CONI: + *data = (uint64)(pd_unit[0].PIA_CH & (CLK_IRQ|PIA_FLG)); + break; + case CONO: + pd_unit[0].PIA_CH &= ~(PIA_FLG); + pd_unit[0].PIA_CH |= (int32)(*data & PIA_FLG); + if (pd_unit[0].PIA_CH & PIA_FLG) { + if (!sim_is_active(pd_unit)) + sim_activate(pd_unit, 10000); + } + if (*data & CLK_IRQ) { + pd_unit[0].PIA_CH &= ~(CLK_IRQ); + clr_interrupt(PD_DEVNUM); + } + break; default: break; } @@ -98,6 +123,23 @@ t_stat pd_devio(uint32 dev, uint64 *data) return SCPE_OK; } +t_stat +pd_srv(UNIT * uptr) +{ + int32 t; + + t = sim_rtcn_calb (pd_tps, TMR_PD); + sim_activate_after(uptr, 1000000/pd_tps); + if (uptr->PIA_CH & PIA_FLG) { + uptr->PIA_CH |= CLK_IRQ; + set_interrupt(PD_DEVNUM, uptr->PIA_CH); + } else + sim_cancel(uptr); + + return SCPE_OK; +} + + const char *pd_description (DEVICE *dptr) { return "Paul DeCoriolis clock"; diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index be42f9a..6ea79cd 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -527,7 +527,7 @@ int auxcpu_write (int addr, t_uint64); #define NUM_DEVS_TU 1 #define NUM_DEVS_PMP WAITS #define NUM_DEVS_DKB WAITS -#define NUM_DEVS_PD ITS +#define NUM_DEVS_PD ITS | KL_ITS #define NUM_DEVS_IMX ITS #define NUM_DEVS_STK ITS #define NUM_DEVS_TK10 ITS diff --git a/makefile b/makefile index 90f0364..c0fb224 100644 --- a/makefile +++ b/makefile @@ -1269,7 +1269,7 @@ KL10D = PDP10 KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \ ${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rp.c \ ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c ${KL10D}/kx10_imp.c \ - ${KL10D}/kl10_fe.c + ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT} PDP1D = PDP1 From 42721f499e7f75bec09d11be6c039f356b44e56c Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 13 Sep 2019 22:04:42 -0400 Subject: [PATCH 10/98] KA10: Updated KL10 to start to work correctly. Tops10 now working. --- PDP10/kl10_fe.c | 328 +++++++++++++++++++++++++++++++++++----------- PDP10/kx10_cpu.c | 120 +++++++++++------ PDP10/kx10_defs.h | 7 +- PDP10/kx10_sys.c | 18 ++- 4 files changed, 350 insertions(+), 123 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 0f7f4c3..ebaf7c2 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -104,8 +104,8 @@ #define SEC_RTM 05400 #define SEC_CMDMSK 07400 #define DTE_MON 00000001 /* Save in unit1 STATUS */ -#define SEC_CLK 00000001 /* Clock enabled */ -#define DTE_ACK_CTY 00000002 /* Send CTY Ack */ +#define SEC_CLK 00000002 /* Clock enabled */ +#define ITS_ON 00000004 /* ITS Is alive */ /* Primary or Queued protocol addresses */ #define PRI_CMTW_0 0 @@ -157,6 +157,20 @@ #define PRI_EMCLK 007 /* Clock */ #define PRI_EMFED 010 /* Front end device */ +#if KL_ITS +/* ITS Timesharing protocol locations */ +#define ITS_DTEVER 0400 /* Protocol version and number of devices */ +#define ITS_DTECHK 0401 /* Increment at 60Hz. Ten setom 2 times per second */ +#define ITS_DTEINP 0402 /* Input from 10 to 11. Line #, Count */ +#define ITS_DTEOUT 0403 /* Output from 10 to 11 Line #, Count */ +#define ITS_DTELSP 0404 /* Line # to set speed of */ +#define ITS_DTELPR 0405 /* Parameter */ +#define ITS_DTEOST 0406 /* Line # to start output on */ +#define ITS_DTETYI 0410 /* Received char (Line #, char) */ +#define ITS_DTEODN 0411 /* Output done (Line #, buffer size) */ +#define ITS_DTEHNG 0412 /* Hangup/dialup */ +#endif + #define TMR_RTC 2 extern int32 tmxr_poll; @@ -164,6 +178,9 @@ t_stat dte_devio(uint32 dev, uint64 *data); int dte_devirq(uint32 dev, int addr); void dte_second(UNIT *uptr); void dte_primary(UNIT *uptr); +#if KL_ITS +void dte_its(UNIT *uptr); +#endif void dte_transfer(UNIT *uptr); void dte_function(UNIT *uptr); int dte_start(UNIT *uptr); @@ -178,6 +195,11 @@ t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cpt const char *dte_description (DEVICE *dptr); extern uint64 SW; /* Switch register */ +#if KL_ITS +#define QITS (cpu_unit[0].flags & UNIT_ITSPAGE) +#else +#define QITS 0 +#endif #define STATUS u3 #define CNT u4 @@ -319,6 +341,7 @@ DEVICE lpt_dev = { #if (NUM_DEVS_TTY > 0) struct _buffer tty_out[NUM_LINES_TTY], tty_in[NUM_LINES_TTY]; +struct _buffer tty_done, tty_hang; TMLN tty_ldsc[NUM_LINES_TTY] = { 0 }; /* Line descriptors */ TMXR tty_desc = { NUM_LINES_TTY, 0, 0, tty_ldsc }; int tty_connect[NUM_LINES_TTY];; @@ -479,6 +502,14 @@ void dte_second(UNIT *uptr) { #endif /* read command */ word = M[SEC_DTCMD + base]; +#if KL_ITS + if (word == 0 && QITS && (uptr->STATUS & ITS_ON) != 0) { + dte_its(uptr); + uptr->STATUS |= DTE_10DB; + uptr->STATUS &= ~DTE_11DB; + return; + } +#endif /* Do it */ sim_debug(DEBUG_DETAIL, &dte_dev, "CTY secondary %012llo\n", word); switch(word & SEC_CMDMSK) { @@ -564,11 +595,142 @@ enter_pri: break; } /* Acknowledge command */ + M[SEC_DTCMD + base] = 0; M[SEC_DTFLG + base] = FMASK; uptr->STATUS |= DTE_10DB; uptr->STATUS &= ~DTE_11DB; } +#if KL_ITS +void dte_its(UNIT *uptr) { + uint64 word; + char ch; + uint16 data; + int cnt; + int ln; + t_stat r; + + /* Check for output Start */ + word = M[ITS_DTEOST]; + if ((word & SMASK) == 0) { + if (((tty_done.in_ptr + 1) & 0xff) != tty_done.out_ptr) { + tty_done.buff[tty_done.in_ptr] = (char)(word & 0xff); + tty_done.in_ptr = (tty_done.in_ptr + 1) & 0xff; + M[ITS_DTEOST] = FMASK; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOST = %012llo\n", word); + } + } + /* Check for input Start */ + word = M[ITS_DTEINP]; + if ((word & SMASK) == 0) { + M[ITS_DTEINP] = FMASK; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEINP = %012llo\n", word); + } + /* Check for output Start */ + word = M[ITS_DTEOUT]; + if ((word & SMASK) == 0) { + cnt = word & 017777; + ln = ((word >> 18) & 077) - 1; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word); + while (cnt > 0) { + if (ln < 0) { + if (!Mem_read_byte(0, &data)) + return; + ch = (data >> 8) & 0177; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY type %x\n", ch); + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + if ((r = sim_putchar_s (ch)) != SCPE_OK) /* Output errors */ + return; + cnt--; + if (cnt) { + ch = data & 0177; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY type %x\n", ch); + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + if ((r = sim_putchar_s (ch)) != SCPE_OK) /* Output errors */ + return; + cnt--; + } + } else { + if (!Mem_read_byte(0, &data)) + return; + ch = (data >> 8) & 0177; + if (((tty_out[ln].in_ptr + 1) & 0xff) == tty_out[ln].out_ptr) + return; + sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln); + tty_out[ln].buff[tty_out[ln].in_ptr] = ch; + tty_out[ln].in_ptr = (tty_out[ln].in_ptr + 1) & 0xff; + cnt--; + if (cnt) { + ch = data & 0177; + if (((tty_out[ln].in_ptr + 1) & 0xff) == tty_out[ln].out_ptr) + return; + sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln); + tty_out[ln].buff[tty_out[ln].in_ptr] = ch; + tty_out[ln].in_ptr = (tty_out[ln].in_ptr + 1) & 0xff; + cnt--; + } + } + } + /* If on CTY Queue output done response */ + if (ln < 0) { + if (((tty_done.in_ptr + 1) & 0xff) != tty_done.out_ptr) { + tty_done.buff[tty_done.in_ptr] = (char)(0 & 0xff); + tty_done.in_ptr = (tty_done.in_ptr + 1) & 0xff; + } + } + M[ITS_DTEOUT] = FMASK; + uptr->STATUS |= DTE_11DN; + if (uptr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, uptr->STATUS); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word); + } + /* Check for line speed */ + word = M[ITS_DTELSP]; + if ((word & SMASK) == 0) { + M[ITS_DTELSP] = FMASK; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTELSP = %012llo %012llo\n", word, M[ITS_DTELPR]); + } +#if 0 + /* Check for input */ + word = M[ITS_DTETYI]; + if ((word & SMASK) != 0) { + int l = uptr->CNT; + do { + if (tty_connect[l]) { +// if ((ch = dte_unit[1].CHHOLD) != 0) { +// word = ch; +// dte_unit[1].CHHOLD = 0; +// M[ITS_DTETYI] = word; +// /* Tell 10 something is ready */ +// uptr->STATUS |= DTE_10DB; +// if (uptr->STATUS & DTE_PIE) +// set_interrupt(DTE_DEVNUM, uptr->STATUS); +// } + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); + } +#endif + /* Check for output done */ + word = M[ITS_DTEODN]; + if ((word & SMASK) != 0) { + if (tty_done.in_ptr != tty_done.out_ptr) { + ln = tty_done.buff[tty_done.out_ptr]; + tty_done.out_ptr = (tty_done.out_ptr + 1) & 0xff; + word = M[ITS_DTEODN] = (((uint64)ln) << 18)|1; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo\n", word); + /* Tell 10 something is ready */ + uptr->STATUS |= DTE_10DB; + if (uptr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, uptr->STATUS); + } + } + /* Check for hangup */ + word = M[ITS_DTEHNG]; + if ((word & SMASK) == 0) { + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEHNG = %012llo\n", word); + } +} +#endif + /* Handle primary protocol */ void dte_primary(UNIT *uptr) { uint64 word, iword; @@ -1049,10 +1211,12 @@ t_stat dtei_svc (UNIT *uptr) uint16 data1; #if KI_22BIT +#if KL_ITS + if ((cpu_unit[0].flags & UNIT_ITSPAGE) == 0) +#endif base = eb_ptr; #endif - - sim_clock_coschedule (uptr, 1000); + sim_activate (uptr, 1000); if ((uptr->STATUS & DTE_SEC) == 0) { dte_function(uptr); /* Process queue */ dte_start(optr); @@ -1067,6 +1231,24 @@ t_stat dtei_svc (UNIT *uptr) uptr->CHHOLD = ch; } sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %x\n", ch); +#if KL_ITS + if (QITS && (optr->STATUS & ITS_ON) != 0) { + uint64 word = M[ITS_DTETYI]; + if ((word & SMASK) != 0) { + if (ch != 0) { + word = ch; + uptr->CHHOLD = 0; + M[ITS_DTETYI] = word; + /* Tell 10 something is ready */ + optr->STATUS |= DTE_10DB; + if (optr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, optr->STATUS); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); + } + } + return SCPE_OK; + } +#endif if (optr->STATUS & DTE_SEC) { if (optr->STATUS & DTE_MON && M[SEC_DTMTI + base] == 0) { sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %x\n", ch & 0177); @@ -1078,6 +1260,10 @@ t_stat dtei_svc (UNIT *uptr) uptr->CHHOLD = 0; } } else { +#if KL_ITS + if (QITS) + return SCPE_OK; +#endif data1 = (PRI_EMCTY << 8) | ch; if (dte_queue(uptr, PRI_EMLNC, PRI_EMCTY, 1, &data1) != 0) uptr->CHHOLD = 0; @@ -1091,7 +1277,6 @@ dtertc_srv(UNIT * uptr) int32 t; UNIT *optr = &dte_unit[0]; - t = sim_rtcn_calb (rtc_tps, TMR_RTC); sim_activate_after(uptr, 1000000/rtc_tps); if (uptr->STATUS & SEC_CLK) { rtc_tick++; @@ -1111,6 +1296,22 @@ dtertc_srv(UNIT * uptr) rtc_tick, rtc_wait, optr->STATUS); } } +#if KL_ITS + if (QITS) { + uint64 word; + + word = (M[ITS_DTECHK] + 1) & FMASK; + if (word == 0) { + optr->STATUS |= ITS_ON; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS ON\n"); + } else if (word >= (15 * 60)) { + optr->STATUS &= ~ITS_ON; + word = 15 * 60; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS OFF\n"); + } + M[ITS_DTECHK] = word; + } +#endif if ((optr->STATUS & DTE_SEC) == 0) { int addr = 0144 + eb_ptr; uint64 word; @@ -1409,9 +1610,7 @@ const char *lpt_description (DEVICE *dptr) t_stat ttyi_svc (UNIT *uptr) { int32 ln; - int n = 0; TMLN *lp; - uint16 data1[32]; int flg; if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ @@ -1419,68 +1618,45 @@ t_stat ttyi_svc (UNIT *uptr) sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */ - /* Check if room in queue for at least one packet */ - if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { - sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n", - dte_out_res, dte_out_ptr); - return SCPE_OK; + /* If we have room see if any new lines */ + if (((tty_hang.in_ptr + 1) & 0xff) != tty_hang.out_ptr) { + ln = tmxr_poll_conn (&tty_desc); /* look for connect */ + if (ln >= 0) { /* got one? rcv enb*/ + tty_hang.buff[tty_hang.in_ptr] = ln + 1; + tty_hang.in_ptr = (tty_hang.in_ptr + 1) & 0xff; + tty_connect[ln] = 1; + sim_debug(DEBUG_DETAIL, &tty_dev, "TTY line connect %d\n", ln); + } } - ln = tmxr_poll_conn (&tty_desc); /* look for connect */ - if (ln >= 0) { /* got one? rcv enb*/ - tty_ldsc[ln].rcve = 1; - tty_ldsc[ln].xmte = 1; - data1[0] = ((ln + 1) << 8) | (ln + 1); - tty_connect[ln] = 1; - (void)dte_queue(&dte_unit[0], PRI_EMDSC, PRI_EMDLS, 1, data1); -// data1[0] = (ln + 1) << 8; - // /* Send out any data we got */ - // (void)dte_queue(&dte_unit[0], PRI_EMACK, PRI_EMDLS, 1, data1); - sim_debug(DEBUG_DETAIL, &tty_dev, "TTY line connect %d\n", ln); - } tmxr_poll_tx(&tty_desc); tmxr_poll_rx(&tty_desc); - /* Check if room in queue for at least one packet */ - if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { - sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n", - dte_out_res, dte_out_ptr); - return SCPE_OK; - } - ln = uptr->CNT; - do { - flg = 0; - lp = &tty_ldsc[ln]; - /* Check to see if any pending data for this line */ - if (lp->rcve && tmxr_input_pending_ln(lp) > 0) { - int32 ch = tmxr_getc_ln (lp); - sim_debug(DEBUG_DETAIL, &tty_dev, "TTY recieve %d: %02x\n", ln, ch); - if ((ch & SCPE_BREAK) == 0) { /* break? */ - ch = sim_tt_inpcvt (ch, TT_GET_MODE(tty_unit[0].flags) | TTUF_KSR); - data1[n++] = ((ln + 1) << 8) | ch; - } - flg = 1; - } - if (++ln >= tty_desc.lines) - ln = 0; - } while (flg && n < 32); - uptr->CNT = ln; - - /* Send out any data we got */ - if (n > 0) - (void)dte_queue(&dte_unit[0], PRI_EMLNC, PRI_EMDLS, n, data1); - - /* Look for lines that have been disconnected */ + /* Scan each line for input */ for (ln = 0; ln < tty_desc.lines; ln++) { - if (tty_connect[ln] == 1 && tty_ldsc[ln].conn == 0) { - data1[0] = (ln + 1) << 8; - if (dte_queue(&dte_unit[0], PRI_EMHUD, PRI_EMDLS, 1, data1) != 0) { - /* Check if disconnect */ + lp = &tty_ldsc[ln]; + flg = 1; + /* Spool up as much as we have room for */ + while (flg && ((tty_out[ln].in_ptr + 1) & 0xff) != tty_out[ln].out_ptr) { + int32 ch = tmxr_getc_ln(lp); + if ((ch & TMXR_VALID) != 0) { + ch = sim_tt_inpcvt (ch, TT_GET_MODE(tty_unit[0].flags) | TTUF_KSR); + tty_in[ln].buff[tty_in[ln].in_ptr] = ch & 0377; + tty_in[ln].in_ptr = (tty_in[ln].in_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &tty_dev, "TTY recieve %d: %02x\n", ln, ch); + } else + flg = 0; + } + /* Look for lines that have been disconnected */ + if (tty_connect[ln] == 1 && lp->conn == 0) { + if (((tty_hang.in_ptr + 1) & 0xff) != tty_hang.out_ptr) { + tty_hang.buff[tty_hang.in_ptr] = ln + 1; + tty_hang.in_ptr = (tty_hang.in_ptr + 1) & 0xff; tty_connect[ln] = 0; sim_debug(DEBUG_DETAIL, &tty_dev, "TTY line disconnect %d\n", ln); } } - } + } return SCPE_OK; } @@ -1503,14 +1679,10 @@ t_stat ttyo_svc (UNIT *uptr) lp = &tty_ldsc[ln]; if (lp->conn == 0) continue; + if (((tty_done.in_ptr + 1) & 0xff) == tty_done.out_ptr) + return SCPE_OK; if (tty_out[ln].out_ptr == tty_out[ln].in_ptr) continue; - /* Check if room in queue for at least one packet */ - if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { - sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n", - dte_out_res, dte_out_ptr); - return SCPE_OK; - } while (tty_out[ln].out_ptr != tty_out[ln].in_ptr) { int32 ch = tty_out[ln].buff[tty_out[ln].out_ptr]; ch = sim_tt_outcvt(ch, TT_GET_MODE (tty_unit[0].flags) | TTUF_KSR); @@ -1521,20 +1693,20 @@ t_stat ttyo_svc (UNIT *uptr) else if (r == SCPE_LOST) { tty_out[ln].out_ptr = tty_out[ln].in_ptr = 0; continue; - } + } else + continue; } - data1[n++] = (ln + 1) << 8; - /* Send out any data we got */ - if (n > 32) { - (void)dte_queue(&dte_unit[0], PRI_EMACK, PRI_EMDLS, n, data1); - n = 0; - } - } - - /* Send out any data we got */ - if (n > 0) - (void)dte_queue(&dte_unit[0], PRI_EMACK, PRI_EMDLS, n, data1); - + tty_done.buff[tty_done.in_ptr] = ln + 1; + tty_done.in_ptr = (tty_done.in_ptr + 1) & 0xff; +#if KL_ITS + /* Tell 10 we have something for it */ + if (QITS) { + dte_unit[0].STATUS |= DTE_10DB; + if (dte_unit[0].STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); + } +#endif + } return SCPE_OK; } diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index d8666c6..764afd1 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1206,8 +1206,10 @@ t_stat dev_pag(uint32 dev, uint64 *data) { case CONO: eb_ptr = (*data & 017777) << 9; - for (i = 0; i < 512; i++) + for (i = 0; i < 512; i++) { e_tlb[i] = 0; + u_tlb[i] = 0; + } for (;i < 546; i++) u_tlb[i] = 0; page_enable = (*data & 020000) != 0; @@ -1224,17 +1226,17 @@ t_stat dev_pag(uint32 dev, uint64 *data) { page &= ~7; /* Map the page */ - for(i = 0; i < 8; i++) + for(i = 0; i < 8; i++) { u_tlb[page+i] = 0; - for(i = 0; i < 8; i++) e_tlb[page+i] = 0; + } /* If not user do exec mappping */ if (/*!uf && !t20_page &&*/ (page & 0740) == 0340) { /* Pages 340-377 via UBT */ page += 01000 - 0340; upmp = 1; - for(i = 0; i < 8; i++) - u_tlb[page+i] = 0; + for(i = 0; i < 8; i++) + u_tlb[page+i] = 0; } } else { res = *data; @@ -1257,8 +1259,10 @@ t_stat dev_pag(uint32 dev, uint64 *data) { } if (res & BIT2) { ub_ptr = (res & 017777) << 9; - for (i = 0; i < 512; i++) + for (i = 0; i < 512; i++) { u_tlb[i] = 0; + e_tlb[i] = 0; + } for (;i < 546; i++) u_tlb[i] = 0; } @@ -1290,6 +1294,7 @@ t_stat dev_pag(uint32 dev, uint64 *data) { */ t_stat dev_cca(uint32 dev, uint64 *data) { irq_flags |= 020; + *data = 0; check_apr_irq(); return SCPE_OK; } @@ -1618,8 +1623,8 @@ t_stat dev_pag(uint32 dev, uint64 *data) { e_tlb[i] = u_tlb[i] = 0; for (;i < 546; i++) u_tlb[i] = 0; - user_addr_cmp = (res & 00020000000000LL) != 0; - small_user = (res & 00040000000000LL) != 0; + user_addr_cmp = (res & BIT4) != 0; + small_user = (res & BIT3) != 0; fm_sel = (uint8)(res >> 29) & 060; } pag_reload = 0; @@ -1634,9 +1639,9 @@ t_stat dev_pag(uint32 dev, uint64 *data) { res |= 020000; res |= ((uint64)(ub_ptr)) << 9; if (user_addr_cmp) - res |= 00020000000000LL; + res |= BIT4; if (small_user) - res |= 00040000000000LL; + res |= BIT3; res |= ((uint64)(fm_sel)) << 29; *data = res; sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI PAG %012llo\n", *data); @@ -1933,9 +1938,19 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) data &= RMASK; pg = 0; switch(data >> 16) { - case 0: break; /* No access */ + case 0: + fault_data = 033LL << 30 |((uf)?SMASK:0); + page_fault = 1; + return 0; /* No access */ case 1: /* Read Only */ - case 2: pg = RSIGN; break; /* R/W First */ + case 2: /* R/W First */ + if (wr) { + fault_data = 024LL << 30 |((uf)?SMASK:0); + page_fault = 1; + return 0; + } + pg = RSIGN; + break; case 3: pg = RSIGN|0100000; break; /* R/W */ } pg |= (data & 017777) << 1; @@ -2257,8 +2272,16 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch /* If not valid, go refill it */ if (data == 0) { data = load_tlb(uf, page, upmp, wr, 1, flag); - if (data == 0 && page_fault) + if (data == 0 && page_fault) { + fault_data |= ((uint64)addr); +#if KL_ITS + if (QITS && (xct_flag & 020) != 0) { + PC = (PC + 1) & AMASK; + page_fault = 0; + } +#endif return 0; + } } *loc = ((data & 017777) << 9) + (addr & 0777); @@ -2283,23 +2306,33 @@ fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) } else { e_tlb[page] = 0; } - if (data & 0400000LL) /* A */ - fault_data |= 00100000000000LL; /* BIT2 */ - if (data & 0200000LL) /* P */ - fault_data |= 00004000000000LL; /* BIT6 */ - if (data & 0100000LL) /* W */ - fault_data |= 00040000000000LL; /* BIT3 */ - if (data & 0040000LL) /* S */ - fault_data |= 00020000000000LL; /* BIT4 */ - if (wr) /* T */ - fault_data |= 00010000000000LL; /* BIT5 */ if (data & 0020000LL) /* C */ - fault_data |= 00002000000000LL; /* BIT7 */ + fault_data |= BIT7; /* BIT7 */ + if (data & 0200000LL) /* P */ + fault_data |= BIT6; /* BIT6 */ #if KL_ITS - if (QITS && (xct_flag & 020) != 0) - PC = (PC + 1) & AMASK; - else + if (QITS) { + if ((xct_flag & 020) != 0) { + PC = (PC + 1) & AMASK; + page_fault = 0; + } else if ((data & RSIGN) == 0) { + fault_data = ((uint64)addr) | 033LL << 30 |((uf)?SMASK:0); + page_fault = 1; + } else {// if (wr & ((data & 0100000) == 0)) { + fault_data = ((uint64)addr) | 024LL << 30 |((uf)?SMASK:0); + page_fault = 1; + } + return 0; + } #endif + if (wr) /* T */ + fault_data |= BIT5; /* BIT5 */ + if (data & 0040000LL) /* S */ + fault_data |= BIT4; /* BIT4 */ + if (data & 0100000LL) /* W */ + fault_data |= BIT3; /* BIT3 */ + if (data & 0400000LL) /* A */ + fault_data |= BIT2; /* BIT2 */ page_fault = 1; return 0; } @@ -4255,7 +4288,7 @@ unasign: brk_flags = 017 & (MB >> 23); AB = (AB + 1) & RMASK; MB = M[AB]; /* WD 2 */ - fault_data = MB; + FM[(6<<4)|0] = MB; AB = (AB + 1) & RMASK; MB = M[AB]; /* WD 3 */ dbr1 = MB; @@ -4279,7 +4312,7 @@ unasign: MB |= ((uint64)brk_flags) << 23; M[AB] = MB; /* WD 1 */ AB = (AB + 1) & RMASK; - MB = fault_data; + MB = FM[(6<<4)|0]; M[AB] = MB; /* WD 2 */ AB = (AB + 1) & RMASK; MB = dbr1; @@ -6718,7 +6751,6 @@ xjrstf: goto xjrstf; /* Fall through */ - case 002: /* JRSTF */ BR = AR >> 23; /* Move into position */ jrstf: @@ -6932,8 +6964,8 @@ jrstf: if (!page_enable || AB < 020) { AR = AB; /* direct map */ if (flag1) /* U */ - AR |= SMASK; /* BIT8 */ - AR |= BIT8|BIT2|00040000000000LL; /* BIT3 */ + AR |= SMASK; /* BIT0 */ + AR |= BIT2|BIT3|BIT4|BIT8; set_reg(AC, AR); break; } @@ -6952,16 +6984,16 @@ jrstf: if (BR & 0400000LL) { /* A */ AR = ((AR & 017777LL) << 9) + (AB & 0777); if (flag1) /* U */ - AR |= SMASK; /* BIT8 */ - AR |= 00100000000000LL; /* BIT2 */ + AR |= SMASK; /* BIT0 */ + AR |= BIT2; /* BIT2 */ if (BR & 0200000LL) /* P */ - AR |= 00004000000000LL; /* BIT6 */ + AR |= BIT6; /* BIT6 */ if (BR & 0100000LL) /* W */ - AR |= 00040000000000LL; /* BIT3 */ + AR |= BIT3; /* BIT3 */ if (BR & 0040000LL) /* S */ - AR |= 00020000000000LL; /* BIT4 */ + AR |= BIT4; /* BIT4 */ if (BR & 0020000LL) /* C */ - AR |= 00002000000000LL; /* BIT7 */ + AR |= BIT7; /* BIT7 */ } else AR = (f & 01740) ? 0 : 0377777LL; AR |= BIT8; @@ -7730,6 +7762,12 @@ test_op: goto muuo; } else { int d = ((IR & 077) << 1) | ((AC & 010) != 0); +#if KL + if (d == 3) { + irq_flags |= 020; + goto last; + } +#endif fetch_opr: switch(AC & 07) { case 0: /* 00 BLKI */ @@ -7864,6 +7902,12 @@ last: } fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); BYF5 = 0; +#if KL_ITS + if (QITS) { + AB = eb_ptr + 0500; + FM[(6<<4)|0] = fault_data; + } else +#endif AB = ub_ptr + 0500; MB = fault_data; Mem_write_nopage(); diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 6ea79cd..bbaff38 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -174,6 +174,9 @@ extern DEBTAB crd_debug[]; #define BIT1 00200000000000LL #define BIT2 00100000000000LL #define BIT3 00040000000000LL +#define BIT4 00020000000000LL +#define BIT5 00010000000000LL +#define BIT6 00004000000000LL #define BIT7 00002000000000LL #define BIT8 00001000000000LL #define BIT9 00000400000000LL @@ -405,6 +408,7 @@ extern DEVICE pmp_dev; extern DEVICE dk_dev; extern DEVICE pd_dev; extern DEVICE dpy_dev; +extern DEVICE iii_dev; extern DEVICE imx_dev; extern DEVICE imp_dev; extern DEVICE ch10_dev; @@ -514,7 +518,7 @@ int auxcpu_write (int addr, t_uint64); #define NUM_DEVS_DK 0 #define NUM_DEVS_DP 0 #define NUM_DEVS_TTY 1 -#define NUM_LINES_TTY 16 +#define NUM_LINES_TTY 40 #else #define NUM_DEVS_RC 1 #define NUM_DEVS_DT 1 @@ -527,6 +531,7 @@ int auxcpu_write (int addr, t_uint64); #define NUM_DEVS_TU 1 #define NUM_DEVS_PMP WAITS #define NUM_DEVS_DKB WAITS +#define NUM_DEVS_III 0 #define NUM_DEVS_PD ITS | KL_ITS #define NUM_DEVS_IMX ITS #define NUM_DEVS_STK ITS diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index 6febd27..a7ae6e1 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -42,11 +42,8 @@ sim_load binary loader */ -#if KLB -char sim_name[] = "KL-10B"; -#endif -#if KLA -char sim_name[] = "KL-10A"; +#if KL +char sim_name[] = "KL-10"; #endif #if KI char sim_name[] = "KI-10"; @@ -162,6 +159,9 @@ DEVICE *sim_devices[] = { &wcnsls_dev, #endif #endif +#if (NUM_DEVS_III > 0) + &iii_dev, +#endif #if NUM_DEVS_IMP > 0 &imp_dev, #endif @@ -203,7 +203,8 @@ DEVICE *sim_devices[] = { const char *sim_stop_messages[] = { "Unknown error", "HALT instruction", - "Breakpoint" + "Breakpoint", + "Invalid access" }; /* Simulator debug controls */ @@ -556,6 +557,7 @@ t_stat load_sav (FILE *fileref) wc = (int32)(data >> 18); pa = (uint32) (data & RMASK); if (wc == (OP_JRST << 9)) { + printf("Start addr=%06o\n", pa); PC = pa; return SCPE_OK; } @@ -673,12 +675,16 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */ if (get_word(fileref, &pagbuf[k])) return SCPE_FMT; } +// wc = sim_fread (pagbuf, sizeof (uint64), PAG_SIZE, fileref); + // if (wc < PAG_SIZE) + // return SCPE_FMT; fpage++; } ma = mpage << PAG_V_PN; /* mem addr */ for (k = 0; k < PAG_SIZE; k++, ma++) { /* copy buf to mem */ if (ma > MEMSIZE) return SCPE_NXM; +fprintf(stderr, "M %06o %012llo\n", ma, pagbuf[k]); M[ma] = fpage? (pagbuf[k] & FMASK): 0; } /* end copy */ } /* end rpt */ From f0715d2bbbfab4cfc39589b71addeb0e5c17557d Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 13 Sep 2019 22:10:20 -0400 Subject: [PATCH 11/98] KA10: Start of WAITS III Display. --- PDP10/ka10_iii.c | 622 ++++++++++++++++++++++++++++++++++++++++++++++ PDP10/kx10_defs.h | 2 +- makefile | 2 +- 3 files changed, 624 insertions(+), 2 deletions(-) create mode 100644 PDP10/ka10_iii.c diff --git a/PDP10/ka10_iii.c b/PDP10/ka10_iii.c new file mode 100644 index 0000000..59a73c8 --- /dev/null +++ b/PDP10/ka10_iii.c @@ -0,0 +1,622 @@ +/* ka10_iii.c: Triple III display processor. + + Copyright (c) 2013-2019, Richard Cornwell + + 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 + RICHARD CORNWELL 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 Richard Cornwell shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Richard Cornwell + +*/ + +#include "kx10_defs.h" +#ifndef NUM_DEVS_III +#define NUM_DEVS_III 0 +#endif + +#if NUM_DEVS_III > 0 +#include "display/display.h" + + +#define III_DEVNUM 0430 + +#define STATUS u3 +#define MAR u4 +#define PIA u5 +#define POS u6 + +/* CONO Bits */ +#define SET_PIA 000000010 /* Set if this bit is zero */ +#define STOP 000000020 /* Stop processor after instruction */ +#define CONT 000000040 /* Start execution at address */ +#define F 000000100 /* Clear flags */ +#define SET_MSK 000360000 /* Set mask */ +#define RST_MSK 007400000 /* Reset mask */ + +/* CONI Bits */ +#define PIA_MSK 000000007 +#define INST_HLT 000000010 /* Halt instruction */ +#define WRAP_ENB 000000020 /* Wrap around mask */ +#define EDGE_ENB 000000040 /* Edge interrupt mask */ +#define LIGH_ENB 000000100 /* Light pen enable mask */ +#define CLK_STOP 000000200 /* Clock stop */ +#define CLK_BIT 000001000 /* Clock */ +#define NXM_BIT 000002000 /* Non-existent memory */ +#define IRQ_BIT 000004000 /* Interrupt pending */ +#define DATAO_LK 000010000 /* PDP10 gave DATAO when running */ +#define LIGHT_FLG 000020000 /* Light pen flag */ +#define WRAP_FLG 000040000 /* Wrap around flag */ +#define EDGE_FLG 000100000 /* Edge overflow */ +#define HLT_FLG 000200000 /* Not running */ + +#define WRAP_MSK 00001 +#define EDGE_MSK 00002 +#define LIGH_MSK 00004 +#define HLT_MSK 00010 +#define WRP_FBIT 00020 +#define EDG_FBIT 00040 +#define LIT_FBIT 00100 +#define CTL_FBIT 00200 +#define HLT_FBIT 00400 +#define NXM_FLG 01000 +#define DATA_FLG 02000 +#define RUN_FLG 04000 + +#define TSS_INST 012 /* Test */ +#define LVW_INST 006 /* Long Vector */ +#define SVW_INST 002 /* Short vector */ +#define JMP_INST 000 /* Jump or Halt */ +#define JSR_INST 004 /* JSR(1) or JMS(0), SAVE(3) */ +#define RES_INST 014 /* Restore */ +#define SEL_INST 010 /* Select instruction */ + +#define CSIZE 00000000007 /* Current char size */ +#define CBRT 00000000070 /* Current brightness */ +#define POS_Y 00000377700 +#define POS_X 01777400000 +#define CSIZE_V 0 +#define CBRT_V 3 +#define POS_X_V 6 +#define POS_Y_V 16 + +/* + * Character map. + * M(x,y) moves pointer to x,y. + * V(x,y) draws a vector between current pointer and x,y. + * All characters start at 0,6 and end at 8,6. + * In the map there are up to 18 points per character. For a character a M(0,0) indicates + * that drawing is done and a move to 8,6 should be done. + */ +#define M(x,y) (x << 4)|y|0000 +#define V(x,y) (x << 4)|y|0200 + +uint8 map[128][18] = { + { 0 }, + { M(0,9), V(3,6), V(3,14), M(3,6), V(6,9) }, + { M(6,6), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(6,9) }, + { V(2,8), V(2,13), V(3,14), V(5,14), V(6,13), V(6,12), V(5,11), V(2,11), M(5,11), + V(6,10), V(6,9), V(5,8), V(3,8), V(2,9) }, + { M(0,8), V(3,11), V(6,8) }, + { M(0,10), V(6,10), V(6,7) }, + { M(3,9), V(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(2,6), V(3,7), M(2,8), V(0,8) }, + { M(0,10), V(6,10), M(4,10), V(4,6), M(2,6), V(2,10) }, + { V(3,9), M(0,11), V(1,11), V(6,6) }, + { M(0,11), V(1,12), V(2,12), V(5,9), V(5,7), V(4,6), V(3,6), V(2,7), V(2,8), V(6,12) }, + { M(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9), V(3,10), V(2,10), + V(2,12), V(4,12) }, + { M(0,7), V(1,6), V(2,6), V(3,7), V(3,12), V(4,13), V(5,13), V(6,12) }, + { M(0,9), V(4,9), M(2,11), V(2,7), M(0,7), V(4,7) }, + { M(0,8), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9), V(3,10), V(1,10), V(0,9), V(0,8), + V(4,8), M(2,10), V(2,6) }, + { M(0,10), V(1,9), V(2,9), V(4,11), V(5,11), V(6,10), V(5,9), V(4,9), V(2,11), V(1,11), + V(0,10) }, + { M(4,8), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(4,7), V(4,10), V(2,12), + V(1,12) }, + { M(3,11), V(1,11), V(0,10), V(0,8), V(1,7), V(3,7) }, + { M(0,11), V(2,11), V(3,10), V(3,8), V(2,7), V(0,7) }, + { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7) }, + { M(0,10), V(0,8), V(1,7), V(3,7), V(4,8), V(4,10) }, + { M(0,13), V(0,8), V(2,6), V(4,6), V(6,8), V(6,13), M(0,10), V(6,10) }, + { V(6,6), V(6,14), V(0,14), M(2,10), V(6,10) }, + { V(4,10), M(0,10), V(4,6), M(3,6), V(1,6), V(0,7), V(0,9), V(1,10), V(3,10), V(4,9), + V(4,7), V(3,6) }, + { M(2,8), V(0,10), V(2,12), M(0,10), V(6,10), M(4,12), V(6,10), V(4,8) }, + { M(0,5), V(6,5) }, + { M(0,10), V(6,10), M(3,13), V(6,10), V(3,7) }, + { M(0,12), V(2,14), V(4,12), V(6,14) }, + { V(6,12), M(0,10), V(6,10), M(0,8), V(6,8) }, + { V(3,6), M(3,7), V(0,10), V(3,13) }, + { V(3,6), M(0,7), V(3,10), V(0,13) }, + { M(0,7), V(6,7), M(6,9), V(0,9), M(0,11), V(6,11) }, + { M(0,11), V(3,8), V(6,11) }, + { }, + { M(2,6), V(2,7), M(2,8), V(2,13) }, + { M(2,12), V(2,14), M(4,14), V(4,12) }, + { M(2,7), V(2,13), M(4,13), V(4,7), M(6,9), V(0,9), M(0,11), V(6,11) }, + { M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14), V(4,14), V(6,12), + M(4,14), V(4,6), M(2,6), V(2,14) }, + { V(6,12), V(1,12), V(0,11), V(0,10), V(1,9), V(2,9), V(3,10), V(3,11), V(2,12), M(4,9), + V(3,8), V(3,7), V(4,6), V(5,6), V(6,7), V(6,8), V(5,9), V(4,9) }, + { M(6,6), V(1,11), V(1,13), V(2,14), V(3,14), V(4,13), V(0,9), V(0,7), V(1,6), V(3,6), + V(5,8) }, + { M(2,12), V(4,14) }, + { M(2,6), V(0,8), V(0,12), V(2,14) }, + { V(2,8), V(2,12), V(0,14) }, + { M(1,8), V(5,12), M(3,13), V(3,7), M(5,8), V(1,12), M(0,10), V(6,10) }, + { M(2,7), V(2,11), M(0,9), V(4,9) }, + { M(0,7), V(1,6), V(1,5), V(0,4) }, + { M(0,9), V(4,9) }, + { M(2,6), V(3,6), V(3,7), V(2,7), V(2,6) }, + { V(6,12) }, + { M(0,7), V(6,13), M(6,12), V(4,14), V(2,14), V(0,12), V(0,8), V(2,6), V(4,6), V(6,8), + V(6,12) }, + { M(1,12), V(3,14), V(3,6) }, + { M(0,13), V(1,14), V(4,14), V(6,12), V(6,11), V(5,10), V(2,10), V(0,8), V(0,6), V(6,6) }, + { M(0,14), V(6,14), V(6,12), V(4,10), V(5,10), V(6,9), V(6,7), V(5,6), V(0,6) }, + { M(5,6), V(5,14), V(0,9), V(6,9) }, + { M(0,7), V(1,6), V(4,6), V(6,8), V(6,9), V(5,10), V(1,10), V(0,9), V(0,14), V(6,14) }, + { M(0,9), V(1,10), V(5,10), V(6,9), V(6,7), V(5,6), V(1,6), V(0,7), V(0,10), V(4,14) }, + { V(6,12), V(6,14), V(0,14) }, + { M(1,10), V(0,9), V(0,7), V(1,6), V(5,6), V(6,7), V(6,9), V(5,10), V(6,11), V(6,13), + V(5,14), V(1,14), V(0,13), V(0,11), V(1,10), V(5,10) }, + { M(2,6), V(6,10), V(6,13), V(5,14), V(1,14), V(0,13), V(0,11), V(1,10), V(5,10), + V(6,11) }, + { M(2,6), V(3,6), V(3,7), V(2,7), V(2,6), M(2,10), V(3,10), V(3,11), V(2,11), V(2,10) }, + { M(2,7), V(3,6), V(3,5), V(2,4), M(2,10), V(3,10), V(3,11), V(2,11), V(2,10) }, + { M(3,7), V(0,10), V(3,13) }, + { M(0,8), V(6,8), M(6,10), V(0,10) }, + { M(0,7), V(3,10), V(0,13) }, + { M(0,13), V(1,14), V(2,13), V(2,12), V(1,11), V(1,8), M(1,7), V(1,6) }, + { M(1,6), V(0,7), V(0,11), V(1,12), V(5,12), V(6,11), V(6,8), V(5,7), V(4,8), V(4,11), + M(4,10), V(3,11), V(2,11), V(1,10), V(1,9), V(2,8), V(3,8), V(4,9) }, + { V(0,12), V(2,14), V(4,14), V(6,12), V(6,9), V(0,9), V(6,9), V(6,6) }, + { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(5,10), V(6,9), V(6,7), V(5,6), + V(0,6) }, + { M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(5,6), V(6,7) }, + { V(0,14), V(4,14), V(6,12), V(6,8), V(4,6), V(0,6) }, + { M(6,6), V(0,6), V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) }, + { V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) }, + { M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(4,6), V(6,8), V(6,10), V(4,10) }, + { V(0,14), V(0,10), V(6,10), V(6,14), V(6,6) }, + { M(1,6), V(5,6), V(3,6), V(3,14), V(1,14), V(5,14) }, + { M(1,9), V(1,7), V(2,6), V(3,6), V(4,7), V(4,14), V(2,14), V(6,14) }, + { V(0,14), V(0,8), V(6,14), V(2,10), V(6,6) }, + { M(0,14), V(0,6), V(6,6) }, + { V(0,14), V(3,11), V(6,14), V(6,6) }, + { V(0,14), V(0,13), V(6,7), V(6,6), V(6,14) }, + { M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6), V(0,8) }, + { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10) }, + { M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6), V(0,8), M(3,9), + V(6,6) }, + { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(2,10), V(6,6) }, + { M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14), V(4,14), V(6,12) }, + { M(3,6), V(3,14), V(0,14), V(6,14) }, + { M(0,14), V(0,7), V(1,6), V(5,6), V(6,7), V(6,14) }, + { M(0,14), V(0,9), V(3,6), V(6,9), V(6,14) }, + { M(0,14), V(0,6), V(3,9), V(6,6), V(6,14) }, + { V(0,7), V(6,13), V(6,14), M(0,14), V(0,13), V(6,7), V(6,6) }, + { M(0,14), V(3,11), V(6,14), V(3,11), V(3,6) }, + { M(0,14), V(6,14), V(6,13), V(0,7), V(0,6), V(6,6) }, + { M(3,5), V(0,5), V(0,15), V(3,15) }, + { M(0,12), V(6,6) }, + { M(0,5), V(3,5), V(3,15), V(0,15) }, + { M(0,11), V(3,14), V(6,11), M(3,14), V(3,6) }, + { M(3,7), V(0,10), V(3,13), M(0,10), V(6,10) }, + { M(2,14), V(4,12) }, + { M(0,9), V(1,10), V(3,10), V(4,9), V(4,6), M(4,8), V(3,9), V(1,9), V(0,8), V(0,7), + V(1,6), V(3,6), V(4,7) }, + { V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) }, + { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7) }, + { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7), M(4,6), + V(4,13) }, + { M(4,7), V(3,6), V(1,6), V(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,8), V(0,8) }, + { M(2,6), V(2,12), V(3,13), V(4,13), V(5,12), M(0,11), V(4,11) }, + { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), M(4,10), V(4,5), + V(3,4), V(1,4), V(0,5) }, + { V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,6) }, + { M(3,12), V(3,11), M(3,10), V(3,7), V(4,6), V(5,6) }, + { M(3,12), V(3,11), M(3,10), V(3,5), V(2,4), V(1,3) }, + { V(0,13), M(0,8), V(2,10), M(0,8), V(2,6) }, + { M(2,6), V(2,13) }, + { V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6), M(3,9), V(4,10), V(5,10), V(6,9), + V(6,6) }, + { V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6) }, + { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) }, + { M(0,4), V(0,10), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) }, + { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), M(4,10), V(4,4) }, + { V(0,10), M(0,9), V(1,10), V(3,10), V(4,9) }, + { M(0,7), V(1,6), V(3,6), V(4,7), V(3,8), V(1,8), V(0,9), V(1,10), V(3,10), V(4,9) }, + { M(2,13), V(2,7), V(3,6), V(4,6), V(5,7), M(1,11), V(3,11) }, + { M(0,10), V(0,7), V(1,6), V(3,6), V(4,7), V(4,10), V(4,6) }, + { M(0,9), V(3,6), V(6,9) }, + { M(0,10), V(0,6), V(2,8), V(4,6), V(4,10) }, + { V(4,10), M(0,10), V(4,6) }, + { M(0,9), V(3,6), M(6,9), V(1,4), V(0,4) }, + { M(0,10), V(4,10), V(0,6), V(4,6) }, + { M(3,15), V(2,14), V(2,12), V(0,10), V(2,8), V(2,6), V(3,5) }, + { M(2,4), V(2,14) }, + { M(3,6), V(0,9), V(3,12), V(6,9), V(3,6) }, + { M(0,15), V(1,14), V(1,12), V(3,10), V(1,8), V(1,6), V(0,5) }, + { M(0,12), V(6,6) }, +}; + +uint64 iii_instr; /* Currently executing instruction */ +int iii_sel; /* Select mask */ + +t_stat iii_devio(uint32 dev, uint64 *data); +t_stat iii_svc(UNIT *uptr); +static void draw_point(int x, int y, int b); +static void draw_line(int x1, int y1, int x2, int y2, int b); +t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *iii_description (DEVICE *dptr); + +DIB iii_dib = { III_DEVNUM, 1, iii_devio, NULL}; + +UNIT iii_unit[] = { + {UDATA (&iii_svc, UNIT_IDLE, 0) }, + { 0 } + }; + + +MTAB iii_mod[] = { + { 0 } + }; + +DEVICE iii_dev = { + "III", iii_unit, NULL, iii_mod, + 2, 10, 31, 1, 8, 8, + NULL, NULL, NULL, + NULL, NULL, NULL, &iii_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS, 0, dev_debug, + NULL, NULL, &iii_help, NULL, NULL, &iii_description + }; + +int status; +t_stat iii_devio(uint32 dev, uint64 *data) { + UNIT *uptr = &iii_unit[0]; + switch(dev & 3) { + case CONI: + *data = (((uint64)iii_sel) << 18) | (uint64)(uptr->PIA); + if ((iii_instr & 037) == 0) + *data |= INST_HLT; + *data |= (uptr->STATUS & 07) << 4; + if (uptr->STATUS & NXM_FLG) + *data |= NXM_BIT; + if (uptr->STATUS & DATA_FLG) + *data |= DATAO_LK; + if ((uptr->STATUS & RUN_FLG) == 0) + *data |= HLT_FLG; + if (uptr->STATUS & WRP_FBIT) + *data |= WRAP_FLG; + if (uptr->STATUS & EDG_FBIT) + *data |= EDGE_FLG; + if (uptr->STATUS & LIT_FBIT) + *data |= LIGHT_FLG; + sim_debug(DEBUG_CONI, &iii_dev, "III %03o CONI %06o\n", dev, (uint32)*data); + break; + case CONO: + if (*data & SET_PIA) + uptr->PIA = (int)(*data&PIA_MSK); + if (*data & F) + uptr->STATUS &= ~(WRP_FBIT|EDG_FBIT|LIT_FBIT|DATA_FLG|NXM_FLG); + uptr->STATUS &= ~(017 & ((*data >> 14) ^ (*data >> 10))); + uptr->STATUS ^= (017 & (*data >> 10)); + if (*data & STOP) + uptr->STATUS |= RUN_FLG; + if (*data & CONT) { + uptr->STATUS &= ~RUN_FLG; + iii_instr = M[uptr->MAR]; + sim_activate(uptr, 10); + } + sim_debug(DEBUG_CONO, &iii_dev, "III %03o CONO %06o\n", dev, (uint32)*data); + break; + case DATAI: + sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAI %06o\n", dev, (uint32)*data); + break; + case DATAO: + if (uptr->STATUS & RUN_FLG) + uptr->STATUS |= DATA_FLG; + else { + iii_instr = *data; + sim_activate(uptr, 10); + } + sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAO %06o\n", dev, (uint32)*data); + break; + } + return SCPE_OK; +} + +t_stat +iii_svc (UNIT *uptr) +{ + uint64 temp; + int A; + int ox, oy, nx, ny, br, sz; + int i, j, ch; + switch(iii_instr & 017) { + case 000: /* JMP and HLT */ + if (iii_instr & 020) { + uptr->MAR = (iii_instr >> 18) & RMASK; + } else { + uptr->STATUS &= ~RUN_FLG; + } + break; + case 001: + case 003: + case 005: + case 007: + case 011: + case 013: + case 015: + case 017: /* Draw 4 characters */ + /* Extract X,Y,Bright and Size */ + sz = (uptr->POS & CSIZE) >> CSIZE_V; + br = (uptr->POS & CBRT) >> CBRT_V; + ox = (uptr->POS & POS_X) >> POS_X_V; + oy = (uptr->POS & POS_Y) >> POS_Y_V; + for (i = 29; i >= 1; i -= 7) { + /* Extract character and compute initial point */ + int cx, cy; + uint8 v; + ch = (iii_instr >> i) & 0177; + cx = ox; + cy = oy + (6 * sz); + /* Scan map and draw lines as needed */ + for(j = 0; j < 18; j++) { + v = map[i][j]; + if (v == 0) + break; + nx = cx + (((v >> 4) & 07) * sz); + ny = cy + ((v & 017) * sz); + if (v & 0200) + draw_line(cx, cy, nx, ny, br); + cx = nx; + cy = ny; + } + ox += 8 * sz; + } + /* Repack to new position. */ + uptr->POS = (POS_X & (nx << POS_X_V)) | + (POS_Y & (ny << POS_Y_V)) | + (uptr->POS & (CBRT|CSIZE)); + break; + + case 002: /* Short Vector */ + /* Extract X,Y,Bright and Size */ + sz = (uptr->POS & CSIZE) >> CSIZE_V; + br = (uptr->POS & CBRT) >> CBRT_V; + ox = (uptr->POS & POS_X) >> POS_X_V; + oy = (uptr->POS & POS_Y) >> POS_Y_V; + /* Do first point */ + nx = (iii_instr >> 29) & 077; + ny = (iii_instr >> 22) & 077; + /* Sign extend */ + if (nx & 0100) + nx |= 03700; + if (ny & 0100) + ny |= 03700; + /* Compute relative position. */ + nx += ox; + ny += oy; + if ((iii_instr & 010000000LL) == 0) { /* Check if visible */ + if ((iii_instr & 004000000LL) == 0) { /* Draw a line */ + draw_line(ox, oy, nx, ny, br); + } else { + draw_point(nx, ny, br); + } + } + /* Do second point */ + nx = (iii_instr >> 13) & 0177; + ny = (iii_instr >> 6) & 0177; + /* Sign extend */ + if (nx & 0100) + nx |= 03700; + if (ny & 0100) + ny |= 03700; + /* Compute relative position. */ + nx += ox; + ny += oy; + if ((iii_instr & 040) == 0) { /* Check if visible */ + if ((iii_instr & 020) == 0) { /* Draw a line */ + draw_line(ox, oy, nx, ny, br); + } else { + draw_point(nx, ny, br); + } + } + /* Repack to new position. */ + uptr->POS = (POS_X & (nx << POS_X_V)) | + (POS_Y & (ny << POS_Y_V)) | + (uptr->POS & (CBRT|CSIZE)); + break; + + case 004: /* JSR, JMS, SAVE */ + temp = (((uint64)uptr->MAR) << 18) | 020 /* | CPC */; + A = (iii_instr >> 18) & RMASK; + if ((iii_instr & 030) != 030) { + M[A] = temp; + A++; + } + if ((iii_instr & 020) != 020) { + temp = uptr->STATUS & 0377; + temp |= ((uint64)uptr->POS) << 8; + M[A] = temp; + A++; + } + if ((iii_instr & 030) != 030) { + uptr->MAR = A; + } + break; + + case 006: /* Long Vector */ + /* Extract X,Y,Bright and Size */ + sz = (uptr->POS & CSIZE) >> CSIZE_V; + br = (uptr->POS & CBRT) >> CBRT_V; + ox = (uptr->POS & POS_X) >> POS_X_V; + oy = (uptr->POS & POS_Y) >> POS_Y_V; + /* Update sizes if needed */ + if (((iii_instr >> 9) & CSIZE) != 0) + sz = (iii_instr >> 9) & CSIZE; + if (((iii_instr >> 12) & 7) != 0) + br = (iii_instr > 12) & 7; + nx = (iii_instr >> 25) & 03777; + ny = (iii_instr >> 15) & 03777; + if ((iii_instr & 0100) == 0) { /* Relative mode */ + nx += ox; + ny += oy; + } + if ((iii_instr & 040) == 0) { /* Check if visible */ + if ((iii_instr & 020) == 0) /* Draw a line */ + draw_line(ox, oy, nx, ny, br); + else + draw_point(nx, ny, br); + } + /* Repack to new position. */ + uptr->POS = (POS_X & (nx << POS_X_V)) | + (POS_Y & (ny << POS_Y_V)) | + (CBRT & (br << CBRT_V)) | + (CSIZE & (sz << CSIZE_V)); + break; + + case 010: /* Select instruction */ + break; + + case 012: /* Test instruction */ + A = (uptr->STATUS & (int32)(iii_instr >> 12) & 0377) != 0; + uptr->STATUS &= ~(0377 & ((iii_instr >> 28) ^ (iii_instr >> 20))); + uptr->STATUS ^= (0377 & (iii_instr >> 20)); + if (A ^ ((iii_instr & 020) != 0)) + uptr->MAR++; + break; + + case 014: /* Restore */ + A = (iii_instr >> 18) & RMASK; + temp = M[A]; + if ((iii_instr & 020) != 0) { + uptr->STATUS &= ~0377; + uptr->STATUS |= temp & 0377; + } + if ((iii_instr & 040) != 0) { + uptr->POS = (temp >> 8) & (POS_X|POS_Y|CBRT|CSIZE); + } + break; + + case 016: /* Nop */ + break; + } + if (uptr->STATUS & RUN_FLG) { + iii_instr = M[uptr->MAR]; + uptr->MAR++; + uptr->MAR &= RMASK; + sim_activate(uptr, 10); + } +} + + +/* Draw a point at x,y with intensity b. */ +/* X and Y runs from -512 to 512. */ +static void +draw_point(int x, int y, int b) +{ + display_point(x, y, b, 0); +} + +/* Draw a line between two points */ +static void +draw_line(int x1, int y1, int x2, int y2, int b) +{ + int dx, px; + int dy, py; + int i, p; + int minx, miny; + int maxx, maxy; + + dx = x1 - x2; + dy = y1 - y2; + if (x1 < 0) { + dx = -1; + px = -x1; + } else if (x1 > 0) { + dx = 1; + px = x1; + } else { + dx = 0; + px = 0; + } + + if (y1 < 0) { + dy = -1; + py = -y1; + } else if (y1 > 0) { + dy = 1; + py = y1; + } else { + dy = 0; + py = 0; + } + + if (dx == 0) { + /* Vertical line */ + for (i = 1; i < py; i++) { + dy += dy; + draw_point(dx, dy, b); + } + } else if (dy == 0) { + /* Horizontal line */ + for (i = 1; i < px; i++) { + dx += dx; + draw_point(dx, dy, b); + } + } else if (py > px) { + /* More horizontal */ + p = 2 * px - py; + for (i = 1; i < py; i++) { + if (p > 0) { + dx += dx; + p += (2 * px) - (2 * py); + } else { + p += 2 * px; + } + dy += dy; + draw_point(dx, dy, b); + } + } else { + /* More vertical */ + p = 2 * py - px; + for (i = 1; i < px; i++) { + if (p > 0) { + dy += dy; + p += (2 * py) - (2 * px); + } else { + p += 2 * py; + } + dx += dx; + draw_point(dx, dy, b); + } + } +} + +t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +return SCPE_OK; +} + +const char *iii_description (DEVICE *dptr) +{ + return "Triple III Display"; +} +#endif diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index bbaff38..9d24a5d 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -531,7 +531,7 @@ int auxcpu_write (int addr, t_uint64); #define NUM_DEVS_TU 1 #define NUM_DEVS_PMP WAITS #define NUM_DEVS_DKB WAITS -#define NUM_DEVS_III 0 +#define NUM_DEVS_III (WAITS & USE_DISPLAY) #define NUM_DEVS_PD ITS | KL_ITS #define NUM_DEVS_IMX ITS #define NUM_DEVS_STK ITS diff --git a/makefile b/makefile index c0fb224..f7e9174 100644 --- a/makefile +++ b/makefile @@ -1237,7 +1237,7 @@ KA10 = ${KA10D}/kx10_cpu.c ${KA10D}/kx10_sys.c ${KA10D}/kx10_df.c \ ${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c ${KA10D}/pdp6_dtc.c \ ${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c ${KA10D}/pdp6_dcs.c \ ${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c ${PDP10D}/ka10_ai.c \ - ${DISPLAYL} $(DISPLAY340) + ${KA10D}/ka10_iii.c ${DISPLAYL} $(DISPLAY340) KA10_OPT = -DKA=1 -DUSE_INT64 -I $(KA10D) -DUSE_SIM_CARD ${NETWORK_OPT} $(DISPLAY_OPT) $(KA10_DISPLAY_OPT) ifneq ($(PANDA_LIGHTS),) # ONLY for Panda display. From 093f71d2788f56a75800b127256c8f3e24a36085 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 13 Sep 2019 23:09:55 -0400 Subject: [PATCH 12/98] KA10: Updated timout for CTY input. --- PDP10/kl10_fe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index ebaf7c2..ba840bc 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -1216,7 +1216,7 @@ t_stat dtei_svc (UNIT *uptr) #endif base = eb_ptr; #endif - sim_activate (uptr, 1000); + sim_clock_coschedule (uptr, tmxr_poll); if ((uptr->STATUS & DTE_SEC) == 0) { dte_function(uptr); /* Process queue */ dte_start(optr); From 1832aed1c104607016568e904a29d5f7da78d2e0 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 15 Sep 2019 15:43:12 -0400 Subject: [PATCH 13/98] KA10: Cleanup of KL10 PXCT of bytepointers, added missing ITS instruction. --- PDP10/kx10_cpu.c | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 764afd1..279a236 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1933,6 +1933,11 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) pg = (page & 0377) >> 2; /* 2 1024 word page entries */ data = M[dbr + pg]; //fprintf(stderr, "Load page %06o dbr%012llo pg%06o data=%012llo -> ", page, dbr, pg, data); + if ((page & 02) == 0) + data &= ~0160000000000LL; + else + data &= ~0160000LL; + M[dbr + pg] = data; if ((page & 02) == 0) data >>= 18; data &= RMASK; @@ -2242,9 +2247,9 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch uf = 0; else if (xct_flag != 0 && !uf && !fetch) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); - if (((xct_flag & 8) != 0 && cur_context) || + if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || - ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || + ((xct_flag & 2) != 0 && cur_context && ptr_flg) || ((xct_flag & 1) != 0 && !cur_context && BYF5 )) { uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; @@ -3999,11 +4004,15 @@ no_fetch: #if KL // if (xct_flag != 0) //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o m=%012llo\n\r", IR, PC, AB, xct_flag, MB); - if ((xct_flag & 8) != 0 && (FLAGS & USER) == 0) - AR = MB = (AB + FM[prev_ctx|ix]) & FMASK; + if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || + ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) + AR = FM[prev_ctx|ix]; else -#endif + AR = get_reg(ix); + AR = MB = (AB + AR) & FMASK; +#else AR = MB = (AB + get_reg(ix)) & FMASK; +#endif AB = MB & RMASK; } if (IR != 0254) @@ -5422,7 +5431,7 @@ unasign: #if KL if (AC != 0) { /* ADJBP */ modify = 1; - if (Mem_read(0, !QITS, 0)) { + if (Mem_read(0, 0, 0)) { goto last; } AR = MB; @@ -5466,8 +5475,10 @@ unasign: modify = 1; #if KL ptr_flg = 1; -#endif + if (Mem_read(0, 1, 0)) { +#else if (Mem_read(0, !QITS, 0)) { +#endif #if PDP6 FLAGS |= BYTI; #endif @@ -5488,7 +5499,11 @@ unasign: AR &= PMASK; AR |= (uint64)(SC & 077) << 30; MB = AR; +#if KL + if (Mem_write(0, 1)) +#else if (Mem_write(0, !QITS)) +#endif goto last; if ((IR & 04) == 0) break; @@ -5501,8 +5516,10 @@ unasign: if ((FLAGS & BYTI) == 0 || !BYF5) { #if KL ptr_flg = 1; -#endif + if (Mem_read(0, 1, 0)) +#else if (Mem_read(0, !QITS, 0)) +#endif goto last; AR = MB; ldb_ptr: @@ -6773,6 +6790,16 @@ jrstf: check_apr_irq(); break; + case 017: /* Invalid */ +#if KL_ITS + if (QITS) { + BR = AR >> 23; /* Move into position */ + pi_enable = 1; + goto jrstf; + } +#endif + goto muuo; + case 007: /* XPCW */ #if KLB if (QKLB) { @@ -6787,6 +6814,8 @@ jrstf: goto xjrstf; } #endif + goto muuo; + case 014: /* SFM */ #if KLB if (QKLB) { @@ -6796,12 +6825,13 @@ jrstf: goto last; } #endif + goto muuo; + case 003: /* Invalid */ case 011: /* Invalid */ case 013: /* Invalid */ case 015: /* Invalid */ case 016: /* Invalid */ - case 017: /* Invalid */ goto muuo; case 004: /* HALT */ From 8837ae97717c79f01c2f32414aed7033ce9aee41 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 17 Sep 2019 23:31:42 -0400 Subject: [PATCH 14/98] KA10: Updated ITS paging, start of KL10B working. --- PDP10/kl10_fe.c | 212 +++++++++++++++++++++----------- PDP10/kx10_cpu.c | 304 ++++++++++++++++++++++++++++++++++++++-------- PDP10/kx10_defs.h | 3 +- 3 files changed, 398 insertions(+), 121 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index ba840bc..94bf88a 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -238,6 +238,8 @@ struct _buffer { char buff[256]; /* Buffer */ } cty_in, cty_out; +int cty_data; + DIB dte_dib[] = { { DTE_DEVNUM|000, 1, dte_devio, dte_devirq}, }; @@ -505,7 +507,7 @@ void dte_second(UNIT *uptr) { #if KL_ITS if (word == 0 && QITS && (uptr->STATUS & ITS_ON) != 0) { dte_its(uptr); - uptr->STATUS |= DTE_10DB; +// uptr->STATUS |= DTE_10DB; uptr->STATUS &= ~DTE_11DB; return; } @@ -515,14 +517,16 @@ void dte_second(UNIT *uptr) { switch(word & SEC_CMDMSK) { default: case SEC_MONO: /* Ouput character in monitor mode */ - ch = (int32)(word & 0177); - M[SEC_DTCHR + base] = ch; - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - if ((r = sim_putchar_s (ch)) != SCPE_OK) { /* Output errors */ + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) { sim_activate(uptr, 1000); return; } - M[SEC_DTMTD + base] = FMASK ^ 1; + ch = (int32)(word & 0177); + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + cty_out.buff[cty_out.in_ptr] = (char)(word & 0x7f); + cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + M[SEC_DTCHR + base] = ch; + M[SEC_DTMTD + base] = FMASK; M[SEC_DTF11 + base] = 0; break; case SEC_SETPRI: @@ -542,21 +546,22 @@ enter_pri: /* Start input process */ break; case SEC_SETDDT: /* Read character from console */ - if ((ch = dte_unit[1].CHHOLD) == 0) { - sim_activate(uptr, 100); - return; + if (cty_in.in_ptr == cty_in.out_ptr) { + sim_activate(uptr, 100); + return; } + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; M[SEC_DTF11 + base] = 0177 & ch; M[SEC_DTMTI + base] = FMASK; - dte_unit[1].CHHOLD = 0; break; case SEC_CLRDDT: /* Clear DDT input mode */ uptr->STATUS &= ~DTE_MON; - sim_cancel(&dte_unit[1]); +// sim_cancel(&dte_unit[1]); break; case SEC_MONON: uptr->STATUS |= DTE_MON; - sim_activate(&dte_unit[1], 100); +// sim_activate(&dte_unit[1], 100); break; case SEC_RDSW: /* Read switch register */ M[SEC_DTSWR + base] = SW; @@ -686,10 +691,27 @@ void dte_its(UNIT *uptr) { } /* Check for line speed */ word = M[ITS_DTELSP]; - if ((word & SMASK) == 0) { + if ((word & SMASK) == 0) { /* Ready? */ M[ITS_DTELSP] = FMASK; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTELSP = %012llo %012llo\n", word, M[ITS_DTELPR]); } + /* Check if any input for it */ + if ((uptr->STATUS & ITS_ON) != 0) { + word = M[ITS_DTETYI]; + if ((word & SMASK) != 0) { /* Ready? */ + if (cty_in.in_ptr != cty_in.out_ptr) { + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + word = (uint64)ch; + M[ITS_DTETYI] = word; + /* Tell 10 something is ready */ + uptr->STATUS |= DTE_10DB; + if (uptr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, uptr->STATUS); + } + } + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); + } #if 0 /* Check for input */ word = M[ITS_DTETYI]; @@ -865,16 +887,16 @@ dte_function(UNIT *uptr) data1[0] = 0; if (dte_queue(uptr, PRI_EM2TI, PRI_EMCTY, 1, data1) == 0) return; -#if (NUM_DEVS_LP > 0) - data1[0] = 140; - if (dte_queue(uptr, PRI_EMHLA, PRI_EMLPT, 1, data1) == 0) - return; -#endif +//#if (NUM_DEVS_LP > 0) +// data1[0] = 140; +// if (dte_queue(uptr, PRI_EMHLA, PRI_EMLPT, 1, data1) == 0) +// return; +//#endif // data1[0] = ((ln + 1) << 8) | 32; // (void)dte_queue(uptr, PRI_EMHLA, PRI_EMDL1, 1, data1); - if (dte_queue(uptr, PRI_EMAKA, PRI_EMDH1, 0, data1) == 0) - return; +// if (dte_queue(uptr, PRI_EMAKA, PRI_EMDH1, 0, data1) == 0) +// return; break; case PRI_EM2TI: /* Replay to initial message. */ @@ -934,19 +956,20 @@ dte_function(UNIT *uptr) cty: data1[0] = 0; while (cmd->dptr < cmd->dcnt) { + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) + return; ch = (int32)(cmd->data[cmd->dptr >> 1]); if ((cmd->dptr & 1) == 0) ch >>= 8; ch &= 0177; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY type %x\n", ch); ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - if ((r = sim_putchar_s (ch)) != SCPE_OK) /* Output errors */ - return; + cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); + cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + cty_data = 1; /* Let output know it needs to ack this */ cmd->dptr++; } if (cmd->dptr != cmd->dcnt) - return; - if (dte_queue(uptr, PRI_EMACK, PRI_EMCTY, 1, data1) == 0) return; break; @@ -1126,6 +1149,37 @@ error: return; } +void +dte_input() +{ + uint16 data1; + uint16 dataq[32]; + int n; + int save_ptr; + char ch; + + /* Check if CTY done with input */ + if (cty_data && cty_out.in_ptr == cty_out.out_ptr) { + data1 = 0; + if (dte_queue(&dte_unit[0], PRI_EMACK, PRI_EMCTY, 1, &data1) == 0) + return; + cty_data = 0; + } + n = 0; + save_ptr = cty_in.out_ptr; + while (cty_in.in_ptr != cty_in.out_ptr && n < 32) { + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &tty_dev, "CTY recieve %02x\n", ch); + dataq[n++] = ch; + } + if (n > 0 && dte_queue(&dte_unit[0], PRI_EMLNC, PRI_EMCTY, n, dataq) == 0) { + /* Restore the input pointer */ + cty_in.out_ptr = save_ptr; + return; + } +} + /* * Queue up a packet to send to 10. */ @@ -1217,57 +1271,71 @@ t_stat dtei_svc (UNIT *uptr) base = eb_ptr; #endif sim_clock_coschedule (uptr, tmxr_poll); - if ((uptr->STATUS & DTE_SEC) == 0) { +#if KL_ITS + if ((uptr->STATUS & (DTE_SEC|ITS_ON)) == 0) { +#else + if ((uptr->STATUS & (DTE_SEC)) == 0) { +#endif dte_function(uptr); /* Process queue */ + dte_input(uptr); dte_start(optr); } - /* continue poll */ - if ((ch = uptr->CHHOLD) == 0) { - if ((ch = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ - return ch; - if (ch & SCPE_BREAK) /* ignore break */ - return SCPE_OK; - ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (uptr->flags)); - uptr->CHHOLD = ch; + + /* Flush out any pending CTY output */ + while(cty_out.in_ptr != cty_out.out_ptr) { + ch = cty_out.buff[cty_out.out_ptr]; + if (sim_putchar(ch) != SCPE_OK) + break; + cty_out.out_ptr = (cty_out.out_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY outch %x '%c'\n", ch, + ((ch > 040 && ch < 0177)? ch: '.')); + } + + /* If we have room see if any new lines */ + if (((cty_in.in_ptr + 1) & 0xff) != cty_in.out_ptr) { + ch = sim_poll_kbd (); + if (ch & SCPE_KFLAG) { + ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (uptr->flags)); + cty_in.buff[cty_in.in_ptr] =ch & 0377; + cty_in.in_ptr = (cty_in.in_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %x '%c'\n", ch, + ((ch > 040 && ch < 0177)? ch: '.')); + } + } +#if KL_ITS + if ((optr->STATUS & (DTE_SEC|ITS_ON)) == (DTE_SEC) && +#else + if ((optr->STATUS & DTE_SEC) != 0 && +#endif + cty_in.in_ptr != cty_in.out_ptr && + (optr->STATUS & DTE_MON) != 0 && + M[SEC_DTMTI + base] == 0) { + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + M[SEC_DTF11 + base] = ch; + M[SEC_DTMTI + base] = FMASK; + optr->STATUS |= DTE_10DB; + if (optr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, optr->STATUS); } - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %x\n", ch); #if KL_ITS if (QITS && (optr->STATUS & ITS_ON) != 0) { uint64 word = M[ITS_DTETYI]; if ((word & SMASK) != 0) { - if (ch != 0) { - word = ch; - uptr->CHHOLD = 0; + if (cty_in.in_ptr != cty_in.out_ptr) { + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + word = (uint64)ch; M[ITS_DTETYI] = word; /* Tell 10 something is ready */ optr->STATUS |= DTE_10DB; if (optr->STATUS & DTE_PIE) set_interrupt(DTE_DEVNUM, optr->STATUS); sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); - } + } } - return SCPE_OK; } #endif - if (optr->STATUS & DTE_SEC) { - if (optr->STATUS & DTE_MON && M[SEC_DTMTI + base] == 0) { - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %x\n", ch & 0177); - M[SEC_DTF11 + base] = ch; - M[SEC_DTMTI + base] = FMASK; - optr->STATUS |= DTE_10DB; - if (optr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, optr->STATUS); - uptr->CHHOLD = 0; - } - } else { -#if KL_ITS - if (QITS) - return SCPE_OK; -#endif - data1 = (PRI_EMCTY << 8) | ch; - if (dte_queue(uptr, PRI_EMLNC, PRI_EMCTY, 1, &data1) != 0) - uptr->CHHOLD = 0; - } return SCPE_OK; } @@ -1278,6 +1346,7 @@ dtertc_srv(UNIT * uptr) UNIT *optr = &dte_unit[0]; sim_activate_after(uptr, 1000000/rtc_tps); + /* Check if clock requested */ if (uptr->STATUS & SEC_CLK) { rtc_tick++; if (rtc_wait != 0) { @@ -1297,21 +1366,24 @@ dtertc_srv(UNIT * uptr) } } #if KL_ITS - if (QITS) { - uint64 word; + /* Check if Timesharing is running */ + if (QITS) { + uint64 word; - word = (M[ITS_DTECHK] + 1) & FMASK; - if (word == 0) { - optr->STATUS |= ITS_ON; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS ON\n"); - } else if (word >= (15 * 60)) { - optr->STATUS &= ~ITS_ON; - word = 15 * 60; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS OFF\n"); - } - M[ITS_DTECHK] = word; + word = (M[ITS_DTECHK] + 1) & FMASK; + if (word == 0) { + optr->STATUS |= ITS_ON; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS ON\n"); + } else if (word >= (15 * 60)) { + optr->STATUS &= ~ITS_ON; + word = 15 * 60; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS OFF\n"); } + M[ITS_DTECHK] = word; + } else #endif + + /* Update out keep alive timer if in secondary protocol */ if ((optr->STATUS & DTE_SEC) == 0) { int addr = 0144 + eb_ptr; uint64 word; diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 279a236..1971d7e 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -190,6 +190,7 @@ int brk_flags; /* Break flags */ int t20_page; /* Tops 20 paging selected */ int ptr_flg; /* Access to pointer value */ #if KLB +int sect; /* Actual resolved section */ int cur_sect; /* Current section */ int prev_sect; /* Previous section */ int pc_sect; /* Program counter section */ @@ -1247,7 +1248,7 @@ t_stat dev_pag(uint32 dev, uint64 *data) { if (res & BIT1) { /* Load previous section */ #if KLB - prev_sect = (res >> 18) & 077; + prev_sect = (res >> 18) & 07777; #endif } if ((res & RSIGN) == 0) { @@ -1999,19 +2000,19 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) if (QKLB) { base = 0540; if (!flag) - base += (cur_sect & 037); + base += (sect & 037); } #endif if (uf) data = M[ub_ptr + base]; else data = M[eb_ptr + base]; -fprintf(stderr, "Map %012llo %012llo %012llo\n\r", data, spt, cst); +//fprintf(stderr, "Map %06o %03o %012llo %012llo %012llo\n\r", base, sect, data, spt, cst); /* Find correct page table */ do { switch ((data >> 33) & 07) { default: /* Invalid page */ - fault_data = 0; + fault_data = 024LL << 30; page_fault = 1; return 0; case 1: /* Direct page */ @@ -2044,13 +2045,13 @@ fprintf(stderr, "Map %012llo %012llo %012llo\n\r", data, spt, cst); } } while (!match); -fprintf(stderr, "XMap %012llo\n\r", data); +//fprintf(stderr, "XMap %012llo\n\r", data); match = 0; /* Now look up address of final table entry */ do { if ((data >> 18) & PG_STG) { -fprintf(stderr, "ZMap %012llo not in stg\n\r", data); +//fprintf(stderr, "ZMap %012llo not in stg\n\r", data); if (trap) { fault_data = 0; page_fault = 1; @@ -2063,7 +2064,7 @@ fprintf(stderr, "ZMap %012llo not in stg\n\r", data); if (cst) { uint64 c = M[cst + pg]; if ((c & PG_AGE) == 0) { -fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); +//fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); if (trap) { fault_data = 0; page_fault = 1; @@ -2075,13 +2076,13 @@ fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); /* Get address of page */ data = M[(pg << 9) + page]; -fprintf(stderr, "YMap %012llo\n\r", data); +//fprintf(stderr, "YMap %012llo\n\r", data); /* Decode map pointer */ switch ((data >> 33) & 07) { default: /* Invalid page */ if (trap) { - fault_data = 0; + fault_data = 024LL << 30; page_fault = 1; } return 0; @@ -2167,7 +2168,7 @@ fprintf(stderr, "YMap %012llo\n\r", data); data |= 0020000; #if KLB if (QKLB) - data |= (((flag) ? 0: cur_sect) & 037) << 18; + data |= (((flag) ? 0: sect) & 037) << 18; #endif /* And save it */ if (uf) @@ -2192,8 +2193,8 @@ fprintf(stderr, "YMap %012llo\n\r", data); data = e_tlb[page]; } } -//fprintf(stderr, "Page %03o %06o %o\r\n", page, (data & RMASK), uf); - return (int)(data & RMASK); +//fprintf(stderr, "Page %03o %08o %o\r\n", page, data, uf); + return (int)(data); } /* @@ -2249,13 +2250,27 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || - ((xct_flag & 2) != 0 && cur_context && ptr_flg) || + ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || ((xct_flag & 1) != 0 && !cur_context && BYF5 )) { uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; +#if KLB + if (QKLB) + sect = prev_sect; +#endif } //fprintf(stderr, "%o %o\n\r", uf, pub); } +#if KLB + if (QKLB && t20_page && !flag && (sect & 07740) != 0) { +//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); + fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); + if (uf) /* U */ + fault_data |= SMASK; /* BIT0 */ + page_fault = 1; + return 0; + } +#endif /* Handle KI paging odditiy */ if (!uf && !t20_page && (page & 0740) == 0340) { @@ -2271,7 +2286,7 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch data = e_tlb[page]; #if KLB - if (QKLB && t20_page && ((data >> 18) & 037) != ((flag) ? 0 : cur_sect)) + if (QKLB && t20_page && ((data >> 18) & 077) != ((flag) ? 0 : sect)) data = 0; #endif /* If not valid, go refill it */ @@ -2279,6 +2294,12 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch data = load_tlb(uf, page, upmp, wr, 1, flag); if (data == 0 && page_fault) { fault_data |= ((uint64)addr); + if (uf) /* U */ + fault_data |= SMASK; /* BIT0 */ +#if KLB + if (QKLB) + fault_data = (((uint64)sect) << 18); +#endif #if KL_ITS if (QITS && (xct_flag & 020) != 0) { PC = (PC + 1) & AMASK; @@ -2302,8 +2323,12 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch /* Check for access error */ if ((data & RSIGN) == 0 || (wr & ((data & 0100000) == 0))) { -fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); +//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); fault_data = BIT8 | (uint64)addr; +#if KLB + if (QKLB) + fault_data |= (((uint64)sect) << 18); +#endif /* Remap the flag bits */ if (uf) { /* U */ fault_data |= SMASK; /* BIT0 */ @@ -2402,13 +2427,17 @@ int Mem_read(int flag, int cur_context, int fetch) { int addr; sim_interval--; +#if KLB + if ((glb_sect == 0 || sect == 0 || (glb_sect && sect == 1)) && AB < 020) { +#else if (AB < 020) { +#endif if (xct_flag != 0 && !fetch && (FLAGS & USER) == 0) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgr ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); - if (((xct_flag & 8) != 0 && cur_context) || + if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || - ((xct_flag & 1) != 0 && !cur_context && BYF5)) { + ((xct_flag & 1) != 0 && !cur_context && BYF5 )) { MB = FM[prev_ctx|AB]; //fprintf(stderr, "prev \n\r"); return 0; @@ -2434,13 +2463,17 @@ int Mem_write(int flag, int cur_context) { int addr; sim_interval--; +#if KLB + if ((glb_sect == 0 || sect == 0 || (glb_sect && sect == 1)) && AB < 020) { +#else if (AB < 020) { +#endif if (xct_flag != 0 && (FLAGS & USER) == 0) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgw ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); - if (((xct_flag & 8) != 0 && cur_context) || + if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || - ((xct_flag & 1) != 0 && !cur_context && BYF5)) { + ((xct_flag & 1) != 0 && !cur_context && BYF5 )) { //fprintf(stderr, "prev \n\r"); FM[prev_ctx|AB] = MB; return 0; @@ -3920,18 +3953,18 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ #if KI | KL trap_flag = 0; #if KL +#if KLB + if (QKLB) + sect = cur_sect = pc_sect; + else + sect = cur_sect = 0; + glb_sect = 0; +#endif extend = 0; ptr_flg = 0; #endif #endif AB = PC; -#if KLB - if (QKLB) - cur_sect = pc_sect; - else - cur_sect = 0; - glb_sect = 0; -#endif uuo_cycle = 0; f_pc_inh = 0; } @@ -3952,13 +3985,17 @@ fetch: } #endif +#if KL & KLB + glb_sect = (cur_sect != 0); +#endif + if (Mem_read(pi_cycle | uuo_cycle, 1, 1)) { pi_rq = check_irq_level(); if (pi_rq) goto st_pi; #if KL - if ((FLAGS & (TRP1|TRP2)) == 0) - PC = (PC + 1) & RMASK; + if (((fault_data >> 30) & 037) == 021) + PC = (PC + 1) & RMASK; #endif goto last; } @@ -3985,6 +4022,9 @@ no_fetch: } #endif +#if KLB + glb_sect = 0; +#endif /* Handle indirection repeat until no longer indirect */ do { @@ -4000,26 +4040,81 @@ no_fetch: AR = MB; AB = MB & RMASK; ix = GET_XR(MB); +#if KLB + if (QKLB) { + if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || + ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) + sect = cur_sect = prev_sect; + } +#endif if (ix) { #if KL // if (xct_flag != 0) //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o m=%012llo\n\r", IR, PC, AB, xct_flag, MB); - if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || - ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) - AR = FM[prev_ctx|ix]; - else - AR = get_reg(ix); + if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || + ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) + AR = FM[prev_ctx|ix]; + else + AR = get_reg(ix); +#if KLB + /* Check if extended indexing */ + if (QKLB && cur_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { +fprintf(stderr, "Index %06o %012llo %06o\n\r", AB, AR, cur_sect); + AR = (AR + ((AB & RSIGN) ? SECTM|((uint64)AB): (uint64)AB)) & (SECTM|RMASK); + sect = cur_sect = (AR >> 18) & 07777; + glb_sect = 1; +fprintf(stderr, "Index2 %06o %012llo %06o\n\r", AB, AR, cur_sect); + AB = 0; + } else + glb_sect = 0; +#endif AR = MB = (AB + AR) & FMASK; #else AR = MB = (AB + get_reg(ix)) & FMASK; #endif AB = MB & RMASK; } - if (IR != 0254) - AR &= RMASK; - if (ind & !pi_rq) - if (Mem_read(pi_cycle | uuo_cycle, 1, 0)) +#if KL & KLB +in_loop: +#endif + if (ind & !pi_rq) { + if (Mem_read(pi_cycle | uuo_cycle, 1, 0)) goto last; +#if KL & KLB + /* Check if extended indexing */ + if (QKLB && cur_sect != 0) { + if (MB & SMASK) { /* Instruction format IFIW */ + if (MB & BIT1) { /* Illegal index word */ + fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | + (AR & RMASK) | ((uint64)cur_sect << 18); +fprintf(stderr, "fault %012llo %06o %012llo\n\r", fault_data, FLAGS << 5, AR); + page_fault = 1; + goto last; + } + glb_sect = 0; + } else { /* Extended index EFIW */ + ind = (MB & BIT1) != 0; + ix = (MB >> 30) & 017; + if (ix != 0) { + if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || + ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) + AR = FM[prev_ctx|ix]; + else + AR = get_reg(ix); + AR = (AR + MB) & (SECTM|RMASK); + } else + AR = MB; + sect = cur_sect = (AR >> 18) & 07777; + AB = AR & RMASK; + glb_sect = 1; + ix = 0; +fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); + if (ind) + goto in_loop; + } + } +#endif + } /* Handle events during a indirect loop */ if (sim_interval-- <= 0) { if ((reason = sim_process_event()) != SCPE_OK) { @@ -4027,6 +4122,12 @@ no_fetch: } } } while (ind & !pi_rq); + if (IR != 0254) { +#if KL & KLB +// if (QKLB && IR != 0415) +#endif + AR &= RMASK; + } /* If there is a interrupt handle it. */ @@ -4088,11 +4189,15 @@ st_pi: hst_p = 0; } hst[hst_p].pc = HIST_PC | ((BYF5)? (HIST_PC2|PC) : IA); + hst[hst_p].ea = AB; #if KL if (extend) hst[hst_p].pc |= HIST_PCE; +#if KLB + hst[hst_p].pc |= (pc_sect << 18); + hst[hst_p].ea |= (sect << 18); +#endif #endif - hst[hst_p].ea = AB; hst[hst_p].ir = AD; hst[hst_p].flags = (FLAGS << 5) #if KA | KI | PDP6 @@ -4191,11 +4296,21 @@ muuo: #endif unasign: /* Save Opcode */ +#if KL & KLB + if (QKLB) + MB = ((uint64)(IR) << 10) | ((uint64)(AC) << 6) | ((uint64)(FLAGS) << 23); + else +#endif MB = ((uint64)(IR) << 27) | ((uint64)(AC) << 23) | (uint64)(AB); AB = ub_ptr | 0424; Mem_write_nopage(); /* Save flags */ AB++; +#if KL & KLB + if (QKLB) + MB = ((uint64)(pc_sect) << 18) | ((PC + (trap_flag == 0)) & RMASK); + else +#endif MB = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + (trap_flag == 0)) & RMASK); if ((FLAGS & USER) == 0) { MB &= ~SMASK; @@ -4203,6 +4318,13 @@ unasign: } Mem_write_nopage(); #if KL +#if KLB + if (QKLB) { /* Save address */ + MB = ((uint64)(cur_sect) << 18) | (AB & RMASK); + AB ++; + Mem_write_nopage(); + } +#endif /* Save context */ AB ++; MB = (ub_ptr >> 9) | ((uint64)(prev_ctx & 0160)) << 20 | @@ -4221,6 +4343,12 @@ unasign: AB |= 4; Mem_read_nopage(); +#if KL & KLB + if (QKLB) { + pc_sect = (MB >> 18) & 07777; + FLAGS = 0; + } else +#endif FLAGS = (MB >> 23) & 017777; /* If transistioning from user to executive adjust flags */ if ((FLAGS & USER) != 0 && (AB & 4) != 0) @@ -5474,8 +5602,7 @@ unasign: if ((FLAGS & BYTI) == 0) { /* BYF6 */ modify = 1; #if KL - ptr_flg = 1; - if (Mem_read(0, 1, 0)) { + if (Mem_read(0, 0, 0)) { #else if (Mem_read(0, !QITS, 0)) { #endif @@ -5500,7 +5627,7 @@ unasign: AR |= (uint64)(SC & 077) << 30; MB = AR; #if KL - if (Mem_write(0, 1)) + if (Mem_write(0, 0)) #else if (Mem_write(0, !QITS)) #endif @@ -5515,8 +5642,7 @@ unasign: case 0137:/* DPB */ if ((FLAGS & BYTI) == 0 || !BYF5) { #if KL - ptr_flg = 1; - if (Mem_read(0, 1, 0)) + if (Mem_read(0, 0, 0)) #else if (Mem_read(0, !QITS, 0)) #endif @@ -5530,6 +5656,9 @@ ldb_ptr: f_inst_fetch = 0; f_pc_inh = 1; FLAGS |= BYTI; +#if KL + ptr_flg = 1; +#endif BYF5 = 1; #if ITS if (QITS && pi_cycle == 0 && mem_prot == 0) { @@ -6744,14 +6873,16 @@ left: xjrstf: if (Mem_read(0, 0, 0)) goto last; - BR = MB >> 32; /* Move flags into position */ + BR = MB >> 23; /* Move flags into position */ AB = (AB + 1) & RMASK; if (Mem_read(0, 0, 0)) goto last; AR = MB; /* Get PC. */ #if KLB - if (QKLB) - pc_sect = (MB >> 18) & 017; + if (QKLB) { + pc_sect = (AR >> 18) & 07777; + fprintf(stderr, "xjrstf %012llo\n\r", AR); + } #endif goto jrstf; @@ -6858,6 +6989,10 @@ jrstf: } #endif PC = AR & RMASK; +#if KLB + if (QKLB && glb_sect) + pc_sect = (AR >> 18) & 07777; +#endif #else /* JEN */ if (AC & 010) { /* Restore interrupt level. */ @@ -7173,6 +7308,11 @@ jrstf: break; case 0264: /* JSR */ /* AR Frm PC */ +#if KL & KLB + if (QKLB && pc_sect != 0) + MB = ((uint64)pc_sect << 18) + (PC + !pi_cycle); + else +#endif MB = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + !pi_cycle) & RMASK); #if KI | KL if ((FLAGS & USER) == 0) { @@ -7198,11 +7338,24 @@ jrstf: } #endif PC_CHANGE +#if KL & KLB + if (QKLB) { + AR = AR + 1; + if (glb_sect) + pc_sect = (AR >> 18) & 07777; + PC = AR & RMASK; + } else +#endif PC = (AR + 1) & RMASK; f_pc_inh = 1; break; case 0265: /* JSP */ /* AR Frm PC */ +#if KL & KLB + if (QKLB && pc_sect != 0) + AD = ((uint64)pc_sect << 18) + (PC + !pi_cycle); + else +#endif AD = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + !pi_cycle) & RMASK); FLAGS &= ~ (BYTI|ADRFLT|TRP1|TRP2); @@ -7223,6 +7376,10 @@ jrstf: } #endif PC_CHANGE +#if KL & KLB + if (QKLB && glb_sect) + pc_sect = (AR >> 18) & 07777; +#endif PC = AR & RMASK; AR = AD; f_pc_inh = 1; @@ -7241,6 +7398,10 @@ jrstf: } #endif PC_CHANGE +#if KL & KLB + if (QKLB && glb_sect) + pc_sect = (AR >> 18) & 07777; +#endif PC = AR & RMASK; AR = BR; break; @@ -7930,7 +8091,7 @@ last: pi_cycle = 0; set_pi_hold(); /* Hold off all lower interrupts */ } -fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); +//fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); BYF5 = 0; #if KL_ITS if (QITS) { @@ -7944,6 +8105,11 @@ fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); AB++; FLAGS |= trap_flag & (TRP1|TRP2); trap_flag = (TRP1|TRP2); +#if KLB + if (QKLB) + MB = (((uint64)(FLAGS) << 23) & LMASK); + else +#endif MB = (((uint64)(FLAGS) << 23) & LMASK) | (PC & RMASK); if ((FLAGS & USER) == 0) { MB &= ~SMASK; @@ -7951,6 +8117,13 @@ fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); } Mem_write_nopage(); AB++; +#if KLB + if (QKLB) { + MB = (((uint64)pc_sect) << 18) | (PC & RMASK); + Mem_write_nopage(); + AB++; + } +#endif flag1 = flag3 = 0; if (FLAGS & PUBLIC) flag3 = 1; @@ -7964,6 +8137,10 @@ fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); if ((FLAGS & USER) == 0 && (flag3 || (FLAGS & OVR) != 0)) FLAGS |= PRV_PUB|OVR; PC = MB & RMASK; +#if KLB + if (QKLB) + pc_sect = (MB >> 18) & 07777; +#endif f_pc_inh = 1; } #endif @@ -7989,6 +8166,14 @@ fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); FLAGS &= ~ADRFLT; #else if (!f_pc_inh && !pi_cycle) { +#endif +#if KLB + if (QKLB) { + PC++; + if (PC & BIT17) + pc_sect = (pc_sect + 1) & 07777; + PC &= RMASK; + } else #endif PC = (PC + 1) & RMASK; } @@ -8882,6 +9067,11 @@ do_extend(uint32 ia) break; case 020: /* XBLT */ +#if KLB + if (QKLB) { + return 0; + } +#endif case 021: /* GSNGL */ case 022: /* GDBLE */ case 023: /* GDFIX */ @@ -9298,14 +9488,28 @@ else lnt = hst_lnt; di = hst_p - lnt; /* work forward */ if (di < 0) di = di + hst_lnt; -fprintf (st, "PC AC EA AR RES FLAGS IR\n\n"); +fprintf (st, "PC AC EA AR RES FLAGS IR\n\n"); for (k = 0; k < lnt; k++) { /* print specified */ h = &hst[(++di) % hst_lnt]; /* entry pointer */ if (h->pc & HIST_PC) { /* instruction? */ - fprintf (st, "%06o ", h->pc & 0777777); +#if KL +#if KLB + if (QKLB) + fprintf(st, "%09o ", h->pc & 0777777777); + else +#endif +#endif + fprintf (st, "%06o ", h->pc & 0777777); fprint_val (st, h->ac, 8, 36, PV_RZRO); fputs (" ", st); - fprintf (st, "%06o ", h->ea); +#if KL +#if KLB + if (QKLB) + fprintf(st, "%09o ", h->ea & 0777777777); + else +#endif +#endif + fprintf (st, "%06o ", h->ea); fputs (" ", st); fprint_val (st, h->mb, 8, 36, PV_RZRO); fputs (" ", st); diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 9d24a5d..8949d15 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -171,6 +171,7 @@ extern DEBTAB crd_debug[]; #define XMASK 03777777777777LL #define EMASK 00777000000000LL #define MMASK 00000777777777LL +#define SECTM 00007777000000LL #define BIT1 00200000000000LL #define BIT2 00100000000000LL #define BIT3 00040000000000LL @@ -531,7 +532,7 @@ int auxcpu_write (int addr, t_uint64); #define NUM_DEVS_TU 1 #define NUM_DEVS_PMP WAITS #define NUM_DEVS_DKB WAITS -#define NUM_DEVS_III (WAITS & USE_DISPLAY) +#define NUM_DEVS_III (WAITS * USE_DISPLAY) #define NUM_DEVS_PD ITS | KL_ITS #define NUM_DEVS_IMX ITS #define NUM_DEVS_STK ITS From 5fa30e7528e15ff4f7a0b312ee912ca50742bf48 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 19 Sep 2019 00:01:29 -0400 Subject: [PATCH 15/98] KA10: More KL10B support, don't clear output on reset DTE. --- PDP10/kl10_fe.c | 10 ++-- PDP10/kx10_cpu.c | 153 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 119 insertions(+), 44 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 94bf88a..8149f38 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -1408,11 +1408,11 @@ t_stat dte_reset (DEVICE *dptr) dte_unit[1].STATUS = DTE_SEC; dte_unit[1].CHHOLD = 0; dte_unit[2].STATUS = 0; - dte_in_ptr = dte_in_cmd = dte_out_ptr = dte_out_res = 0; - cty_in.in_ptr = 0; - cty_in.out_ptr = 0; - cty_out.in_ptr = 0; - cty_out.out_ptr = 0; +// dte_in_ptr = dte_in_cmd = dte_out_ptr = dte_out_res = 0; +// cty_in.in_ptr = 0; +// cty_in.out_ptr = 0; +// cty_out.in_ptr = 0; +// cty_out.out_ptr = 0; sim_rtcn_init_unit (&dte_unit[2], dte_unit[2].wait, TMR_RTC); sim_activate(&dte_unit[1], 100); sim_activate(&dte_unit[2], 100); diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 1971d7e..2e9a0c3 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2007,7 +2007,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) data = M[ub_ptr + base]; else data = M[eb_ptr + base]; -//fprintf(stderr, "Map %06o %03o %012llo %012llo %012llo\n\r", base, sect, data, spt, cst); +fprintf(stderr, "Map %06o %03o %012llo %012llo %012llo\n\r", base, sect, data, spt, cst); /* Find correct page table */ do { switch ((data >> 33) & 07) { @@ -2045,13 +2045,13 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) } } while (!match); -//fprintf(stderr, "XMap %012llo\n\r", data); +fprintf(stderr, "XMap %012llo\n\r", data); match = 0; /* Now look up address of final table entry */ do { if ((data >> 18) & PG_STG) { -//fprintf(stderr, "ZMap %012llo not in stg\n\r", data); +fprintf(stderr, "ZMap %012llo not in stg\n\r", data); if (trap) { fault_data = 0; page_fault = 1; @@ -2064,7 +2064,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) if (cst) { uint64 c = M[cst + pg]; if ((c & PG_AGE) == 0) { -//fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); +fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); if (trap) { fault_data = 0; page_fault = 1; @@ -2076,7 +2076,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) /* Get address of page */ data = M[(pg << 9) + page]; -//fprintf(stderr, "YMap %012llo\n\r", data); +fprintf(stderr, "YMap %012llo\n\r", data); /* Decode map pointer */ switch ((data >> 33) & 07) { @@ -2261,16 +2261,6 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch } //fprintf(stderr, "%o %o\n\r", uf, pub); } -#if KLB - if (QKLB && t20_page && !flag && (sect & 07740) != 0) { -//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); - fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); - if (uf) /* U */ - fault_data |= SMASK; /* BIT0 */ - page_fault = 1; - return 0; - } -#endif /* Handle KI paging odditiy */ if (!uf && !t20_page && (page & 0740) == 0340) { @@ -2323,7 +2313,7 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch /* Check for access error */ if ((data & RSIGN) == 0 || (wr & ((data & 0100000) == 0))) { -//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); +fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); fault_data = BIT8 | (uint64)addr; #if KLB if (QKLB) @@ -2428,6 +2418,16 @@ int Mem_read(int flag, int cur_context, int fetch) { sim_interval--; #if KLB + /* Check if invalid section */ + if (QKLB && t20_page && !flag && (sect & 07740) != 0) { + fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); + if (USER==0) /* U */ + fault_data |= SMASK; /* BIT0 */ +fprintf(stderr, "Invalid section %012llo\n\r", fault_data); + page_fault = 1; + return 0; + } + if ((glb_sect == 0 || sect == 0 || (glb_sect && sect == 1)) && AB < 020) { #else if (AB < 020) { @@ -2464,6 +2464,16 @@ int Mem_write(int flag, int cur_context) { sim_interval--; #if KLB + /* Check if invalid section */ + if (QKLB && t20_page && !flag && (sect & 07740) != 0) { + fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); + if (USER==0) /* U */ + fault_data |= SMASK; /* BIT0 */ +fprintf(stderr, "Invalid section %012llo\n\r", fault_data); + page_fault = 1; + return 0; + } + if ((glb_sect == 0 || sect == 0 || (glb_sect && sect == 1)) && AB < 020) { #else if (AB < 020) { @@ -3985,10 +3995,6 @@ fetch: } #endif -#if KL & KLB - glb_sect = (cur_sect != 0); -#endif - if (Mem_read(pi_cycle | uuo_cycle, 1, 1)) { pi_rq = check_irq_level(); if (pi_rq) @@ -4005,6 +4011,10 @@ no_fetch: AC = (MB >> 23) & 017; AD = MB; /* Save for historical sake */ IA = AB; +#if KL & KLB + glb_sect = (cur_sect != 0); +#endif + i_flags = opflags[IR]; BYF5 = 0; } @@ -4124,7 +4134,7 @@ fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB) } while (ind & !pi_rq); if (IR != 0254) { #if KL & KLB -// if (QKLB && IR != 0415) + if (QKLB && (pc_sect == 0 || IR != 0415)) #endif AR &= RMASK; } @@ -4183,7 +4193,7 @@ st_pi: } /* Update history */ - if (hst_lnt && PC >= 020) { + if (hst_lnt && PC > 020) { hst_p = hst_p + 1; if (hst_p >= hst_lnt) { hst_p = 0; @@ -7195,6 +7205,11 @@ jrstf: /* Stack, JUMP */ case 0260: /* PUSHJ */ /* AR Frm PC */ +#if KL & KLB + if (QKLB && pc_sect != 0) + MB = ((uint64)pc_sect << 18) + (PC + !pi_cycle); + else +#endif MB = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + !pi_cycle) & RMASK); #if KI | KL if ((FLAGS & USER) == 0) { @@ -7203,11 +7218,18 @@ jrstf: } #endif BR = AB; +#if KL + BYF5 = 1; +#if KLB + if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR++; + glb_sect = 1; + sect = (AR >> 18) & 07777; + } else +#endif +#endif AR = AOB(AR); AB = AR & RMASK; -#if KL - BYF5 = 1; -#endif if (Mem_write(uuo_cycle | pi_cycle, 0)) goto last; FLAGS &= ~ (BYTI|ADRFLT|TRP1|TRP2); @@ -7235,6 +7257,10 @@ jrstf: if ((FLAGS & USER) && QITS) { jpc = PC; } +#endif +#if KL & KLB + if (QKLB && pc_sect != 0) + pc_sect = (BR >> 18) & 07777; #endif PC = BR & RMASK; PC_CHANGE @@ -7242,6 +7268,16 @@ jrstf: break; case 0261: /* PUSH */ +#if KL + BYF5 = 1; +#if KLB + if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR++; + sect = (AR >> 18) & 07777; + glb_sect = 1; + } else +#endif +#endif AR = AOB(AR); AB = AR & RMASK; if (AR & C1) { @@ -7254,24 +7290,45 @@ jrstf: #endif } MB = BR; -#if KL - BYF5 = 1; -#endif if (Mem_write(0, 0)) goto last; break; case 0262: /* POP */ +#if KL + BYF5 = 1; /* Tell PXCT that this is stack */ +#if KLB + if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + sect = (AR >> 18) & 07777; + f = glb_sect; + glb_sect = 1; + AD = AR - 1; + } else +#endif +#endif + AD = SOB(AR); AB = AR & RMASK; if (Mem_read(0, 0, 0)) goto last; - AR = SOB(AR); AB = BR & RMASK; #if KL - BYF5 = 1; /* Tell PXCT that this is stack */ + BYF5 = 0; /* Tell PXCT that this is stack */ +#if KLB + sect = cur_sect; + glb_sect = f; +#endif #endif if (Mem_write(0, 0)) goto last; +#if KL +#if KLB + if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR = AD; + break; + } +#endif +#endif + AR = AD; if ((AR & C1) == 0) { #if KI | KL if (!pi_cycle) @@ -7285,6 +7342,17 @@ jrstf: case 0263: /* POPJ */ AB = AR & RMASK; +#if KL + BYF5 = 1; /* Tell PXCT that this is stack */ +#if KLB + if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + sect = (AR >> 18) & 07777; + glb_sect = 1; + AD = AR - 1; + } else +#endif +#endif + AD = SOB(AR); if (Mem_read(0, 0, 0)) goto last; #if ITS | KL_ITS @@ -7294,7 +7362,20 @@ jrstf: #endif PC_CHANGE PC = MB & RMASK; - AR = SOB(AR); +#if KL + BYF5 = 0; /* Tell PXCT that this is stack */ +#if KLB +if (pc_sect != 0) +fprintf(stderr, "Popj %012llo\n\r", MB); + if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + pc_sect = (MB >> 18) & 07777; + AR = AD; + f_pc_inh = 1; + break; + } +#endif +#endif + AR = AD; if ((AR & C1) == 0) { #if KI | KL if (!pi_cycle) @@ -8141,6 +8222,8 @@ last: if (QKLB) pc_sect = (MB >> 18) & 07777; #endif + xct_flag = 0; + f_load_pc = 1; f_pc_inh = 1; } #endif @@ -8166,14 +8249,6 @@ last: FLAGS &= ~ADRFLT; #else if (!f_pc_inh && !pi_cycle) { -#endif -#if KLB - if (QKLB) { - PC++; - if (PC & BIT17) - pc_sect = (pc_sect + 1) & 07777; - PC &= RMASK; - } else #endif PC = (PC + 1) & RMASK; } From 60894b566ecea0e59e3544c0be5ed81a6c1c9063 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 20 Sep 2019 20:17:00 -0400 Subject: [PATCH 16/98] KA10: More KL10B support, fixed ITS 1-Proceed. --- PDP10/kx10_cpu.c | 446 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 324 insertions(+), 122 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 2e9a0c3..9ae2c70 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -189,6 +189,7 @@ uint32 brk_addr; /* Address break */ int brk_flags; /* Break flags */ int t20_page; /* Tops 20 paging selected */ int ptr_flg; /* Access to pointer value */ +int extend = 0; /* Process extended instruction */ #if KLB int sect; /* Actual resolved section */ int cur_sect; /* Current section */ @@ -489,17 +490,14 @@ MTAB cpu_mod[] = { { UNIT_M_PAGE, UNIT_KL10B, "KL10B", "KL10B", NULL, NULL, NULL, "Extended addressing support for KL10"}, #endif -#if KL_ITS - { UNIT_M_PAGE, UNIT_ITSPAGE, "ITS", "ITS", NULL, NULL, NULL, - "Paging hardware for ITS"}, -#endif #endif #if KA { UNIT_M_PAGE, 0, "ONESEG", "ONESEG", NULL, NULL, NULL, "One Relocation Register"}, { UNIT_M_PAGE, UNIT_TWOSEG, "TWOSEG", "TWOSEG", NULL, NULL, NULL, "Two Relocation Registers"}, -#if ITS +#endif +#if ITS | KL_ITS { UNIT_M_PAGE, UNIT_ITSPAGE, "ITS", "ITS", NULL, NULL, NULL, "Paging hardware for ITS"}, #endif @@ -519,6 +517,7 @@ MTAB cpu_mod[] = { { UNIT_M_MPX, 0, NULL, "NOMPX", NULL, NULL, NULL, "Disables the MPX device"}, #endif +#if PDP6 | KA | KI { UNIT_MAOFF, UNIT_MAOFF, "MAOFF", "MAOFF", NULL, NULL, NULL, "Interrupts relocated to 140"}, { UNIT_MAOFF, 0, NULL, "NOMAOFF", NULL, NULL, NULL, @@ -880,6 +879,42 @@ int opflags[] = { #define QKLB 0 #endif +#if KL & KLB +struct { + int p; + int s; + int n; + int l; +} _byte_adj[] = { + { /* 37 */ 36, 6, 38, 0 }, + { /* 38 */ 30, 6, 39, 0 }, + { /* 39 */ 24, 6, 40, 0 }, + { /* 40 */ 18, 6, 41, 0 }, + { /* 41 */ 12, 6, 42, 0 }, + { /* 42 */ 6, 6, 43, 0 }, + { /* 43 */ 0, 6, 37, 1 }, + { /* 44 */ 36, 8, 45, 0 }, + { /* 45 */ 28, 8, 46, 0 }, + { /* 46 */ 20, 8, 47, 0 }, + { /* 47 */ 12, 8, 48, 0 }, + { /* 48 */ 4, 8, 44, 1 }, + { /* 49 */ 36, 7, 50, 0 }, + { /* 50 */ 29, 7, 51, 0 }, + { /* 51 */ 22, 7, 52, 0 }, + { /* 52 */ 15, 7, 53, 0 }, + { /* 53 */ 8, 7, 54, 0 }, + { /* 54 */ 1, 7, 49, 1 }, + { /* 55 */ 36, 9, 56, 0 }, + { /* 56 */ 27, 9, 57, 0 }, + { /* 57 */ 18, 9, 58, 0 }, + { /* 58 */ 9, 9, 59, 0 }, + { /* 59 */ 0, 9, 55, 1 }, + { /* 60 */ 36,18, 61, 0 }, + { /* 61 */ 18,18, 62, 0 }, + { /* 62 */ 0,18, 60, 1 } +}; +#endif + #if ITS /* * Set quantum clock to qua_time. @@ -1245,12 +1280,12 @@ t_stat dev_pag(uint32 dev, uint64 *data) { fm_sel = (uint8)(res >> 23) & 0160; prev_ctx = (res >> 20) & 0160; } +#if KLB if (res & BIT1) { /* Load previous section */ -#if KLB prev_sect = (res >> 18) & 07777; -#endif } +#endif if ((res & RSIGN) == 0) { int t; double us = sim_activate_time_usecs (&cpu_unit[0]); @@ -1440,8 +1475,8 @@ t_stat dev_mtr(uint32 dev, uint64 *data) { /* RDMACT */ /* Read memory accounting */ if (page_enable) { - res = (M[ub_ptr + 0507] & CMASK); - BR = M[ub_ptr + 0506]; + res = M[ub_ptr + 0506]; + BR = (M[ub_ptr + 0507] & CMASK); } else { res = 0 << 12; BR = 0; @@ -1456,11 +1491,11 @@ t_stat dev_mtr(uint32 dev, uint64 *data) { update_times(t); rtc_tim = ((int)us); if (page_enable) { - res = (M[ub_ptr + 0505] & CMASK); - BR = M[ub_ptr + 0504]; + res = M[ub_ptr + 0504]; + BR = (M[ub_ptr + 0505] & CMASK); } else { - res = t << 12; - BR = 0; + res = 0; + BR = t << 12; } sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI MTR %012llo\n", *data); } @@ -1532,8 +1567,8 @@ t_stat dev_tim(uint32 dev, uint64 *data) { update_times(t); rtc_tim = ((int)us); if (page_enable) { - res = (M[ub_ptr + 0505]); - BR = M[ub_ptr + 0504]; + res = (M[ub_ptr + 0504]); + BR = M[ub_ptr + 0505]; } else { res = 0 << 12; BR = t; @@ -1547,11 +1582,11 @@ t_stat dev_tim(uint32 dev, uint64 *data) { update_times(t); rtc_tim = ((int)us); if (page_enable) { - res = (M[eb_ptr + 0511]); - BR = M[eb_ptr + 0510]; + res = (M[eb_ptr + 0510]); + BR = M[eb_ptr + 0511]; } else { - res = t << 12; - BR = 0; + res = 0; + BR = t << 12; } sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI TIM %012llo\n", *data); } @@ -2007,7 +2042,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) data = M[ub_ptr + base]; else data = M[eb_ptr + base]; -fprintf(stderr, "Map %06o %03o %012llo %012llo %012llo\n\r", base, sect, data, spt, cst); +//fprintf(stderr, "Map %06o %03o %012llo %012llo %012llo\n\r", base, sect, data, spt, cst); /* Find correct page table */ do { switch ((data >> 33) & 07) { @@ -2045,13 +2080,13 @@ fprintf(stderr, "Map %06o %03o %012llo %012llo %012llo\n\r", base, sect, data, s } } while (!match); -fprintf(stderr, "XMap %012llo\n\r", data); +//fprintf(stderr, "XMap %012llo\n\r", data); match = 0; /* Now look up address of final table entry */ do { if ((data >> 18) & PG_STG) { -fprintf(stderr, "ZMap %012llo not in stg\n\r", data); +//fprintf(stderr, "ZMap %012llo not in stg\n\r", data); if (trap) { fault_data = 0; page_fault = 1; @@ -2064,7 +2099,7 @@ fprintf(stderr, "ZMap %012llo not in stg\n\r", data); if (cst) { uint64 c = M[cst + pg]; if ((c & PG_AGE) == 0) { -fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); +//fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); if (trap) { fault_data = 0; page_fault = 1; @@ -2076,7 +2111,7 @@ fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); /* Get address of page */ data = M[(pg << 9) + page]; -fprintf(stderr, "YMap %012llo\n\r", data); +//fprintf(stderr, "YMap %012llo\n\r", data); /* Decode map pointer */ switch ((data >> 33) & 07) { @@ -2248,6 +2283,9 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch uf = 0; else if (xct_flag != 0 && !uf && !fetch) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); +#if KLB +//fprintf(stderr, " s%o", sect); +#endif if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || @@ -2255,11 +2293,12 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; #if KLB - if (QKLB) + if (QKLB && !glb_sect && !extend) sect = prev_sect; +//fprintf(stderr, " os%o", sect); #endif } -//fprintf(stderr, "%o %o\n\r", uf, pub); +//fprintf(stderr, " %o %o\n\r", uf, pub); } /* Handle KI paging odditiy */ @@ -2296,11 +2335,20 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch page_fault = 0; } #endif + /* Ignore faults if flag set */ + if (FLAGS & ADRFLT) { + page_fault = 0; + return 1; + } return 0; } } *loc = ((data & 017777) << 9) + (addr & 0777); + /* Ignore faults if flag set */ + if (FLAGS & ADRFLT) + return 1; + /* If PUBLIC and private page, make sure we are fetching a Portal */ if ((data & RSIGN) && !flag && pub && ((data & 0200000) == 0) && (!fetch || (M[*loc] & 00777740000000LL) != 0254040000000LL)) { @@ -2433,7 +2481,7 @@ fprintf(stderr, "Invalid section %012llo\n\r", fault_data); if (AB < 020) { #endif if (xct_flag != 0 && !fetch && (FLAGS & USER) == 0) { -//fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgr ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); +//fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgr ", IR, PC, AB, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || @@ -3892,12 +3940,9 @@ int flag1; int flag3; int instr_count = 0; /* Number of instructions to execute */ uint32 IA; -#if ITS | KL_ITS +#if ITS char one_p_arm = 0; /* One proceed arm */ #endif -#if KL -int extend = 0; /* Process extended instruction */ -#endif if (sim_step != 0) { instr_count = sim_step; @@ -3924,12 +3969,10 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ ptr_flg = 0; #endif #endif -#if ITS | KL_ITS +#if ITS if (QITS) { one_p_arm = 0; -#if !KL_ITS set_quantum(); -#endif } #endif watch_stop = 0; @@ -3985,9 +4028,7 @@ fetch: #endif #if ITS if (QITS && pi_cycle == 0 && mem_prot == 0) { -#if !KL_ITS opc = PC | (FLAGS << 18); -#endif if ((FLAGS & ONEP) != 0) { one_p_arm = 1; FLAGS &= ~ONEP; @@ -4022,6 +4063,11 @@ no_fetch: #if KI | KL /* Handle page fault and traps */ if (page_enable && trap_flag == 0 && (FLAGS & (TRP1|TRP2))) { +#if KL_ITS + if (QITS && (FLAGS & ADRFLT) != 0) { + FLAGS &= ~ADRFLT; + } else { +#endif AB = 0420 + ((FLAGS & (TRP1|TRP2)) >> 2); trap_flag = FLAGS & (TRP1|TRP2); FLAGS &= ~(TRP1|TRP2); @@ -4029,6 +4075,9 @@ no_fetch: AB += (FLAGS & USER) ? ub_ptr : eb_ptr; Mem_read_nopage(); goto no_fetch; +#if KL_ITS + } +#endif } #endif @@ -4046,6 +4095,12 @@ no_fetch: ) { pi_rq = check_irq_level(); } +#if KLB + if (QKLB && ptr_flg && pc_sect != 0 && (AR & 040000000LL) != 0) { /* Full pointer */ + ind = 1; + goto in_loop; + } +#endif ind = TST_IND(MB) != 0; AR = MB; AB = MB & RMASK; @@ -4085,6 +4140,9 @@ fprintf(stderr, "Index2 %06o %012llo %06o\n\r", AB, AR, cur_sect); AB = MB & RMASK; } #if KL & KLB + else /* No index so become local */ + glb_sect = 0; + in_loop: #endif if (ind & !pi_rq) { @@ -4097,11 +4155,15 @@ in_loop: if (MB & BIT1) { /* Illegal index word */ fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | (AR & RMASK) | ((uint64)cur_sect << 18); -fprintf(stderr, "fault %012llo %06o %012llo\n\r", fault_data, FLAGS << 5, AR); page_fault = 1; goto last; } glb_sect = 0; + if (ptr_flg && (AR & 040000000LL) != 0) { /* Full pointer */ + ind = 0; + AR = MB; + AB = AR & RMASK; + } } else { /* Extended index EFIW */ ind = (MB & BIT1) != 0; ix = (MB >> 30) & 017; @@ -4133,10 +4195,15 @@ fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB) } } while (ind & !pi_rq); if (IR != 0254) { -#if KL & KLB - if (QKLB && (pc_sect == 0 || IR != 0415)) -#endif AR &= RMASK; +#if KL & KLB + if (QKLB && IR == 0415 && pc_sect != 0) { + if (glb_sect == 0 && AR < 020) + AR |= BIT17; + else + AR |= ((uint64)cur_sect) << 18; + } +#endif } @@ -4153,6 +4220,10 @@ st_pi: #if KI | KL xct_flag = 0; #if KL +#if KLB + if (QKLB) + sect = cur_sect = 0; +#endif extend = 0; #endif /* @@ -4193,7 +4264,7 @@ st_pi: } /* Update history */ - if (hst_lnt && PC > 020) { + if (hst_lnt && PC > 017) { hst_p = hst_p + 1; if (hst_p >= hst_lnt) { hst_p = 0; @@ -4238,11 +4309,11 @@ st_pi: f_pc_inh = 0; #if KL if (extend) { - extend = 0; - if (IR == 0 || IR > 031 || AC != 0) - goto muuo; - if (do_extend(IA)) + if (IR == 0 || IR > 031 || AC != 0 || do_extend(IA)) { + IR = 0123; + AC = IA; goto muuo; + } goto last; } #endif @@ -4308,7 +4379,7 @@ unasign: /* Save Opcode */ #if KL & KLB if (QKLB) - MB = ((uint64)(IR) << 10) | ((uint64)(AC) << 6) | ((uint64)(FLAGS) << 23); + MB = ((uint64)(IR) << 12) | ((uint64)(AC) << 8) | ((uint64)(FLAGS) << 23) | ((uint64)cur_sect & 037); else #endif MB = ((uint64)(IR) << 27) | ((uint64)(AC) << 23) | (uint64)(AB); @@ -4328,6 +4399,7 @@ unasign: } Mem_write_nopage(); #if KL + extend = 0; #if KLB if (QKLB) { /* Save address */ MB = ((uint64)(cur_sect) << 18) | (AB & RMASK); @@ -4402,7 +4474,7 @@ unasign: Mem_write(uuo_cycle, 1); AB += 1; f_load_pc = 0; -#if ITS | KL_ITS +#if ITS if (QITS && one_p_arm) { FLAGS |= ONEP; one_p_arm = 0; @@ -4477,10 +4549,22 @@ unasign: #if KL case 0105: /* ADJSP */ BR = get_reg(AC); +#if KLB + if (QKLB && pc_sect != 0 && (BR & SMASK) == 0 && (BR & SECTM) != 0) { + AD = (((AR & RSIGN)?(LMASK|AR):AR) + BR) & (SECTM|RMASK); + AD |= BR & ~(SECTM|RMASK); + } else { +#endif AD = (BR + AR) & RMASK; AD |= (BR & LMASK) + ((AR << 18) & LMASK); +#if KLB + if (QKLB && pc_sect == 0) +#endif if (((BR ^ AD) & SMASK) != 0) FLAGS |= TRP2; +#if KLB + } +#endif set_reg(AC, AD & FMASK); break; #endif @@ -5554,7 +5638,7 @@ unasign: uuo_cycle = 1; Mem_write(uuo_cycle, 0); AB += 1; -#if ITS | KL_ITS +#if ITS if (QITS && one_p_arm) { FLAGS |= ONEP; one_p_arm = 0; @@ -5622,11 +5706,39 @@ unasign: goto last; } AR = MB; + SCAD = (AR >> 30) & 077; +#if KL & KLB + if (QKLB && SCAD > 36) { /* Extended pointer */ + int i = SCAD - 37; + if (_byte_adj[i].l) + AR = (AR + 1) & (SECTM|RMASK); + AR |= ((uint64)_byte_adj[i].n) << 30; + MB = AR; + if (Mem_write(0, 0)) + goto last; + goto ld_ptr; + } +#endif SC = (AR >> 24) & 077; - SCAD = (((AR >> 30) & 077) + (0777 ^ SC) + 1) & 0777; + SCAD = (SCAD + (0777 ^ SC) + 1) & 0777; if (SCAD & 0400) { - SC = ((0777 ^ ((AR >> 24) & 077)) + 044 + 1) & 0777; + SC = ((0777 ^ SC) + 044 + 1) & 0777; #if KI | KL +#if KLB + if (QKLB && pc_sect != 0 && (AR & 040000000LL) != 0) { /* Full pointer */ + uint32 AT = AB; + AB = (AB + 1) & RMASK; + if (Mem_read(0, 0, 0)) + goto last; + if (MB & SMASK) + MB = (MB & LMASK) | ((MB + 1) & RMASK); + else + MB++; + if (Mem_write(0,0)) + goto last; + AB = AT; + } else +#endif AR = (AR & LMASK) | ((AR + 1) & RMASK); #else AR = (AR + 1) & FMASK; @@ -5658,6 +5770,21 @@ unasign: #endif goto last; AR = MB; +#if KL & KLB +ld_ptr: + SCAD = (AR >> 30) & 077; + if (QKLB && SCAD > 36) { /* Extended pointer */ + int i = SCAD - 37; + SC = _byte_adj[i].p; + MQ = (uint64)(1) << _byte_adj[i].s; + MQ -= 1; + sect = (AR >> 18) & 07777; + AB = AR & RMASK; + BYF5 = 1; + FLAGS |= BYTI; + goto ex_byte; + } +#endif ldb_ptr: SC = (AR >> 30) & 077; MQ = (uint64)(1) << ( 077 & (AR >> 24)); @@ -5666,10 +5793,15 @@ ldb_ptr: f_inst_fetch = 0; f_pc_inh = 1; FLAGS |= BYTI; + BYF5 = 1; #if KL ptr_flg = 1; +#if KLB + if (QKLB && pc_sect != 0 && (AR & 040000000LL) != 0) { /* Full pointer */ + AB = (AB + 1) & RMASK; + } +#endif #endif - BYF5 = 1; #if ITS if (QITS && pi_cycle == 0 && mem_prot == 0) { opc = PC | (FLAGS << 18); @@ -5677,6 +5809,9 @@ ldb_ptr: #endif } else { #if KL +#if KLB +ex_byte: +#endif ptr_flg = 0; #endif AB = AR & RMASK; @@ -6652,7 +6787,7 @@ left: SC = 0; if (AR != 0) { #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -6797,9 +6932,11 @@ left: AR = AOB(AR) & FMASK; #endif f_pc_inh = 1; +#if KA | PDP6 #if ITS if (QITS) set_reg(AC, AR); +#endif #else set_reg(AC, AR); #endif @@ -6821,9 +6958,11 @@ left: AR = AOB(AR) & FMASK; #endif f_pc_inh = 1; +#if KA | PDP6 #if ITS if (QITS) set_reg(AC, AR); +#endif #else set_reg(AC, AR); #endif @@ -6838,7 +6977,7 @@ left: AR = AOB(AR); if ((AR & SMASK) == 0) { #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -6852,7 +6991,7 @@ left: AR = AOB(AR); if ((AR & SMASK) != 0) { #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -6865,7 +7004,7 @@ left: case 0254: /* JRST */ /* AR Frm PC */ if (uuo_cycle | pi_cycle) { FLAGS &= ~USER; /* Clear USER */ -#if ITS | KL_ITS +#if ITS if (QITS && one_p_arm) { FLAGS |= ONEP; one_p_arm = 0; @@ -6883,7 +7022,7 @@ left: xjrstf: if (Mem_read(0, 0, 0)) goto last; - BR = MB >> 23; /* Move flags into position */ + BR = MB; AB = (AB + 1) & RMASK; if (Mem_read(0, 0, 0)) goto last; @@ -6891,9 +7030,11 @@ xjrstf: #if KLB if (QKLB) { pc_sect = (AR >> 18) & 07777; - fprintf(stderr, "xjrstf %012llo\n\r", AR); - } + prev_sect = BR & 037; + fprintf(stderr, "xjrstf %012llo %012llo\n\r", BR, AR); + } #endif + BR = BR >> 23; /* Move flags into position */ goto jrstf; case 006: /* XJEN */ @@ -6905,14 +7046,14 @@ xjrstf: } else { pi_restore = 1; } - if ((AC & 010) == 0) + if (AC == 06) goto xjrstf; /* Fall through */ case 002: /* JRSTF */ BR = AR >> 23; /* Move into position */ jrstf: - FLAGS &= ~(OVR|NODIV|FLTUND|BYTI|FLTOVR|CRY1|CRY0|TRP1|TRP2|PCHNG); + FLAGS &= ~(OVR|NODIV|FLTUND|BYTI|FLTOVR|CRY1|CRY0|TRP1|TRP2|PCHNG|ADRFLT); /* If executive mode, copy USER and UIO */ if ((FLAGS & (PUBLIC|USER)) == 0) FLAGS |= BR & (USER|USERIO|PUBLIC); @@ -6920,11 +7061,7 @@ jrstf: if ((BR & USERIO) == 0) FLAGS &= ~USERIO; FLAGS |= BR & (OVR|NODIV|FLTUND|BYTI|FLTOVR|CRY1|CRY0|\ - TRP1|TRP2|PUBLIC|PCHNG); -#if KL_ITS - if (QITS) - FLAGS |= BR & (PURE|ONEP); -#endif + TRP1|TRP2|PUBLIC|PCHNG|ADRFLT); FLAGS &= ~PRV_PUB; if ((FLAGS & USER) == 0) FLAGS |= (BR & OVR) ? PRV_PUB : 0; @@ -6944,11 +7081,11 @@ jrstf: case 007: /* XPCW */ #if KLB if (QKLB) { - MB = ((uint64)FLAGS) << 23; + MB = (((uint64)FLAGS) << 23) | (prev_sect & 037); if (Mem_write(0, 0)) goto last; AB = (AB + 1) & RMASK; - MB = (((uint64)pc_sect) << 18) | PC; + MB = (((((uint64)pc_sect) << 18) | PC) + !pi_cycle) & (SECTM|RMASK); if (Mem_write(0, 0)) goto last; AB = (AB + 1) & RMASK; @@ -6960,8 +7097,7 @@ jrstf: case 014: /* SFM */ #if KLB if (QKLB) { - MB = ((uint64)FLAGS) << 23; - MB |= prev_sect; + MB = (((uint64)FLAGS) << 23) | (prev_sect & 037); (void)Mem_write(0, 0); goto last; } @@ -6994,7 +7130,7 @@ jrstf: break; } #if KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -7031,7 +7167,7 @@ jrstf: } } #if ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -7039,7 +7175,7 @@ jrstf: PC_CHANGE /* JRSTF */ if (AC & 02) { - FLAGS &= ~(OVR|NODIV|FLTUND|BYTI|FLTOVR|CRY1|CRY0|TRP1|TRP2|PCHNG); + FLAGS &= ~(OVR|NODIV|FLTUND|BYTI|FLTOVR|CRY1|CRY0|TRP1|TRP2|PCHNG|ADRFLT); AR >>= 23; /* Move into position */ /* If executive mode, copy USER and UIO */ if ((FLAGS & (PUBLIC|USER)) == 0) @@ -7052,7 +7188,7 @@ jrstf: user_io = (FLAGS & USERIO) != 0; #endif FLAGS |= AR & (OVR|NODIV|FLTUND|BYTI|FLTOVR|CRY1|CRY0|\ - TRP1|TRP2|PUBLIC|PCHNG); + TRP1|TRP2|PUBLIC|PCHNG|ADRFLT); #if ITS if (QITS) FLAGS |= AR & (PURE|ONEP); @@ -7079,7 +7215,7 @@ jrstf: case 0255: /* JFCL */ if ((FLAGS >> 9) & AC) { #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -7105,7 +7241,7 @@ jrstf: if (QWAITS && (FLAGS & USER) == 0) xct_flag = AC; #endif -#if ITS | KL_ITS +#if ITS if (QITS && one_p_arm) { FLAGS |= ONEP; one_p_arm = 0; @@ -7208,7 +7344,7 @@ jrstf: #if KL & KLB if (QKLB && pc_sect != 0) MB = ((uint64)pc_sect << 18) + (PC + !pi_cycle); - else + else { #endif MB = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + !pi_cycle) & RMASK); #if KI | KL @@ -7216,6 +7352,9 @@ jrstf: MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; } +#if KL & KLB + } +#endif #endif BR = AB; #if KL @@ -7223,7 +7362,7 @@ jrstf: #if KLB if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { AR++; - glb_sect = 1; + // glb_sect = 1; sect = (AR >> 18) & 07777; } else #endif @@ -7245,7 +7384,7 @@ jrstf: #if !PDP6 if (uuo_cycle | pi_cycle) { FLAGS &= ~(USER|PUBLIC); /* Clear USER */ -#if ITS | KL_ITS +#if ITS if (QITS && one_p_arm) { FLAGS |= ONEP; one_p_arm = 0; @@ -7254,7 +7393,7 @@ jrstf: } #endif #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -7274,7 +7413,7 @@ jrstf: if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { AR++; sect = (AR >> 18) & 07777; - glb_sect = 1; + // glb_sect = 1; } else #endif #endif @@ -7298,37 +7437,41 @@ jrstf: #if KL BYF5 = 1; /* Tell PXCT that this is stack */ #if KLB - if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - sect = (AR >> 18) & 07777; - f = glb_sect; - glb_sect = 1; - AD = AR - 1; + flag1 = glb_sect; + if (QKLB) { + f = (pc_sect != 0); + if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) + f = (prev_sect != 0); + if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + sect = (AR >> 18) & 07777; + glb_sect = 1; + } } else -#endif -#endif - AD = SOB(AR); + f = 0; +#endif +#endif AB = AR & RMASK; if (Mem_read(0, 0, 0)) goto last; AB = BR & RMASK; #if KL - BYF5 = 0; /* Tell PXCT that this is stack */ + BYF5 = 0; /* Now back to data */ #if KLB sect = cur_sect; - glb_sect = f; + glb_sect = flag1; #endif #endif if (Mem_write(0, 0)) goto last; -#if KL +#if KL & KLB + if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR = AR - 1; + } else +#endif + AR = SOB(AR); #if KLB - if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - AR = AD; - break; - } + if (QKLB && !f) #endif -#endif - AR = AD; if ((AR & C1) == 0) { #if KI | KL if (!pi_cycle) @@ -7345,37 +7488,41 @@ jrstf: #if KL BYF5 = 1; /* Tell PXCT that this is stack */ #if KLB - if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - sect = (AR >> 18) & 07777; - glb_sect = 1; - AD = AR - 1; + if (QKLB) { + f = (pc_sect != 0); + if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) + f = (prev_sect != 0); + if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + sect = (AR >> 18) & 07777; + glb_sect = 1; + } } else + f = 0; #endif #endif - AD = SOB(AR); if (Mem_read(0, 0, 0)) goto last; #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif + f_pc_inh = 1; PC_CHANGE PC = MB & RMASK; #if KL BYF5 = 0; /* Tell PXCT that this is stack */ #if KLB -if (pc_sect != 0) -fprintf(stderr, "Popj %012llo\n\r", MB); - if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { pc_sect = (MB >> 18) & 07777; - AR = AD; - f_pc_inh = 1; - break; - } + AR = AR - 1; + } else +#endif #endif + AR = SOB(AR); +#if KLB + if (QKLB && !f) #endif - AR = AD; if ((AR & C1) == 0) { #if KI | KL if (!pi_cycle) @@ -7385,14 +7532,13 @@ fprintf(stderr, "Popj %012llo\n\r", MB); check_apr_irq(); #endif } - f_pc_inh = 1; break; case 0264: /* JSR */ /* AR Frm PC */ #if KL & KLB if (QKLB && pc_sect != 0) MB = ((uint64)pc_sect << 18) + (PC + !pi_cycle); - else + else { #endif MB = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + !pi_cycle) & RMASK); #if KI | KL @@ -7400,6 +7546,9 @@ fprintf(stderr, "Popj %012llo\n\r", MB); MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; } +#if KL & KLB + } +#endif #endif #if PDP6 if (ill_op | uuo_cycle | pi_cycle | ex_uuo_sync) { @@ -7414,7 +7563,7 @@ fprintf(stderr, "Popj %012llo\n\r", MB); goto last; FLAGS &= ~ (BYTI|ADRFLT|TRP1|TRP2); #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -7435,7 +7584,7 @@ fprintf(stderr, "Popj %012llo\n\r", MB); #if KL & KLB if (QKLB && pc_sect != 0) AD = ((uint64)pc_sect << 18) + (PC + !pi_cycle); - else + else { #endif AD = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + !pi_cycle) & RMASK); @@ -7445,6 +7594,9 @@ fprintf(stderr, "Popj %012llo\n\r", MB); AD &= ~SMASK; AD |= (FLAGS & PRV_PUB) ? SMASK : 0; } +#if KL & KLB + } +#endif #endif #if !PDP6 if (uuo_cycle | pi_cycle) { @@ -7452,7 +7604,7 @@ fprintf(stderr, "Popj %012llo\n\r", MB); } #endif #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -7474,7 +7626,7 @@ fprintf(stderr, "Popj %012llo\n\r", MB); } #endif #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -7494,7 +7646,7 @@ fprintf(stderr, "Popj %012llo\n\r", MB); goto last; set_reg(AC, MB); #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -7649,7 +7801,7 @@ jump_op: f = f & IR; if (((IR & 04) != 0) == (f == 0)) { #if ITS | KL_ITS - if ((FLAGS & USER) && QITS) { + if (QITS && (FLAGS & USER)) { jpc = PC; } #endif @@ -8339,9 +8491,9 @@ fprintf(stderr, "Page fault trap %06o\n\r", PC); #endif return SCPE_STEP; } -#if KL - FLAGS &= ~ADRFLT; -#endif +//#if KL +// FLAGS &= ~ADRFLT; +//#endif } /* Should never get here */ #if ITS @@ -9144,6 +9296,56 @@ do_extend(uint32 ia) case 020: /* XBLT */ #if KLB if (QKLB) { + reg = get_reg(ext_ac); +// if ((xct_flag & 2) != 0 && (FLAGS & USER) == 0) + // val1 = FM[prev_ctx|(ext_ac + 1)]; + // else + val1 = get_reg(ext_ac + 1); + // if ((xct_flag & 1) != 0 && (FLAGS & USER) == 0) + // val2 = FM[prev_ctx|(ext_ac + 2)]; + // else + val2 = get_reg(ext_ac + 2); +fprintf(stderr, "XBLT: %012llo %012llo %012llo\n\r", reg, val1, val2); + while (reg != 0) { + if (reg & SMASK) { + sect = (val1 >> 18) & 07777; + AB = val1 & RMASK; + if (Mem_read(0, 0, 0)) + goto xblt_done; +fprintf(stderr, " XBLT: D=%012llo 1-%012llo 2-%012llo\n\r", MB, val1, val2); + sect = (val2 >> 18) & 07777; + AB = val2 & RMASK; + if (Mem_write(0, 0)) + goto xblt_done; + reg = (reg + 1) & FMASK; + val1 = (val1 - 1) & (SECTM|RMASK); + val2 = (val2 - 1) & (SECTM|RMASK); + } else { + sect = (val1 >> 18) & 07777; + AB = val1 & RMASK; + if (Mem_read(0, 0, 0)) + goto xblt_done; +fprintf(stderr, " XBLT: D=%012llo 1-%012llo 2-%012llo\n\r", MB, val1, val2); + sect = (val2 >> 18) & 07777; + AB = val2 & RMASK; + if (Mem_write(0, 0)) + goto xblt_done; + val1 = (val1 + 1) & (SECTM|RMASK); + val2 = (val2 + 1) & (SECTM|RMASK); + reg = (reg - 1) & FMASK; + } + } +xblt_done: +fprintf(stderr, "XBLT done: %012llo %012llo %012llo\n\r", reg, val1, val2); + set_reg(ext_ac, reg); + // if ((xct_flag & 2) != 0 && (FLAGS & USER) == 0) + // FM[prev_ctx|(ext_ac + 1)] = val1; + // else + set_reg(ext_ac + 1, val1); + // if ((xct_flag & 1) != 0 && (FLAGS & USER) == 0) + // FM[prev_ctx|(ext_ac + 2)] = val2; + // else + set_reg(ext_ac + 2, val2); return 0; } #endif From a31b200c57bf2a0de3a6b4984073df170afb26f1 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Mon, 23 Sep 2019 22:59:55 -0400 Subject: [PATCH 17/98] KA10: Made ITS XCTR and XCTRI behave the same. --- PDP10/kx10_cpu.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 9ae2c70..4fb1295 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2328,12 +2328,6 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch #if KLB if (QKLB) fault_data = (((uint64)sect) << 18); -#endif -#if KL_ITS - if (QITS && (xct_flag & 020) != 0) { - PC = (PC + 1) & AMASK; - page_fault = 0; - } #endif /* Ignore faults if flag set */ if (FLAGS & ADRFLT) { @@ -2380,10 +2374,7 @@ fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) fault_data |= BIT6; /* BIT6 */ #if KL_ITS if (QITS) { - if ((xct_flag & 020) != 0) { - PC = (PC + 1) & AMASK; - page_fault = 0; - } else if ((data & RSIGN) == 0) { + if ((data & RSIGN) == 0) { fault_data = ((uint64)addr) | 033LL << 30 |((uf)?SMASK:0); page_fault = 1; } else {// if (wr & ((data & 0100000) == 0)) { @@ -4488,7 +4479,7 @@ unasign: if (QITS && (FLAGS & USER) == 0) { f_load_pc = 0; f_pc_inh = 1; - xct_flag = AC | ((IR & 1) << 4); + xct_flag = AC; break; } goto unasign; From 94709e1fabb1db5030c5d8fffca72ba7614b1b82 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 25 Sep 2019 19:46:16 -0400 Subject: [PATCH 18/98] KA10: Cleaned up FE support, ITS IMP now working. --- PDP10/kl10_fe.c | 625 ++++++++++++++++++++++++---------------------- PDP10/kx10_cpu.c | 73 +++--- PDP10/kx10_defs.h | 4 +- PDP10/kx10_imp.c | 407 ++++++++++++++++++++++++++++-- makefile | 5 +- 5 files changed, 750 insertions(+), 364 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 8149f38..c73b8b0 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -156,6 +156,7 @@ #define PRI_EMCDR 006 /* CDR */ #define PRI_EMCLK 007 /* Clock */ #define PRI_EMFED 010 /* Front end device */ +#define PRI_CTYDV 000 /* Line number for CTY */ #if KL_ITS /* ITS Timesharing protocol locations */ @@ -183,9 +184,11 @@ void dte_its(UNIT *uptr); #endif void dte_transfer(UNIT *uptr); void dte_function(UNIT *uptr); +void dte_input(); int dte_start(UNIT *uptr); -int dte_queue(UNIT *uptr, int func, int dev, int dcnt, uint16 *data); +int dte_queue(int func, int dev, int dcnt, uint16 *data); t_stat dtei_svc (UNIT *uptr); +t_stat dte_svc (UNIT *uptr); t_stat dteo_svc (UNIT *uptr); t_stat dtertc_srv(UNIT * uptr); t_stat dte_reset (DEVICE *dptr); @@ -195,6 +198,11 @@ t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cpt const char *dte_description (DEVICE *dptr); extern uint64 SW; /* Switch register */ +char *pri_name[] = { "(0)", "EM2EI", "EM2TI", "EMSTR", "EMLNC", "EMRDS", "(6)", + "EMHDS", "(10)", "EMRDT", "EMHDR", "EMFLO", "EMSNA", "EMDSC", "EMHUD", + "EMACK", "EMXOF", "EMXON", "EMHLS", "EMHLA", "EMRBI", "EMAKA", "EMTDO", + "EMEDR", "EMLDR", "EMLDV" }; + #if KL_ITS #define QITS (cpu_unit[0].flags & UNIT_ITSPAGE) #else @@ -203,7 +211,6 @@ extern uint64 SW; /* Switch register */ #define STATUS u3 #define CNT u4 -#define CHHOLD u5 extern uint32 eb_ptr; static int32 rtc_tps = 60; @@ -237,8 +244,7 @@ struct _buffer { int out_ptr; /* Remove pointer */ char buff[256]; /* Buffer */ } cty_in, cty_out; - -int cty_data; +int cty_done; DIB dte_dib[] = { { DTE_DEVNUM|000, 1, dte_devio, dte_devirq}, @@ -254,15 +260,16 @@ MTAB dte_mod[] = { }; UNIT dte_unit[] = { - { UDATA (&dteo_svc, TT_MODE_7B, 0), 10000 }, - { UDATA (&dtei_svc, TT_MODE_7B|UNIT_DIS, 0), 10000 }, + { UDATA (&dte_svc, TT_MODE_7B, 0), 100}, + { UDATA (&dteo_svc, TT_MODE_7B, 0), 100}, + { UDATA (&dtei_svc, TT_MODE_7B|UNIT_DIS, 0), 1000 }, { UDATA (&dtertc_srv, UNIT_IDLE|UNIT_DIS, 0), 1000 } }; DEVICE dte_dev = { "CTY", dte_unit, NULL, dte_mod, - 3, 10, 31, 1, 8, 8, + 4, 10, 31, 1, 8, 8, NULL, NULL, &dte_reset, NULL, NULL, NULL, &dte_dib, DEV_DEBUG, 0, dev_debug, NULL, NULL, &dte_help, NULL, NULL, &dte_description @@ -343,10 +350,10 @@ DEVICE lpt_dev = { #if (NUM_DEVS_TTY > 0) struct _buffer tty_out[NUM_LINES_TTY], tty_in[NUM_LINES_TTY]; -struct _buffer tty_done, tty_hang; TMLN tty_ldsc[NUM_LINES_TTY] = { 0 }; /* Line descriptors */ TMXR tty_desc = { NUM_LINES_TTY, 0, 0, tty_ldsc }; -int tty_connect[NUM_LINES_TTY];; +int tty_connect[NUM_LINES_TTY]; +int tty_done[NUM_LINES_TTY]; int tty_enable = 0; extern int32 tmxr_poll; @@ -471,7 +478,7 @@ dte_devirq(uint32 dev, int addr) { } /* Handle TO11 interrupts */ -t_stat dteo_svc (UNIT *uptr) +t_stat dte_svc (UNIT *uptr) { t_stat r; @@ -498,7 +505,7 @@ void dte_second(UNIT *uptr) { #if KI_22BIT #if KL_ITS - if ((cpu_unit[0].flags & UNIT_ITSPAGE) == 0) + if (!QITS) #endif base = eb_ptr; #endif @@ -507,7 +514,6 @@ void dte_second(UNIT *uptr) { #if KL_ITS if (word == 0 && QITS && (uptr->STATUS & ITS_ON) != 0) { dte_its(uptr); -// uptr->STATUS |= DTE_10DB; uptr->STATUS &= ~DTE_11DB; return; } @@ -528,6 +534,7 @@ void dte_second(UNIT *uptr) { M[SEC_DTCHR + base] = ch; M[SEC_DTMTD + base] = FMASK; M[SEC_DTF11 + base] = 0; + sim_activate(&dte_unit[1], 100); break; case SEC_SETPRI: enter_pri: @@ -540,9 +547,9 @@ enter_pri: dte_et10_off = dte_dt10_off + 16; dte_et11_off = dte_base + 16; uptr->STATUS &= ~DTE_SEC; - dte_unit[1].STATUS &= ~DTE_SEC; dte_in_ptr = dte_out_ptr = 0; dte_in_cmd = dte_out_res = 0; + cty_done = 0; /* Start input process */ break; case SEC_SETDDT: /* Read character from console */ @@ -557,11 +564,9 @@ enter_pri: break; case SEC_CLRDDT: /* Clear DDT input mode */ uptr->STATUS &= ~DTE_MON; -// sim_cancel(&dte_unit[1]); break; case SEC_MONON: uptr->STATUS |= DTE_MON; -// sim_activate(&dte_unit[1], 100); break; case SEC_RDSW: /* Read switch register */ M[SEC_DTSWR + base] = SW; @@ -585,12 +590,12 @@ enter_pri: case SEC_CLKCTL: /* Clock control: Used by KLDCP */ switch(word) { case SEC_CLKOFF: - dte_unit[2].STATUS &= ~SEC_CLK; + dte_unit[3].STATUS &= ~SEC_CLK; break; case SEC_CLKWT: rtc_wait = (uint16)(M[SEC_DTT11 + base] & 0177777); case SEC_CLKON: - dte_unit[2].STATUS |= SEC_CLK; + dte_unit[3].STATUS |= SEC_CLK; rtc_tick = 0; break; case SEC_CLKRD: @@ -607,6 +612,7 @@ enter_pri: } #if KL_ITS +/* Process ITS Ioeleven locations */ void dte_its(UNIT *uptr) { uint64 word; char ch; @@ -615,16 +621,6 @@ void dte_its(UNIT *uptr) { int ln; t_stat r; - /* Check for output Start */ - word = M[ITS_DTEOST]; - if ((word & SMASK) == 0) { - if (((tty_done.in_ptr + 1) & 0xff) != tty_done.out_ptr) { - tty_done.buff[tty_done.in_ptr] = (char)(word & 0xff); - tty_done.in_ptr = (tty_done.in_ptr + 1) & 0xff; - M[ITS_DTEOST] = FMASK; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOST = %012llo\n", word); - } - } /* Check for input Start */ word = M[ITS_DTEINP]; if ((word & SMASK) == 0) { @@ -639,48 +635,29 @@ void dte_its(UNIT *uptr) { sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word); while (cnt > 0) { if (ln < 0) { - if (!Mem_read_byte(0, &data)) + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) return; - ch = (data >> 8) & 0177; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY type %x\n", ch); - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - if ((r = sim_putchar_s (ch)) != SCPE_OK) /* Output errors */ - return; + if (!Mem_read_byte(0, &data, 1)) + return; + ch = data & 0177; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %x\n", ch); + cty_out.buff[cty_out.in_ptr] = ch; + cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; cnt--; - if (cnt) { - ch = data & 0177; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY type %x\n", ch); - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - if ((r = sim_putchar_s (ch)) != SCPE_OK) /* Output errors */ - return; - cnt--; - } + sim_activate(&dte_unit[1], 100); +#if (NUM_DEVS_TTY > 0) } else { - if (!Mem_read_byte(0, &data)) + struct _buffer *otty = &tty_out[ln]; + if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) return; - ch = (data >> 8) & 0177; - if (((tty_out[ln].in_ptr + 1) & 0xff) == tty_out[ln].out_ptr) + if (!Mem_read_byte(0, &data, 1)) return; + ch = data & 0177; sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln); - tty_out[ln].buff[tty_out[ln].in_ptr] = ch; - tty_out[ln].in_ptr = (tty_out[ln].in_ptr + 1) & 0xff; + otty->buff[otty->in_ptr] = ch; + otty->in_ptr = (otty->in_ptr + 1) & 0xff; cnt--; - if (cnt) { - ch = data & 0177; - if (((tty_out[ln].in_ptr + 1) & 0xff) == tty_out[ln].out_ptr) - return; - sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln); - tty_out[ln].buff[tty_out[ln].in_ptr] = ch; - tty_out[ln].in_ptr = (tty_out[ln].in_ptr + 1) & 0xff; - cnt--; - } - } - } - /* If on CTY Queue output done response */ - if (ln < 0) { - if (((tty_done.in_ptr + 1) & 0xff) != tty_done.out_ptr) { - tty_done.buff[tty_done.in_ptr] = (char)(0 & 0xff); - tty_done.in_ptr = (tty_done.in_ptr + 1) & 0xff; +#endif } } M[ITS_DTEOUT] = FMASK; @@ -695,60 +672,19 @@ void dte_its(UNIT *uptr) { M[ITS_DTELSP] = FMASK; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTELSP = %012llo %012llo\n", word, M[ITS_DTELPR]); } - /* Check if any input for it */ - if ((uptr->STATUS & ITS_ON) != 0) { - word = M[ITS_DTETYI]; - if ((word & SMASK) != 0) { /* Ready? */ - if (cty_in.in_ptr != cty_in.out_ptr) { - ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; - word = (uint64)ch; - M[ITS_DTETYI] = word; - /* Tell 10 something is ready */ - uptr->STATUS |= DTE_10DB; - if (uptr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, uptr->STATUS); - } - } - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); - } -#if 0 - /* Check for input */ - word = M[ITS_DTETYI]; - if ((word & SMASK) != 0) { - int l = uptr->CNT; - do { - if (tty_connect[l]) { -// if ((ch = dte_unit[1].CHHOLD) != 0) { -// word = ch; -// dte_unit[1].CHHOLD = 0; -// M[ITS_DTETYI] = word; -// /* Tell 10 something is ready */ -// uptr->STATUS |= DTE_10DB; -// if (uptr->STATUS & DTE_PIE) -// set_interrupt(DTE_DEVNUM, uptr->STATUS); -// } - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); - } -#endif - /* Check for output done */ - word = M[ITS_DTEODN]; - if ((word & SMASK) != 0) { - if (tty_done.in_ptr != tty_done.out_ptr) { - ln = tty_done.buff[tty_done.out_ptr]; - tty_done.out_ptr = (tty_done.out_ptr + 1) & 0xff; - word = M[ITS_DTEODN] = (((uint64)ln) << 18)|1; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo\n", word); - /* Tell 10 something is ready */ - uptr->STATUS |= DTE_10DB; - if (uptr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, uptr->STATUS); - } - } - /* Check for hangup */ - word = M[ITS_DTEHNG]; + dte_input(); + /* Check for output Start */ + word = M[ITS_DTEOST]; if ((word & SMASK) == 0) { - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEHNG = %012llo\n", word); + if (word == 0) + cty_done = 1; +#if (NUM_DEVS_TTY > 0) + else if (word > 0 && word < tty_desc.lines) { + tty_done[word-1] = 1; + } +#endif + M[ITS_DTEOST] = FMASK; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOST = %012llo\n", word); } } #endif @@ -779,7 +715,6 @@ error: uptr->STATUS |= DTE_SEC; return; } - sim_debug(DEBUG_EXP, &dte_dev, "DTE: Read status: %012llo\n", word); if ((word & PRI_CMT_QP) == 0) { uptr->STATUS |= DTE_SEC; @@ -792,23 +727,19 @@ error: fprintf(stderr, "DTE out of sync\n\r"); return; } - word = M[0140 + eb_ptr]; - sim_debug(DEBUG_EXP, &dte_dev, "DTE: Read pointer: %012llo\n", word); - word = M[0141 + eb_ptr]; - sim_debug(DEBUG_EXP, &dte_dev, "DTE: write pointer: %012llo\n", word); /* Get size of transfer */ if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_CNT, &iword)) goto error; - sim_debug(DEBUG_EXP, &dte_dev, "DTE: count: %012llo\n", iword); + sim_debug(DEBUG_EXP, &dte_dev, "DTE: count: %012llo\n", iword); in->dcnt = (uint16)(iword & 0177777); /* Read in data */ dp = &in->data[0]; for (cnt = in->dcnt; cnt >= 0; cnt -=2) { /* Read in data */ - if (!Mem_read_byte(0, dp)) + if (!Mem_read_byte(0, dp, 0)) goto error; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o\n", - *dp, *dp >> 8, *dp & 0377); + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o %06o\n", + *dp, *dp >> 8, *dp & 0377, ((*dp & 0377) << 8) | ((*dp >> 8) & 0377)); dp++; } uptr->STATUS &= ~DTE_IND; @@ -817,28 +748,29 @@ error: /* Transfer from 10 */ in->dptr = 0; /* Read in count */ - if (!Mem_read_byte(0, &data1)) + if (!Mem_read_byte(0, &data1, 0)) goto error; in->cnt = data1; cnt = in->cnt-2; - if (!Mem_read_byte(0, &data1)) + if (!Mem_read_byte(0, &data1, 0)) goto error; in->func = data1; cnt -= 2; - if (!Mem_read_byte(0, &data1)) + if (!Mem_read_byte(0, &data1, 0)) goto error; in->dev = data1; cnt -= 2; - if (!Mem_read_byte(0, &data1)) + if (!Mem_read_byte(0, &data1, 0)) goto error; in->spare = data1; cnt -= 2; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read CMD: %o %o %o\n", - in->cnt, in->func, in->dev); + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read CMD: %o %o %s %o\n", + in->cnt, in->func, + ((in->func & 0377) > PRI_EMLDV)?"***":pri_name[in->func & 0377], in->dev); dp = &in->data[0]; for (; cnt > 0; cnt -=2) { /* Read in data */ - if (!Mem_read_byte(0, dp)) + if (!Mem_read_byte(0, dp, 0)) goto error; sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read data: %06o %03o %03o\n", *dp, *dp >> 8, *dp & 0377); @@ -861,8 +793,10 @@ done: uptr->STATUS |= DTE_11DN; if (uptr->STATUS & DTE_PIE) set_interrupt(DTE_DEVNUM, uptr->STATUS); + dte_function(uptr); } +/* Process primary protocol packets */ void dte_function(UNIT *uptr) { @@ -870,6 +804,7 @@ dte_function(UNIT *uptr) int32 ch; struct _dte_queue *cmd; t_stat r; + int func; /* Check if queue is empty */ @@ -880,23 +815,23 @@ dte_function(UNIT *uptr) return; } cmd = &dte_in[dte_in_cmd]; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: func %02o %o %d %d\n", cmd->func & 0377, + func = cmd->func & 0377; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: func %02o %s dev %o cnt %d dcnt %d\n", func, + (func > PRI_EMLDV) ? "***" : pri_name[func], cmd->dev, cmd->dcnt, cmd->dptr ); - switch (cmd->func & 0377) { + switch (func) { case PRI_EM2EI: /* Initial message to 11 */ - data1[0] = 0; - if (dte_queue(uptr, PRI_EM2TI, PRI_EMCTY, 1, data1) == 0) + data1[0] = PRI_CTYDV; + if (dte_queue(PRI_EM2TI, PRI_EMCTY, 1, data1) == 0) + return; +#if (NUM_DEVS_LP > 0) + data1[0] = 140; + if (dte_queue(PRI_EMHLA, PRI_EMLPT, 1, data1) == 0) + return; +#endif + data1[0] = 0; + if (dte_queue(PRI_EMAKA, PRI_EMCLK, 0, data1) == 0) return; -//#if (NUM_DEVS_LP > 0) -// data1[0] = 140; -// if (dte_queue(uptr, PRI_EMHLA, PRI_EMLPT, 1, data1) == 0) -// return; -//#endif - -// data1[0] = ((ln + 1) << 8) | 32; - // (void)dte_queue(uptr, PRI_EMHLA, PRI_EMDL1, 1, data1); -// if (dte_queue(uptr, PRI_EMAKA, PRI_EMDH1, 0, data1) == 0) -// return; break; case PRI_EM2TI: /* Replay to initial message. */ @@ -906,6 +841,7 @@ dte_function(UNIT *uptr) case PRI_EMSTR: /* String data */ +#if (NUM_DEVS_LP > 0) /* Handle printer data */ if (cmd->dev == PRI_EMLPT) { if (!sim_is_active(&lpt_unit)) @@ -925,35 +861,42 @@ dte_function(UNIT *uptr) return; break; } +#endif +#if (NUM_DEVS_TTY > 0) /* Handle terminal data */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 1; - if (ln < 0) + int ln = ((cmd->sdev >> 8) & 0377); + struct _buffer *otty; + if (ln == PRI_CTYDV) goto cty; - if (ln >= tty_desc.lines) + ln -= 2; + if (ln > 0 && ln >= tty_desc.lines) break; + otty = &tty_out[ln]; while (cmd->dptr < cmd->dcnt) { - if (((tty_out[ln].in_ptr + 1) & 0xff) == tty_out[ln].out_ptr) + if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) return; ch = (int32)(cmd->data[cmd->dptr >> 1]); if ((cmd->dptr & 1) == 0) ch >>= 8; ch &= 0177; - sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln); - tty_out[ln].buff[tty_out[ln].in_ptr] = ch; - tty_out[ln].in_ptr = (tty_out[ln].in_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %o %d\n", ch, ln); + otty->buff[otty->in_ptr] = ch; + otty->in_ptr = (otty->in_ptr + 1) & 0xff; cmd->dptr++; } if (cmd->dptr != cmd->dcnt) return; break; } +#endif /* Fall through */ case PRI_EMSNA: /* Send all (ttys) */ if (cmd->dev != PRI_EMCTY) break; cty: + sim_activate(&dte_unit[1], 100); data1[0] = 0; while (cmd->dptr < cmd->dcnt) { if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) @@ -962,11 +905,10 @@ cty: if ((cmd->dptr & 1) == 0) ch >>= 8; ch &= 0177; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY type %x\n", ch); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; - cty_data = 1; /* Let output know it needs to ack this */ cmd->dptr++; } if (cmd->dptr != cmd->dcnt) @@ -975,34 +917,16 @@ cty: case PRI_EMLNC: /* Line-Char */ /* Send by DTE only? */ -#if 0 - data1[0] = 0; - while (cmd->dptr < cmd->dcnt) { - ch = (int32)(cmd->data[cmd->dptr >> 1]); - if ((ch >> 8) == PRI_EMCTY) { - ch &= 0177; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ltype %x\n", ch); - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - if ((r = sim_putchar_s (ch)) != SCPE_OK) /* Output errors */ - return; - data1[0] = (PRI_EMCTY << 8); - } - cmd->dptr+=2; - } - if (cmd->dptr != cmd->dcnt) - return; - if (dte_queue(uptr, PRI_EMACK, PRI_EMCTY, 1, data1) == 0) - return; -#endif break; case PRI_EMRDS: /* Request device status */ case PRI_EMHDS: /* Here is device status */ case PRI_EMRDT: /* Request Date/Time */ case PRI_EMHDR: /* Here is date and time */ break; +#if (NUM_DEVS_TTY > 0) case PRI_EMFLO: /* Flush output */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 1;; + int ln = ((cmd->sdev >> 8) & 0377) - 2;; tty_out[ln].in_ptr = tty_out[ln].out_ptr = 0; } break; @@ -1010,7 +934,7 @@ cty: break; case PRI_EMHUD: /* Hang up dataset */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 1; + int ln = ((cmd->sdev >> 8) & 0377) - 2; TMLN *lp = &tty_ldsc[ln]; tmxr_linemsg (lp, "\r\nLine Hangup\r\n"); tmxr_reset_ln(lp); @@ -1019,19 +943,19 @@ cty: break; case PRI_EMXOF: /* XOFF line */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 1; + int ln = ((cmd->sdev >> 8) & 0377) - 2; tty_ldsc[ln].rcve = 0; } break; case PRI_EMXON: /* XON line */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 1; + int ln = ((cmd->sdev >> 8) & 0377) - 2; tty_ldsc[ln].rcve = 1; } break; case PRI_EMHLS: /* Here is line speeds */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 1; + int ln = ((cmd->sdev >> 8) & 0377) - 2; } break; case PRI_EMHLA: /* Here is line allocation */ @@ -1053,6 +977,7 @@ cty: } } break; +#endif case PRI_EMLDR: /* Load LP RAM */ case PRI_EMLDV: /* Load LP VFU */ default: @@ -1142,41 +1067,177 @@ void dte_transfer(UNIT *uptr) { dte_out_ptr = (dte_out_ptr + 1) & 0x1f; done: uptr->STATUS |= DTE_10DN; -//fprintf(stderr, "Xfer done %06o\n\r", uptr->CNT ); if (uptr->STATUS & DTE_PIE) set_interrupt(DTE_DEVNUM, uptr->STATUS); error: return; } +/* Process input from CTY and TTY's to 10. */ void dte_input() { uint16 data1; uint16 dataq[32]; int n; + int ln; int save_ptr; char ch; + int flg; + UNIT *uptr = &dte_unit[0]; - /* Check if CTY done with input */ - if (cty_data && cty_out.in_ptr == cty_out.out_ptr) { - data1 = 0; - if (dte_queue(&dte_unit[0], PRI_EMACK, PRI_EMCTY, 1, &data1) == 0) - return; - cty_data = 0; - } - n = 0; - save_ptr = cty_in.out_ptr; - while (cty_in.in_ptr != cty_in.out_ptr && n < 32) { - ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; - sim_debug(DEBUG_DETAIL, &tty_dev, "CTY recieve %02x\n", ch); - dataq[n++] = ch; - } - if (n > 0 && dte_queue(&dte_unit[0], PRI_EMLNC, PRI_EMCTY, n, dataq) == 0) { - /* Restore the input pointer */ - cty_in.out_ptr = save_ptr; - return; +#if KL_ITS + if (QITS && (uptr->STATUS & ITS_ON) != 0) { + uint64 word; + word = M[ITS_DTEODN]; + /* Check if ready for output done */ + if ((word & SMASK) != 0) { + if (cty_done) { + word = 64LL; + cty_done = 0; +#if (NUM_DEVS_TTY > 0) + } else { + for (ln = 0; ln < tty_desc.lines; ln++) { + if (tty_done[ln]) { + word = (((uint64)ln + 1) << 18); + word |=(tty_connect[ln])? 64: 1; + tty_done[ln] = 0; + break; + } + } +#endif + } + if ((word & SMASK) == 0) { + M[ITS_DTEODN] = word; + /* Tell 10 something is ready */ + uptr->STATUS |= DTE_10DB; + if (uptr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, uptr->STATUS); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo\n", word); + } + } + /* Check if ready for any input */ + word = M[ITS_DTETYI]; + if ((word & SMASK) != 0) { + /* CTY first. */ + if (cty_in.in_ptr != cty_in.out_ptr) { + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + word = (uint64)ch; +#if (NUM_DEVS_TTY > 0) + } else { + ln = uptr->CNT; + while ((word & SMASK) != 0) { + if (tty_in[ln].in_ptr != tty_in[ln].out_ptr) { + ch = tty_in[ln].buff[tty_in[ln].out_ptr]; + tty_in[ln].out_ptr = (tty_in[ln].out_ptr + 1) & 0xff; + word = ((uint64)(ln+1) << 18) | (uint64)ch; + } + ln++; + if (ln >= tty_desc.lines) + ln = 0; + if (ln == uptr->CNT) + break; + } + uptr->CNT = ln; +#endif + } + if ((word & SMASK) == 0) { + M[ITS_DTETYI] = word; + /* Tell 10 something is ready */ + uptr->STATUS |= DTE_10DB; + if (uptr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, uptr->STATUS); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); + } + } +#if (NUM_DEVS_TTY > 0) + /* Check ready for hang up message */ + word = M[ITS_DTEHNG]; + if ((word & SMASK) != 0) { + for (ln = 0; ln < tty_desc.lines; ln++) { + if (tty_connect[ln] != tty_ldsc[ln].conn) { + if (tty_ldsc[ln].conn) + word = 015500 + ln + 1; + else + word = ln + 1; + tty_connect[ln] = tty_ldsc[ln].conn; + tty_done[ln] = tty_ldsc[ln].conn; + break; + } + } + /* Tell 10 something is ready */ + if ((word & SMASK) == 0) { + M[ITS_DTEHNG] = word; + uptr->STATUS |= DTE_10DB; + if (uptr->STATUS & DTE_PIE) + set_interrupt(DTE_DEVNUM, uptr->STATUS); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEHNG = %012llo\n", word); + } + } +#endif + } else +#endif + if ((uptr->STATUS & DTE_SEC) == 0) { + /* Check if CTY done with input */ + if (cty_done) { + data1 = PRI_CTYDV; + if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, &data1) == 0) + return; + cty_done = 0; + } + /* Grab a chunck of input from CTY if any */ + n = 0; + save_ptr = cty_in.out_ptr; + while (cty_in.in_ptr != cty_in.out_ptr && n < 32) { + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY recieve %02x\n", ch); + dataq[n++] = (PRI_CTYDV << 8) | ch; + } + if (n > 0 && dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) { + /* Restore the input pointer */ + cty_in.out_ptr = save_ptr; + return; + } +#if (NUM_DEVS_TTY > 0) + n = 0; + /* While we have room for one more packet, grab as much input as we can */ + for (ln = 0; ln < tty_desc.lines && ((dte_out_res + 1) & 0x1f) != dte_out_ptr; ln++) { + while (tty_in[ln].in_ptr != tty_in[ln].out_ptr) { + ch = tty_in[ln].buff[tty_in[ln].out_ptr]; + tty_in[ln].out_ptr = (tty_in[ln].out_ptr + 1) & 0xff; + dataq[n++] = ((ln + 2) << 8) | ch; + if (n == 32) { + if (dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) + return; + n = 0; + continue; + } + } + } + if (n > 0 && dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) + return; + n = 0; + for (ln = 0; ln < tty_desc.lines; ln++) { + if (tty_connect[ln] != tty_ldsc[ln].conn) { + data1 = ln + 2; + if (tty_ldsc[ln].conn) + n = PRI_EMDSC; + else + n = PRI_EMHUD; + if (dte_queue(n, PRI_EMDLS, 1, &data1) == 0) + return; + tty_connect[ln] = tty_ldsc[ln].conn; + } + if (tty_done[ln]) { + data1 = ln + 2; + if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, &data1) == 0) + return; + tty_done[ln] = 0; + } + } +#endif } } @@ -1184,11 +1245,10 @@ dte_input() * Queue up a packet to send to 10. */ int -dte_queue(UNIT *uptr, int func, int dev, int dcnt, uint16 *data) +dte_queue(int func, int dev, int dcnt, uint16 *data) { uint64 word; uint16 *dp; - UNIT *optr = &dte_unit[0]; struct _dte_queue *out; /* Check if room in queue for this packet. */ @@ -1202,8 +1262,9 @@ dte_queue(UNIT *uptr, int func, int dev, int dcnt, uint16 *data) out->dev = dev; out->dcnt = (dcnt-1)*2; out->spare = 0; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d queue resp: %o %o %o\n", - dte_out_ptr, dte_out_res, out->cnt, out->func, out->dev); + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d queue resp: %o %o %s %o\n", + dte_out_ptr, dte_out_res, out->cnt, out->func, + (out->func > PRI_EMLDV)? "***":pri_name[out->func], out->dev); for (dp = &out->data[0]; dcnt > 0; dcnt--) { *dp++ = *data++; } @@ -1256,40 +1317,28 @@ error: } -/* Handle TO10 traffic */ +/* Check for input from CTY and put on queue. */ t_stat dtei_svc (UNIT *uptr) { int32 ch; uint32 base = 0; UNIT *optr = &dte_unit[0]; uint16 data1; + int f; #if KI_22BIT #if KL_ITS - if ((cpu_unit[0].flags & UNIT_ITSPAGE) == 0) + if (!QITS) #endif base = eb_ptr; #endif sim_clock_coschedule (uptr, tmxr_poll); -#if KL_ITS - if ((uptr->STATUS & (DTE_SEC|ITS_ON)) == 0) { -#else - if ((uptr->STATUS & (DTE_SEC)) == 0) { -#endif + dte_input(); + if ((optr->STATUS & (DTE_SEC)) == 0) { dte_function(uptr); /* Process queue */ - dte_input(uptr); dte_start(optr); } - /* Flush out any pending CTY output */ - while(cty_out.in_ptr != cty_out.out_ptr) { - ch = cty_out.buff[cty_out.out_ptr]; - if (sim_putchar(ch) != SCPE_OK) - break; - cty_out.out_ptr = (cty_out.out_ptr + 1) & 0xff; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY outch %x '%c'\n", ch, - ((ch > 040 && ch < 0177)? ch: '.')); - } /* If we have room see if any new lines */ if (((cty_in.in_ptr + 1) & 0xff) != cty_in.out_ptr) { @@ -1298,18 +1347,14 @@ t_stat dtei_svc (UNIT *uptr) ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (uptr->flags)); cty_in.buff[cty_in.in_ptr] =ch & 0377; cty_in.in_ptr = (cty_in.in_ptr + 1) & 0xff; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %x '%c'\n", ch, + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %o '%c'\n", ch, ((ch > 040 && ch < 0177)? ch: '.')); } } -#if KL_ITS - if ((optr->STATUS & (DTE_SEC|ITS_ON)) == (DTE_SEC) && -#else - if ((optr->STATUS & DTE_SEC) != 0 && -#endif - cty_in.in_ptr != cty_in.out_ptr && - (optr->STATUS & DTE_MON) != 0 && - M[SEC_DTMTI + base] == 0) { + + /* If Monitor input, place in buffer */ + if ((optr->STATUS & (DTE_SEC|DTE_MON)) == (DTE_SEC|DTE_MON) && + cty_in.in_ptr != cty_in.out_ptr && M[SEC_DTMTI + base] == 0) { ch = cty_in.buff[cty_in.out_ptr]; cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; M[SEC_DTF11 + base] = ch; @@ -1318,27 +1363,32 @@ t_stat dtei_svc (UNIT *uptr) if (optr->STATUS & DTE_PIE) set_interrupt(DTE_DEVNUM, optr->STATUS); } -#if KL_ITS - if (QITS && (optr->STATUS & ITS_ON) != 0) { - uint64 word = M[ITS_DTETYI]; - if ((word & SMASK) != 0) { - if (cty_in.in_ptr != cty_in.out_ptr) { - ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; - word = (uint64)ch; - M[ITS_DTETYI] = word; - /* Tell 10 something is ready */ - optr->STATUS |= DTE_10DB; - if (optr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, optr->STATUS); - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); - } - } - } -#endif return SCPE_OK; } +/* Handle output of characters to CTY. Started whenever there is output pending */ +t_stat dteo_svc (UNIT *uptr) +{ + /* Flush out any pending CTY output */ + while(cty_out.in_ptr != cty_out.out_ptr) { + char ch = cty_out.buff[cty_out.out_ptr]; + if (ch != 0) { + if (sim_putchar(ch) != SCPE_OK) { + sim_activate(uptr, 1000); + return SCPE_OK;; + } + } + cty_out.out_ptr = (cty_out.out_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY outch %o '%c'\n", ch, + ((ch > 040 && ch < 0177)? ch: '.')); + } + cty_done = 1; + dte_input(); + return SCPE_OK; +} + + +/* Handle FE timer interrupts. And keepalive counts */ t_stat dtertc_srv(UNIT * uptr) { @@ -1373,10 +1423,15 @@ dtertc_srv(UNIT * uptr) word = (M[ITS_DTECHK] + 1) & FMASK; if (word == 0) { optr->STATUS |= ITS_ON; + cty_done = 0; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS ON\n"); + sim_activate(&tty_unit[0], 1000); + sim_activate(&tty_unit[1], 1000); } else if (word >= (15 * 60)) { optr->STATUS &= ~ITS_ON; word = 15 * 60; + sim_cancel(&tty_unit[0]); + sim_cancel(&tty_unit[1]); sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS OFF\n"); } M[ITS_DTECHK] = word; @@ -1389,12 +1444,11 @@ dtertc_srv(UNIT * uptr) uint64 word; (void)Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word); -//fprintf(stderr, "Timer %06o %012llo\n\r", optr->STATUS, word); addr = (M[addr+1] + dte_off + PRI_CMTW_KAC) & RMASK; word = M[addr]; word = (word + 1) & FMASK; M[addr] = word; - sim_debug(DEBUG_EXP, &dte_dev, "CTY keepalive %06o %012llo %06o\n", + sim_debug(DEBUG_EXP, &dte_dev, "CTY keepalive %06o %012llo %06o\n", addr, word, optr->STATUS); } @@ -1405,17 +1459,12 @@ dtertc_srv(UNIT * uptr) t_stat dte_reset (DEVICE *dptr) { dte_unit[0].STATUS = DTE_SEC; - dte_unit[1].STATUS = DTE_SEC; - dte_unit[1].CHHOLD = 0; + dte_unit[1].STATUS = 0; dte_unit[2].STATUS = 0; -// dte_in_ptr = dte_in_cmd = dte_out_ptr = dte_out_res = 0; -// cty_in.in_ptr = 0; -// cty_in.out_ptr = 0; -// cty_out.in_ptr = 0; -// cty_out.out_ptr = 0; - sim_rtcn_init_unit (&dte_unit[2], dte_unit[2].wait, TMR_RTC); - sim_activate(&dte_unit[1], 100); - sim_activate(&dte_unit[2], 100); + dte_unit[3].STATUS = 0; + sim_rtcn_init_unit (&dte_unit[3], 1000, TMR_RTC); + sim_activate(&dte_unit[3], 1000); + sim_activate(&dte_unit[2], 1000); return SCPE_OK; } @@ -1492,7 +1541,7 @@ lpt_printline(UNIT *uptr, int nl) { uptr->COL = 0; uptr->POS = 0; // if (uptr->LINE == 0) - // (void)dte_queue(&dte_unit[0], PRI_EMHDS, PRI_EMLPT, 1, &data1); + // (void)dte_queue(PRI_EMHDS, PRI_EMLPT, 1, &data1); return; } @@ -1589,7 +1638,7 @@ t_stat lpt_svc (UNIT *uptr) lpt_output(uptr, c); } } - if (dte_queue(&dte_unit[0], PRI_EMACK, PRI_EMLPT, 1, &data1) == 0) + if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, &data1) == 0) sim_activate(uptr, 1000); return SCPE_OK; } @@ -1691,14 +1740,10 @@ t_stat ttyi_svc (UNIT *uptr) sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */ /* If we have room see if any new lines */ - if (((tty_hang.in_ptr + 1) & 0xff) != tty_hang.out_ptr) { - ln = tmxr_poll_conn (&tty_desc); /* look for connect */ - if (ln >= 0) { /* got one? rcv enb*/ - tty_hang.buff[tty_hang.in_ptr] = ln + 1; - tty_hang.in_ptr = (tty_hang.in_ptr + 1) & 0xff; - tty_connect[ln] = 1; + ln = tmxr_poll_conn (&tty_desc); /* look for connect */ + if (ln >= 0) { + tty_ldsc[ln].rcve = 1; sim_debug(DEBUG_DETAIL, &tty_dev, "TTY line connect %d\n", ln); - } } tmxr_poll_tx(&tty_desc); @@ -1706,28 +1751,22 @@ t_stat ttyi_svc (UNIT *uptr) /* Scan each line for input */ for (ln = 0; ln < tty_desc.lines; ln++) { + struct _buffer *iptr = &tty_in[ln]; lp = &tty_ldsc[ln]; + if (lp->conn == 0) + continue; flg = 1; + while (flg && ((iptr->in_ptr + 1) & 0xff) != iptr->out_ptr) { /* Spool up as much as we have room for */ - while (flg && ((tty_out[ln].in_ptr + 1) & 0xff) != tty_out[ln].out_ptr) { int32 ch = tmxr_getc_ln(lp); if ((ch & TMXR_VALID) != 0) { ch = sim_tt_inpcvt (ch, TT_GET_MODE(tty_unit[0].flags) | TTUF_KSR); - tty_in[ln].buff[tty_in[ln].in_ptr] = ch & 0377; - tty_in[ln].in_ptr = (tty_in[ln].in_ptr + 1) & 0xff; - sim_debug(DEBUG_DETAIL, &tty_dev, "TTY recieve %d: %02x\n", ln, ch); + iptr->buff[iptr->in_ptr] = ch & 0377; + iptr->in_ptr = (iptr->in_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &tty_dev, "TTY recieve %d: %o\n", ln, ch); } else flg = 0; } - /* Look for lines that have been disconnected */ - if (tty_connect[ln] == 1 && lp->conn == 0) { - if (((tty_hang.in_ptr + 1) & 0xff) != tty_hang.out_ptr) { - tty_hang.buff[tty_hang.in_ptr] = ln + 1; - tty_hang.in_ptr = (tty_hang.in_ptr + 1) & 0xff; - tty_connect[ln] = 0; - sim_debug(DEBUG_DETAIL, &tty_dev, "TTY line disconnect %d\n", ln); - } - } } return SCPE_OK; @@ -1748,36 +1787,26 @@ t_stat ttyo_svc (UNIT *uptr) sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */ for (ln = 0; ln < tty_desc.lines; ln++) { + struct _buffer *optr = &tty_out[ln]; lp = &tty_ldsc[ln]; if (lp->conn == 0) continue; - if (((tty_done.in_ptr + 1) & 0xff) == tty_done.out_ptr) - return SCPE_OK; - if (tty_out[ln].out_ptr == tty_out[ln].in_ptr) + if (optr->out_ptr == optr->in_ptr) continue; - while (tty_out[ln].out_ptr != tty_out[ln].in_ptr) { - int32 ch = tty_out[ln].buff[tty_out[ln].out_ptr]; + while (optr->out_ptr != optr->in_ptr) { + int32 ch = optr->buff[optr->out_ptr]; ch = sim_tt_outcvt(ch, TT_GET_MODE (tty_unit[0].flags) | TTUF_KSR); - sim_debug(DEBUG_DATA, &tty_dev, "TTY: %d output %02x\n", ln, ch); + sim_debug(DEBUG_DATA, &tty_dev, "TTY: %d output %o\n", ln, ch); r = tmxr_putc_ln (lp, ch); if (r == SCPE_OK) - tty_out[ln].out_ptr = (tty_out[ln].out_ptr + 1) & 0xff; + optr->out_ptr = (optr->out_ptr + 1) & 0xff; else if (r == SCPE_LOST) { - tty_out[ln].out_ptr = tty_out[ln].in_ptr = 0; + optr->out_ptr = optr->in_ptr = 0; continue; } else continue; } - tty_done.buff[tty_done.in_ptr] = ln + 1; - tty_done.in_ptr = (tty_done.in_ptr + 1) & 0xff; -#if KL_ITS - /* Tell 10 we have something for it */ - if (QITS) { - dte_unit[0].STATUS |= DTE_10DB; - if (dte_unit[0].STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); - } -#endif + tty_done[ln] = 1; } return SCPE_OK; } diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 4fb1295..5a7a8f1 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -157,6 +157,7 @@ int pi_enable; /* Interrupts enabled */ int parity_irq; /* Parity interupt */ int pi_pending; /* Interrupt pending. */ int pi_enc; /* Flag for pi */ +int pi_vect; /* Last pi location used for IRQ */ int apr_irq; /* Apr Irq level */ int clk_en; /* Enable clock interrupts */ int clk_irq; /* Clock interrupt */ @@ -266,6 +267,8 @@ int32 tmxr_poll = 10000; /* Physical address range for auxiliary PDP-6. */ #define AUXCPURANGE(addr) ((addr) >= 03000000 && (addr) < 03040000) + +/* List of RH10 & RH20 devices */ DEVICE *rh_devs[] = { #if (NUM_DEVS_RS > 0) &rsa_dev, @@ -287,16 +290,10 @@ DEVICE *rh_devs[] = { #endif NULL, }; - -struct rh_dev rh[] = { - { 0270, NULL, }, - { 0274, NULL, }, - { 0360, NULL, }, - { 0364, NULL, }, - { 0370, NULL, }, - { 0374, NULL, }, - { 0, NULL, }, -}; +/* RH10 device numbers */ +int rh_nums[] = { 0270, 0274, 0360, 0364, 0370, 0374, 0}; +/* Maps RH10 & RH20 device number to DEVICE structure */ +struct rh_dev rh[8]; typedef struct { uint32 pc; @@ -2355,7 +2352,7 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch /* Check for access error */ if ((data & RSIGN) == 0 || (wr & ((data & 0100000) == 0))) { -fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); +//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); fault_data = BIT8 | (uint64)addr; #if KLB if (QKLB) @@ -2462,7 +2459,7 @@ int Mem_read(int flag, int cur_context, int fetch) { fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); if (USER==0) /* U */ fault_data |= SMASK; /* BIT0 */ -fprintf(stderr, "Invalid section %012llo\n\r", fault_data); +//fprintf(stderr, "Invalid section %012llo\n\r", fault_data); page_fault = 1; return 0; } @@ -2508,7 +2505,7 @@ int Mem_write(int flag, int cur_context) { fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); if (USER==0) /* U */ fault_data |= SMASK; /* BIT0 */ -fprintf(stderr, "Invalid section %012llo\n\r", fault_data); +//fprintf(stderr, "Invalid section %012llo\n\r", fault_data); page_fault = 1; return 0; } @@ -2615,12 +2612,12 @@ int Mem_deposit_word(int n, int wrd, uint64 *data) { /* * Read in 16 bits of data from a byte pointer. */ -int Mem_read_byte(int n, uint16 *data) { +int Mem_read_byte(int n, uint16 *data, int byte) { int addr; uint64 val; uint64 msk; int p, s, np; - int need = 16; + int need = byte? 8: 16; *data = 0; while (need > 0) { @@ -4222,18 +4219,23 @@ st_pi: * hit at a given level. */ for (f = 0; f < 128; f++) { - if (dev_irqv[f] != 0) - sim_debug(DEBUG_IRQ, &cpu_dev, "vect irq %o %03o \n", - pi_enc, dev_irq[f]); if (dev_irqv[f] != 0 && dev_irq[f] & (0200 >> pi_enc)) { AB = dev_irqv[f](f << 2, AB); + if (dev_irqv[f] != 0) + sim_debug(DEBUG_IRQ, &cpu_dev, "vect irq %o %03o %06o\n", + pi_enc, dev_irq[f], AB); break; } } - AB |= eb_ptr; + if (AB & RSIGN) + AB &= 0777; + else + AB |= eb_ptr; + pi_vect = AB; Mem_read_nopage(); goto no_fetch; #else + pi_vect = AB; goto fetch; #endif } @@ -7022,7 +7024,6 @@ xjrstf: if (QKLB) { pc_sect = (AR >> 18) & 07777; prev_sect = BR & 037; - fprintf(stderr, "xjrstf %012llo %012llo\n\r", BR, AR); } #endif BR = BR >> 23; /* Move flags into position */ @@ -8409,7 +8410,7 @@ last: #if KI | KL if (page_enable && page_fault) { page_fault = 0; -fprintf(stderr, "Page fault trap %06o\n\r", PC); +//fprintf(stderr, "Page fault trap %06o\n\r", PC); pi_cycle = 0; #if KI inout_fail = 1; @@ -8428,9 +8429,8 @@ fprintf(stderr, "Page fault trap %06o\n\r", PC); if ((!pi_hold) & f_inst_fetch) { pi_cycle = 0; } else { - AB = 040 | (pi_enc << 1) | pi_ov | maoff; + AB = pi_vect | pi_ov; #if KI | KL - AB |= eb_ptr; Mem_read_nopage(); #else Mem_read(1, 0, 1); @@ -8441,11 +8441,10 @@ fprintf(stderr, "Page fault trap %06o\n\r", PC); if ((IR & 0700) == 0700) { (void)check_irq_level(); } - AB = 040 | (pi_enc << 1) | pi_ov | maoff; + AB = pi_vect | pi_ov; pi_ov = 0; pi_hold = 0; #if KI | KL - AB |= eb_ptr; Mem_read_nopage(); #else Mem_read(1, 0, 1); @@ -9572,7 +9571,7 @@ t_bool build_dev_tab (void) DEVICE *dptr; DIB *dibp; uint32 i, j, d; -int rh20 = 0540; +int rh20; /* Set trap offset based on MAOFF flag */ maoff = (cpu_unit[0].flags & UNIT_MAOFF)? 0100 : 0; @@ -9626,15 +9625,23 @@ if (QBBN) dev_tab[024>>2] = &dev_pag; #endif -/* Assign all RH10 devices */ +/* Assign all RH10 & RH20 devices */ +rh20 = 0540; for (j = i = 0; (dptr = rh_devs[i]) != NULL; i++) { dibp = (DIB *) dptr->ctxt; if (dibp && !(dptr->flags & DEV_DIS)) { /* enabled? */ - if (rh[j].dev_num == 0) - break; - d = rh[j].dev_num; + d = dibp->dev_num; /* Check type */ + if (d & RH10_DEV) { /* Skip RH10 devices */ + d = rh_nums[j]; + if (d == 0) + break; + } else if (d & RH20_DEV) { /* RH20, grab next device */ + d = rh20; + rh20 += 4; + } dev_tab[(d >> 2)] = dibp->io; dev_irqv[(d >> 2)] = dibp->irq; + rh[j].dev_num = d; rh[j].dev = dptr; j++; } @@ -9653,12 +9660,8 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { for (j = 0; j < dibp->num_devs; j++) { /* loop thru disp */ if (dibp->io) { /* any dispatch? */ d = dibp->dev_num; - if (d & RH10_DEV) /* Skip RH10 devices */ + if (d & (RH10_DEV|RH20_DEV)) /* Skip RH10 & RH20 devices */ continue; - if (d & RH20_DEV) { /* RH20, grab next device */ - d = rh20; - rh20 += 4; - } if (dev_tab[(d >> 2) + j] != &null_dev) { /* already filled? */ sim_printf ("%s device number conflict at %02o\n", diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 8949d15..669a6fe 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -376,7 +376,7 @@ extern UNIT auxcpu_unit[]; /* DTE memory access functions, n = DTE# */ extern int Mem_examine_word(int n, int wrd, uint64 *data); extern int Mem_deposit_word(int n, int wrd, uint64 *data); -extern int Mem_read_byte(int n, uint16 *data); +extern int Mem_read_byte(int n, uint16 *data, int byte); extern int Mem_write_byte(int n, uint16 *data); extern DEVICE dte_dev; extern DEVICE tty_dev; @@ -541,7 +541,7 @@ int auxcpu_write (int addr, t_uint64); #define NUM_DEVS_TEN11 ITS #define NUM_DEVS_AUXCPU ITS #define NUM_DEVS_IMP 1 -#define NUM_DEVS_CH10 ITS +#define NUM_DEVS_CH10 ITS | KL_ITS #define NUM_DEVS_DPK ITS #define NUM_DEVS_AI ITS #endif diff --git a/PDP10/kx10_imp.c b/PDP10/kx10_imp.c index 897c698..46367a2 100644 --- a/PDP10/kx10_imp.c +++ b/PDP10/kx10_imp.c @@ -145,7 +145,7 @@ #endif #endif -#define IMP_ARPTAB_SIZE 8 +#define IMP_ARPTAB_SIZE 64 #define IMP_ARP_MAX_AGE 100 uint32 mask[] = { @@ -199,6 +199,12 @@ struct tcp { uint32 seq; /* Sequence number */ uint32 ack; /* Ack number */ uint16 flags; /* Flags */ +#define TCP_FL_FIN 0x01 +#define TCP_FL_SYN 0x02 +#define TCP_FL_RST 0x04 +#define TCP_FL_PSH 0x08 +#define TCP_FL_ACK 0x10 +#define TCP_FL_URG 0x20 uint16 window; /* Window size */ uint16 chksum; /* packet checksum */ uint16 urgent; /* Urgent pointer */ @@ -445,6 +451,7 @@ static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff}; static CONST in_addr_T broadcast_ipaddr = {0xffffffff}; t_stat imp_devio(uint32 dev, uint64 *data); +t_stat imp_devirq(uint32 dev, int addr); t_stat imp_srv(UNIT *); t_stat imp_eth_srv(UNIT *); t_stat imp_tim_srv(UNIT *); @@ -473,6 +480,8 @@ void imp_arp_arpin(struct imp_device *imp, ETH_PACK *packet); void imp_arp_arpout(struct imp_device *imp, in_addr_T ipaddr); struct arp_entry * imp_arp_lookup(struct imp_device *imp, in_addr_T ipaddr); void imp_packet_out(struct imp_device *imp, ETH_PACK *packet); +void imp_packet_debug(struct imp_device *imp, const char *action, ETH_PACK *packet); +void imp_write(struct imp_device *imp, ETH_PACK *packet); void imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *packet); void imp_dhcp_timer(struct imp_device *imp); void imp_dhcp_discover(struct imp_device *imp); @@ -495,7 +504,13 @@ UNIT imp_unit[] = { {UDATA(imp_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ {UDATA(imp_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ }; -DIB imp_dib = {IMP_DEVNUM, 1, &imp_devio, NULL}; +DIB imp_dib = {IMP_DEVNUM, 1, &imp_devio, +#if KL + &imp_devirq, +#else + NULL +#endif +}; MTAB imp_mod[] = { { MTAB_XTD|MTAB_VDV|MTAB_VALR|MTAB_NC, 0, "MAC", "MAC=xx:xx:xx:xx:xx:xx", @@ -529,11 +544,38 @@ MTAB imp_mod[] = { { 0 } }; +/* Simulator debug controls */ +DEBTAB imp_debug[] = { + {"CMD", DEBUG_CMD, "Show command execution to devices"}, + {"DATA", DEBUG_DATA, "Show data transfers"}, + {"DETAIL", DEBUG_DETAIL, "Show details about device"}, + {"EXP", DEBUG_EXP, "Show exception information"}, + {"CONI", DEBUG_CONI, "Show coni instructions"}, + {"CONO", DEBUG_CONO, "Show coni instructions"}, + {"DATAIO", DEBUG_DATAIO, "Show datai and datao instructions"}, + {"IRQ", DEBUG_IRQ, "Show IRQ requests"}, +#define DEBUG_DHCP (DEBUG_IRQ<<1) + {"DHCP", DEBUG_DHCP, "Show DHCP activities"}, +#define DEBUG_ARP (DEBUG_DHCP<<1) + {"ARP", DEBUG_ARP, "Show ARP activities"}, +#define DEBUG_TCP (DEBUG_ARP<<1) + {"TCP", DEBUG_TCP, "Show TCP packet activities"}, +#define DEBUG_UDP (DEBUG_TCP<<1) + {"UDP", DEBUG_UDP, "Show UDP packet activities"}, +#define DEBUG_ICMP (DEBUG_UDP<<1) + {"ICMP", DEBUG_ICMP, "Show ICMP packet activities"}, +#define DEBUG_ETHER (DEBUG_ICMP<<1) + {"ETHER", DEBUG_ETHER, "Show ETHER activities"}, + {0, 0} +}; + + + DEVICE imp_dev = { "IMP", imp_unit, NULL, imp_mod, 3, 8, 0, 1, 8, 36, NULL, NULL, &imp_reset, NULL, &imp_attach, &imp_detach, - &imp_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, dev_debug, + &imp_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, imp_debug, NULL, NULL, &imp_help, NULL, NULL, &imp_description }; #define IMP_OCHN 0000007 @@ -600,6 +642,7 @@ t_stat imp_devio(uint32 dev, uint64 *data) uptr->STATUS |= IMPIHE; if (*data & IMPLHW) /* Last host word. */ uptr->STATUS |= IMPLHW; + check_interrupts(uptr); break; case TYPE_BBN: break; @@ -696,6 +739,20 @@ t_stat imp_devio(uint32 dev, uint64 *data) return SCPE_OK; } +#if KL +/* Handle KL style interrupt vectors for ITS */ +int +imp_devirq(uint32 dev, int addr) { + if ((cpu_unit[0].flags & UNIT_ITSPAGE) != 0 && (imp_data.pia & 7) == 1) { + if (imp_unit[0].STATUS & IMPID && (imp_unit[0].STATUS & IMPLW) == 0) + return 070|RSIGN; + if (imp_unit[0].STATUS & IMPOD) + return 072|RSIGN; + } + return addr; +} +#endif + t_stat imp_srv(UNIT * uptr) { DEVICE *dptr = find_dev_from_unit(uptr); @@ -831,8 +888,8 @@ t_stat imp_eth_srv(UNIT * uptr) imp_data.dhcp_state != DHCP_STATE_REBINDING && imp_data.dhcp_state != DHCP_STATE_RENEWING) return SCPE_OK; - sim_debug(DEBUG_DETAIL, &imp_dev, "IMP init Nop %d\n", - imp_data.init_state); + sim_debug(DEBUG_DETAIL, &imp_dev, "IMP init Nop %d\n", + imp_data.init_state); if (imp_unit[0].ILEN == 0) { /* Queue up a nop packet */ imp_data.rbuffer[0] = 0x4; @@ -922,6 +979,7 @@ imp_packet_in(struct imp_device *imp) } return; } + imp_packet_debug(imp, "Received", &read_buffer); hdr = (struct imp_eth_hdr *)(&read_buffer.msg[0]); type = ntohs(hdr->type); if (type == ETHTYPE_ARP) { @@ -1083,9 +1141,11 @@ imp_packet_in(struct imp_device *imp) /* Lastly check if ICMP */ } else if (ip_hdr->ip_p == ICMP_PROTO) { struct icmp *icmp_hdr = (struct icmp *)payload; - checksumadjust((uint8 *)&icmp_hdr->chksum, - (uint8 *)(&ip_hdr->ip_src), sizeof(in_addr_T), - (uint8 *)(&imp_data.hostip), sizeof(in_addr_T)); + if ((icmp_hdr->type != 0) && /* Not Echo Reply */ + (icmp_hdr->type != 8)) /* and Not Echo */ + checksumadjust((uint8 *)&icmp_hdr->chksum, + (uint8 *)(&ip_hdr->ip_src), sizeof(in_addr_T), + (uint8 *)(&imp_data.hostip), sizeof(in_addr_T)); } checksumadjust((uint8 *)&ip_hdr->ip_sum, (uint8 *)(&ip_hdr->ip_dst), sizeof(in_addr_T), @@ -1309,9 +1369,11 @@ imp_packet_out(struct imp_device *imp, ETH_PACK *packet) { /* Lastly check if ICMP */ } else if (pkt->iphdr.ip_p == ICMP_PROTO) { struct icmp *icmp_hdr = (struct icmp *)payload; - checksumadjust((uint8 *)&icmp_hdr->chksum, - (uint8 *)(&pkt->iphdr.ip_src), sizeof(in_addr_T), - (uint8 *)(&imp->ip), sizeof(in_addr_T)); + if ((icmp_hdr->type != 0) && /* Not Echo Reply */ + (icmp_hdr->type != 8)) /* and Not Echo */ + checksumadjust((uint8 *)&icmp_hdr->chksum, + (uint8 *)(&pkt->iphdr.ip_src), sizeof(in_addr_T), + (uint8 *)(&imp->ip), sizeof(in_addr_T)); } /* Lastly update the header and IP address */ checksumadjust((uint8 *)&pkt->iphdr.ip_sum, @@ -1337,7 +1399,7 @@ imp_packet_out(struct imp_device *imp, ETH_PACK *packet) { memcpy(&pkt->ethhdr.dest, &tabptr->ethaddr, 6); memcpy(&pkt->ethhdr.src, &imp->mac, 6); pkt->ethhdr.type = htons(ETHTYPE_IP); - eth_write(&imp->etherface, packet, NULL); + imp_write(imp, packet); imp->rfnm_count++; return; } @@ -1357,6 +1419,259 @@ imp_packet_out(struct imp_device *imp, ETH_PACK *packet) { } +void imp_packet_debug(struct imp_device *imp, const char *action, ETH_PACK *packet) { + struct imp_eth_hdr *eth = (struct imp_eth_hdr *)&packet->msg[0]; + struct arp_hdr *arp = (struct arp_hdr *)eth; + struct ip *ip = (struct ip *)&packet->msg[sizeof(struct imp_eth_hdr)]; + struct udp *udp; + struct tcp *tcp; + struct icmp *icmp; + uint8 *payload; + struct in_addr ipaddr; + size_t len; + int flag; + char src_ip[20]; + char dst_ip[20]; + char src_port[8]; + char dst_port[8]; + char mac_buf[20]; + char flags[64]; + static struct tcp_flag_bits { + const char *name; + uint16 bitmask; + } bits[] = { + {"FIN", TCP_FL_FIN}, + {"SYN", TCP_FL_SYN}, + {"RST", TCP_FL_RST}, + {"PSH", TCP_FL_PSH}, + {"ACK", TCP_FL_ACK}, + {"URG", TCP_FL_URG}, + {NULL, 0} + }; + static const char *icmp_types[] = { + "Echo Reply", // Type 0 + "Type 1 - Unassigned", + "Type 2 - Unassigned", + "Destination Unreachable", // Type 3 + "Source Quench (Deprecated)", // Type 4 + "Redirect", // Type 5 + "Type 6 - Alternate Host Address (Deprecated)", + "Type 7 - Unassigned", + "Echo Request", // Type 8 + "Router Advertisement", // Type 9 + "Router Selection", // Type 10 + "Time Exceeded", // Type 11 + "Type 12 - Parameter Problem", + "Type 13 - Timestamp", + "Type 14 - Timestamp Reply", + "Type 15 - Information Request (Deprecated)", + "Type 16 - Information Reply (Deprecated)", + "Type 17 - Address Mask Request (Deprecated)", + "Type 18 - Address Mask Reply (Deprecated)", + "Type 19 - Reserved (for Security)", + "Type 20 - Reserved (for Robustness Experiment)", + "Type 21 - Reserved (for Robustness Experiment)", + "Type 22 - Reserved (for Robustness Experiment)", + "Type 23 - Reserved (for Robustness Experiment)", + "Type 24 - Reserved (for Robustness Experiment)", + "Type 25 - Reserved (for Robustness Experiment)", + "Type 26 - Reserved (for Robustness Experiment)", + "Type 27 - Reserved (for Robustness Experiment)", + "Type 28 - Reserved (for Robustness Experiment)", + "Type 29 - Reserved (for Robustness Experiment)", + "Type 30 - Traceroute (Deprecated)", + "Type 31 - Datagram Conversion Error (Deprecated)", + "Type 32 - Mobile Host Redirect (Deprecated)", + "Type 33 - IPv6 Where-Are-You (Deprecated)", + "Type 34 - IPv6 I-Am-Here (Deprecated)", + "Type 35 - Mobile Registration Request (Deprecated)", + "Type 36 - Mobile Registration Reply (Deprecated)", + "Type 37 - Domain Name Request (Deprecated)", + "Type 38 - Domain Name Reply (Deprecated)", + "Type 39 - SKIP (Deprecated)", + "Type 40 - Photuris", + "Type 41 - ICMP messages utilized by experimental mobility protocols such as Seamoby", + "Type 42 - Extended Echo Request", + "Type 43 - Extended Echo Reply" + }; + + if (ntohs(eth->type) == ETHTYPE_ARP) { + struct in_addr in_addr; + const char *arp_op = (ARP_REQUEST == ntohs(arp->opcode)) ? "REQUEST" : ((ARP_REPLY == ntohs(arp->opcode)) ? "REPLY" : "Unknown"); + char eth_src[20], eth_dst[20]; + char arp_shwaddr[20], arp_dhwaddr[20]; + char arp_sipaddr[20], arp_dipaddr[20]; + + if (!(imp_dev.dctrl & DEBUG_ARP)) + return; + eth_mac_fmt(&arp->ethhdr.src, eth_src); + eth_mac_fmt(&arp->ethhdr.dest, eth_dst); + eth_mac_fmt(&arp->shwaddr, arp_shwaddr); + memcpy(&in_addr, &arp->sipaddr, sizeof(in_addr)); + strlcpy(arp_sipaddr, ipv4_inet_ntoa(in_addr), sizeof(arp_sipaddr)); + eth_mac_fmt(&arp->dhwaddr, arp_dhwaddr); + memcpy(&in_addr, &arp->dipaddr, sizeof(in_addr)); + strlcpy(arp_dipaddr, ipv4_inet_ntoa(in_addr), sizeof(arp_dipaddr)); + sim_debug(DEBUG_ARP, &imp_dev, + "%s %s EthDst=%s EthSrc=%s shwaddr=%s sipaddr=%s dhwaddr=%s dipaddr=%s\n", + action, arp_op, eth_dst, eth_src, arp_shwaddr, arp_sipaddr, arp_dhwaddr, arp_dipaddr); + return; + } + if (ntohs(eth->type) != ETHTYPE_IP) + return; + if (!(imp_dev.dctrl & (DEBUG_TCP|DEBUG_UDP|DEBUG_ICMP))) + return; + memcpy(&ipaddr, &ip->ip_src, sizeof(ipaddr)); + strlcpy(src_ip, ipv4_inet_ntoa(ipaddr), sizeof(src_ip)); + memcpy(&ipaddr, &ip->ip_dst, sizeof(ipaddr)); + strlcpy(dst_ip, ipv4_inet_ntoa(ipaddr), sizeof(dst_ip)); + payload = (uint8 *)&packet->msg[sizeof(struct imp_eth_hdr) + (ip->ip_v_hl & 0xf) * 4]; + switch (ip->ip_p) { + case UDP_PROTO: + udp = (struct udp *)payload; + snprintf(src_port, sizeof(src_port), "%d", ntohs(udp->udp_sport)); + snprintf(dst_port, sizeof(dst_port), "%d", ntohs(udp->udp_dport)); + sim_debug(DEBUG_UDP, &imp_dev, "%s %d byte packet from %s:%s to %s:%s\n", action, + ntohs(udp->len), src_ip, src_port, dst_ip, dst_port); + if ((imp_dev.dctrl & DEBUG_DHCP) && + (((ntohs(udp->udp_sport) == DHCP_UDP_PORT_CLIENT) && + (ntohs(udp->udp_dport) == DHCP_UDP_PORT_SERVER)) || + ((ntohs(udp->udp_dport) == DHCP_UDP_PORT_CLIENT) && + (ntohs(udp->udp_sport) == DHCP_UDP_PORT_SERVER)))) { + struct dhcp *dhcp = (struct dhcp *)(payload + sizeof(struct udp)); + uint8 *opt = &dhcp->options[0]; + + sim_debug(DEBUG_DHCP, &imp_dev, "%s XID=%08X", + (dhcp->op == DHCP_BOOTREQUEST) ? "REQUEST" : + (dhcp->op == DHCP_BOOTREPLY) ? "REPLY" : + "??????", + dhcp->xid); + if (dhcp->ciaddr) { + memcpy(&ipaddr, &dhcp->ciaddr, sizeof(ipaddr)); + sim_debug(DEBUG_DHCP, &imp_dev, ", ciaddr=%s", ipv4_inet_ntoa(ipaddr)); + } + if (dhcp->yiaddr) { + memcpy(&ipaddr, &dhcp->yiaddr, sizeof(ipaddr)); + sim_debug(DEBUG_DHCP, &imp_dev, ", yiaddr=%s", ipv4_inet_ntoa(ipaddr)); + } + if (dhcp->siaddr) { + memcpy(&ipaddr, &dhcp->siaddr, sizeof(ipaddr)); + sim_debug(DEBUG_DHCP, &imp_dev, ", siaddr=%s", ipv4_inet_ntoa(ipaddr)); + } + if (dhcp->giaddr) { + memcpy(&ipaddr, &dhcp->giaddr, sizeof(ipaddr)); + sim_debug(DEBUG_DHCP, &imp_dev, ", giaddr=%s", ipv4_inet_ntoa(ipaddr)); + } + eth_mac_fmt((ETH_MAC*)&dhcp->chaddr, mac_buf); + sim_debug(DEBUG_DHCP, &imp_dev, ", chaddr=%s Options: ", mac_buf); + while (*opt != DHCP_OPTION_END) { + int opt_len; + u_long numeric; + static const char *opr_names[] = { + "", "DISCOVER", "OFFER", "REQUEST", + "DECLINE", "ACK", "NAK", "RELEASE", + "INFORM" + }; + + + switch(*opt++) { + case DHCP_OPTION_PAD: + break; + default: + opt_len = *opt++; + opt += opt_len; + break; + case DHCP_OPTION_SUBNET_MASK: + opt_len = *opt++; + memcpy(&ipaddr, opt, 4); + sim_debug(DEBUG_DHCP, &imp_dev, ", mask=%s", ipv4_inet_ntoa(ipaddr)); + opt += opt_len; + break; + case DHCP_OPTION_ROUTER: + opt_len = *opt++; + memcpy(&ipaddr, opt, 4); + sim_debug(DEBUG_DHCP, &imp_dev, ", router=%s", ipv4_inet_ntoa(ipaddr)); + opt += opt_len; + break; + case DHCP_OPTION_REQUESTED_IP: + opt_len = *opt++; + memcpy(&ipaddr, opt, 4); + sim_debug(DEBUG_DHCP, &imp_dev, ", requested-ip=%s", ipv4_inet_ntoa(ipaddr)); + opt += opt_len; + break; + case DHCP_OPTION_LEASE_TIME: + opt_len = *opt++; + memcpy(&numeric, opt, 4); + sim_debug(DEBUG_DHCP, &imp_dev, ", lease-time=%d", ntohl(numeric)); + opt += opt_len; + break; + case DHCP_OPTION_T1: + opt_len = *opt++; + memcpy(&numeric, opt, 4); + sim_debug(DEBUG_DHCP, &imp_dev, ", renew-time=%d", ntohl(numeric)); + opt += opt_len; + break; + case DHCP_OPTION_T2: + opt_len = *opt++; + memcpy(&numeric, opt, 4); + sim_debug(DEBUG_DHCP, &imp_dev, ", rebind-time=%d", ntohl(numeric)); + opt += opt_len; + break; + case DHCP_OPTION_SERVER_ID: + opt_len = *opt++; + memcpy(&ipaddr, opt, 4); + sim_debug(DEBUG_DHCP, &imp_dev, ", server-ip=%s", ipv4_inet_ntoa(ipaddr)); + opt += opt_len; + break; + case DHCP_OPTION_MESSAGE_TYPE: + opt_len = *opt++; + sim_debug(DEBUG_DHCP, &imp_dev, "MessageType=%s", opr_names[*opt]); + opt += opt_len; + break; + } + } + sim_debug(DEBUG_DHCP, &imp_dev, "\n"); + } else { + if (udp->len && (imp_dev.dctrl & DEBUG_UDP)) + sim_data_trace(&imp_dev, imp_unit, payload + sizeof(struct udp), "", + ntohs(udp->len), "", DEBUG_DATA); + } + break; + case TCP_PROTO: + tcp = (struct tcp *)payload; + snprintf(src_port, sizeof(src_port), "%d", ntohs(tcp->tcp_sport)); + snprintf(dst_port, sizeof(dst_port), "%d", ntohs(tcp->tcp_dport)); + strlcpy(flags, "", sizeof(flags)); + for (flag=0; bits[flag].name; flag++) { + if (ntohs(tcp->flags) & bits[flag].bitmask) { + if (*flags) + strlcat(flags, ",", sizeof(flags)); + strlcat(flags, bits[flag].name, sizeof(flags)); + } + + } + len = ntohs(ip->ip_len) - ((ip->ip_v_hl & 0xf) * 4 + (ntohs(tcp->flags) >> 12) * 4); + sim_debug(DEBUG_TCP, &imp_dev, "%s %s%s %d byte packet from %s:%s to %s:%s\n", action, + flags, *flags ? ":" : "", (int)len, src_ip, src_port, dst_ip, dst_port); + if (len && (imp_dev.dctrl & DEBUG_TCP)) + sim_data_trace(&imp_dev, imp_unit, payload + 4 * (ntohs(tcp->flags) >> 12), "", len, "", DEBUG_DATA); + break; + case ICMP_PROTO: + icmp = (struct icmp *)payload; + len = ntohs(ip->ip_len) - (ip->ip_v_hl & 0xf) * 4; + sim_debug(DEBUG_ICMP, &imp_dev, "%s %s %d byte packet from %s to %s\n", action, + (icmp->type < sizeof(icmp_types)/sizeof(icmp_types[0])) ? icmp_types[icmp->type] : "", (int)len, src_ip, dst_ip); + if (len && (imp_dev.dctrl & DEBUG_ICMP)) + sim_data_trace(&imp_dev, imp_unit, payload + sizeof(struct icmp), "", len, "", DEBUG_DATA); + break; + } +} + +void imp_write(struct imp_device *imp, ETH_PACK *packet) { + imp_packet_debug(imp, "Sending", packet); + eth_write(&imp->etherface, packet, NULL); +} + /* * Update the ARP table, first use free entry, else use oldest. */ @@ -1365,6 +1680,7 @@ imp_arp_update(struct imp_device *imp, in_addr_T ipaddr, ETH_MAC *ethaddr, int a { struct arp_entry *tabptr; int i; + char mac_buf[20]; /* Check if entry already in the table. */ for (i = 0; i < IMP_ARPTAB_SIZE; i++) { @@ -1372,7 +1688,13 @@ imp_arp_update(struct imp_device *imp, in_addr_T ipaddr, ETH_MAC *ethaddr, int a if (tabptr->ipaddr != 0) { if (tabptr->ipaddr == ipaddr) { - memcpy(&tabptr->ethaddr, ethaddr, sizeof(ETH_MAC)); + if (0 != memcmp(&tabptr->ethaddr, ethaddr, sizeof(ETH_MAC))) { + memcpy(&tabptr->ethaddr, ethaddr, sizeof(ETH_MAC)); + eth_mac_fmt(ethaddr, mac_buf); + sim_debug(DEBUG_ARP, &imp_dev, + "updating entry for IP %s to %s\n", + ipv4_inet_ntoa(*((struct in_addr *)&ipaddr)), mac_buf); + } if (tabptr->age != ARP_DONT_AGE) tabptr->age = age; return; @@ -1402,10 +1724,14 @@ imp_arp_update(struct imp_device *imp, in_addr_T ipaddr, ETH_MAC *ethaddr, int a tabptr = &imp->arp_table[fnd]; } - /* Now update the entry */ + /* Now save the entry */ memcpy(&tabptr->ethaddr, ethaddr, sizeof(ETH_MAC)); tabptr->ipaddr = ipaddr; tabptr->age = age; + eth_mac_fmt(ethaddr, mac_buf); + sim_debug(DEBUG_ARP, &imp_dev, + "creating entry for IP %s to %s, initial age=%d\n", + ipv4_inet_ntoa(*((struct in_addr *)&ipaddr)), mac_buf, age); } /* @@ -1423,6 +1749,12 @@ void imp_arp_age(struct imp_device *imp) tabptr->age++; /* Age it */ /* expire too old entries */ if (tabptr->age > IMP_ARP_MAX_AGE) { + char mac_buf[20]; + + eth_mac_fmt(&tabptr->ethaddr, mac_buf); + sim_debug(DEBUG_ARP, &imp_dev, + "discarding ARP entry for IP %s %s after %d seconds\n", + ipv4_inet_ntoa(*((struct in_addr *)&tabptr->ipaddr)), mac_buf, IMP_ARP_MAX_AGE); memset(tabptr, 0, sizeof(*tabptr)); } } @@ -1438,18 +1770,20 @@ void imp_arp_arpin(struct imp_device *imp, ETH_PACK *packet) { struct arp_hdr *arp; + struct in_addr in_addr; int op; + char mac_buf[20]; /* Ignore packet if too short */ if (packet->len < sizeof(struct arp_hdr)) return; arp = (struct arp_hdr *)(&packet->msg[0]); op = ntohs(arp->opcode); + imp_arp_update(imp, arp->sipaddr, &arp->shwaddr, 0); switch (op) { case ARP_REQUEST: if (arp->dipaddr == imp->ip) { - imp_arp_update(imp, arp->sipaddr, &arp->shwaddr, 0); arp->opcode = htons(ARP_REPLY); memcpy(&arp->dhwaddr, &arp->shwaddr, 6); @@ -1461,7 +1795,10 @@ imp_arp_arpin(struct imp_device *imp, ETH_PACK *packet) arp->sipaddr = imp->ip; arp->ethhdr.type = htons(ETHTYPE_ARP); packet->len = sizeof(struct arp_hdr); - eth_write(&imp->etherface, packet, NULL); + imp_write(imp, packet); + eth_mac_fmt(&arp->dhwaddr, mac_buf); + sim_debug(DEBUG_ARP, &imp_dev, "replied to received request for IP %s from %s\n", + ipv4_inet_ntoa(*((struct in_addr *)&imp->ip)), mac_buf); } break; @@ -1469,7 +1806,11 @@ imp_arp_arpin(struct imp_device *imp, ETH_PACK *packet) /* Check if this is our address */ if (arp->dipaddr == imp->ip) { struct imp_packet *nq = NULL; /* New send queue */ - imp_arp_update(imp, arp->sipaddr, &arp->shwaddr, 0); + + eth_mac_fmt(&arp->shwaddr, mac_buf); + memcpy(&in_addr, &arp->sipaddr, sizeof(in_addr)); + sim_debug(DEBUG_ARP, &imp_dev, "received reply for IP %s as %s\n", + ipv4_inet_ntoa(in_addr), mac_buf); /* Scan send queue, and send all packets for this host */ while (imp->sendq != NULL) { struct imp_packet *temp = imp->sendq; @@ -1481,7 +1822,7 @@ imp_arp_arpin(struct imp_device *imp, ETH_PACK *packet) memcpy(&pkt->ethhdr.dest, &arp->shwaddr, 6); memcpy(&pkt->ethhdr.src, &imp->mac, 6); pkt->ethhdr.type = htons(ETHTYPE_IP); - eth_write(&imp->etherface, &temp->packet, NULL); + imp_write(imp, &temp->packet); imp->rfnm_count++; imp_free_packet(imp, temp); } else { @@ -1522,7 +1863,8 @@ imp_arp_arpout(struct imp_device *imp, in_addr_T ipaddr) arp->protolen = 4; arp_pkt.len = sizeof(struct arp_hdr); - eth_write(&imp->etherface, &arp_pkt, NULL); + imp_write(imp, &arp_pkt); + sim_debug(DEBUG_ARP, &imp_dev, "sending request for IP %s\n", ipv4_inet_ntoa(*((struct in_addr *)&ipaddr))); } /* @@ -1625,7 +1967,9 @@ imp_do_send_dhcp(struct imp_device *imp, struct ip_hdr *pkt; struct udp *udp; struct udp_hdr udp_hdr; + struct in_addr in_addr; int len; + char mac_buf[20]; pkt = (struct ip_hdr *)(&packet->msg[0]); udp = (struct udp *)(&packet->msg[sizeof(struct imp_eth_hdr) + @@ -1658,9 +2002,13 @@ imp_do_send_dhcp(struct imp_device *imp, checksumadjust((uint8 *)&udp->chksum, (uint8 *)(&udp_hdr), 0, (uint8 *)(&udp_hdr), sizeof(udp_hdr)); packet->len = len + sizeof(struct ip_hdr); - eth_write(&imp->etherface, packet, NULL); - sim_debug(DEBUG_DETAIL, &imp_dev, - "DHCP client sent %s packet\n", op); + imp_write(imp, packet); + + eth_mac_fmt (&pkt->ethhdr.dest, mac_buf); + memcpy(&in_addr, &udp_hdr.ip_dst, sizeof(in_addr)); + sim_debug(DEBUG_DHCP, &imp_dev, + "client sent %s packet to: %s:%d(%s)\n", + op, ipv4_inet_ntoa(in_addr), ntohs(udp->udp_dport), mac_buf); } /* Handle incoming DCHP offer and other requests */ @@ -1674,6 +2022,7 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer) struct dhcp *dhcp; struct udp *upkt; struct udp_hdr udp_hdr; + struct in_addr in_addr; uint8 *opt; uint16 sum; int len; @@ -1685,6 +2034,7 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer) int rebind_time = 0; /* Rebind time */ in_addr_T dhcpip = 0; /* DHCP server address */ int opr = -1; /* DHCP operation */ + char mac_buf[20]; /* Source MAC address */ upkt = (struct udp *)(&((uint8 *)(ip_hdr))[hl]); dhcp = (struct dhcp *)(&((uint8 *)(upkt))[sizeof(struct udp)]); @@ -1771,10 +2121,13 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer) } } - sim_debug(DEBUG_DETAIL, &imp_dev, - "DHCP client incoming %s packet: dhcp_state=%s - wait_time=%d\n", + eth_mac_fmt(ð->src, mac_buf); + memcpy(&in_addr, &udp_hdr.ip_src, sizeof(in_addr)); + sim_debug(DEBUG_DHCP, &imp_dev, + "client incoming %s packet: dhcp_state=%s - wait_time=%d from: %s:%d(%s)\n", (opr == -1) ? "" : dhcp_opr_names[opr], - dhcp_state_names[imp->dhcp_state], imp->dhcp_wait_time); + dhcp_state_names[imp->dhcp_state], imp->dhcp_wait_time, + ipv4_inet_ntoa(in_addr), ntohs(upkt->udp_sport), mac_buf); /* Process an offer message */ if (opr == DHCP_OFFER && imp->dhcp_state == DHCP_STATE_SELECTING) { @@ -1829,7 +2182,7 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer) arp->hwlen = 6; arp->protolen = 4; arp_pkt.len = sizeof(struct arp_hdr); - eth_write(&imp->etherface, &arp_pkt, NULL); + imp_write(imp, &arp_pkt); } } if (opr == DHCP_NAK && (imp->dhcp_state == DHCP_STATE_REQUESTING || @@ -2338,7 +2691,7 @@ t_stat imp_attach(UNIT* uptr, CONST char* cptr) if (tptr == NULL) return SCPE_MEM; strcpy(tptr, cptr); - status = eth_open(&imp_data.etherface, cptr, &imp_dev, 0xFFFF); + status = eth_open(&imp_data.etherface, cptr, &imp_dev, DEBUG_ETHER); if (status != SCPE_OK) { free(tptr); return status; diff --git a/makefile b/makefile index f7e9174..f32920e 100644 --- a/makefile +++ b/makefile @@ -107,10 +107,11 @@ ifneq (,$(findstring besm6,$(MAKECMDGOALS))) VIDEO_USEFUL = true BESM6_BUILD = true endif -# building the KA10 needs video support +# building the PDP6, KA10 or KI10 needs video support ifneq (,$(or $(findstring pdp6,$(MAKECMDGOALS)),$(findstring pdp10-ka,$(MAKECMDGOALS)),$(findstring pdp10-ki,$(MAKECMDGOALS)))) VIDEO_USEFUL = true endif +# building the KA10, KI10 or KL10 networking can be used. ifneq (,$(or $(findstring pdp10-ka,$(MAKECMDGOALS)),$(findstring pdp10-ki,$(MAKECMDGOALS),$(findstring pdp10-kl,$MAKECMDGOALS)))) NETWORK_USEFUL = true endif @@ -1269,7 +1270,7 @@ KL10D = PDP10 KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \ ${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rp.c \ ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c ${KL10D}/kx10_imp.c \ - ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c + ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c ${KL10D}/ka10_ch10.c KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT} PDP1D = PDP1 From 65645bc527673454b17fe642a21bd8a74ed77482 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 26 Sep 2019 20:30:46 -0400 Subject: [PATCH 19/98] KA10: Fixed KL10 FE to handle ITS CTY better. --- PDP10/kl10_fe.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index c73b8b0..050334b 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -644,7 +644,8 @@ void dte_its(UNIT *uptr) { cty_out.buff[cty_out.in_ptr] = ch; cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; cnt--; - sim_activate(&dte_unit[1], 100); + if (! sim_is_active(&dte_unit[1])) + sim_activate(&dte_unit[1], 100); #if (NUM_DEVS_TTY > 0) } else { struct _buffer *otty = &tty_out[ln]; @@ -677,7 +678,7 @@ void dte_its(UNIT *uptr) { word = M[ITS_DTEOST]; if ((word & SMASK) == 0) { if (word == 0) - cty_done = 1; + cty_done++; #if (NUM_DEVS_TTY > 0) else if (word > 0 && word < tty_desc.lines) { tty_done[word-1] = 1; @@ -1091,10 +1092,11 @@ dte_input() uint64 word; word = M[ITS_DTEODN]; /* Check if ready for output done */ + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo %d\n", word, cty_done); if ((word & SMASK) != 0) { if (cty_done) { word = 64LL; - cty_done = 0; + cty_done--; #if (NUM_DEVS_TTY > 0) } else { for (ln = 0; ln < tty_desc.lines; ln++) { @@ -1184,7 +1186,7 @@ dte_input() data1 = PRI_CTYDV; if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, &data1) == 0) return; - cty_done = 0; + cty_done--; } /* Grab a chunck of input from CTY if any */ n = 0; @@ -1341,7 +1343,7 @@ t_stat dtei_svc (UNIT *uptr) /* If we have room see if any new lines */ - if (((cty_in.in_ptr + 1) & 0xff) != cty_in.out_ptr) { + while (((cty_in.in_ptr + 1) & 0xff) != cty_in.out_ptr) { ch = sim_poll_kbd (); if (ch & SCPE_KFLAG) { ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (uptr->flags)); @@ -1349,7 +1351,8 @@ t_stat dtei_svc (UNIT *uptr) cty_in.in_ptr = (cty_in.in_ptr + 1) & 0xff; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %o '%c'\n", ch, ((ch > 040 && ch < 0177)? ch: '.')); - } + } else + break; } /* If Monitor input, place in buffer */ @@ -1382,7 +1385,7 @@ t_stat dteo_svc (UNIT *uptr) sim_debug(DEBUG_DETAIL, &dte_dev, "CTY outch %o '%c'\n", ch, ((ch > 040 && ch < 0177)? ch: '.')); } - cty_done = 1; + cty_done++; dte_input(); return SCPE_OK; } @@ -1423,7 +1426,6 @@ dtertc_srv(UNIT * uptr) word = (M[ITS_DTECHK] + 1) & FMASK; if (word == 0) { optr->STATUS |= ITS_ON; - cty_done = 0; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS ON\n"); sim_activate(&tty_unit[0], 1000); sim_activate(&tty_unit[1], 1000); @@ -1462,6 +1464,7 @@ t_stat dte_reset (DEVICE *dptr) dte_unit[1].STATUS = 0; dte_unit[2].STATUS = 0; dte_unit[3].STATUS = 0; + cty_done = 0; sim_rtcn_init_unit (&dte_unit[3], 1000, TMR_RTC); sim_activate(&dte_unit[3], 1000); sim_activate(&dte_unit[2], 1000); From ce627981df794a8497c17dc834df92fbfbde3323 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 27 Sep 2019 23:44:33 -0400 Subject: [PATCH 20/98] KA10: Fixed bug in ADJBP. --- PDP10/ka10_ch10.c | 2 -- PDP10/kx10_cpu.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/PDP10/ka10_ch10.c b/PDP10/ka10_ch10.c index 09d332e..e9a6548 100644 --- a/PDP10/ka10_ch10.c +++ b/PDP10/ka10_ch10.c @@ -335,8 +335,6 @@ void ch10_command (uint32 data) t_stat ch10_devio(uint32 dev, uint64 *data) { - DEVICE *dptr = &imx_dev; - switch(dev & 07) { case CONO: sim_debug (DBG_REG, &ch10_dev, "CONO %012llo %012llo \n", *data, ch10_status); diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 5a7a8f1..e737a40 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -5677,7 +5677,7 @@ unasign: } FE = 36 - (adjb * SC) - ((36 - FE) % SC); /* New P */ AR = (((uint64)(FE & 077)) << 30) | /* Make new BP */ - (AR & 00777777000000LL) | /* S,IX,I */ + (AR & PMASK & LMASK) | /* S,IX,I */ ((AR + adjw) & RMASK); } set_reg(AC, AR); From 56d4a6bfaf1078c2c9ade58aaad8b8975363d568 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 29 Sep 2019 12:22:13 -0400 Subject: [PATCH 21/98] KA10: Fixed ITS one proceed during byte instructions. --- PDP10/kx10_cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index e737a40..136d5e9 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -4052,7 +4052,7 @@ no_fetch: /* Handle page fault and traps */ if (page_enable && trap_flag == 0 && (FLAGS & (TRP1|TRP2))) { #if KL_ITS - if (QITS && (FLAGS & ADRFLT) != 0) { + if (QITS && (FLAGS & (ADRFLT|BYTI)) == ADRFLT) { FLAGS &= ~ADRFLT; } else { #endif From b13cc9ba698eeef990c8dac994367171e0bcda23 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Mon, 30 Sep 2019 22:46:42 -0400 Subject: [PATCH 22/98] KA10: Fixed one-proceed for ITS in JRSTF. --- PDP10/kx10_cpu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 136d5e9..c277ddf 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -7045,6 +7045,10 @@ xjrstf: case 002: /* JRSTF */ BR = AR >> 23; /* Move into position */ jrstf: +#if KL_ITS + if (QITS) + f = FLAGS & (TRP1|TRP2); +#endif FLAGS &= ~(OVR|NODIV|FLTUND|BYTI|FLTOVR|CRY1|CRY0|TRP1|TRP2|PCHNG|ADRFLT); /* If executive mode, copy USER and UIO */ if ((FLAGS & (PUBLIC|USER)) == 0) @@ -7057,6 +7061,10 @@ jrstf: FLAGS &= ~PRV_PUB; if ((FLAGS & USER) == 0) FLAGS |= (BR & OVR) ? PRV_PUB : 0; +#if KL_ITS + if (QITS) + FLAGS |= f; +#endif check_apr_irq(); break; From 56252c02b8d20a1e6a9e03e9b0b4cf88df7460ad Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 6 Oct 2019 01:03:41 -0400 Subject: [PATCH 23/98] Updated README to indicate the status of KL10. --- README.md | 98 +++++++++++++++++++++++-------------------------------- 1 file changed, 41 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index d06d307..979d60d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ [![Coverity Scan Build Status](https://scan.coverity.com/projects/12020/badge.svg)](https://scan.coverity.com/projects/rcornwell-sims) -This is a working copy of my Burroughs B5500, Dec PDP6, KA10, KI10, SEL32, IBM 360 and IBM7000 -series simulators for SimH. +This is a working copy of my Burroughs B5500, Dec PDP6, KA10, KI10, KL10, SEL32, IBM 360 +and IBM7000 series simulators for SimH. # Stable released simulators. @@ -64,7 +64,14 @@ Latest status for I7000 Cpus: Emulates a dual CPU B5500 with up to 32K of memory. I can support either DFX disks or dual disks up to 20 units. Up to 16 magnetic tapes drives is support. 2 Card readers - a card punch and a pair of line printers. + a card punch and a pair of line printers. Will run MCP XIII and XV. + + * Up to either 10 disks with DFX support or 20 disks without. + * Up to 16 magnetic tape drives. + * Dual card reader. + * Dual Line printer. + * Single card punch. + * Up to 32 terminal lines. # Dec PDP6 @@ -88,76 +95,57 @@ The PDP6 runs TOPS 10 4.5 off Dectape. Type 340 graphics display. -# Dec KA10 & KI10 +# Dec KA10 & KI10 & KL10 -These are nearing release. Please report any issues that you find in them. - -The KA10 sim has successfully run Tops 10 4.5, 5.03 and Tops 10 6.03. -The KI10 sim has successfully run Tops 10 6.03 with VMSER -The KA10 sim has successfully run ITS. -The KA10 sim has successfully run WAITS (with and without BBN pager). +The KA10 sim has successfully run Tops 10 4.5, 5.03 and Tops 10 6.03, ITS and WAITS. +The KI10 sim has successfully run Tops 10 6.03 with VMSER. +The KL10 sim has successfully run Tops 10 6.03 with VMSER and ITS. +KL10 extended addressing support is still in development. Disk * RC10 RD10/RM10 * RP10 RP01/RP02/RP03 - * RH10 RP04/RP06/RP07 (RP07 not supported under 6.03). - * RH10 RS04 + * RH10/RH20 RP04/RP06/RP07 (RP07 not supported under 6.03). + * RH10/RH20 RS04 * PMP (P. PETIT'S IBM CHANNEL) * System Concepts DC-10 IBM 2314 Tape * TM10A or B - * RH10 TM03/TU16 + * RH10/RH20 TM03/TU16 * TD10 Dectape Paper Tape * Punch * Reader - DC10E terminal mux. - Morton tty Mux for ITS. - Knight Kludge mux for ITS. + * DC10E terminal mux. + * Morton tty Mux for ITS. + * Knight Kludge mux for ITS. + * Terminals on KL10 Front End. - IMP networking support for ITS and TENEX. - CH10 networking support for ITS. + * IMP networking support for ITS and TENEX. + * CH10 networking support for ITS. - 340 Display Station support. + * 340 Display Station support. + * III Display support for WAITS (in progress). - Optional support for PDP6 devices (standard if WAITS included). + * Optional support for PDP6 devices (standard if WAITS included). The RP10 supports boot (actual hardware did not), by reading in Blocks 4-7 and transfering to the loaded value. RC10, RH10, TM10 support readin mode. - Support for KL10A will be started in the summer. - -# Development Simulators. - -# Dec KL10 - -Still in initial coding stages. - - Disk - * RH10 RP04/RP06/RP07 - * RH10 RS04 - * RH20 RP04/RP06/RP07 - * RH20 RS04 - - Tape - * TM10A or B - * RH10 TM03/TU16 - * RH20 TM03/TU16 - - DC10E terminal mux. - Terminals attached to front end processor - - IMP networking support for ITS and TENEX. - # ICL 1900 simulator. This is a new simulator. Will pass 1904E/1905E CPU diagnostics (FLIT). Will boot paper tape executive E4BM and tape executive E6RM. Still need to add more devices and test with Goerge 2 and 3. + The CPU can be configured for model A, B or C type system. Or models 1901 throgh 1909. +Paging is currently not supported. Both standard interface and older non-standard interface +are supported on most device. + + # IBM 360 simulator. Currently will run IPL TOS/360, DOS/360, OS/360. TSO support still in progress. @@ -186,18 +174,14 @@ The current test version is for the SEL 32/27, 32/67, 32/87, 32/97 computers. Support for 32/55, 32/75, V6, and V9 computers may be added in the future. This simulator is co-authors with James C. Bevier. I did the initial parts of the simulator, James took it to a working simulator, I am assisting him -in maintaining and enhancing the simulator. - -# SEL Concept/32 - -This simulator is running a test version of MPX-32 1.5F. It is capable of -creating a disk image of the O/S from a SDT tape. The disk image can be -booted, initialized, and run many of the MPX utilities; including OPCOM & TSM. -Eight terminals can be used to access TSM via Telnet port 4747. Initial -support has been added for excess 64 floating point arithmetic. More testing -is still required. The sim32disk.gz can be uncompressed and booted with the -sel32.27.sim32.disk.ini initialization file. The sim32sdt.tap.gz file can -also be uncompressed and started with the sel32.27.sim32.tape.ini initialization -file to install from tape. +in maintaining and enhancing the simulator. This simulator is running a test +version of MPX-32 1.5F. It is capable of creating a disk image of the O/S +from a SDT tape. The disk image can be booted, initialized, and run many of +the MPX utilities; including OPCOM & TSM. Eight terminals can be used to +access TSM via Telnet port 4747. Initial support has been added for excess +64 floating point arithmetic. More testing is still required. The sim32disk.gz +can be uncompressed and booted with the sel32.27.sim32.disk.ini initialization file. +The sim32sdt.tap.gz file can also be uncompressed and started with the +sel32.27.sim32.tape.ini initialization file to install from tape. From baa7791b974dcdf53fe8947f1959a6c7cc2ad24c Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 15 Oct 2019 23:49:02 -0400 Subject: [PATCH 24/98] KA10: KL10B working, RH20 support added. --- PDP10/kl10_fe.c | 8 +- PDP10/kx10_cpu.c | 1021 ++++++++++++++++++++++++++++++++++----------- PDP10/kx10_defs.h | 92 +++- PDP10/kx10_df.c | 12 +- PDP10/kx10_dp.c | 3 +- PDP10/kx10_rh.c | 750 +++++++++++++++++++++++++++++++++ PDP10/kx10_rp.c | 704 ++++++++++--------------------- PDP10/kx10_rs.c | 503 ++++++---------------- PDP10/kx10_sys.c | 37 +- PDP10/kx10_tu.c | 581 +++++++------------------- README.md | 1 - makefile | 29 +- 12 files changed, 2175 insertions(+), 1566 deletions(-) create mode 100644 PDP10/kx10_rh.c diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 050334b..13e900d 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -533,7 +533,6 @@ void dte_second(UNIT *uptr) { cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; M[SEC_DTCHR + base] = ch; M[SEC_DTMTD + base] = FMASK; - M[SEC_DTF11 + base] = 0; sim_activate(&dte_unit[1], 100); break; case SEC_SETPRI: @@ -554,8 +553,9 @@ enter_pri: break; case SEC_SETDDT: /* Read character from console */ if (cty_in.in_ptr == cty_in.out_ptr) { - sim_activate(uptr, 100); - return; + M[SEC_DTF11 + base] = 0; + M[SEC_DTMTI + base] = FMASK; + break; } ch = cty_in.buff[cty_in.out_ptr]; cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; @@ -1543,8 +1543,6 @@ lpt_printline(UNIT *uptr, int nl) { uptr->pos += uptr->POS; uptr->COL = 0; uptr->POS = 0; -// if (uptr->LINE == 0) - // (void)dte_queue(PRI_EMHDS, PRI_EMLPT, 1, &data1); return; } diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index c277ddf..d8e6f9d 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -312,6 +312,8 @@ InstHistory *hst = NULL; /* instruction history */ /* Forward and external declarations */ #if KL +int Mem_read(int flag, int cur_context, int fetch); +int Mem_write(int flag, int cur_context); int do_extend(uint32 IA); #endif t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); @@ -414,9 +416,15 @@ REG cpu_reg[] = { #endif { FLDATA (PIHOLD, pi_hold, 0), REG_HRO}, { FLDATA (PIREST, pi_restore, 0), REG_HRO}, -#if KI | KL +#if KI { ORDATAD (UB, ub_ptr, 18, "User Base Pointer") }, { ORDATAD (EB, eb_ptr, 18, "Executive Base Pointer") }, +#endif +#if KL + { ORDATAD (UB, ub_ptr, 22, "User Base Pointer") }, + { ORDATAD (EB, eb_ptr, 22, "Executive Base Pointer") }, +#endif +#if KI | KL { ORDATAD (FMSEL, fm_sel, 8, "Register set select") }, { ORDATAD (SERIAL, apr_serial, 10, "System Serial Number") }, { FLDATA (INOUT, inout_fail, 0), REG_RO}, @@ -1163,8 +1171,21 @@ t_stat dev_pi(uint32 dev, uint64 *data) { case DATAO: #if KL - if (dev & 040) { /* SDIAG */ -// fprintf(stderr, "SDIAG %012llo\n\r", *data); + if (dev & 040) { /* SBDIAG */ + AB = (AB + 1) & RMASK; + res = 0; +// fprintf(stderr, "SBDIAG %012llo\n\r", *data); + if (((*data >> 31) & 037) == 010) { + switch(*data & 037) { + case 0: res = 06000000000LL; break; + case 1: res = 0500000000LL; break; + case 2: res = 0; break; + default: res = 0; break; + } + // fprintf(stderr, "SBDIAG return %012llo\n\r", res); + } + MB = res; + (void)Mem_write(0, 0); break; } #else @@ -1280,7 +1301,7 @@ t_stat dev_pag(uint32 dev, uint64 *data) { #if KLB if (res & BIT1) { /* Load previous section */ - prev_sect = (res >> 18) & 07777; + prev_sect = (res >> 18) & 037; } #endif if ((res & RSIGN) == 0) { @@ -1314,6 +1335,10 @@ t_stat dev_pag(uint32 dev, uint64 *data) { res |= ((uint64)(prev_ctx & 0160)) << 20; res |= ((uint64)(fm_sel & 0160)) << 23; res |= SMASK|BIT1|BIT2; +#if KLB + if (QKLB) + res |= ((uint64)prev_sect & 037) << 18; +#endif *data = res; sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI PAG %012llo\n", *data); break; @@ -1346,7 +1371,6 @@ void check_apr_irq() { } } -int Mem_write(int flag, int cur_context); /* * APR device for KL10. @@ -2009,12 +2033,11 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) #define PG_WRT 0020000 #define PG_CAC 0004000 #define PG_STG 0000037 -#define PG_IDX 0000377 +#define PG_IDX 0000777 #define PG_MASK 0000003777777LL #define PG_AGE 0770000000000LL #define PG_PAG 0007777 -//fprintf(stderr, "Lookup Page %03o %0o %o %o\r\n", page, t20_page, upmp, uf); if (t20_page) { /* Start with full access */ int acc_bits = PG_PUB|PG_WRT|PG_CAC; uint64 spt = FM[(06<<4)|3] & PG_MASK; @@ -2024,8 +2047,13 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) int index; int match = 0; int pg; +#if EPT440 int base = 0440; +#else + int base = 0540; +#endif +//fprintf(stderr, "Lookup Page %o %03o %0o %o %o\r\n", sect, page, t20_page, upmp, uf); /* Get segment pointer */ /* And save it */ #if KLB @@ -2108,7 +2136,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) /* Get address of page */ data = M[(pg << 9) + page]; -//fprintf(stderr, "YMap %012llo\n\r", data); +//fprintf(stderr, "YMap %012llo %o %o\n\r", data, pg << 9, page); /* Decode map pointer */ switch ((data >> 33) & 07) { @@ -2134,16 +2162,9 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) case 3: /* Indirect page */ acc_bits &= (data >> 18) & RMASK; - index = (data >> 18) & PG_IDX; + page = (data >> 18) & PG_IDX; data = M[(data & RMASK) + spt]; - if ((data >> 18) & PG_STG) { - if (trap) { - fault_data = 0; - page_fault = 1; - } - return 0; - } - data = M[(data & RMASK) + index]; +//fprintf(stderr, "IMap %012llo %o %o\n\r", data, pg << 9, page); break; } @@ -2247,9 +2268,6 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch int pub = (FLAGS & PUBLIC) != 0; int upmp = 0; - if (page_fault) - return 0; - /* If paging is not enabled, address is direct */ if (!page_enable) { *loc = addr; @@ -2326,6 +2344,7 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch if (QKLB) fault_data = (((uint64)sect) << 18); #endif +//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); /* Ignore faults if flag set */ if (FLAGS & ADRFLT) { page_fault = 0; @@ -2464,7 +2483,8 @@ int Mem_read(int flag, int cur_context, int fetch) { return 0; } - if ((glb_sect == 0 || sect == 0 || (glb_sect && sect == 1)) && AB < 020) { + if ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1)) && AB < 020) || + (!QKLB && AB < 020)) { #else if (AB < 020) { #endif @@ -2510,7 +2530,8 @@ int Mem_write(int flag, int cur_context) { return 0; } - if ((glb_sect == 0 || sect == 0 || (glb_sect && sect == 1)) && AB < 020) { + if ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1)) && AB < 020) || + (!QKLB && AB < 020)) { #else if (AB < 020) { #endif @@ -3917,6 +3938,7 @@ int pi_rq; /* Interrupt request */ int pi_ov; /* Overflow during PI cycle */ int pi_cycle; /* Executing an interrupt */ int ind; /* Indirect bit */ +int ix; int f_load_pc; /* Load AB from PC at start of instruction */ int f_inst_fetch; /* Fetch new instruction */ int f_pc_inh; /* Inhibit PC increment after instruction */ @@ -4075,7 +4097,6 @@ no_fetch: /* Handle indirection repeat until no longer indirect */ do { - int ix; if ((!pi_cycle) & pi_pending #if KI | KL & (!trap_flag) @@ -4084,7 +4105,7 @@ no_fetch: pi_rq = check_irq_level(); } #if KLB - if (QKLB && ptr_flg && pc_sect != 0 && (AR & 040000000LL) != 0) { /* Full pointer */ + if (QKLB && ptr_flg && pc_sect != 0 && (AR & BIT12) != 0) { /* Full pointer */ ind = 1; goto in_loop; } @@ -4102,8 +4123,6 @@ no_fetch: #endif if (ix) { #if KL -// if (xct_flag != 0) -//fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o m=%012llo\n\r", IR, PC, AB, xct_flag, MB); if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) AR = FM[prev_ctx|ix]; @@ -4112,11 +4131,9 @@ no_fetch: #if KLB /* Check if extended indexing */ if (QKLB && cur_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { -fprintf(stderr, "Index %06o %012llo %06o\n\r", AB, AR, cur_sect); AR = (AR + ((AB & RSIGN) ? SECTM|((uint64)AB): (uint64)AB)) & (SECTM|RMASK); sect = cur_sect = (AR >> 18) & 07777; glb_sect = 1; -fprintf(stderr, "Index2 %06o %012llo %06o\n\r", AB, AR, cur_sect); AB = 0; } else glb_sect = 0; @@ -4139,6 +4156,7 @@ in_loop: #if KL & KLB /* Check if extended indexing */ if (QKLB && cur_sect != 0) { +// fprintf(stderr, "Ind %06o %012llo\n\r", AB, MB); if (MB & SMASK) { /* Instruction format IFIW */ if (MB & BIT1) { /* Illegal index word */ fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | @@ -4147,31 +4165,55 @@ in_loop: goto last; } glb_sect = 0; - if (ptr_flg && (AR & 040000000LL) != 0) { /* Full pointer */ - ind = 0; + ind = TST_IND(MB) != 0; + ix = GET_XR(MB); + AB = MB & RMASK; + if (ix) { + if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || + ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) + AR = FM[prev_ctx|ix]; + else + AR = get_reg(ix); + /* Check if extended indexing */ + if ((AR & SMASK) != 0 || (AR & SECTM) == 0) { /* Local index word */ + AR = (AR + AB) & RMASK; + } else { + AR = (AR + AB) & FMASK; + glb_sect = 1; + sect = cur_sect = (AR >> 18) & 07777; + } + MB = AR; + } else AR = MB; - AB = AR & RMASK; - } + AB = AR & RMASK; + if (!glb_sect && AB < 020) /* Map to global AC */ + sect = cur_sect = 1; +//fprintf(stderr, "IFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); } else { /* Extended index EFIW */ ind = (MB & BIT1) != 0; ix = (MB >> 30) & 017; - if (ix != 0) { + AB = MB & (SECTM|RMASK); + if (ix) { if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) AR = FM[prev_ctx|ix]; else AR = get_reg(ix); - AR = (AR + MB) & (SECTM|RMASK); + if ((AR & SMASK) != 0 || (AR & SECTM) == 0) { /* Local index word */ + AR = AB + (((AR & RSIGN) ? 0: 0)|(AR & RMASK)); + } else + AR = AR + AB; + AR &= FMASK; + MB = AR; } else AR = MB; sect = cur_sect = (AR >> 18) & 07777; AB = AR & RMASK; glb_sect = 1; - ix = 0; -fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); - if (ind) - goto in_loop; +//fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); } + if (ind) + goto in_loop; } #endif } @@ -4304,7 +4346,7 @@ st_pi: if (extend) { if (IR == 0 || IR > 031 || AC != 0 || do_extend(IA)) { IR = 0123; - AC = IA; + AC = ext_ac; goto muuo; } goto last; @@ -4371,9 +4413,10 @@ muuo: unasign: /* Save Opcode */ #if KL & KLB - if (QKLB) - MB = ((uint64)(IR) << 12) | ((uint64)(AC) << 8) | ((uint64)(FLAGS) << 23) | ((uint64)cur_sect & 037); - else + if (QKLB && t20_page) { + AR = (((uint64)cur_sect) << 18) | (uint64)AB; /* Save address */ + MB = (((uint64)((IR << 9) | (AC << 5))) | ((uint64)(FLAGS) << 23)) & FMASK; + } else #endif MB = ((uint64)(IR) << 27) | ((uint64)(AC) << 23) | (uint64)(AB); AB = ub_ptr | 0424; @@ -4381,7 +4424,7 @@ unasign: /* Save flags */ AB++; #if KL & KLB - if (QKLB) + if (QKLB && t20_page) MB = ((uint64)(pc_sect) << 18) | ((PC + (trap_flag == 0)) & RMASK); else #endif @@ -4394,18 +4437,25 @@ unasign: #if KL extend = 0; #if KLB - if (QKLB) { /* Save address */ - MB = ((uint64)(cur_sect) << 18) | (AB & RMASK); + if (QKLB && t20_page) { /* Save address */ + MB = AR; AB ++; Mem_write_nopage(); } #endif /* Save context */ AB ++; - MB = (ub_ptr >> 9) | ((uint64)(prev_ctx & 0160)) << 20 | - ((uint64)(fm_sel & 0160)) << 23 | SMASK|BIT1|BIT2; + MB = SMASK|BIT1 | + ((uint64)(fm_sel & 0160) << 23) | + ((uint64)(prev_ctx & 0160) << 20) | +#if KLB + ((uint64)(prev_sect & 037) << 18) | +#endif + (ub_ptr >> 9); +#if KLB + prev_sect = pc_sect; +#endif Mem_write_nopage(); -// prev_ctx = fm_sel; #endif /* Read in new PC and flags */ FLAGS &= ~ (PRV_PUB|BYTI|ADRFLT|TRP1|TRP2); @@ -4419,14 +4469,14 @@ unasign: Mem_read_nopage(); #if KL & KLB - if (QKLB) { + if (QKLB && t20_page) { pc_sect = (MB >> 18) & 07777; FLAGS = 0; } else #endif FLAGS = (MB >> 23) & 017777; /* If transistioning from user to executive adjust flags */ - if ((FLAGS & USER) != 0 && (AB & 4) != 0) + if ((FLAGS & USER) == 0 && (AB & 4) != 0) FLAGS |= USERIO; if ((FLAGS & USER) == 0 && (AB & 2 || (FLAGS & OVR) != 0)) FLAGS |= PRV_PUB|OVR; @@ -4446,6 +4496,40 @@ unasign: case 0024: case 0025: case 0026: case 0027: case 0030: case 0031: case 0032: case 0033: case 0034: case 0035: case 0036: case 0037: +#if KL & KLB + /* LUUO's in non-zero section are different */ + if (QKLB && t20_page && pc_sect != 0) { + AR = (((uint64)cur_sect) << 18) | AB; /* Save address */ + /* Grab address of LUUO block from user base 420 */ + AB = ((FLAGS & USER) ? ub_ptr : eb_ptr) + 0420; + Mem_read_nopage(); + /* Now save like MUUO */ + AB = MB & RMASK; + sect = (MB >> 18) & 07777; + MB = (((uint64)((IR << 9) | (AC << 5))) | ((uint64)(FLAGS) << 23)) & FMASK; + if ((FLAGS & USER) == 0) { + MB &= ~SMASK; + MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + } + Mem_write_nopage(); + /* Save PC */ + AB++; + MB = ((uint64)(pc_sect) << 18) | ((PC + (trap_flag == 0)) & RMASK); + Mem_write_nopage(); + extend = 0; + /* Save Effective address */ + MB = AR; + AB ++; + Mem_write_nopage(); + AB ++; + /* Read PC */ + Mem_read_nopage(); + pc_sect = (MB >> 18) & 07777; + PC = MB & RMASK; + f_pc_inh = 1; + break; + } +#endif #if PDP6 ill_op = 1; ex_uuo_sync = 1; @@ -5645,17 +5729,22 @@ unasign: case 0133: /* IBP/ADJBP */ #if KL if (AC != 0) { /* ADJBP */ - modify = 1; - if (Mem_read(0, 0, 0)) { + if (Mem_read(0, 0, 0)) goto last; - } AR = MB; SC = (AR >> 24) & 077; /* S */ if (SC) { - int bpw, left, newb, adjw, adjb, c; + int bpw, left, newb, adjw, adjb; + f = 0; FE = (AR >> 30) & 077; /* P */ - AB = AR & RMASK; /* Address */ +#if KLB + if (QKLB && FE > 36) { + f = 1; + SC = _byte_adj[(FE - 37)].s; + FE = _byte_adj[(FE - 37)].p; + } +#endif left = (36 - FE) / SC; /* Number bytes left (36 - P)/S */ bpw = left + (FE / SC); /* Bytes per word */ if (bpw == 0) { @@ -5676,6 +5765,36 @@ unasign: adjw--; } FE = 36 - (adjb * SC) - ((36 - FE) % SC); /* New P */ +#if KLB + if (f) { + /* Short pointer */ + f = (AR >> 30) & 077; /* P */ + AR = (((uint64)((f + adjb) & 077)) << 30) | /* Make new BP */ + ((AR + adjw) & (SECTM|RMASK)); + set_reg(AC, AR); + break; + } else if (QKLB && pc_sect != 0 && (AR & BIT12) != 0) { + /* Full pointer */ + AB = (AB + 1) & RMASK; + if (Mem_read(0, 0, 0)) + goto last; + AR = (((uint64)(FE & 077)) << 30) | /* Make new BP */ + (AR & PMASK); /* S and below */ + if (MB & SMASK) { + if (MB & BIT1) { + fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | + (AB & RMASK) | ((uint64)cur_sect << 18); + page_fault = 1; + goto last; + } + BR = (MB + adjw) & RMASK | (MB & LMASK); + } else + BR = (MB + adjw) & (SECTM|RMASK) | (MB & ~(SECTM|RMASK)); + set_reg(AC, AR); + set_reg(AC+1, BR); + break; + } +#endif AR = (((uint64)(FE & 077)) << 30) | /* Make new BP */ (AR & PMASK & LMASK) | /* S,IX,I */ ((AR + adjw) & RMASK); @@ -5716,22 +5835,30 @@ unasign: SCAD = (SCAD + (0777 ^ SC) + 1) & 0777; if (SCAD & 0400) { SC = ((0777 ^ SC) + 044 + 1) & 0777; -#if KI | KL +#if KL #if KLB - if (QKLB && pc_sect != 0 && (AR & 040000000LL) != 0) { /* Full pointer */ - uint32 AT = AB; + if (QKLB && pc_sect != 0 && (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; if (Mem_read(0, 0, 0)) goto last; - if (MB & SMASK) - MB = (MB & LMASK) | ((MB + 1) & RMASK); - else - MB++; +//fprintf(stderr, "ILBP %o %o %06o %012llo\n\r", SC, SCAD, AB, MB); + if (MB & SMASK) { + if (MB & BIT1) { + fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | + (AB & RMASK) | ((uint64)cur_sect << 18); + page_fault = 1; + goto last; + } + MB = (MB + 1) & RMASK | (MB & LMASK); + } else + MB = (MB + 1) & (SECTM|RMASK) | (MB & ~(SECTM|RMASK)); if (Mem_write(0,0)) goto last; - AB = AT; + AB = (AB - 1) & RMASK; } else + AR = (AR & LMASK) | ((AR + 1) & RMASK); #endif +#elif KI AR = (AR & LMASK) | ((AR + 1) & RMASK); #else AR = (AR + 1) & FMASK; @@ -5790,8 +5917,10 @@ ldb_ptr: #if KL ptr_flg = 1; #if KLB - if (QKLB && pc_sect != 0 && (AR & 040000000LL) != 0) { /* Full pointer */ + if (QKLB && pc_sect != 0 && (AR & BIT12) != 0) { + /* Full pointer */ AB = (AB + 1) & RMASK; +//fprintf(stderr, "LBP %o %o %06o %012llo\n\r", SC, SCAD, AB, MB); } #endif #endif @@ -7023,7 +7152,9 @@ xjrstf: #if KLB if (QKLB) { pc_sect = (AR >> 18) & 07777; - prev_sect = BR & 037; + if ((FLAGS & USER) == 0 && ((BR >> 23) & USER) == 0) + prev_sect = BR & 037; +//fprintf(stderr, "XJRST %06o %06o %06o %012llo\r\n", pc_sect, prev_sect, FLAGS, BR); } #endif BR = BR >> 23; /* Move flags into position */ @@ -7097,7 +7228,8 @@ jrstf: case 014: /* SFM */ #if KLB if (QKLB) { - MB = (((uint64)FLAGS) << 23) | (prev_sect & 037); + MB = ((((uint64)FLAGS) << 23) | (uint64)(prev_sect & 037)) & FMASK; +//fprintf(stderr, "SFM %012llo\n\r", MB); (void)Mem_write(0, 0); goto last; } @@ -7419,6 +7551,23 @@ jrstf: #endif AR = AOB(AR); AB = AR & RMASK; +#if KLB + flag1 = glb_sect; + if (QKLB) { + f = (pc_sect != 0); + if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) { + sect = prev_sect; + f = (prev_sect != 0); + } + if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + sect = (AR >> 18) & 07777; + glb_sect = 1; + } + } else + f = 0; +//fprintf(stderr, "Pop %o %o %06o %06o %06o %012llo %012llo\n\r", f, xct_flag, prev_sect, sect, cur_sect, AR, BR); + if (QKLB && !f) +#endif if (AR & C1) { #if KI | KL if (!pi_cycle) @@ -7440,14 +7589,17 @@ jrstf: flag1 = glb_sect; if (QKLB) { f = (pc_sect != 0); - if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) + if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) { + sect = prev_sect; f = (prev_sect != 0); + } if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { sect = (AR >> 18) & 07777; glb_sect = 1; } } else f = 0; +//fprintf(stderr, "Pop %o %o %06o %06o %06o %012llo %012llo\n\r", f, xct_flag, prev_sect, sect, cur_sect, AR, BR); #endif #endif AB = AR & RMASK; @@ -7490,8 +7642,10 @@ jrstf: #if KLB if (QKLB) { f = (pc_sect != 0); - if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) + if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) { f = (prev_sect != 0); + sect = prev_sect; + } if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { sect = (AR >> 18) & 07777; glb_sect = 1; @@ -8206,6 +8360,7 @@ fetch_opr: AR = MB; } dev_tab[d](040|DATAO|(d<<2), &AR); +if (d == 1) fprintf(stderr, "SBDIAG return %012llo\n\r", AR); } else { dev_tab[d](040|DATAI|(d<<2), &AR); MB = AR; @@ -8430,6 +8585,11 @@ last: pi_rq = check_irq_level(); goto st_pi; } + if (trap_flag != 0) { + pi_hold = pi_ov = 0; + f_pc_inh = 0; + trap_flag = 0; + } #endif if ((IR & 0700) == 0700 && ((AC & 04) == 0)) { @@ -8504,78 +8664,281 @@ return reason; #if KL +/* Handle indirection for extended byte instructions */ +int +do_byte_setup(int n, int wr, int *pos, int *sz) +{ + uint64 val1; + uint64 val2; + uint64 temp; + int s; + int p; + int np; + int ix; + int ind; + + /* Get pointer */ + val1 = get_reg(n+1); + val2 = get_reg(n+2); + /* Extract index */ + *sz = s = (val1 >> 24) & 077; + p = (val1 >> 30) & 077; + np = (p + (0777 ^ s) + 1) & 0777; + /* Advance pointer */ +//fprintf(stderr, "%s %012llo %012llo %2o %2o %03o\n\r", (wr)?"store":"load", val1, val2, s, p, np); +#if KLB + if (QKLB) { + if (p > 36) { /* Extended pointer */ + int i = p - 37; + s = _byte_adj[i].s; + p = _byte_adj[i].p; + np = p = (p + (0777 ^ s) + 1) & 0777; + val2 = val1 & (SECTM|RMASK); /* Convert to long pointer */ + val1 = ((uint64)s << 24) | BIT12; + if (p & 0400) { + np = p = ((0777 ^ s) + 044 + 1) & 0777; + val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); + } + ind = 0; + ix = 0; + MB = val2 & (SECTM|RMASK); + sect = (MB >> 18) & 07777; + glb_sect = 1; + } else if (pc_sect != 0 && (val1 & BIT12) != 0) { /* Full pointer */ + if (np & 0400) { + np = p = ((0777 ^ s) + 044 + 1) & 0777; + if (val2 & SMASK) + val2 = (val2 & LMASK) | ((val2 + 1) & RMASK); + else + val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); + } + if (val2 & SMASK) { + if (val2 & BIT1) { + fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | + (val2 & RMASK) | ((uint64)sect << 18); + page_fault = 1; + return 1; + } + ind = TST_IND(val2) != 0; + ix = GET_XR(val2); + MB = (val2 & RMASK) | ((val2 & RSIGN)? LMASK:0); + sect = cur_sect; + if ((FLAGS & USER) == 0 && + (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) + sect = prev_sect; + glb_sect = 0; +//fprintf(stderr, "Load_byte1 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); + } else { + ind = (val2 & BIT1) != 0; + ix = (val2 >> 30) & 017; + MB = val2 & (SECTM|RMASK); + sect = (MB >> 18) & 07777; + glb_sect = 1; +//fprintf(stderr, "Load_byte2 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); + } + } else { + if (np & 0400) { + np = p = ((0777 ^ s) + 044 + 1) & 0777; + val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); + } + ix = GET_XR(val1); + ind = TST_IND(val1) != 0; + MB = (val1 & RMASK) | ((val1 & RSIGN)? LMASK:0); + sect = cur_sect; + if ((FLAGS & USER) == 0 && + (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) + sect = prev_sect; + glb_sect = 0; +//fprintf(stderr, "Load_byte3 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); + } + } else +#endif + { + if (np & 0400) { + np = p = ((0777 ^ s) + 044 + 1) & 0777; + val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); + } + ix = GET_XR(val1); + ind = TST_IND(val1) != 0; + MB = (val1 & RMASK) | ((val1 & RSIGN)? LMASK:0); +#if KLB + sect = cur_sect; + if ((FLAGS & USER) == 0 && + (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) + sect = prev_sect; + glb_sect = 0; +#endif +//fprintf(stderr, "Load_byte4 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); + } + *pos = np & 077; + + AB = MB & RMASK; + if (ix) { + temp = get_reg(ix); +#if KLB + /* Check if extended indexing */ + if (QKLB && glb_sect != 0 && (temp & SMASK) == 0 && (temp & SECTM) != 0) { +//fprintf(stderr, "Index %06o %012llo %06o\n\r", AB, temp, sect); + temp = (temp + MB) & (SECTM|RMASK); + sect = (temp >> 18) & 07777; + MB = 0; + glb_sect = 1; +//fprintf(stderr, "Index2 %06o %012llo %06o\n\r", AB, temp, sect); + } else + glb_sect = 0; +#endif + temp = MB = (MB + temp) & FMASK; + AB = MB & RMASK; + } + while (ind & !check_irq_level()) { + ptr_flg = 1; + if (Mem_read(0, 1, 0)) { + ptr_flg = 0; + return 1; + } + ptr_flg = 0; +#if KLB + /* Check if extended indexing */ + if (QKLB && sect != 0) { +inx: + if (MB & SMASK) { /* Instruction format IFIW */ + if (MB & BIT1) { /* Illegal index word */ + fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | + (temp & RMASK) | ((uint64)sect << 18); + page_fault = 1; + return 1; + } + glb_sect = 0; + ix = GET_XR(MB); + ind = TST_IND(MB) != 0; + AB = MB & RMASK; + if (ix) { + temp = get_reg(ix); + /* Check if extended indexing */ + if ((temp & SMASK) != 0 || (temp & SECTM) == 0) { /* Local index word */ + temp = (temp + AB) & RMASK; + } else { + temp = (temp + AB) & FMASK; + glb_sect = 1; + sect = cur_sect = (temp >> 18) & 07777; + } + MB = temp; + } else + temp = MB; + AB = temp & RMASK; +//fprintf(stderr, "IFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); + } else { /* Extended index EFIW */ + ind = (MB & BIT1) != 0; + ix = (MB >> 30) & 017; + AB = MB & (SECTM|RMASK); + if (ix) { + temp = get_reg(ix); + if ((temp & SMASK) != 0 || (temp & SECTM) == 0) { /* Local index word */ + temp = AB + (((temp & RSIGN) ? 0: 0)|(temp & RMASK)); + } else + temp = temp + AB; + temp &= FMASK; + MB = temp; + } else + temp = MB; + sect = cur_sect = (temp >> 18) & 07777; + AB = temp & RMASK; + glb_sect = 1; +//fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, sect, AB); + } + } else { +#endif + ix = GET_XR(MB); + ind = TST_IND(MB) != 0; + AB = MB & RMASK; + if (ix) { + temp = get_reg(ix); +#if KLB + /* Check if extended indexing */ + if (QKLB && sect != 0 && (temp & SMASK) == 0 && (temp & SECTM) != 0) { +//fprintf(stderr, "Index %06o %012llo %06o\n\r", AB, temp, sect); + temp = (temp + ((AB & RSIGN) ? SECTM|((uint64)AB): (uint64)AB)) & (SECTM|RMASK); + sect = (temp >> 18) & 07777; + MB = 0; + glb_sect = 1; +//fprintf(stderr, "Index2 %06o %012llo %06o\n\r", AB, temp, sect); + AB = 0; + } else + glb_sect = 0; +#endif + temp = MB = (MB + temp) & FMASK; + AB = MB & RMASK; + } +#if KLB + } +#endif + /* Handle events during a indirect loop */ + if (sim_interval-- <= 0) { + if (sim_process_event() != SCPE_OK) { + return 1; + } + } + }; + /* Update pointer */ + val1 &= PMASK; + val1 |= (uint64)(np) << 30; + + /* Save pointer */ + set_reg(n+1, val1); + set_reg(n+2, val2); + + modify = wr; + ptr_flg = !wr; + BYF5 = wr; + /* Read final value */ + if (Mem_read(0, 0, 0)) { + modify = ptr_flg = BYF5 = 0; + return 1; + } +//fprintf(stderr, "Load %06o %06llo -> %012llo\n\r", sect, AB, MB); + modify = 0; + return 0; +} + /* Get data from pointer */ int load_byte(int n, uint64 *data, uint64 fill, int cnt) { - uint64 val, msk; - int s, p, addr, ind, np; + uint64 val1, val2, msk; + int s, p, addr, ind, np, ix; /* Check if should return fill */ - val = get_reg(n); - if (cnt && (val & MANT) == 0) { + val1 = get_reg(n); + if (cnt && (val1 & MANT) == 0) { *data = fill; return 1; } - /* Get pointer */ - val = get_reg(n+1); - /* Extract index */ - s = (val >> 24) & 077; - p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; - /* Advance pointer */ - if (p & 0400) { - np = p = ((0777 ^ s) + 044 + 1) & 0777; - val = (val & LMASK) | ((val + 1) & RMASK); - } else - np = p; - np &= 077; - /* Update pointer */ - val &= PMASK; - val |= (uint64)(np) << 30; - AB = val & RMASK; - MB = val; - /* Handle indirection repeat until no longer indirect */ - do { - ind = (MB & 020000000) != 0; - if (MB & 017000000) { - AB = (AB + get_reg((MB >> 18) & 017)) & RMASK; - } - if (ind) { - if (Mem_read(0, 1, 0)) - goto back; - AB = MB & RMASK; - } - if (sim_interval <= 0) { - sim_process_event(); - } - } while (ind & pi_pending); - - /* Save pointer */ - set_reg(n+1, val); - - /* Read final value */ - if (Mem_read(0, 0, 0)) + /* Fetch Pointer word */ + if (do_byte_setup(n, 0, &p, &s)) goto back; /* Generate mask for given size */ msk = (uint64)(1) << s; msk--; *data = (MB >> p) & msk; +//fprintf(stderr, "Load_bytes %2o %2o %06o %06o %012llo\n\r", s, p, sect, AB, *data); if (cnt) { /* Decrement count */ - val = get_reg(n); - val--; - set_reg(n, val); + val1 = get_reg(n); + val1--; + set_reg(n, val1); } return 1; back: - val = get_reg(n+1); - val &= PMASK; - val |= (uint64)(p + s) << 30; - set_reg(n+1, val); +//fprintf(stderr, "Load_bytef %2o %2o %06o %06o %012llo\n\r", s, p, sect, AB, *data); + ptr_flg = 0; + val1 = get_reg(n+1); + val1 &= PMASK; + val1 |= (uint64)(p + s) << 30; + set_reg(n+1, val1); return 0; } @@ -8583,76 +8946,39 @@ back: int store_byte(int n, uint64 data, int cnt) { - uint64 val, msk; - int s, p, addr, ind, np; - - /* Get pointer */ - val = get_reg(n+1); - /* Extract index */ - s = (val >> 24) & 077; - p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; - /* Advance pointer */ - if (p & 0400) { - np = p = ((0777 ^ s) + 044 + 1) & 0777; - val = (val & LMASK) | ((val + 1) & RMASK); - } else - np = p; - np &= 077; - /* Update pointer */ - val &= PMASK; - val |= (uint64)(np) << 30; - AB = val & RMASK; - MB = val; - - /* Handle indirection repeat until no longer indirect */ - do { - ind = (MB & 020000000) != 0; - if (MB & 017000000) { - AB = (AB + get_reg((MB >> 18) & 017)) & RMASK; - } - if (ind) { - if (Mem_read(0, 1, 0)) - goto back; - AB = MB & RMASK; - } - if (sim_interval <= 0) { - sim_process_event(); - } - } while (ind & pi_pending); - - /* Save pointer */ - set_reg(n+1, val); + uint64 val1, val2, msk; + int s, p, addr, ind, np, ix; + /* Fetch Pointer word */ + if (do_byte_setup(n, 1, &p, &s)) + goto back; /* Generate mask for given size */ msk = (uint64)(1) << s; msk--; - - /* Read final value */ - modify = 1; - if (Mem_read(0, 0, 0)) - goto back; - msk <<= p; MB &= CM(msk); MB |= msk & ((uint64)(data) << p); +//fprintf(stderr, "store_bytes %2o %2o %06o %06o %012llo\n\r", s, p, sect, AB, data); + BYF5 = 1; if (Mem_write(0, 0)) goto back; if (cnt) { /* Decrement count */ - val = get_reg(n); - val--; - set_reg(n, val); + val1 = get_reg(n); + val1--; + set_reg(n, val1); } return 1; back: - val = get_reg(n+1); - val &= PMASK; - val |= (uint64)(p + s) << 30; - set_reg(n+1, val); + BYF5 = 0; + val1 = get_reg(n+1); + val1 &= PMASK; + val1 |= (uint64)(p + s) << 30; + set_reg(n+1, val1); return 0; } @@ -8670,40 +8996,120 @@ get_mask(int n, uint64 *msk) *msk = ((uint64)(1) << s) - 1; } +/* Adjust a pointer to be valid */ +void +adj_byte(int n) +{ + uint64 val1, val2; + int s, p, np; + + /* Get pointer */ + val1 = get_reg(n+1); + val2 = get_reg(n+2); + /* Extract index */ + s = (val1 >> 24) & 077; + p = (val2 >> 30) & 077; + /* Advance pointer */ + np = (p + (0777 ^ s) + 1) & 0777; +#if KLB + if (QKLB) { + if (p > 36) { /* Extended pointer */ + int i = p - 37; + s = _byte_adj[i].s; + p = _byte_adj[i].p; + val2 = val1 & (SECTM|RMASK); /* Convert to long pointer */ + val1 = ((uint64)s << 24) | BIT12; + /* Save pointer */ + set_reg(n+1, val1); + set_reg(n+2, val2); + return; + } else if (pc_sect != 0 && (val1 & BIT12) != 0) { /* Full pointer */ + if (np & 0400) + val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); + } else { + if (np & 0400) + val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); + } + } else +#endif + { + if (np & 0400) + val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); + } + if ((np & 0400) == 0) + return; + /* Update pointer */ + val1 &= PMASK; + val1 |= (uint64)(044) << 30; + + /* Save pointer */ + set_reg(n+1, val1); + set_reg(n+2, val2); +} + + /* Advance a pointer by 1 */ void adv_byte(int n) { - uint64 val; + uint64 val1, val2; int s, p, np; /* Check if should return fill */ - val = get_reg(n); - if ((val & MANT) == 0) + val1 = get_reg(n); + if ((val1 & MANT) == 0) return; /* Decrement count */ - val--; - set_reg(n, val); + val1--; + set_reg(n, val1); /* Get pointer */ - val = get_reg(n+1); + val1 = get_reg(n+1); + val2 = get_reg(n+2); /* Extract index */ - s = (val >> 24) & 077; - p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; + s = (val1 >> 24) & 077; + p = (val2 >> 30) & 077; /* Advance pointer */ - if (p & 0400) { - p = np = (36 + (0777 ^ s) + 1) & 0777; - val = (val & LMASK) | ((val + 1) & RMASK); - } else - np = p; +#if KLB + if (QKLB) { + if (p > 36) { /* Extended pointer */ + int i = p - 37; + s = _byte_adj[i].s; + p = _byte_adj[i].p; + p = (p + (0777 ^ s) + 1) & 0777; + val2 = val1 & (SECTM|RMASK); /* Convert to long pointer */ + val1 = ((uint64)s << 24) | BIT12; + if (p & 0400) { + np = p = ((0777 ^ s) + 044 + 1) & 0777; + val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); + } else + np = p; + } else if (pc_sect != 0 && (val1 & BIT12) != 0) { /* Full pointer */ + p = (p + (0777 ^ s) + 1) & 0777; + if (p & 0400) { + np = p = ((0777 ^ s) + 044 + 1) & 0777; + val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); + } else + np = p; + } + } else +#endif + { + p = (p + (0777 ^ s) + 1) & 0777; + if (p & 0400) { + np = p = ((0777 ^ s) + 044 + 1) & 0777; + val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); + } else + np = p; + } np &= 077; /* Update pointer */ - val &= PMASK; - val |= (uint64)(np) << 30; - MB = val; + val1 &= PMASK; + val1 |= (uint64)(np) << 30; /* Save pointer */ - set_reg(n+1, val); + set_reg(n+1, val1); + set_reg(n+2, val2); } /* back a pointer by 1 */ @@ -8828,6 +9234,7 @@ do_extend(uint32 ia) uint64 val1, val2; uint64 msk; uint64 reg; + int xlat_sect; int f, i; @@ -8883,6 +9290,12 @@ do_extend(uint32 ia) case 004: /* EDIT */ val2 = MB; /* Save address of translate table */ +#if KLB + if (QKLB && pc_sect != 0 && glb_sect) + xlat_sect = (val2 >> 18) & 07777; + else + xlat_sect = cur_sect; +#endif /* Fetch filler values */ AB = (ia + 1) & RMASK; if (Mem_read(0, 1, 0)) @@ -8900,6 +9313,15 @@ do_extend(uint32 ia) /* Read in pattern control */ reg = get_reg(ext_ac); AB = reg & RMASK; +#if KLB + if (QKLB && pc_sect != 0) { + sect = (reg >> 18) & 07777; + glb_sect = 1; + } else { + sect = cur_sect; + glb_sect = 0; + } +#endif if (Mem_read(0, 0, 0)) return 0; i = (reg >> 30) & 03; @@ -8907,23 +9329,32 @@ do_extend(uint32 ia) val1 = (MB >> ((3 - i) * 9)) & 0777; i++; if (i > 3) { - reg++; +#if KLB + if (QKLB && pc_sect != 0) + reg = (reg & ~(SECTM|RMASK)) | ((reg + 1) & (SECTM|RMASK)); + else +#endif + reg = (reg & LMASK) | ((reg+1) & RMASK); i = 0; } reg |= ((uint64)i) << 30; i = 0; a = 0; +//fprintf(stderr, "Edit pat %03o %012llo %012llo\n\r", val1, reg, MB); switch ((val1 >> 6) & 07) { case 0: /* Individual options */ switch (val1 & 077) { case 0: /* Stop */ f = 0; break; - case 1: + case 1: /* SELECT */ if (!load_byte(ext_ac, &val1, 0, 0)) return 0; a = 1; AB = (val2 + (val1 >> 1)) & RMASK; +#if KLB + sect = xlat_sect; +#endif if (Mem_read(0, 0, 0)) return 0; if ((val1 & 1) == 0) @@ -8951,16 +9382,38 @@ do_extend(uint32 ia) case 4: func4: if ((reg & SMASK) == 0) { - AB = get_reg(ext_ac+3) & RMASK; + adj_byte(ext_ac+3); + reg |= SMASK; + AR = get_reg(ext_ac+3); +#if KLB + if (QKLB && pc_sect != 0) { + sect = (AR >> 18) & 07777; + glb_sect = 1; + } else { + sect = cur_sect; + glb_sect = 0; + } +#endif + AB = AR & RMASK; MB = get_reg(ext_ac+4); if (Mem_write(0, 0)) return 0; - if (fill2 != 0) { - val1 = fill2; - i = 1; +#if KLB + if (QKLB && pc_sect != 0 && (MB & BIT12) != 0) { + AB = (++AR) & RMASK; + sect = (AR >> 18) & 07777; + MB = get_reg(ext_ac+5); + if (Mem_write(0,0)) + return 0; } - } else - i = 1; +#endif + if (fill2 != 0) { + if (!store_byte(ext_ac+3, fill1, 0)) { + return 0; + } + } + } + i = 1; reg |= SMASK|BIT1; /* Set S & N */ break; case 5: @@ -8976,10 +9429,29 @@ do_extend(uint32 ia) break; case 2: /* Set signifigance */ if ((reg & SMASK) == 0) { - AB = get_reg(ext_ac+3) & RMASK; + AR = get_reg(ext_ac+3); +#if KLB + if (QKLB && pc_sect != 0) { + sect = (AR >> 18) & 07777; + glb_sect = 1; + } else { + sect = cur_sect; + glb_sect = 0; + } +#endif + AB = AR & RMASK; MB = get_reg(ext_ac+4); if (Mem_write(0, 0)) return 0; +#if KLB + if (QKLB && pc_sect != 0 && (MB & BIT12) != 0) { + AB = (++AR) & RMASK; + sect = (AR >> 18) & 07777; + MB = get_reg(ext_ac+5); + if (Mem_write(0,0)) + return 0; + } +#endif if (fill2 != 0) { val1 = fill2; i = 1; @@ -8991,22 +9463,56 @@ do_extend(uint32 ia) reg &= ~(SMASK|BIT1|BIT2); /* Clear S & N */ break; case 4: /* Exchange Mark */ - AB = get_reg(ext_ac+3) & RMASK; + AR = get_reg(ext_ac+3); +#if KLB + if (QKLB && pc_sect != 0) { + sect = (AR >> 18) & 07777; + glb_sect = 1; + } else { + sect = cur_sect; + glb_sect = 0; + } +#endif + AB = AR & RMASK; if (Mem_read(0, 0, 0)) return 0; - AR = MB; + BR = MB; MB = get_reg(ext_ac+4); +#if KLB + /* Make sure byte pointers are same size */ + if (QKLB && (MB & BIT12) != (BR & BIT12)) + return 0; +#endif if (Mem_write(0, 0)) return 0; - set_reg(ext_ac+4, AR); - AB = (AB + 1) & RMASK; - if (Mem_read(0, 0, 0)) - return 0; - AR = MB; - MB = get_reg(ext_ac+5); - if (Mem_write(0, 0)) - return 0; - set_reg(ext_ac+5, AR); +//fprintf(stderr, "Edit exchange %06o %06o %012llo %012llo\n\r", sect, AB, BR, MB); +#if KLB + if (QKLB && pc_sect != 0 && (BR & BIT12) != 0) { + AB = (AR + 1) & RMASK; + sect = ((AR + 1)>> 18) & 07777; + if (Mem_read(0, 0, 0)) { + AB = AR & RMASK; /* Restore lower pointer */ + sect = (AR >> 18) & 07777; + MB = BR; +//fprintf(stderr, "Restore %06o %06o %012llo\n\r", sect, AB, MB); + (void)Mem_write(0, 0); + return 0; + } + AD = MB; + MB = get_reg(ext_ac+5); +//fprintf(stderr, "Edit exchange2 %06o %06o %012llo %012llo\n\r", sect, AB, AD, MB); + if (Mem_write(0, 0)) { + AB = AR & RMASK; /* Restore lower pointer */ + sect = (AR >> 18) & 07777; + MB = BR; +//fprintf(stderr, "Restore %06o %06o %012llo\n\r", sect, AB, MB); + (void)Mem_write(0, 0); + return 0; + } + set_reg(ext_ac+5, AD); + } +#endif + set_reg(ext_ac+4, BR); break; case 5: i = 0; @@ -9016,6 +9522,9 @@ do_extend(uint32 ia) case 1: /* Insert Message char */ if ((reg & SMASK) != 0) { AB = (ia + (val1 & 077) + 1) & RMASK; +#if KLB + sect = cur_sect; +#endif if (Mem_read(0, 0, 0)) return 0; i = 1; @@ -9058,6 +9567,12 @@ do_extend(uint32 ia) case 010: /* CVTDBO */ case 011: /* CVTDBT */ +#if KLB + if (QKLB && pc_sect != 0 && glb_sect) + xlat_sect = (val2 >> 18) & 07777; + else + xlat_sect = cur_sect; +#endif val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); /* Check if conversion started */ if ((get_reg(ext_ac) & SMASK) == 0) { @@ -9071,17 +9586,22 @@ do_extend(uint32 ia) fill2 |= SMASK; set_reg(ext_ac, fill2); } +//fprintf(stderr, "CVD %04llo %012lld %012llo\n\r", val1, ARX, AR); while ((get_reg(ext_ac) & MANT) != 0) { f = 1; if (!load_byte(ext_ac, &val1, 0, 1)) { - set_reg(ext_ac+3, ARX); - set_reg(ext_ac+4, AR); + set_reg(ext_ac+3, AR); + set_reg(ext_ac+4, ARX); return 0; } - if (IR == 010) + if (IR == 010) { val1 = (val1 + val2) & FMASK; - else + } else { +#if KLB + sect = xlat_sect; +#endif f = do_xlate((uint32)(val2 & RMASK), val1, 017); + } if (f < 0) break; if (f) { @@ -9105,6 +9625,7 @@ do_extend(uint32 ia) AR = AR + BR + f; ARX &= CMASK; AR &= FMASK; +//fprintf(stderr, "CVD %04llo %012lld %012llo\n\r", val1, ARX, AR); } } ARX &= CMASK; @@ -9127,6 +9648,12 @@ do_extend(uint32 ia) val2 = AB; else val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); +#if KLB + if (QKLB && pc_sect != 0 && glb_sect) + xlat_sect = (val2 >> 18) & 07777; + else + xlat_sect = cur_sect; +#endif /* Get fill */ AB = (ia + 1) & RMASK; if (Mem_read(0, 1, 0)) @@ -9180,6 +9707,9 @@ do_extend(uint32 ia) if (IR == 013) { /* Read first translation entry */ AB = (val1 + val2) & RMASK; +#if KLB + sect = xlat_sect; +#endif if (Mem_read(0, 0, 0)) { set_reg(ext_ac + 3, (reg & (SMASK|EXPO)) | (f+1)); return 0; @@ -9210,9 +9740,15 @@ do_extend(uint32 ia) get_mask(ext_ac+3, &msk); if ((((get_reg(ext_ac) & (077LL << 26))| get_reg(ext_ac+3)) & EMASK) != 0) return 1; - if (IR == 014) + if (IR == 014) { val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); - else if (IR == 015) { +#if KLB + if (QKLB && pc_sect != 0 && glb_sect) + xlat_sect = (val2 >> 18) & 07777; + else + xlat_sect = cur_sect; +#endif + } else if (IR == 015) { AB = ia; if (Mem_read(0, 1, 0)) return 0; @@ -9233,10 +9769,14 @@ do_extend(uint32 ia) if (!load_byte(ext_ac, &val1, fill1, 1)) { return 0; } - if (IR == 014) + if (IR == 014) { val1 = (val1 + val2) & FMASK; - else if (IR == 015) + } else if (IR == 015) { +#if KLB + sect = xlat_sect; +#endif f = do_xlate((uint32)(val2), val1, 07777); + } if (f < 0) return 0; if (f) { @@ -9294,56 +9834,59 @@ do_extend(uint32 ia) case 020: /* XBLT */ #if KLB if (QKLB) { + glb_sect = 1; reg = get_reg(ext_ac); -// if ((xct_flag & 2) != 0 && (FLAGS & USER) == 0) - // val1 = FM[prev_ctx|(ext_ac + 1)]; - // else - val1 = get_reg(ext_ac + 1); - // if ((xct_flag & 1) != 0 && (FLAGS & USER) == 0) - // val2 = FM[prev_ctx|(ext_ac + 2)]; - // else - val2 = get_reg(ext_ac + 2); -fprintf(stderr, "XBLT: %012llo %012llo %012llo\n\r", reg, val1, val2); + val1 = get_reg(ext_ac + 1); + val2 = get_reg(ext_ac + 2); +//fprintf(stderr, "XBLT: %012llo %012llo %012llo\n\r", reg, val1, val2); while (reg != 0) { if (reg & SMASK) { + val1 = (val1 - 1) & (SECTM|RMASK); sect = (val1 >> 18) & 07777; AB = val1 & RMASK; - if (Mem_read(0, 0, 0)) + ptr_flg = 1; + if (Mem_read(0, 0, 0)) { + val1 = (val1 + 1) & (SECTM|RMASK); goto xblt_done; -fprintf(stderr, " XBLT: D=%012llo 1-%012llo 2-%012llo\n\r", MB, val1, val2); + } +//fprintf(stderr, " XBLT: D=%012llo 1-%012llo 2-%012llo\n\r", MB, val1, val2); + val2 = (val2 - 1) & (SECTM|RMASK); sect = (val2 >> 18) & 07777; AB = val2 & RMASK; - if (Mem_write(0, 0)) + ptr_flg = 0; + BYF5 = 1; + if (Mem_write(0, 0)) { + val1 = (val1 + 1) & (SECTM|RMASK); + val2 = (val2 + 1) & (SECTM|RMASK); goto xblt_done; + } + BYF5 = 0; reg = (reg + 1) & FMASK; - val1 = (val1 - 1) & (SECTM|RMASK); - val2 = (val2 - 1) & (SECTM|RMASK); } else { sect = (val1 >> 18) & 07777; AB = val1 & RMASK; + ptr_flg = 1; if (Mem_read(0, 0, 0)) goto xblt_done; -fprintf(stderr, " XBLT: D=%012llo 1-%012llo 2-%012llo\n\r", MB, val1, val2); +//fprintf(stderr, " XBLT: D=%012llo 1-%012llo 2-%012llo\n\r", MB, val1, val2); sect = (val2 >> 18) & 07777; AB = val2 & RMASK; + ptr_flg = 0; + BYF5 = 1; if (Mem_write(0, 0)) goto xblt_done; val1 = (val1 + 1) & (SECTM|RMASK); val2 = (val2 + 1) & (SECTM|RMASK); reg = (reg - 1) & FMASK; + BYF5 = 0; } } xblt_done: -fprintf(stderr, "XBLT done: %012llo %012llo %012llo\n\r", reg, val1, val2); +//fprintf(stderr, "XBLT done: %012llo %012llo %012llo\n\r", reg, val1, val2); + ptr_flg = BYF5 = 0; set_reg(ext_ac, reg); - // if ((xct_flag & 2) != 0 && (FLAGS & USER) == 0) - // FM[prev_ctx|(ext_ac + 1)] = val1; - // else - set_reg(ext_ac + 1, val1); - // if ((xct_flag & 1) != 0 && (FLAGS & USER) == 0) - // FM[prev_ctx|(ext_ac + 2)] = val2; - // else - set_reg(ext_ac + 2, val2); + set_reg(ext_ac + 1, val1); + set_reg(ext_ac + 2, val2); return 0; } #endif @@ -9356,6 +9899,7 @@ fprintf(stderr, "XBLT done: %012llo %012llo %012llo\n\r", reg, val1, val2); case 027: /* DGFLTR */ case 030: /* GFLTR */ case 031: /* GFSC */ + default: return 1; } return 0; @@ -9651,6 +10195,7 @@ for (j = i = 0; (dptr = rh_devs[i]) != NULL; i++) { dev_irqv[(d >> 2)] = dibp->irq; rh[j].dev_num = d; rh[j].dev = dptr; + rh[j].rh = dibp->rh; j++; } } diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 669a6fe..6ba7e7d 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -52,7 +52,8 @@ #if KL #define KLA 1 -#define KLB 0 +#define KLB 1 +#define EPT440 0 /* Force KL10A to 440 section address */ #endif #ifndef KLA @@ -183,6 +184,7 @@ extern DEBTAB crd_debug[]; #define BIT9 00000400000000LL #define BIT10 00000200000000LL #define BIT10_35 00000377777777LL +#define BIT12 00000040000000LL #define BIT17 00000001000000LL #define MANT 00000777777777LL #define EXPO 00377000000000LL @@ -293,6 +295,12 @@ extern DEBTAB crd_debug[]; #define AMASK 00000017777777LL #define WMASK 0037777LL #define CSHIFT 22 +#if KL +#define RH20_WMASK 003777LL +#define RH20_XFER SMASK +#define RH20_HALT BIT1 +#define RH20_REV BIT2 +#endif #else #define AMASK RMASK #define WMASK RMASK @@ -303,6 +311,10 @@ extern DEBTAB crd_debug[]; #define PI_ENABLE 0000000010 /* Clear DONE */ #define BUSY 0000000020 /* STOP */ #define CCW_COMP 0000000040 /* Write Final CCW */ +/* RH10 / RH20 interrupt */ +#define IADR_ATTN 0000000000040LL /* Interrupt on attention */ +#define IARD_RAE 0000000000100LL /* Interrupt on register access error */ +#define CCW_COMP_1 0000000040000LL /* Control word written. */ #if KI #define DEF_SERIAL 514 /* Default DEC test machine */ @@ -353,7 +365,12 @@ extern DEBTAB crd_debug[]; #define UNIT_V_MPX (UNIT_V_WAITS + 1) #define UNIT_M_MPX (1 << UNIT_V_MPX) #define UNIT_MPX (UNIT_M_MPX) /* MPX Device for ITS */ -#define DEV_V_RH (DEV_V_UF + 8) /* Type RH20 */ +#define CNTRL_V_RH (UNIT_V_UF + 4) +#define CNTRL_M_RH 7 +#define GET_CNTRL_RH(x) (((x) >> CNTRL_V_RH) & CNTRL_M_RH) +#define CNTRL_RH(x) (((x) & CNTRL_M_RH) << CNTRL_V_RH) +#define DEV_V_RH (DEV_V_UF + 1) /* Type RH20 */ +#define DEV_M_RH (1 << DEV_V_RH) #define TYPE_RH10 (0 << DEV_V_RH) #define TYPE_RH20 (1 << DEV_V_RH) @@ -432,39 +449,64 @@ extern t_stat (*dev_tab[128])(uint32 dev, t_uint64 *data); #define VEC_DEVMAX 8 /* max device vec */ +/* DF10 Interface */ +struct df10 { + uint32 status; /* DF10 status word */ + uint32 cia; /* Initial transfer address */ + uint32 ccw; /* Next control word address */ + uint32 wcr; /* CUrrent word count */ + uint32 cda; /* Current transfer address */ + uint32 devnum; /* Device number */ + t_uint64 buf; /* Data buffer */ + uint8 nxmerr; /* Bit to set for NXM */ + uint8 ccw_comp; /* Have we written out CCW */ +} ; + +/* RH10/RH20 Interface */ +struct rh_if { + void (*rh_write)(DEVICE *dptr, struct rh_if *rh, int reg, uint32 data); + uint32 (*rh_read)(DEVICE *dptr, struct rh_if *rh, int reg); + void (*rh_reset)(DEVICE *dptr); + t_uint64 buf; /* Data buffer */ + uint32 status; /* DF10 status word */ + uint32 cia; /* Initial transfer address */ + uint32 ccw; /* Current word count */ + uint32 wcr; + uint32 cda; /* Current transfer address */ + uint32 devnum; /* Device number */ + int ivect; /* Interrupt vector */ + uint8 imode; /* Mode of vector */ + int cop; /* RH20 Channel operator */ + uint32 sbar; /* RH20 Starting address */ + uint32 stcr; /* RH20 Count */ + uint32 pbar; + uint32 ptcr; + int reg; /* Last register selected */ + int drive; /* Last drive selected */ + int rae; /* Access register error */ + int attn; /* Attention bits */ + int xfer_drive; /* Current transfering drive */ +}; + /* Device context block */ struct pdp_dib { uint32 dev_num; /* device address */ uint32 num_devs; /* length */ t_stat (*io)(uint32 dev, t_uint64 *data); int (*irq)(uint32 dev, int addr); + struct rh_if *rh; }; - + #define RH10_DEV 01000 #define RH20_DEV 02000 struct rh_dev { uint32 dev_num; DEVICE *dev; + struct rh_if *rh; }; - typedef struct pdp_dib DIB; - -/* DF10 Interface */ -struct df10 { - uint32 status; - uint32 cia; - uint32 ccw; - uint32 wcr; - uint32 cda; - uint32 devnum; - t_uint64 buf; - uint8 nxmerr; - uint8 ccw_comp; -} ; - - void df10_setirq(struct df10 *df) ; void df10_writecw(struct df10 *df) ; void df10_finish_op(struct df10 *df, int flags) ; @@ -478,6 +520,18 @@ int dct_write(int u, t_uint64 *data, int c); int dct_is_connect(int u); #endif +/* Define RH10/RH20 functions */ +t_stat rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat rh_devio(uint32 dev, t_uint64 *data); +int rh_devirq(uint32 dev, int addr); +void rh_setattn(struct rh_if *rh, int unit); +int rh_blkend(struct rh_if *rh); +void rh_setirq(struct rh_if *rh) ; +void rh_finish_op(struct rh_if *rh, int flags); +int rh_read(struct rh_if *rh); +int rh_write(struct rh_if *rh); + int ten11_read (int addr, t_uint64 *data); int ten11_write (int addr, t_uint64 data); diff --git a/PDP10/kx10_df.c b/PDP10/kx10_df.c index ceeb46e..841ca9f 100644 --- a/PDP10/kx10_df.c +++ b/PDP10/kx10_df.c @@ -1,6 +1,6 @@ -/* ka10_df.c: DF10 common routines. +/* kx10_df.c: DF10 common routines. - Copyright (c) 2015-2017, Richard Cornwell + Copyright (c) 2015-2019, Richard Cornwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,11 +23,14 @@ #include "kx10_defs.h" + +/* Set an IRQ for a DF10 device */ void df10_setirq(struct df10 *df) { df->status |= PI_ENABLE; set_interrupt(df->devnum, df->status); } +/* Generate the DF10 complete word */ void df10_writecw(struct df10 *df) { df->status |= 1 << df->ccw_comp; if (df->wcr != 0) @@ -35,6 +38,7 @@ void df10_writecw(struct df10 *df) { M[df->cia|1] = ((uint64)(df->ccw & WMASK) << CSHIFT) | ((uint64)(df->cda) & AMASK); } +/* Finish off a DF10 transfer */ void df10_finish_op(struct df10 *df, int flags) { df->status &= ~BUSY; df->status |= flags; @@ -42,6 +46,7 @@ void df10_finish_op(struct df10 *df, int flags) { df10_setirq(df); } +/* Setup for a DF10 transfer */ void df10_setup(struct df10 *df, uint32 addr) { df->cia = addr & ICWA; df->ccw = df->cia; @@ -50,6 +55,7 @@ void df10_setup(struct df10 *df, uint32 addr) { df->status &= ~(1 << df->ccw_comp); } +/* Fetch the next IO control word */ int df10_fetch(struct df10 *df) { uint64 data; if (df->ccw > MEMSIZE) { @@ -84,6 +90,7 @@ int df10_fetch(struct df10 *df) { return 1; } +/* Read next word */ int df10_read(struct df10 *df) { uint64 data; if (df->wcr == 0) { @@ -113,6 +120,7 @@ int df10_read(struct df10 *df) { return 1; } +/* Write next word */ int df10_write(struct df10 *df) { if (df->wcr == 0) { if (!df10_fetch(df)) diff --git a/PDP10/kx10_dp.c b/PDP10/kx10_dp.c index 2f41a4f..15f8d62 100644 --- a/PDP10/kx10_dp.c +++ b/PDP10/kx10_dp.c @@ -423,7 +423,6 @@ t_stat dp_devio(uint32 dev, uint64 *data) { if (*data & BUSY) { /* Stop controller */ sim_cancel(uptr); - uptr->STATUS &= ~BUSY; df10_finish_op(df10, 0); } /* Clear flags */ @@ -722,7 +721,7 @@ t_stat dp_svc (UNIT *uptr) CLR_BUF(uptr); } if (r) - sim_activate(uptr, 25); + sim_activate(uptr, 10); else { uptr->STATUS &= ~(SRC_DONE|END_CYL|BUSY); uptr->UFLAGS |= DONE; diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c new file mode 100644 index 0000000..b337018 --- /dev/null +++ b/PDP10/kx10_rh.c @@ -0,0 +1,750 @@ +/* kx10_rh.c: RH10/RH20 interace routines. + + Copyright (c) 2015-2019, Richard Cornwell + + 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 + RICHARD CORNWELL 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. + +*/ + +#include "kx10_defs.h" + + +/* CONI Flags */ +#define IADR_ATTN 0000000000040LL /* Interrupt on attention */ +#define IARD_RAE 0000000000100LL /* Interrupt on register access error */ +#define DIB_CBOV 0000000000200LL /* Control bus overrun */ +#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */ +#define CXR_ILC 0000000004000LL /* Illegal function code */ +#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */ +#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */ +#define CCW_COMP_1 0000000040000LL /* Control word written. */ +#define CXR_CHAN_ER 0000000100000LL /* Channel Error */ +#define CXR_EXC 0000000200000LL /* Error in drive transfer */ +#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */ +#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */ +#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */ +#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */ +#define CXR_SD_RAE 0000200000000LL /* Register access error */ +#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */ +#define B22_FLAG 0004000000000LL /* 22 bit channel */ +#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */ +#define CC_CHAN_ACT 0020000000000LL /* Channel in use */ +#define CC_INH 0040000000000LL /* Disconnect channel */ +#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */ +#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */ + +/* RH20 CONI Flags */ +#define RH20_PCR_FULL 0000000000020LL /* Primary command file full */ +#define RH20_ATTN_ENA 0000000000040LL /* Attention enable */ +#define RH20_SCR_FULL 0000000000100LL /* Secondary command full */ +#define RH20_ATTN 0000000000200LL /* Attention */ +#define RH20_MASS_ENA 0000000000400LL /* Mass bus enable */ +#define RH20_DATA_OVR 0000000001000LL /* Data overrun */ +#define RH20_CHAN_RDY 0000000002000LL /* Channel ready to start */ +#define RH20_RAE 0000000004000LL /* Register access error */ +#define RH20_DR_RESP 0000000010000LL /* Drive no response */ +#define RH20_CHAN_ERR 0000000020000LL /* Channel error */ +#define RH20_SHRT_WC 0000000040000LL /* Short word count */ +#define RH20_LONG_WC 0000000100000LL /* Long word count */ +#define RH20_DR_EXC 0000000200000LL /* Exception */ +#define RH20_DATA_PRI 0000000400000LL /* Data parity error */ +#define RH20_SBAR 0000001000000LL /* SBAR set */ +#define RH20_XEND 0000002000000LL /* Transfer ended */ + +/* CONO Flags */ +#define ATTN_EN 0000000000040LL /* enable attention interrupt. */ +#define REA_EN 0000000000100LL /* enable register error interrupt */ +#define CBOV_CLR 0000000000200LL /* Clear CBOV */ +#define CONT_RESET 0000000002000LL /* Clear All error bits */ +#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */ +#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */ +#define OVER_CLR 0000000020000LL /* Clear DTC overrun */ +#define WRT_CW 0000000040000LL /* Write control word */ +#define CHN_CLR 0000000100000LL /* Clear Channel Error */ +#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */ +#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */ + +/* RH20 CONO Flags */ +#define RH20_DELETE_SCR 0000000000100LL /* Clear SCR */ +#define RH20_RCLP 0000000000200LL /* Reset command list */ +#define RH20_MASS_EN 0000000000400LL /* Mass bus enable */ +#define RH20_XFER_CLR 0000000001000LL /* Clear XFER error */ +#define RH20_CLR_MBC 0000000002000LL /* Clear MBC */ +#define RH20_CLR_RAE 0000000004000LL /* Clear RAE error */ + +/* DATAO/DATAI */ +#define CR_REG 0770000000000LL /* Register number */ +#define LOAD_REG 0004000000000LL /* Load register */ +#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */ +#define CR_DRIVE 0000007000000LL +#define CR_GEN_EVD 0000000400000LL /* Enable Parity */ +#define CR_DXES 0000000200000LL /* Disable DXES errors */ +#define CR_INAD 0000000077600LL +#define CR_WTEVM 0000000000100LL /* Verify Parity */ +#define CR_FUNC 0000000000076LL +#define CR_GO 0000000000001LL + +#define IRQ_VECT 0000000000177LL /* Interupt vector */ +#define IRQ_KI10 0000002000000LL +#define IRQ_KA10 0000001000000LL +#define FNC_XFER 024 /* >=? data xfr */ + +/* Status register settings */ +#define DS_OFF 0000001 /* offset mode */ +#define DS_VV 0000100 /* volume valid */ +#define DS_DRY 0000200 /* drive ready */ +#define DS_DPR 0000400 /* drive present */ +#define DS_PGM 0001000 /* programable NI */ +#define DS_LST 0002000 /* last sector */ +#define DS_WRL 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 */ + +/* RH20 channel status flags */ +#define RH20_MEM_PAR 00200000000000LL /* Memory parity error */ +#define RH20_ADR_PAR 00100000000000LL /* Address parity error */ +#define RH20_NOT_WC0 00040000000000LL /* Word count not zero */ +#define RH20_NXM_ERR 00020000000000LL /* Non existent memory */ +#define RH20_LAST_ERR 00000400000000LL /* Last transfer error */ +#define RH20_ERROR 00000200000000LL /* RH20 error */ +#define RH20_LONG_STS 00000100000000LL /* Did not reach wc */ +#define RH20_SHRT_STS 00000040000000LL /* WC reached zero */ +#define RH20_OVER 00000020000000LL /* Overrun error */ + +/* 0-37 mass bus register. + 70 SBAR, block address. + 71 STCR, neg block count, func + 72 PBAR + 73 PTCR + 74 IVIR Interrupt vector address. + 75 Diags read. + 76 Diags write. + 77 Status (tra,cb test, bar test, ev par, r/w, exc,ebl, 0, attn, sclk +*/ + +/* + * CCW 000..... New channel comand list pointer HALT. + 010..... Next CCW Address JUMP + 1xycount-address. x=halt last xfer, y=reverse +*/ + +extern uint32 eb_ptr; +void rh20_setup(struct rh_if *rhc); +void rh_setup(struct rh_if *rh, uint32 addr); +void rh_writecw(struct rh_if *rh, int nxm); + + +t_stat +rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + DEVICE *dptr; + DIB *dibp; + dptr = find_dev_from_unit (uptr); + if (dptr == NULL) + return SCPE_IERR; + dibp = (DIB *) dptr->ctxt; + dptr->flags &= ~DEV_M_RH; + dptr->flags |= val; + dibp->dev_num &= ~(RH10_DEV|RH20_DEV); + dibp->dev_num |= (val) ? RH20_DEV: RH10_DEV; + return SCPE_OK; +} + +t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + DEVICE *dptr; + + if (uptr == NULL) + return SCPE_IERR; + + dptr = find_dev_from_unit(uptr); + if (dptr == NULL) + return SCPE_IERR; + fprintf (st, "%s", (dptr->flags & TYPE_RH20) ? "RH20" : "RH10"); + return SCPE_OK; +} + + +t_stat rh_devio(uint32 dev, uint64 *data) { + DEVICE *dptr = NULL; + struct rh_if *rhc = NULL; + int drive; + + for (drive = 0; rh[drive].dev_num != 0; drive++) { + if (rh[drive].dev_num == (dev & 0774)) { + rhc = rh[drive].rh; + dptr = rh[drive].dev; + break; + } + } + if (rhc == NULL) + return SCPE_OK; + rhc->devnum = dev & 0774; +#if KL + if (dptr->flags & TYPE_RH20) { + switch(dev & 3) { + case CONI: + *data = rhc->status & RMASK; + if (rhc->attn != 0) + *data |= RH20_ATTN; + if (rhc->rae != 0) + *data |= RH20_RAE; + if ((rhc->status & PI_ENABLE) == 0) + *data |= RH20_CHAN_RDY; + sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n", + dptr->name, dev, (uint32)*data, PC, rhc->attn); + return SCPE_OK; + + case CONO: + clr_interrupt(dev); + rhc->status &= ~(07LL|IADR_ATTN|RH20_MASS_EN); + rhc->status |= *data & (07LL|IADR_ATTN|RH20_MASS_EN); + /* Clear flags */ + if (*data & RH20_CLR_MBC) { + if (rhc->rh_reset != NULL) + rhc->rh_reset(dptr); + rhc->imode = 2; + } + if (*data & RH20_DELETE_SCR) + rhc->status &= ~(RH20_SBAR|RH20_SCR_FULL); + if (*data & (RH20_RCLP|RH20_CLR_MBC)) + rhc->cia = eb_ptr | (rhc->devnum - 0540); + if (*data & (RH20_CLR_RAE|RH20_CLR_MBC)) + rhc->rae = 0; + if (*data & PI_ENABLE) + rhc->status &= ~PI_ENABLE; + if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) + || (rhc->status & PI_ENABLE)) + set_interrupt(rhc->devnum, rhc->status); + sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n", + dptr->name, dev, (uint32)*data, PC, rhc->status); + return SCPE_OK; + + case DATAI: + *data = 0; + if (rhc->status & BUSY && rhc->reg != 04) { + rhc->status |= CC_CHAN_ACT; + return SCPE_OK; + } + if (rhc->reg < 040) { + int parity; + *data = (uint64)(rhc->rh_read(dptr, rhc, rhc->reg) & 0177777); + parity = (int)((*data >> 8) ^ *data); + parity = (parity >> 4) ^ parity; + parity = (parity >> 2) ^ parity; + parity = ((parity >> 1) ^ parity) & 1; + *data |= ((uint64)(parity ^ 1)) << 17; + *data |= ((uint64)(rhc->drive)) << 18; + *data |= BIT10; + } else if ((rhc->reg & 070) != 070) { + rhc->rae = 1; + break; + } else { + switch(rhc->reg & 07) { + case 0: *data = rhc->sbar; break; + case 1: *data = rhc->stcr; break; + case 2: *data = rhc->pbar; break; + case 3: *data = rhc->ptcr; break; + case 4: *data = rhc->ivect; break; + case 5: + case 6: break; + case 7: *data = 0; break; + } + } + *data |= ((uint64)(rhc->reg)) << 30; + sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n", + dptr->name, dev, *data, rhc->drive, PC); + return SCPE_OK; + + case DATAO: + sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n", + dptr->name, dev, *data, PC, rhc->status); + rhc->reg = ((int)(*data >> 30)) & 077; + rhc->imode |= 2; + if (rhc->reg < 040 && rhc->reg != 04) { + rhc->drive = (int)(*data >> 18) & 07; + } + if (*data & LOAD_REG) { + if (rhc->reg < 040) { + clr_interrupt(dev); + /* Check if access error */ + if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0) { + set_interrupt(rhc->devnum, rhc->status); + return SCPE_OK; + } + rhc->rh_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); + if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) + || (rhc->status & PI_ENABLE)) + set_interrupt(rhc->devnum, rhc->status); + /* Check if access error */ + if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0) + set_interrupt(rhc->devnum, rhc->status); + else + rhc->rae &= ~(1 << rhc->drive); + } else if ((rhc->reg & 070) != 070) { + if ((*data & BIT9) == 0) { + rhc->rae = (1 << rhc->drive); + set_interrupt(rhc->devnum, rhc->status); + } + } else { + switch(rhc->reg & 07) { + case 0: + rhc->sbar = (*data) & (CR_DRIVE|RMASK); + rhc->status |= RH20_SBAR; + break; + case 1: + rhc->stcr = (*data) & (BIT10|BIT7|CR_DRIVE|RMASK); + rhc->status |= RH20_SCR_FULL; + break; + case 4: + rhc->ivect = (*data & IRQ_VECT); + break; + case 2: + case 3: + case 5: + case 6: + case 7: + break; + } + } + } + } + if ((rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL)) + rh20_setup(rhc); + return SCPE_OK; + } +#endif + switch(dev & 3) { + case CONI: + *data = rhc->status & ~(IADR_ATTN|IARD_RAE); + if (rhc->attn != 0 && (rhc->status & IADR_ATTN)) + *data |= IADR_ATTN; + if (rhc->rae != 0 && (rhc->status & IARD_RAE)) + *data |= IARD_RAE; +#if KI_22BIT + *data |= B22_FLAG; +#endif + sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n", + dptr->name, dev, (uint32)*data, PC, rhc->attn); + return SCPE_OK; + + case CONO: + clr_interrupt(dev); + rhc->status &= ~(07LL|IADR_ATTN|IARD_RAE); + rhc->status |= *data & (07LL|IADR_ATTN|IARD_RAE); + /* Clear flags */ + if (*data & CONT_RESET && rhc->rh_reset != NULL) + rhc->rh_reset(dptr); + if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)) + rhc->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)); + if (*data & OVER_CLR) + rhc->status &= ~(DTC_OVER); + if (*data & CBOV_CLR) + rhc->status &= ~(DIB_CBOV); + if (*data & CXR_ILC) + rhc->status &= ~(CXR_ILFC|CXR_SD_RAE); + if (*data & WRT_CW) + rh_writecw(rhc, 0); + if (*data & PI_ENABLE) + rhc->status &= ~PI_ENABLE; + if (rhc->status & PI_ENABLE) + set_interrupt(dev, rhc->status); + if ((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) + set_interrupt(dev, rhc->status); + sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n", + dptr->name, dev, (uint32)*data, PC, rhc->status); + return SCPE_OK; + + case DATAI: + *data = 0; + if (rhc->status & BUSY && rhc->reg != 04) { + rhc->status |= CC_CHAN_ACT; + return SCPE_OK; + } + if (rhc->reg == 040) { + *data = (uint64)(rhc->rh_read(dptr, rhc, 0) & 077); + *data |= ((uint64)(rhc->cia)) << 6; + *data |= ((uint64)(rhc->xfer_drive)) << 18; + } else if (rhc->reg == 044) { + *data = (uint64)rhc->ivect; + if (rhc->imode) + *data |= IRQ_KI10; + else + *data |= IRQ_KA10; + } else if (rhc->reg == 054) { + *data = (uint64)(rhc->rae); + } else if ((rhc->reg & 040) == 0) { + int parity; + *data = (uint64)(rhc->rh_read(dptr, rhc, rhc->reg) & 0177777); + parity = (int)((*data >> 8) ^ *data); + parity = (parity >> 4) ^ parity; + parity = (parity >> 2) ^ parity; + parity = ((parity >> 1) ^ parity) & 1; + *data |= ((uint64)(parity ^ 1)) << 17; + *data |= ((uint64)(rhc->drive)) << 18; + } + *data |= ((uint64)(rhc->reg)) << 30; + sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n", + dptr->name, dev, *data, rhc->drive, PC); + return SCPE_OK; + + case DATAO: + sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n", + dptr->name, dev, *data, PC, rhc->status); + rhc->reg = ((int)(*data >> 30)) & 077; + rhc->imode &= ~2; + if (rhc->reg < 040 && rhc->reg != 04) { + rhc->drive = (int)(*data >> 18) & 07; + } + if (*data & LOAD_REG) { + if (rhc->reg == 040) { + if ((*data & 1) == 0) { + return SCPE_OK; + } + + if (rhc->status & BUSY) { + rhc->status |= CC_CHAN_ACT; + return SCPE_OK; + } + + rhc->status &= ~(CCW_COMP_1|PI_ENABLE); + if (((*data >> 1) & 037) < FNC_XFER) { + rhc->status |= CXR_ILC; + rh_setirq(rhc); + sim_debug(DEBUG_DATAIO, dptr, + "%s %03o command abort %012llo, %d PC=%06o %06o\n", + dptr->name, dev, *data, rhc->drive, PC, rhc->status); + return SCPE_OK; + } + /* Check if access error */ + if (rhc->rae & (1 << rhc->drive)) + return SCPE_OK; + /* Start command */ + rh_setup(rhc, (uint32)(*data >> 6)); + rhc->xfer_drive = (int)(*data >> 18) & 07; + rhc->rh_write(dptr, rhc, 0, (uint32)(*data & 077)); + sim_debug(DEBUG_DATAIO, dptr, + "%s %03o command %012llo, %d PC=%06o %06o\n", + dptr->name, dev, *data, rhc->drive, PC, rhc->status); + } else if (rhc->reg == 044) { + /* Set KI10 Irq vector */ + rhc->ivect = (int)(*data & IRQ_VECT); + rhc->imode = (*data & IRQ_KI10) != 0; + } else if (rhc->reg == 050) { + ; /* Diagnostic access to mass bus. */ + } else if (rhc->reg == 054) { + /* clear flags */ + rhc->rae &= ~(*data & 0377); + if (rhc->rae == 0) + clr_interrupt(dev); + } else if ((rhc->reg & 040) == 0) { + rhc->drive = (int)(*data >> 18) & 07; + /* Check if access error */ + if (rhc->rae & (1 << rhc->drive)) { + return SCPE_OK; + } + rhc->rh_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); + } + } + clr_interrupt(dev); + if (((rhc->status & (IADR_ATTN|BUSY)) == IADR_ATTN && rhc->attn != 0) + || (rhc->status & PI_ENABLE)) + set_interrupt(rhc->devnum, rhc->status); + return SCPE_OK; + } + return SCPE_OK; /* Unreached */ +} + +/* Handle KI and KL style interrupt vectors */ +int +rh_devirq(uint32 dev, int addr) { + DEVICE *dptr = NULL; + struct rh_if *rhc = NULL; + int drive; + + for (drive = 0; rh[drive].dev_num != 0; drive++) { + if (rh[drive].dev_num == (dev & 0774)) { + rhc = rh[drive].rh; + break; + } + } + if (rhc != NULL) { + return (rhc->imode ? rhc->ivect : addr); + } + return addr; +} + +/* Set the attention flag for a unit */ +void rh_setattn(struct rh_if *rhc, int unit) +{ + rhc->attn |= 1<status & IADR_ATTN) != 0) + rh_setirq(rhc); +} + +/* Decrement block count for RH20, nop for RH10 */ +int rh_blkend(struct rh_if *rhc) +{ +#if KL + if (rhc->imode == 2) { + rhc->cia = (rhc->cia + 1) & RH20_WMASK; + if (rhc->cia == 0) { + rhc->status |= RH20_XEND; + return 1; + } + } +#endif + return 0; +} + +/* Set an IRQ for a DF10 device */ +void rh_setirq(struct rh_if *rhc) { + rhc->status |= PI_ENABLE; + set_interrupt(rhc->devnum, rhc->status); +} + +/* Generate the DF10 complete word */ +void rh_writecw(struct rh_if *rhc, int nxm) { +#if KL + if (rhc->imode == 2) { + uint32 chan = (rhc->devnum - 0540); + if (rhc->ptcr & BIT10) { + int wc = (rhc->wcr ^ RH20_WMASK) + 1; + uint64 wrd1 = SMASK|(uint64)(rhc->ccw); + if (nxm) + wrd1 |= RH20_NXM_ERR; + if (wc != 0) { + wrd1 |= RH20_NOT_WC0; + if (rhc->status & RH20_XEND) { + wrd1 |= RH20_LONG_STS; + rhc->status |= RH20_LONG_WC; + } + } else if ((rhc->status & RH20_XEND) == 0) { + wrd1 |= RH20_SHRT_STS; + rhc->status |= RH20_SHRT_WC; + } + M[eb_ptr|chan|1] = wrd1; + M[eb_ptr|chan|2] = ((uint64)rhc->cop << 30) | + (((uint64)wc & RH20_WMASK) << CSHIFT) | + ((uint64)(rhc->cda) & AMASK); + } + rhc->status &= ~(RH20_PCR_FULL); + return; + } +#endif + if (nxm) + rhc->status |= CXR_NXM; + rhc->status |= CCW_COMP_1; + if (rhc->wcr != 0) + rhc->cda++; + M[rhc->cia|1] = ((uint64)(rhc->ccw & WMASK) << CSHIFT) | ((uint64)(rhc->cda) & AMASK); +} + +/* Finish off a DF10 transfer */ +void rh_finish_op(struct rh_if *rhc, int nxm) { +#if KL + if (rhc->imode != 2) +#endif + rhc->status &= ~BUSY; + rh_writecw(rhc, nxm); + rh_setirq(rhc); +#if KL + if (rhc->imode == 2 && + (rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL)) + rh20_setup(rhc); +#endif +} + +#if KL + +/* Set up for a RH20 transfer */ +void rh20_setup(struct rh_if *rhc) +{ + int reg; + DEVICE *dptr; + + for (reg = 0; rh[reg].dev_num != 0; reg++) { + if (rh[reg].rh == rhc) { + dptr = rh[reg].dev; + break; + } + } + if (dptr == 0) + return; + rhc->pbar = rhc->sbar; + rhc->ptcr = rhc->stcr; + /* Read drive status */ + rhc->drive = (rhc->ptcr >> 18) & 07; + rhc->status &= ~(RH20_SCR_FULL|PI_ENABLE|RH20_XEND); + rhc->status |= RH20_PCR_FULL; + reg = rhc->rh_read(dptr, rhc, 1); + if ((reg & (DS_DRY|DS_DPR|DS_ERR)) != (DS_DRY|DS_DPR)) + return; + if (rhc->status & RH20_SBAR) { + rhc->drive = (rhc->pbar >> 18) & 07; + rhc->rh_write(dptr, rhc, 5, (rhc->pbar & 0177777)); + rhc->status &= ~RH20_SBAR; + } + if (rhc->ptcr & BIT7) { /* If RCPL reset I/O pointers */ + rhc->ccw = eb_ptr + (rhc->devnum - 0540); + rhc->wcr = 0; + } + /* Hold block count in cia */ + rhc->cia = (rhc->ptcr >> 6); + rhc->rh_write(dptr, rhc, 0, (rhc->ptcr & 077)); + rhc->cop = 0; +} +#endif + +/* Setup for a DF10 transfer */ +void rh_setup(struct rh_if *rhc, uint32 addr) +{ + rhc->cia = addr & ICWA; + rhc->ccw = rhc->cia; + rhc->wcr = 0; + rhc->status |= BUSY; +} + + +/* Fetch the next IO control word */ +int rh_fetch(struct rh_if *rhc) { + uint64 data; +#if KL + if (rhc->imode == 2 && (rhc->cop & 2) != 0) { + rh_finish_op(rhc, 0); + return 0; + } +#endif + if (rhc->ccw > MEMSIZE) { + rh_finish_op(rhc, 1); + return 0; + } + data = M[rhc->ccw]; +#if KL + if (rhc->imode == 2) { + while((data & RH20_XFER) == 0) { + rhc->ccw = (uint32)(data & AMASK); + if ((data & (BIT1|BIT2)) == 0) { + rh_finish_op(rhc, 0); + break; + } + if (rhc->ccw > MEMSIZE) { + rh_finish_op(rhc, 1); + return 0; + } + data = M[rhc->ccw]; + } + rhc->wcr = (((data >> CSHIFT) & RH20_WMASK) ^ WMASK) + 1; + rhc->cda = (data & AMASK); + rhc->cop = (data >> 33) & 07; + rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK); + return 1; + } +#endif + while((data & (WMASK << CSHIFT)) == 0) { + if ((data & AMASK) == 0 || (uint32)(data & AMASK) == rhc->ccw) { + rh_finish_op(rhc,0); + return 0; + } + rhc->ccw = (uint32)(data & AMASK); + if (rhc->ccw > MEMSIZE) { + rh_finish_op(rhc, 1); + return 0; + } + data = M[rhc->ccw]; + } + rhc->wcr = (uint32)((data >> CSHIFT) & WMASK); + rhc->cda = (uint32)(data & AMASK); + rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK); + return 1; +} + +/* Read next word */ +int rh_read(struct rh_if *rhc) { + uint64 data; + if (rhc->wcr == 0) { + if (!rh_fetch(rhc)) + return 0; + } + rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK); + if (rhc->cda != 0) { + if (rhc->cda > MEMSIZE) { + rh_finish_op(rhc, 1); + return 0; + } +#if KL + if (rhc->imode == 2) { + data = M[rhc->cda]; + if (rhc->cop & 01) + rhc->cda = (uint32)((rhc->cda - 1) & AMASK); + else + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + } else { + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + data = M[rhc->cda]; + } +#else + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + data = M[rhc->cda]; +#endif + } else { + data = 0; + } + rhc->buf = data; + if (rhc->wcr == 0) { + return rh_fetch(rhc); + } + return 1; +} + +/* Write next word */ +int rh_write(struct rh_if *rhc) { + if (rhc->wcr == 0) { + if (!rh_fetch(rhc)) + return 0; + } + rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK); + if (rhc->cda != 0) { + if (rhc->cda > MEMSIZE) { + rh_finish_op(rhc, 1); + return 0; + } +#if KL + if (rhc->imode == 2) { + M[rhc->cda] = rhc->buf; + if (rhc->cop & 01) + rhc->cda = (uint32)((rhc->cda - 1) & AMASK); + else + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + } else { + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + M[rhc->cda] = rhc->buf; + } +#else + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + M[rhc->cda] = rhc->buf; +#endif + } + if (rhc->wcr == 0) { + return rh_fetch(rhc); + } + return 1; +} + diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index 37eb5e9..9c421f6 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -45,79 +45,13 @@ #define DTYPE(x) (((x) & UNIT_M_DTYPE) << UNIT_V_DTYPE) #define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) #define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ -#define CNTRL_V_CTYPE (UNIT_V_UF + 4) -#define CNTRL_M_CTYPE 7 -#define GET_CNTRL(x) (((x) >> CNTRL_V_CTYPE) & CNTRL_M_CTYPE) -#define CNTRL(x) (((x) & CNTRL_M_CTYPE) << CNTRL_V_CTYPE) /* Parameters in the unit descriptor */ - -/* CONI Flags */ -#define IADR_ATTN 0000000000040LL /* Interrupt on attention */ -#define IARD_RAE 0000000000100LL /* Interrupt on register access error */ -#define DIB_CBOV 0000000000200LL /* Control bus overrun */ -#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */ -#define CXR_ILC 0000000004000LL /* Illegal function code */ -#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */ -#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */ -#define CCW_COMP_1 0000000040000LL /* Control word written. */ -#define CXR_CHAN_ER 0000000100000LL /* Channel Error */ -#define CXR_EXC 0000000200000LL /* Error in drive transfer */ -#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */ -#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */ -#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */ -#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */ -#define CXR_SD_RAE 0000200000000LL /* Register access error */ -#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */ -#define B22_FLAG 0004000000000LL /* 22 bit channel */ -#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */ -#define CC_CHAN_ACT 0020000000000LL /* Channel in use */ -#define CC_INH 0040000000000LL /* Disconnect channel */ -#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */ -#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */ - -/* CONO Flags */ -#define ATTN_EN 0000000000040LL /* enable attention interrupt. */ -#define REA_EN 0000000000100LL /* enable register error interrupt */ -#define CBOV_CLR 0000000000200LL /* Clear CBOV */ -#define CONT_RESET 0000000002000LL /* Clear All error bits */ -#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */ -#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */ -#define OVER_CLR 0000000020000LL /* Clear DTC overrun */ -#define WRT_CW 0000000040000LL /* Write control word */ -#define CHN_CLR 0000000100000LL /* Clear Channel Error */ -#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */ -#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */ - -/* RH20 CONO Flags */ -#define RH20_DELETE_SCR 0000000000100LL /* Clear SCR */ -#define RH20_RCLP 0000000000200LL /* Reset command list */ -#define RH20_MASS_EN 0000000000400LL /* Mass bus enable */ -#define RH20_XFER_CLR 0000000001000LL /* Clear XFER error */ -#define RH20_CLR_MBC 0000000002000LL /* Clear MBC */ -#define RH20_CLR_RAE 0000000004000LL /* Clear RAE error */ - -/* DATAO/DATAI */ -#define CR_REG 0770000000000LL /* Register number */ -#define LOAD_REG 0004000000000LL /* Load register */ -#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */ -#define CR_DRIVE 0000007000000LL -#define CR_GEN_EVD 0000000400000LL /* Enable Parity */ -#define CR_DXES 0000000200000LL /* Disable DXES errors */ -#define CR_INAD 0000000077600LL -#define CR_WTEVM 0000000000100LL /* Verify Parity */ -#define CR_FUNC 0000000000076LL -#define CR_GO 0000000000001LL - -#define IRQ_VECT 0000000000177LL /* Interupt vector */ -#define IRQ_KI10 0000002000000LL -#define IRQ_KA10 0000001000000LL - #define CMD u3 /* u3 low */ /* RPC - 00 - control */ -#define CS1_GO CR_GO /* go */ +#define CS1_GO 1 /* go */ #define CS1_V_FNC 1 /* function pos */ #define CS1_M_FNC 037 /* function mask */ #define CS1_FNC (CS1_M_FNC << CS1_V_FNC) @@ -291,20 +225,11 @@ struct drvtyp rp_drv_tab[] = { }; -struct df10 rp_df10[NUM_DEVS_RP]; -int rp_xfer_drive[NUM_DEVS_RP]; -uint64 rp_buf[NUM_DEVS_RP][RP_NUMWD]; -int rp_reg[NUM_DEVS_RP]; -int rp_ivect[NUM_DEVS_RP]; -int rp_imode[NUM_DEVS_RP]; -int rp_drive[NUM_DEVS_RP]; -int rp_rae[NUM_DEVS_RP]; -int rp_attn[NUM_DEVS_RP]; - t_stat rp_devio(uint32 dev, uint64 *data); int rp_devirq(uint32 dev, int addr); -void rp_write(int ctlr, int unit, int reg, uint32 data); -uint32 rp_read(int ctlr, int unit, int reg); +void rp_write(DEVICE *dptr, struct rh_if *rh, int reg, uint32 data); +uint32 rp_read(DEVICE *dptr, struct rh_if *rh, int reg); +void rp_rst(DEVICE *dptr); t_stat rp_svc(UNIT *); t_stat rp_boot(int32, DEVICE *); void rp_ini(UNIT *, t_bool); @@ -315,92 +240,107 @@ t_stat rp_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat rp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); const char *rp_description (DEVICE *dptr); +uint64 rp_buf[NUM_DEVS_RP][RP_NUMWD]; UNIT rp_unit[] = { /* Controller 1 */ { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(0), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(0), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(0), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(0), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(0), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(0), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(0), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(0), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(0), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(0), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(0), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(0), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(0), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(0), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(0), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(0), RP06_SIZE) }, #if (NUM_DEVS_RP > 1) /* Controller 2 */ { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(1), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(1), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(1), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(1), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(1), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(1), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(1), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(1), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(1), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(1), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(1), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(1), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(1), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(1), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(1), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(1), RP06_SIZE) }, #if (NUM_DEVS_RP > 2) /* Controller 3 */ { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(2), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(2), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(2), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(2), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(2), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(2), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(2), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(2), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(2), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(2), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(2), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(2), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(2), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(2), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(2), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(2), RP06_SIZE) }, #if (NUM_DEVS_RP > 3) /* Controller 4 */ { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(3), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(3), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(3), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(3), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(3), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(3), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(3), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(3), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(3), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(3), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(3), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(3), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(3), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(3), RP06_SIZE) }, { UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL(3), RP06_SIZE) }, + UNIT_ROABLE+DTYPE(RP06_DTYPE)+CNTRL_RH(3), RP06_SIZE) }, #endif #endif #endif }; +struct rh_if rp_rh[NUM_DEVS_RP] = { + { &rp_write, &rp_read, &rp_rst}, + { &rp_write, &rp_read, &rp_rst}, + { &rp_write, &rp_read, &rp_rst}, + { &rp_write, &rp_read, &rp_rst} +}; + DIB rp_dib[] = { - {RH10_DEV, 1, &rp_devio, &rp_devirq}, - {RH10_DEV, 1, &rp_devio, &rp_devirq}, - {RH10_DEV, 1, &rp_devio, &rp_devirq}, - {RH10_DEV, 1, &rp_devio, &rp_devirq}}; + {RH10_DEV, 1, &rh_devio, &rh_devirq, &rp_rh[0]}, + {RH10_DEV, 1, &rh_devio, &rh_devirq, &rp_rh[1]}, + {RH10_DEV, 1, &rh_devio, &rh_devirq, &rp_rh[2]}, + {RH10_DEV, 1, &rh_devio, &rh_devirq, &rp_rh[3]}}; + MTAB rp_mod[] = { +#if KL + {MTAB_XTD|MTAB_VDV, TYPE_RH10, NULL, "RH10", &rh_set_type, NULL, + NULL, "Sets controller to RH10" }, + {MTAB_XTD|MTAB_VDV, TYPE_RH20, "RH20", "RH20", &rh_set_type, &rh_show_type, + NULL, "Sets controller to RH20"}, +#endif {UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL}, {UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL}, {UNIT_DTYPE, (RP07_DTYPE << UNIT_V_DTYPE), "RP07", "RP07", &rp_set_type }, @@ -410,22 +350,20 @@ MTAB rp_mod[] = { }; REG rpa_reg[] = { - {ORDATA(IVECT, rp_ivect[0], 18)}, - {FLDATA(IMODE, rp_imode[0], 0)}, - {ORDATA(XFER, rp_xfer_drive[0], 3), REG_HRO}, - {ORDATA(DRIVE, rp_drive[0], 3), REG_HRO}, - {ORDATA(REG, rp_reg[0], 6), REG_RO}, - {ORDATA(RAE, rp_rae[0], 8), REG_RO}, - {ORDATA(ATTN, rp_attn[0], 8), REG_RO}, - {ORDATA(STATUS, rp_df10[0].status, 18), REG_RO}, - {ORDATA(CIA, rp_df10[0].cia, 18)}, - {ORDATA(CCW, rp_df10[0].ccw, 18)}, - {ORDATA(WCR, rp_df10[0].wcr, 18)}, - {ORDATA(CDA, rp_df10[0].cda, 18)}, - {ORDATA(DEVNUM, rp_df10[0].devnum, 9), REG_HRO}, - {ORDATA(BUF, rp_df10[0].buf, 36), REG_HRO}, - {ORDATA(NXM, rp_df10[0].nxmerr, 8), REG_HRO}, - {ORDATA(COMP, rp_df10[0].ccw_comp, 8), REG_HRO}, + {ORDATA(IVECT, rp_rh[0].ivect, 18)}, + {FLDATA(IMODE, rp_rh[0].imode, 0)}, + {ORDATA(XFER, rp_rh[0].xfer_drive, 3), REG_HRO}, + {ORDATA(DRIVE, rp_rh[0].drive, 3), REG_HRO}, + {ORDATA(REG, rp_rh[0].reg, 6), REG_RO}, + {ORDATA(RAE, rp_rh[0].rae, 8), REG_RO}, + {ORDATA(ATTN, rp_rh[0].attn, 8), REG_RO}, + {ORDATA(STATUS, rp_rh[0].status, 18), REG_RO}, + {ORDATA(CIA, rp_rh[0].cia, 18)}, + {ORDATA(CCW, rp_rh[0].ccw, 18)}, + {ORDATA(WCR, rp_rh[0].wcr, 18)}, + {ORDATA(CDA, rp_rh[0].cda, 18)}, + {ORDATA(DEVNUM, rp_rh[0].devnum, 9), REG_HRO}, + {ORDATA(BUF, rp_rh[0].buf, 36), REG_HRO}, {BRDATA(BUFF, &rp_buf[0][0], 16, 64, RP_NUMWD), REG_HRO}, {0} }; @@ -440,22 +378,20 @@ DEVICE rpa_dev = { #if (NUM_DEVS_RP > 1) REG rpb_reg[] = { - {ORDATA(IVECT, rp_ivect[1], 18)}, - {FLDATA(IMODE, rp_imode[1], 0)}, - {ORDATA(XFER, rp_xfer_drive[1], 3), REG_HRO}, - {ORDATA(DRIVE, rp_drive[1], 3), REG_HRO}, - {ORDATA(REG, rp_reg[1], 6), REG_RO}, - {ORDATA(RAE, rp_rae[1], 8), REG_RO}, - {ORDATA(ATTN, rp_attn[1], 8), REG_RO}, - {ORDATA(STATUS, rp_df10[1].status, 18), REG_RO}, - {ORDATA(CIA, rp_df10[1].cia, 18)}, - {ORDATA(CCW, rp_df10[1].ccw, 18)}, - {ORDATA(WCR, rp_df10[1].wcr, 18)}, - {ORDATA(CDA, rp_df10[1].cda, 18)}, - {ORDATA(DEVNUM, rp_df10[1].devnum, 9), REG_HRO}, - {ORDATA(BUF, rp_df10[1].buf, 36), REG_HRO}, - {ORDATA(NXM, rp_df10[1].nxmerr, 8), REG_HRO}, - {ORDATA(COMP, rp_df10[1].ccw_comp, 8), REG_HRO}, + {ORDATA(IVECT, rp_rh[1].ivect, 18)}, + {FLDATA(IMODE, rp_rh[1].imode, 0)}, + {ORDATA(XFER, rp_rh[1].xfer_drive, 3), REG_HRO}, + {ORDATA(DRIVE, rp_rh[1].drive, 3), REG_HRO}, + {ORDATA(REG, rp_rh[1].reg, 6), REG_RO}, + {ORDATA(RAE, rp_rh[1].rae, 8), REG_RO}, + {ORDATA(ATTN, rp_rh[1].attn, 8), REG_RO}, + {ORDATA(STATUS, rp_rh[1].status, 18), REG_RO}, + {ORDATA(CIA, rp_rh[1].cia, 18)}, + {ORDATA(CCW, rp_rh[1].ccw, 18)}, + {ORDATA(WCR, rp_rh[1].wcr, 18)}, + {ORDATA(CDA, rp_rh[1].cda, 18)}, + {ORDATA(DEVNUM, rp_rh[1].devnum, 9), REG_HRO}, + {ORDATA(BUF, rp_rh[1].buf, 36), REG_HRO}, {BRDATA(BUFF, &rp_buf[1][0], 16, 64, RP_NUMWD), REG_HRO}, {0} }; @@ -470,22 +406,20 @@ DEVICE rpb_dev = { #if (NUM_DEVS_RP > 2) REG rpc_reg[] = { - {ORDATA(IVECT, rp_ivect[2], 18)}, - {FLDATA(IMODE, rp_imode[2], 0)}, - {ORDATA(XFER, rp_xfer_drive[2], 3), REG_HRO}, - {ORDATA(DRIVE, rp_drive[2], 3), REG_HRO}, - {ORDATA(REG, rp_reg[2], 6), REG_RO}, - {ORDATA(RAE, rp_rae[2], 8), REG_RO}, - {ORDATA(ATTN, rp_attn[2], 8), REG_RO}, - {ORDATA(STATUS, rp_df10[2].status, 18), REG_RO}, - {ORDATA(CIA, rp_df10[2].cia, 18)}, - {ORDATA(CCW, rp_df10[2].ccw, 18)}, - {ORDATA(WCR, rp_df10[2].wcr, 18)}, - {ORDATA(CDA, rp_df10[2].cda, 18)}, - {ORDATA(DEVNUM, rp_df10[2].devnum, 9), REG_HRO}, - {ORDATA(BUF, rp_df10[2].buf, 36), REG_HRO}, - {ORDATA(NXM, rp_df10[2].nxmerr, 8), REG_HRO}, - {ORDATA(COMP, rp_df10[2].ccw_comp, 8), REG_HRO}, + {ORDATA(IVECT, rp_rh[2].ivect, 18)}, + {FLDATA(IMODE, rp_rh[2].imode, 0)}, + {ORDATA(XFER, rp_rh[2].xfer_drive, 3), REG_HRO}, + {ORDATA(DRIVE, rp_rh[2].drive, 3), REG_HRO}, + {ORDATA(REG, rp_rh[2].reg, 6), REG_RO}, + {ORDATA(RAE, rp_rh[2].rae, 8), REG_RO}, + {ORDATA(ATTN, rp_rh[2].attn, 8), REG_RO}, + {ORDATA(STATUS, rp_rh[2].status, 18), REG_RO}, + {ORDATA(CIA, rp_rh[2].cia, 18)}, + {ORDATA(CCW, rp_rh[2].ccw, 18)}, + {ORDATA(WCR, rp_rh[2].wcr, 18)}, + {ORDATA(CDA, rp_rh[2].cda, 18)}, + {ORDATA(DEVNUM, rp_rh[2].devnum, 9), REG_HRO}, + {ORDATA(BUF, rp_rh[2].buf, 36), REG_HRO}, {BRDATA(BUFF, &rp_buf[2][0], 16, 64, RP_NUMWD), REG_HRO}, {0} }; @@ -500,22 +434,20 @@ DEVICE rpc_dev = { #if (NUM_DEVS_RP > 3) REG rpd_reg[] = { - {ORDATA(IVECT, rp_ivect[3], 18)}, - {FLDATA(IMODE, rp_imode[3], 0)}, - {ORDATA(XFER, rp_xfer_drive[3], 3), REG_HRO}, - {ORDATA(DRIVE, rp_drive[3], 3), REG_HRO}, - {ORDATA(REG, rp_reg[3], 6), REG_RO}, - {ORDATA(RAE, rp_rae[3], 8), REG_RO}, - {ORDATA(ATTN, rp_attn[3], 8), REG_RO}, - {ORDATA(STATUS, rp_df10[3].status, 18), REG_RO}, - {ORDATA(CIA, rp_df10[3].cia, 18)}, - {ORDATA(CCW, rp_df10[3].ccw, 18)}, - {ORDATA(WCR, rp_df10[3].wcr, 18)}, - {ORDATA(CDA, rp_df10[3].cda, 18)}, - {ORDATA(DEVNUM, rp_df10[3].devnum, 9), REG_HRO}, - {ORDATA(BUF, rp_df10[3].buf, 36), REG_HRO}, - {ORDATA(NXM, rp_df10[3].nxmerr, 8), REG_HRO}, - {ORDATA(COMP, rp_df10[3].ccw_comp, 8), REG_HRO}, + {ORDATA(IVECT, rp_rh[3].ivect, 18)}, + {FLDATA(IMODE, rp_rh[3].imode, 0)}, + {ORDATA(XFER, rp_rh[3].xfer_drive, 3), REG_HRO}, + {ORDATA(DRIVE, rp_rh[3].drive, 3), REG_HRO}, + {ORDATA(REG, rp_rh[3].reg, 6), REG_RO}, + {ORDATA(RAE, rp_rh[3].rae, 8), REG_RO}, + {ORDATA(ATTN, rp_rh[3].attn, 8), REG_RO}, + {ORDATA(STATUS, rp_rh[3].status, 18), REG_RO}, + {ORDATA(CIA, rp_rh[3].cia, 18)}, + {ORDATA(CCW, rp_rh[3].ccw, 18)}, + {ORDATA(WCR, rp_rh[3].wcr, 18)}, + {ORDATA(CDA, rp_rh[3].cda, 18)}, + {ORDATA(DEVNUM, rp_rh[3].devnum, 9), REG_HRO}, + {ORDATA(BUF, rp_rh[3].buf, 36), REG_HRO}, {BRDATA(BUFF, &rp_buf[3][0], 16, 64, RP_NUMWD), REG_HRO}, {0} }; @@ -546,214 +478,48 @@ DEVICE *rp_devs[] = { }; -t_stat rp_devio(uint32 dev, uint64 *data) { - int ctlr = -1; - DEVICE *dptr = NULL; - struct df10 *df10; - int drive; - - for (drive = 0; rh[drive].dev_num != 0; drive++) { - if (rh[drive].dev_num == (dev & 0774)) { - dptr = rh[drive].dev; - break; - } - } - if (dptr == NULL) - return SCPE_OK; - ctlr = GET_CNTRL(dptr->units[0].flags); - df10 = &rp_df10[ctlr]; - df10->devnum = dev; - switch(dev & 3) { - case CONI: - *data = df10->status & ~(IADR_ATTN|IARD_RAE); - if (rp_attn[ctlr] != 0 && (df10->status & IADR_ATTN)) - *data |= IADR_ATTN; - if (rp_rae[ctlr] != 0 && (df10->status & IARD_RAE)) - *data |= IARD_RAE; -#if KI_22BIT - *data |= B22_FLAG; -#endif - sim_debug(DEBUG_CONI, dptr, "RP %03o CONI %06o PC=%o %o\n", - dev, (uint32)*data, PC, rp_attn[ctlr]); - return SCPE_OK; - - case CONO: - clr_interrupt(dev); - df10->status &= ~(07LL|IADR_ATTN|IARD_RAE); - df10->status |= *data & (07LL|IADR_ATTN|IARD_RAE); - /* Clear flags */ - if (*data & CONT_RESET) { - UNIT *uptr=dptr->units; - for(drive = 0; drive < NUM_UNITS_RP; drive++, uptr++) { - uptr->CMD &= DS_MOL|DS_WRL|DS_DPR|DS_DRY|DS_VV|076; - uptr->DA &= 003400177777; - uptr->CCYL &= 0177777; - uptr->ERR2 = 0; - uptr->ERR3 = 0; - } - } - if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)) - df10->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)); - if (*data & OVER_CLR) - df10->status &= ~(DTC_OVER); - if (*data & CBOV_CLR) - df10->status &= ~(DIB_CBOV); - if (*data & CXR_ILC) - df10->status &= ~(CXR_ILFC|CXR_SD_RAE); - if (*data & WRT_CW) - df10_writecw(df10); - if (*data & PI_ENABLE) - df10->status &= ~PI_ENABLE; - if (df10->status & PI_ENABLE) - set_interrupt(dev, df10->status); - if ((df10->status & IADR_ATTN) != 0 && rp_attn[ctlr] != 0) - set_interrupt(dev, df10->status); - sim_debug(DEBUG_CONO, dptr, "RP %03o CONO %06o %d PC=%06o %06o\n", - dev, (uint32)*data, ctlr, PC, df10->status); - return SCPE_OK; - - case DATAI: - *data = 0; - if (df10->status & BUSY && rp_reg[ctlr] != 04) { - df10->status |= CC_CHAN_ACT; - return SCPE_OK; - } - if (rp_reg[ctlr] == 040) { - *data = (uint64)(rp_read(ctlr, rp_drive[ctlr], 0) & 077); - *data |= ((uint64)(df10->cia)) << 6; - *data |= ((uint64)(rp_xfer_drive[ctlr])) << 18; - } else if (rp_reg[ctlr] == 044) { - *data = (uint64)rp_ivect[ctlr]; - if (rp_imode[ctlr]) - *data |= IRQ_KI10; - else - *data |= IRQ_KA10; - } else if (rp_reg[ctlr] == 054) { - *data = (uint64)(rp_rae[ctlr]); - } else if ((rp_reg[ctlr] & 040) == 0) { - int parity; - *data = (uint64)(rp_read(ctlr, rp_drive[ctlr], rp_reg[ctlr]) & 0177777); - parity = (int)((*data >> 8) ^ *data); - parity = (parity >> 4) ^ parity; - parity = (parity >> 2) ^ parity; - parity = ((parity >> 1) ^ parity) & 1; - *data |= ((uint64)(parity ^ 1)) << 17; - *data |= ((uint64)(rp_drive[ctlr])) << 18; - } - *data |= ((uint64)(rp_reg[ctlr])) << 30; - sim_debug(DEBUG_DATAIO, dptr, "RP %03o DATI %012llo, %d %d PC=%06o\n", - dev, *data, ctlr, rp_drive[ctlr], PC); - return SCPE_OK; - - case DATAO: - sim_debug(DEBUG_DATAIO, dptr, "RP %03o DATO %012llo, %d PC=%06o %06o\n", - dev, *data, ctlr, PC, df10->status); - rp_reg[ctlr] = ((int)(*data >> 30)) & 077; - if (rp_reg[ctlr] < 040 && rp_reg[ctlr] != 04) { - rp_drive[ctlr] = (int)(*data >> 18) & 07; - } - if (*data & LOAD_REG) { - if (rp_reg[ctlr] == 040) { - if ((*data & 1) == 0) { - return SCPE_OK; - } - - if (df10->status & BUSY) { - df10->status |= CC_CHAN_ACT; - return SCPE_OK; - } - - df10->status &= ~(1 << df10->ccw_comp); - df10->status &= ~PI_ENABLE; - if (((*data >> 1) & 037) < FNC_XFER) { - df10->status |= CXR_ILC; - df10_setirq(df10); - sim_debug(DEBUG_DATAIO, dptr, - "RP %03o command abort %012llo, %d[%d] PC=%06o %06o\n", - dev, *data, ctlr, rp_drive[ctlr], PC, df10->status); - return SCPE_OK; - } - /* Start command */ - df10_setup(df10, (uint32)(*data >> 6)); - rp_xfer_drive[ctlr] = (int)(*data >> 18) & 07; - rp_write(ctlr, rp_drive[ctlr], 0, (uint32)(*data & 077)); - sim_debug(DEBUG_DATAIO, dptr, - "RP %03o command %012llo, %d[%d] PC=%06o %06o\n", - dev, *data, ctlr, rp_drive[ctlr], PC, df10->status); - } else if (rp_reg[ctlr] == 044) { - /* Set KI10 Irq vector */ - rp_ivect[ctlr] = (int)(*data & IRQ_VECT); - rp_imode[ctlr] = (*data & IRQ_KI10) != 0; - } else if (rp_reg[ctlr] == 050) { - ; /* Diagnostic access to mass bus. */ - } else if (rp_reg[ctlr] == 054) { - /* clear flags */ - rp_rae[ctlr] &= ~(*data & 0377); - if (rp_rae[ctlr] == 0) - clr_interrupt(dev); - } else if ((rp_reg[ctlr] & 040) == 0) { - rp_drive[ctlr] = (int)(*data >> 18) & 07; - /* Check if access error */ - if (rp_rae[ctlr] & (1 << rp_drive[ctlr])) { - return SCPE_OK; - } - rp_write(ctlr, rp_drive[ctlr], rp_reg[ctlr] & 037, - (int)(*data & 0777777)); - } - } - return SCPE_OK; - } - return SCPE_OK; /* Unreached */ -} - -/* Handle KI and KL style interrupt vectors */ -int -rp_devirq(uint32 dev, int addr) { - DEVICE *dptr = NULL; - int drive; - - for (drive = 0; rh[drive].dev_num != 0; drive++) { - if (rh[drive].dev_num == (dev & 0774)) { - dptr = rh[drive].dev; - break; - } - } - if (dptr != NULL) { - drive = GET_CNTRL(dptr->units[0].flags); - return (rp_imode[drive] ? rp_ivect[drive] : addr); - } - return addr; +void +rp_rst(DEVICE *dptr) +{ + UNIT *uptr=dptr->units; + int drive; + for(drive = 0; drive < NUM_UNITS_RP; drive++, uptr++) { + uptr->CMD &= DS_MOL|DS_WRL|DS_DPR|DS_DRY|DS_VV|076; + uptr->DA &= 003400177777; + uptr->CCYL &= 0177777; + uptr->ERR2 = 0; + uptr->ERR3 = 0; + } } void -rp_write(int ctlr, int unit, int reg, uint32 data) { +rp_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { int i; - DEVICE *dptr = rp_devs[ctlr]; + int unit = rhc->drive; UNIT *uptr = &dptr->units[unit]; - struct df10 *df10 = &rp_df10[ctlr]; int dtype = GET_DTYPE(uptr->flags); - if ((uptr->CMD & CR_GO) && reg != 04) { + if ((uptr->CMD & CS1_GO) && reg != 04) { uptr->CMD |= (ER1_RMR << 16)|DS_ERR; return; } switch(reg) { case 000: /* control */ - sim_debug(DEBUG_DETAIL, dptr, "RP%o %d Status=%06o\n", unit, ctlr, uptr->CMD); + sim_debug(DEBUG_DETAIL, dptr, "%s%o Status=%06o\n", dptr->name, unit, uptr->CMD); /* Set if drive not writable */ if (uptr->flags & UNIT_WLK) uptr->CMD |= DS_WRL; /* If drive not ready don't do anything */ if ((uptr->CMD & DS_DRY) == 0) { uptr->CMD |= (ER1_RMR << 16)|DS_ERR; - sim_debug(DEBUG_DETAIL, dptr, "RP%o %d not ready\n", unit, ctlr); + sim_debug(DEBUG_DETAIL, dptr, "%s%o not ready\n", dptr->name, unit); return; } /* Check if GO bit set */ if ((data & 1) == 0) { uptr->CMD &= ~076; uptr->CMD |= data & 076; - sim_debug(DEBUG_DETAIL, dptr, "RP%o %d no go\n", unit, ctlr); + sim_debug(DEBUG_DETAIL, dptr, "%s%o no go\n", dptr->name, unit); return; /* No, nop */ } uptr->CMD &= DS_ATA|DS_VV|DS_DPR|DS_MOL|DS_WRL; @@ -785,16 +551,13 @@ rp_write(int ctlr, int unit, int reg, uint32 data) { if (GET_CY(uptr->DA) >= rp_drv_tab[dtype].cyl || GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) { - rp_attn[ctlr] &= ~(1<attn &= ~(1<CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA; uptr->CMD &= ~DS_PIP; - df10->status &= ~BUSY; - if ((df10->status & IADR_ATTN) != 0 && rp_attn[ctlr] != 0) - df10_setirq(df10); break; } - uptr->CMD |= CR_GO; + uptr->CMD |= CS1_GO; CLR_BUF(uptr); uptr->DATAPTR = 0; break; @@ -802,14 +565,12 @@ rp_write(int ctlr, int unit, int reg, uint32 data) { case FNC_DCLR: /* drive clear */ uptr->CMD |= DS_DRY; - uptr->CMD &= ~(DS_ATA|CR_GO); + uptr->CMD &= ~(DS_ATA|CS1_GO); uptr->DA &= 003400177777; uptr->CCYL &= 0177777; uptr->ERR2 = 0; uptr->ERR3 = 0; - rp_attn[ctlr] &= ~(1<status & IADR_ATTN) != 0 && rp_attn[ctlr] != 0) - df10_setirq(df10); + rhc->attn &= ~(1<flags & UNIT_ATT) != 0) uptr->CMD |= DS_VV; uptr->CMD |= DS_DRY; - if ((df10->status & IADR_ATTN) != 0 && rp_attn[ctlr] != 0) - df10_setirq(df10); break; default: uptr->CMD |= DS_DRY|DS_ERR|DS_ATA; uptr->CMD |= (ER1_ILF << 16); - rp_attn[ctlr] |= (1<status & IADR_ATTN) != 0 && rp_attn[ctlr] != 0) - df10_setirq(df10); + rhc->attn |= (1<CMD & CR_GO) + if (uptr->CMD & CS1_GO) sim_activate(uptr, 1000); - clr_interrupt(df10->devnum); - if ((df10->status & (IADR_ATTN|BUSY)) == IADR_ATTN && rp_attn[ctlr] != 0) - df10_setirq(df10); - sim_debug(DEBUG_DETAIL, dptr, "RP%o AStatus=%06o\n", unit, uptr->CMD); + sim_debug(DEBUG_DETAIL, dptr, "%s%o AStatus=%06o\n", dptr->name, unit, uptr->CMD); return; case 001: /* status */ break; @@ -855,14 +609,11 @@ rp_write(int ctlr, int unit, int reg, uint32 data) { case 004: /* atten summary */ for (i = 0; i < 8; i++) { if (data & (1<units[i]; + u->CMD &= ~DS_ATA; + rhc->attn &= ~(1<devnum); break; case 005: /* sector/track */ uptr->DA &= 0177777; @@ -898,15 +649,14 @@ rp_write(int ctlr, int unit, int reg, uint32 data) { break; default: uptr->CMD |= (ER1_ILR<<16)|DS_ERR; - rp_rae[ctlr] &= ~(1<rae |= 1 << unit; } } uint32 -rp_read(int ctlr, int unit, int reg) { - DEVICE *dptr = rp_devs[ctlr]; +rp_read(DEVICE *dptr, struct rh_if *rhc, int reg) { + int unit = rhc->drive; UNIT *uptr = &dptr->units[unit]; - struct df10 *df10; uint32 temp = 0; int i; @@ -915,11 +665,10 @@ rp_read(int ctlr, int unit, int reg) { } switch(reg) { case 000: /* control */ - df10 = &rp_df10[ctlr]; temp = uptr->CMD & 076; if (uptr->flags & UNIT_ATT) temp |= CS1_DVA; - if (df10->status & BUSY || uptr->CMD & CR_GO) + if (uptr->CMD & CS1_GO) temp |= CS1_GO; break; case 001: /* status */ @@ -932,7 +681,8 @@ rp_read(int ctlr, int unit, int reg) { break; case 004: /* atten summary */ for (i = 0; i < 8; i++) { - if (rp_unit[(ctlr * 8) + i].CMD & DS_ATA) { + UNIT *u = &dptr->units[i]; + if (u->CMD & DS_ATA) { temp |= 1 << i; } } @@ -953,7 +703,8 @@ rp_read(int ctlr, int unit, int reg) { temp = uptr->CCYL & 0177777; break; case 010: /* serial no */ - temp = (020 * ctlr) + (unit + 1); + i = GET_CNTRL_RH(uptr->flags); + temp = (020 * i) + (unit + 1); break; case 014: /* error register 2 */ temp = uptr->ERR2; @@ -967,7 +718,7 @@ rp_read(int ctlr, int unit, int reg) { break; default: uptr->CMD |= (ER1_ILR<<16); - rp_rae[ctlr] &= ~(1<rae |= 1 << unit; } return temp; } @@ -975,31 +726,29 @@ rp_read(int ctlr, int unit, int reg) { t_stat rp_svc (UNIT *uptr) { - int dtype = GET_DTYPE(uptr->flags); - int ctlr = GET_CNTRL(uptr->flags); - int unit; - DEVICE *dptr; - struct df10 *df; - int cyl = GET_CY(uptr->DA); - int diff, da; - t_stat r; + int dtype = GET_DTYPE(uptr->flags); + int ctlr = GET_CNTRL_RH(uptr->flags); + int cyl = GET_CY(uptr->DA); + int unit; + DEVICE *dptr; + struct rh_if *rhc; + int diff, da; + t_stat r; - /* Find dptr, and df10 */ dptr = rp_devs[ctlr]; + rhc = &rp_rh[ctlr]; unit = uptr - dptr->units; - df = &rp_df10[ctlr]; if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ uptr->CMD |= (ER1_UNS << 16) | DS_ATA|DS_ERR; /* set drive error */ if (GET_FNC(uptr->CMD) >= FNC_XFER) { /* xfr? set done */ - df->status &= ~BUSY; - df10_setirq(df); + rh_setirq(rhc); } return (SCPE_OK); } /* Check if seeking */ if (uptr->CMD & DS_PIP) { - sim_debug(DEBUG_DETAIL, dptr, "RP%o seek %d %d\n", unit, cyl, uptr->CCYL); + sim_debug(DEBUG_DETAIL, dptr, "%s%o seek %d %d\n", dptr->name, unit, cyl, uptr->CCYL); if (cyl >= rp_drv_tab[dtype].cyl) { uptr->CMD &= ~DS_PIP; uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA; @@ -1054,31 +803,27 @@ t_stat rp_svc (UNIT *uptr) if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) uptr->CMD |= (ER1_IAE << 16)|DS_ERR; - rp_attn[ctlr] |= 1<CMD |= DS_DRY|DS_ATA; - uptr->CMD &= ~CR_GO; - if ((df->status & (IADR_ATTN|BUSY)) == IADR_ATTN) - df10_setirq(df); - sim_debug(DEBUG_DETAIL, dptr, "RP%o seekdone %d %o\n", unit, cyl, uptr->CMD); + uptr->CMD &= ~CS1_GO; + rh_setattn(rhc, unit); + sim_debug(DEBUG_DETAIL, dptr, "%s%o seekdone %d %o\n", dptr->name, unit, cyl, uptr->CMD); break; case FNC_SEARCH: /* search */ if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) uptr->CMD |= (ER1_IAE << 16)|DS_ERR; - rp_attn[ctlr] |= 1<CMD |= DS_DRY|DS_ATA; - uptr->CMD &= ~CR_GO; - if ((df->status & (IADR_ATTN|BUSY)) == IADR_ATTN) - df10_setirq(df); - sim_debug(DEBUG_DETAIL, dptr, "RP%o searchdone %d %o\n", unit, cyl, uptr->CMD); + uptr->CMD &= ~CS1_GO; + rh_setattn(rhc, unit); + sim_debug(DEBUG_DETAIL, dptr, "%s%o searchdone %d %o\n", dptr->name, unit, cyl, uptr->CMD); break; case FNC_READ: /* read */ case FNC_READH: /* read w/ headers */ case FNC_WCHK: /* write check */ if (uptr->CMD & DS_ERR) { - sim_debug(DEBUG_DETAIL, dptr, "RP%o read error\n", unit); + sim_debug(DEBUG_DETAIL, dptr, "%s%o read error\n", dptr->name, unit); goto rd_end; } @@ -1088,12 +833,12 @@ t_stat rp_svc (UNIT *uptr) if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) { uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA; - uptr->CMD &= ~CR_GO; - df10_finish_op(df, 0); - sim_debug(DEBUG_DETAIL, dptr, "RP%o readx done\n", unit); + uptr->CMD &= ~CS1_GO; + rh_finish_op(rhc, 0); + sim_debug(DEBUG_DETAIL, dptr, "%s%o readx done\n", dptr->name, unit); return SCPE_OK; } - sim_debug(DEBUG_DETAIL, dptr, "RP%o read (%d,%d,%d)\n", unit, cyl, + sim_debug(DEBUG_DETAIL, dptr, "%s%o read (%d,%d,%d)\n", dptr->name, unit, cyl, GET_SF(uptr->DA), GET_SC(uptr->DA)); da = GET_DA(uptr->DA, dtype) * RP_NUMWD; (void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); @@ -1105,24 +850,24 @@ t_stat rp_svc (UNIT *uptr) uptr->DATAPTR = 0; /* On read headers, transfer 2 words to start */ if (GET_FNC(uptr->CMD) == FNC_READH) { - df->buf = (((uint64)cyl) << 18) | + rhc->buf = (((uint64)cyl) << 18) | ((uint64)((GET_SF(uptr->DA) << 8) | GET_SF(uptr->DA))); - sim_debug(DEBUG_DATA, dptr, "RP%o read word h1 %012llo %09o %06o\n", - unit, df->buf, df->cda, df->wcr); - if (df10_write(df) == 0) + sim_debug(DEBUG_DATA, dptr, "%s%o read word h1 %012llo %09o %06o\n", + dptr->name, unit, rhc->buf, rhc->cda, rhc->wcr); + if (rh_write(rhc) == 0) goto rd_end; - df->buf = ((uint64)((020 * ctlr) + (unit + 1)) << 18) | (uint64)(unit); - sim_debug(DEBUG_DATA, dptr, "RP%o read word h2 %012llo %09o %06o\n", - unit, df->buf, df->cda, df->wcr); - if (df10_write(df) == 0) + rhc->buf = ((uint64)((020 * ctlr) + (unit + 1)) << 18) | (uint64)(unit); + sim_debug(DEBUG_DATA, dptr, "%s%o read word h2 %012llo %09o %06o\n", + dptr->name, unit, rhc->buf, rhc->cda, rhc->wcr); + if (rh_write(rhc) == 0) goto rd_end; } } - df->buf = rp_buf[ctlr][uptr->DATAPTR++]; - sim_debug(DEBUG_DATA, dptr, "RP%o read word %d %012llo %09o %06o\n", - unit, uptr->DATAPTR, df->buf, df->cda, df->wcr); - if (df10_write(df)) { + rhc->buf = rp_buf[ctlr][uptr->DATAPTR++]; + sim_debug(DEBUG_DATA, dptr, "%s%o read word %d %012llo %09o %06o\n", + dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr); + if (rh_write(rhc)) { if (uptr->DATAPTR == RP_NUMWD) { /* Increment to next sector. Set Last Sector */ uptr->DATAPTR = 0; @@ -1137,14 +882,16 @@ t_stat rp_svc (UNIT *uptr) uptr->CMD |= DS_PIP; } } + if (rh_blkend(rhc)) + goto rd_end; } - sim_activate(uptr, 50); + sim_activate(uptr, 10); } else { rd_end: - sim_debug(DEBUG_DETAIL, dptr, "RP%o read done\n", unit); + sim_debug(DEBUG_DETAIL, dptr, "%s%o read done\n", dptr->name, unit); uptr->CMD |= DS_DRY; - uptr->CMD &= ~CR_GO; - df10_finish_op(df, 0); + uptr->CMD &= ~CS1_GO; + rh_finish_op(rhc, 0); return SCPE_OK; } break; @@ -1152,7 +899,7 @@ rd_end: case FNC_WRITE: /* write */ case FNC_WRITEH: /* write w/ headers */ if (uptr->CMD & DS_ERR) { - sim_debug(DEBUG_DETAIL, dptr, "RP%o read error\n", unit); + sim_debug(DEBUG_DETAIL, dptr, "%s%o read error\n", dptr->name, unit); goto wr_end; } @@ -1160,34 +907,34 @@ rd_end: if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) { uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA; - uptr->CMD &= ~CR_GO; - df10_finish_op(df, 0); - sim_debug(DEBUG_DETAIL, dptr, "RP%o writex done\n", unit); + uptr->CMD &= ~CS1_GO; + rh_finish_op(rhc, 0); + sim_debug(DEBUG_DETAIL, dptr, "%s%o writex done\n", dptr->name, unit); return SCPE_OK; } /* On Write headers, transfer 2 words to start */ if (GET_FNC(uptr->CMD) == FNC_WRITEH) { - if (df10_read(df) == 0) + if (rh_read(rhc) == 0) goto wr_end; - sim_debug(DEBUG_DATA, dptr, "RP%o write word h1 %012llo %06o\n", - unit, df->buf, df->wcr); - if (df10_read(df) == 0) + sim_debug(DEBUG_DATA, dptr, "%s%o write word h1 %012llo %06o\n", + dptr->name, unit, rhc->buf, rhc->wcr); + if (rh_read(rhc) == 0) goto wr_end; - sim_debug(DEBUG_DATA, dptr, "RP%o write word h2 %012llo %06o\n", - unit, df->buf, df->wcr); + sim_debug(DEBUG_DATA, dptr, "%s%o write word h2 %012llo %06o\n", + dptr->name, unit, rhc->buf, rhc->wcr); } uptr->DATAPTR = 0; uptr->hwmark = 0; } - r = df10_read(df); - sim_debug(DEBUG_DATA, dptr, "RP%o write word %d %012llo %06o\n", - unit, uptr->DATAPTR, df->buf, df->wcr); - rp_buf[ctlr][uptr->DATAPTR++] = df->buf; + r = rh_read(rhc); + sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %06o\n", + dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->wcr); + rp_buf[ctlr][uptr->DATAPTR++] = rhc->buf; if (r == 0 || uptr->DATAPTR == RP_NUMWD) { while (uptr->DATAPTR < RP_NUMWD) rp_buf[ctlr][uptr->DATAPTR++] = 0; - sim_debug(DEBUG_DETAIL, dptr, "RP%o write (%d,%d,%d)\n", unit, cyl, - GET_SF(uptr->DA), GET_SC(uptr->DA)); + sim_debug(DEBUG_DETAIL, dptr, "%s%o write (%d,%d,%d)\n", dptr->name, + unit, cyl, GET_SF(uptr->DA), GET_SC(uptr->DA)); da = GET_DA(uptr->DA, dtype) * RP_NUMWD; (void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); (void)sim_fwrite (&rp_buf[ctlr][0], sizeof(uint64), RP_NUMWD, @@ -1205,16 +952,18 @@ rd_end: uptr->CMD |= DS_PIP; } } + if (rh_blkend(rhc)) + goto wr_end; } } if (r) { - sim_activate(uptr, 50); + sim_activate(uptr, 10); } else { wr_end: sim_debug(DEBUG_DETAIL, dptr, "RP%o write done\n", unit); uptr->CMD |= DS_DRY; - uptr->CMD &= ~CR_GO; - df10_finish_op(df, 0); + uptr->CMD &= ~CS1_GO; + rh_finish_op(rhc, 0); return SCPE_OK; } break; @@ -1242,12 +991,10 @@ rp_reset(DEVICE * rptr) { int ctlr; for (ctlr = 0; ctlr < NUM_DEVS_RP; ctlr++) { - rp_df10[ctlr].devnum = rp_dib[ctlr].dev_num; - rp_df10[ctlr].nxmerr = 19; - rp_df10[ctlr].ccw_comp = 14; - rp_df10[ctlr].status = 0; - rp_attn[ctlr] = 0; - rp_rae[ctlr] = 0; + rp_rh[ctlr].devnum = rp_dib[ctlr].dev_num; + rp_rh[ctlr].status = 0; + rp_rh[ctlr].attn = 0; + rp_rh[ctlr].rae = 0; } return SCPE_OK; } @@ -1257,14 +1004,16 @@ t_stat rp_boot(int32 unit_num, DEVICE * rptr) { UNIT *uptr = &rptr->units[unit_num]; - int ctlr = GET_CNTRL(uptr->flags); + int ctlr = GET_CNTRL_RH(uptr->flags); DEVICE *dptr; - struct df10 *df; + struct rh_if *rhc; uint32 addr; uint32 ptr = 0; uint64 word; int wc; + rhc = &rp_rh[ctlr]; + dptr = rp_devs[ctlr]; #if KL int sect; /* KL does not support readin, so fake it by reading in sectors 4 to 7 */ @@ -1280,11 +1029,8 @@ rp_boot(int32 unit_num, DEVICE * rptr) } PC = (MEMSIZE - 512) & RMASK; #else - df = &rp_df10[ctlr]; - dptr = rp_devs[ctlr]; (void)sim_fseek(uptr->fileref, 0, SEEK_SET); (void)sim_fread (&rp_buf[0][0], sizeof(uint64), RP_NUMWD, uptr->fileref); - uptr->CMD |= DS_VV; addr = rp_buf[0][ptr] & RMASK; wc = (rp_buf[0][ptr++] >> 18) & RMASK; while (wc != 0) { @@ -1299,12 +1045,12 @@ rp_boot(int32 unit_num, DEVICE * rptr) addr = rp_buf[0][ptr] & RMASK; wc = (rp_buf[0][ptr++] >> 18) & RMASK; word = rp_buf[0][ptr++]; - - rp_reg[ctlr] = 040; - rp_drive[ctlr] = uptr - dptr->units; - df->status |= CCW_COMP_1|PI_ENABLE; PC = word & RMASK; #endif + uptr->CMD |= DS_VV; + rhc->reg = 040; + rhc->drive = uptr - dptr->units; + rhc->status |= CCW_COMP_1|PI_ENABLE; return SCPE_OK; } @@ -1325,14 +1071,18 @@ t_stat rp_attach (UNIT *uptr, CONST char *cptr) if (rptr == 0) return SCPE_OK; dib = (DIB *) rptr->ctxt; + for (ctlr = 0; rh[ctlr].dev_num != 0; ctlr++) { + if (rh[ctlr].dev == rptr) + break; + } ctlr = dib->dev_num & 014; uptr->DA = 0; uptr->CMD &= ~DS_VV; uptr->CMD |= DS_DPR|DS_MOL|DS_DRY; if (uptr->flags & UNIT_WLK) uptr->CMD |= DS_WRL; - rp_df10[ctlr].status |= PI_ENABLE; - set_interrupt(dib->dev_num, rp_df10[ctlr].status); + rp_rh[ctlr].status |= PI_ENABLE; + set_interrupt(dib->dev_num, rp_rh[ctlr].status); return SCPE_OK; } diff --git a/PDP10/kx10_rs.c b/PDP10/kx10_rs.c index 81fae05..cb7ab6d 100644 --- a/PDP10/kx10_rs.c +++ b/PDP10/kx10_rs.c @@ -42,72 +42,14 @@ #define DTYPE(x) (((x) & UNIT_M_DTYPE) << UNIT_V_DTYPE) #define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) #define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ -#define CNTRL_V_CTYPE (UNIT_V_UF + 4) -#define CNTRL_M_CTYPE 7 -#define GET_CNTRL(x) (((x) >> CNTRL_V_CTYPE) & CNTRL_M_CTYPE) -#define CNTRL(x) (((x) & CNTRL_M_CTYPE) << CNTRL_V_CTYPE) /* Parameters in the unit descriptor */ - -/* CONI Flags */ -#define IADR_ATTN 0000000000040LL /* Interrupt on attention */ -#define IARD_RAE 0000000000100LL /* Interrupt on register access error */ -#define DIB_CBOV 0000000000200LL /* Control bus overrun */ -#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */ -#define CXR_ILC 0000000004000LL /* Illegal function code */ -#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */ -#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */ -#define CCW_COMP_1 0000000040000LL /* Control word written. */ -#define CXR_CHAN_ER 0000000100000LL /* Channel Error */ -#define CXR_EXC 0000000200000LL /* Error in drive transfer */ -#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */ -#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */ -#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */ -#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */ -#define CXR_SD_RAE 0000200000000LL /* Register access error */ -#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */ -#define B22_FLAG 0004000000000LL /* 22 bit channel */ -#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */ -#define CC_CHAN_ACT 0020000000000LL /* Channel in use */ -#define CC_INH 0040000000000LL /* Disconnect channel */ -#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */ -#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */ - -/* CONO Flags */ -#define ATTN_EN 0000000000040LL /* enable attention interrupt. */ -#define REA_EN 0000000000100LL /* enable register error interrupt */ -#define CBOV_CLR 0000000000200LL /* Clear CBOV */ -#define CONT_RESET 0000000002000LL /* Clear All error bits */ -#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */ -#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */ -#define OVER_CLR 0000000020000LL /* Clear DTC overrun */ -#define WRT_CW 0000000040000LL /* Write control word */ -#define CHN_CLR 0000000100000LL /* Clear Channel Error */ -#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */ -#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */ - -/* DATAO/DATAI */ -#define CR_REG 0770000000000LL /* Register number */ -#define LOAD_REG 0004000000000LL /* Load register */ -#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */ -#define CR_DRIVE 0000007000000LL -#define CR_GEN_EVD 0000000400000LL /* Enable Parity */ -#define CR_DXES 0000000200000LL /* Disable DXES errors */ -#define CR_INAD 0000000077600LL -#define CR_WTEVM 0000000000100LL /* Verify Parity */ -#define CR_FUNC 0000000000076LL -#define CR_GO 0000000000001LL - -#define IRQ_VECT 0000000000177LL /* Interupt vector */ -#define IRQ_KI10 0000002000000LL -#define IRQ_KA10 0000001000000LL - #define CMD u3 /* u3 low */ /* RSC - 00 - control */ -#define CS1_GO CR_GO /* go */ +#define CS1_GO 1 /* go */ #define CS1_V_FNC 1 /* function pos */ #define CS1_M_FNC 037 /* function mask */ #define CS1_FNC (CS1_M_FNC << CS1_V_FNC) @@ -228,20 +170,21 @@ struct drvtyp rs_drv_tab[] = { }; -struct df10 rs_df10[NUM_DEVS_RS]; -uint32 rs_xfer_drive[NUM_DEVS_RS]; +//struct df10 rs_df10[NUM_DEVS_RS]; +//uint32 rs_xfer_drive[NUM_DEVS_RS]; uint64 rs_buf[NUM_DEVS_RS][RS_NUMWD]; -int rs_reg[NUM_DEVS_RS]; -int rs_ivect[NUM_DEVS_RS]; -int rs_imode[NUM_DEVS_RS]; -int rs_drive[NUM_DEVS_RS]; -int rs_rae[NUM_DEVS_RS]; -int rs_attn[NUM_DEVS_RS]; +//int rs_reg[NUM_DEVS_RS]; +//int rs_ivect[NUM_DEVS_RS]; +//int rs_imode[NUM_DEVS_RS]; +//int rs_drive[NUM_DEVS_RS]; +//int rs_rae[NUM_DEVS_RS]; +//int rs_attn[NUM_DEVS_RS]; -t_stat rs_devio(uint32 dev, uint64 *data); -int rs_devirq(uint32 dev, int addr); -void rs_write(int ctlr, int unit, int reg, uint32 data); -uint32 rs_read(int ctlr, int unit, int reg); +//t_stat rs_devio(uint32 dev, uint64 *data); +//int rs_devirq(uint32 dev, int addr); +void rs_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data); +uint32 rs_read(DEVICE *dptr, struct rh_if *rhc, int reg); +void rs_rst(DEVICE *dptr); t_stat rs_svc(UNIT *); t_stat rs_boot(int32, DEVICE *); void rs_ini(UNIT *, t_bool); @@ -257,28 +200,38 @@ const char *rs_description (DEVICE *dptr); UNIT rs_unit[] = { /* Controller 1 */ { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, + UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) }, { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, + UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) }, { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, + UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) }, { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, + UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) }, { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, + UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) }, { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, + UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) }, { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, + UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) }, { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ - UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, + UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) }, +}; + +struct rh_if rs_rh[] = { + { &rs_write, &rs_read, &rs_rst}, }; DIB rs_dib[] = { - {RH10_DEV, 1, &rs_devio, &rs_devirq} + {RH10_DEV, 1, &rh_devio, &rh_devirq, &rs_rh[0]} }; MTAB rs_mod[] = { +#if KL + {MTAB_XTD|MTAB_VDV, TYPE_RH10, NULL, "RH10", &rh_set_type, NULL, + NULL, "Sets controller to RH10" }, + {MTAB_XTD|MTAB_VDV, TYPE_RH20, "RH20", "RH20", &rh_set_type, &rh_show_type, + NULL, "Sets controller to RH20"}, +#endif {UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL}, {UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL}, {UNIT_DTYPE, (RS03_DTYPE << UNIT_V_DTYPE), "RS03", "RS03", &rs_set_type }, @@ -287,22 +240,20 @@ MTAB rs_mod[] = { }; REG rsa_reg[] = { - {ORDATA(IVECT, rs_ivect[0], 18)}, - {FLDATA(IMODE, rs_imode[0], 0)}, - {ORDATA(XFER, rs_xfer_drive[0], 3), REG_HRO}, - {ORDATA(DRIVE, rs_drive[0], 3), REG_HRO}, - {ORDATA(REG, rs_reg[0], 6), REG_RO}, - {ORDATA(RAE, rs_rae[0], 8), REG_RO}, - {ORDATA(ATTN, rs_attn[0], 8), REG_RO}, - {ORDATA(STATUS, rs_df10[0].status, 18), REG_RO}, - {ORDATA(CIA, rs_df10[0].cia, 18)}, - {ORDATA(CCW, rs_df10[0].ccw, 18)}, - {ORDATA(WCR, rs_df10[0].wcr, 18)}, - {ORDATA(CDA, rs_df10[0].cda, 18)}, - {ORDATA(DEVNUM, rs_df10[0].devnum, 9), REG_HRO}, - {ORDATA(BUF, rs_df10[0].buf, 36), REG_HRO}, - {ORDATA(NXM, rs_df10[0].nxmerr, 8), REG_HRO}, - {ORDATA(COMP, rs_df10[0].ccw_comp, 8), REG_HRO}, + {ORDATA(IVECT, rs_rh[0].ivect, 18)}, + {FLDATA(IMODE, rs_rh[0].imode, 0)}, + {ORDATA(XFER, rs_rh[0].xfer_drive, 3), REG_HRO}, + {ORDATA(DRIVE, rs_rh[0].drive, 3), REG_HRO}, + {ORDATA(REG, rs_rh[0].reg, 6), REG_RO}, + {ORDATA(RAE, rs_rh[0].rae, 8), REG_RO}, + {ORDATA(ATTN, rs_rh[0].attn, 8), REG_RO}, + {ORDATA(STATUS, rs_rh[0].status, 18), REG_RO}, + {ORDATA(CIA, rs_rh[0].cia, 18)}, + {ORDATA(CCW, rs_rh[0].ccw, 18)}, + {ORDATA(WCR, rs_rh[0].wcr, 18)}, + {ORDATA(CDA, rs_rh[0].cda, 18)}, + {ORDATA(DEVNUM, rs_rh[0].devnum, 9), REG_HRO}, + {ORDATA(BUF, rs_rh[0].buf, 36), REG_HRO}, {BRDATA(BUFF, &rs_buf[0][0], 16, 64, RS_NUMWD), REG_HRO}, {0} }; @@ -320,213 +271,44 @@ DEVICE *rs_devs[] = { }; -t_stat rs_devio(uint32 dev, uint64 *data) { - int ctlr = -1; - DEVICE *dptr = NULL; - struct df10 *df10; - int drive; - - for (drive = 0; rh[drive].dev_num != 0; drive++) { - if (rh[drive].dev_num == (dev & 0774)) { - dptr = rh[drive].dev; - break; - } - } - if (dptr == NULL) - return SCPE_OK; - ctlr = GET_CNTRL(dptr->units[0].flags); - df10 = &rs_df10[ctlr]; - df10->devnum = dev; - switch(dev & 3) { - case CONI: - *data = df10->status & ~(IADR_ATTN|IARD_RAE); - if (rs_attn[ctlr] != 0 && (df10->status & IADR_ATTN)) - *data |= IADR_ATTN; - if (rs_rae[ctlr] != 0 && (df10->status & IARD_RAE)) - *data |= IARD_RAE; -#if KI_22BIT - *data |= B22_FLAG; -#endif - sim_debug(DEBUG_CONI, dptr, "RS %03o CONI %06o PC=%o %o\n", - dev, (uint32)*data, PC, rs_attn[ctlr]); - return SCPE_OK; - - case CONO: - clr_interrupt(dev); - df10->status &= ~(07LL|IADR_ATTN|IARD_RAE); - df10->status |= *data & (07LL|IADR_ATTN|IARD_RAE); - /* Clear flags */ - if (*data & CONT_RESET) { - UNIT *uptr=dptr->units; - for(drive = 0; drive < NUM_UNITS_RS; drive++, uptr++) { - uptr->CMD &= DS_MOL|DS_WRL|DS_DPR|DS_DRY|DS_VV|076; - uptr->DA &= 003400177777; - } - } - if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)) - df10->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)); - if (*data & OVER_CLR) - df10->status &= ~(DTC_OVER); - if (*data & CBOV_CLR) - df10->status &= ~(DIB_CBOV); - if (*data & CXR_ILC) - df10->status &= ~(CXR_ILFC|CXR_SD_RAE); - if (*data & WRT_CW) - df10_writecw(df10); - if (*data & PI_ENABLE) - df10->status &= ~PI_ENABLE; - if (df10->status & PI_ENABLE) - set_interrupt(dev, df10->status); - if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0) - set_interrupt(dev, df10->status); - sim_debug(DEBUG_CONO, dptr, "RS %03o CONO %06o %d PC=%06o %06o\n", - dev, (uint32)*data, ctlr, PC, df10->status); - return SCPE_OK; - - case DATAI: - *data = 0; - if (df10->status & BUSY && rs_reg[ctlr] != 04) { - df10->status |= CC_CHAN_ACT; - return SCPE_OK; - } - if (rs_reg[ctlr] == 040) { - *data = (uint64)(rs_read(ctlr, rs_drive[ctlr], 0) & 077); - *data |= ((uint64)(df10->cia)) << 6; - *data |= ((uint64)(rs_xfer_drive[ctlr])) << 18; - } else if (rs_reg[ctlr] == 044) { - *data = (uint64)rs_ivect[ctlr]; - if (rs_imode[ctlr]) - *data |= IRQ_KI10; - else - *data |= IRQ_KA10; - } else if (rs_reg[ctlr] == 054) { - *data = (uint64)(rs_rae[ctlr]); - } else if ((rs_reg[ctlr] & 040) == 0) { - int parity; - - *data = (uint64)(rs_read(ctlr, rs_drive[ctlr], rs_reg[ctlr]) & 0177777); - parity = (int)((*data >> 8) ^ *data); - parity = (parity >> 4) ^ parity; - parity = (parity >> 2) ^ parity; - parity = ((parity >> 1) ^ parity) & 1; - *data |= ((uint64)(parity ^ 1)) << 17; - *data |= ((uint64)(rs_drive[ctlr])) << 18; - } - *data |= ((uint64)(rs_reg[ctlr])) << 30; - sim_debug(DEBUG_DATAIO, dptr, "RS %03o DATI %012llo, %d %d PC=%06o\n", - dev, *data, ctlr, rs_drive[ctlr], PC); - return SCPE_OK; - - case DATAO: - sim_debug(DEBUG_DATAIO, dptr, "RS %03o DATO %012llo, %d PC=%06o %06o\n", - dev, *data, ctlr, PC, df10->status); - rs_reg[ctlr] = ((int)(*data >> 30)) & 077; - if (rs_reg[ctlr] < 040 && rs_reg[ctlr] != 04) { - rs_drive[ctlr] = (int)(*data >> 18) & 07; - } - if (*data & LOAD_REG) { - if (rs_reg[ctlr] == 040) { - if ((*data & 1) == 0) { - return SCPE_OK; - } - - if (df10->status & BUSY) { - df10->status |= CC_CHAN_ACT; - return SCPE_OK; - } - - df10->status &= ~(1 << df10->ccw_comp); - df10->status &= ~PI_ENABLE; - if (((*data >> 1) & 077) < FNC_XFER) { - df10->status |= CXR_ILC; - df10_setirq(df10); - sim_debug(DEBUG_DATAIO, dptr, - "RS %03o command abort %012llo, %d[%d] PC=%06o %06o\n", - dev, *data, ctlr, rs_drive[ctlr], PC, df10->status); - return SCPE_OK; - } - - /* Start command */ - df10_setup(df10, (uint32)(*data >> 6)); - rs_xfer_drive[ctlr] = (int)(*data >> 18) & 07; - rs_write(ctlr, rs_drive[ctlr], 0, (uint32)(*data & 077)); - sim_debug(DEBUG_DATAIO, dptr, - "RS %03o command %012llo, %d[%d] PC=%06o %06o\n", - dev, *data, ctlr, rs_drive[ctlr], PC, df10->status); - } else if (rs_reg[ctlr] == 044) { - /* Set KI10 Irq vector */ - rs_ivect[ctlr] = (int)(*data & IRQ_VECT); - rs_imode[ctlr] = (*data & IRQ_KI10) != 0; - } else if (rs_reg[ctlr] == 050) { - ; /* Diagnostic access to mass bus. */ - } else if (rs_reg[ctlr] == 054) { - /* clear flags */ - rs_rae[ctlr] &= ~(*data & 0377); - if (rs_rae[ctlr] == 0) - clr_interrupt(dev); - } else if ((rs_reg[ctlr] & 040) == 0) { - rs_drive[ctlr] = (int)(*data >> 18) & 07; - /* Check if access error */ - if (rs_rae[ctlr] & (1 << rs_drive[ctlr])) { - return SCPE_OK; - } - rs_drive[ctlr] = (int)(*data >> 18) & 07; - rs_write(ctlr, rs_drive[ctlr], rs_reg[ctlr] & 037, - (int)(*data & 0777777)); - } - } - return SCPE_OK; - } - return SCPE_OK; /* Unreached */ -} - -/* Handle KI and KL style interrupt vectors */ -int -rs_devirq(uint32 dev, int addr) { - DEVICE *dptr = NULL; - int drive; - - for (drive = 0; rh[drive].dev_num != 0; drive++) { - if (rh[drive].dev_num == (dev & 0774)) { - dptr = rh[drive].dev; - break; - } - } - if (dptr != NULL) { - drive = GET_CNTRL(dptr->units[0].flags); - return (rs_imode[drive] ? rs_ivect[drive] : addr); - } - return addr; +void +rs_rst(DEVICE *dptr) +{ + UNIT *uptr=dptr->units; + int drive; + for(drive = 0; drive < NUM_UNITS_RS; drive++, uptr++) { + uptr->CMD &= DS_MOL|DS_WRL|DS_DPR|DS_DRY|DS_VV|076; + uptr->DA &= 003400177777; + } } void -rs_write(int ctlr, int unit, int reg, uint32 data) { +rs_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { int i; - DEVICE *dptr = rs_devs[ctlr]; - struct df10 *df10 = &rs_df10[ctlr]; + int unit = rhc->drive; UNIT *uptr = &dptr->units[unit]; - if ((uptr->CMD & CR_GO) && reg != 04) { + if ((uptr->CMD & CS1_GO) && reg != 04) { uptr->CMD |= (ER1_RMR << 16)|DS_ERR; return; } switch(reg) { case 000: /* control */ - sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d Status=%06o\n", unit, ctlr, uptr->CMD); + sim_debug(DEBUG_DETAIL, dptr, "%s%o Status=%06o\n", dptr->name, unit, uptr->CMD); /* Set if drive not writable */ if (uptr->flags & UNIT_WLK) uptr->CMD |= DS_WRL; /* If drive not ready don't do anything */ if ((uptr->CMD & DS_DRY) == 0) { uptr->CMD |= (ER1_RMR << 16)|DS_ERR; - sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d busy\n", unit, ctlr); + sim_debug(DEBUG_DETAIL, dptr, "%s%o busy\n", dptr->name, unit); return; } /* Check if GO bit set */ if ((data & 1) == 0) { uptr->CMD &= ~076; uptr->CMD |= data & 076; - sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d no go\n", unit, ctlr); + sim_debug(DEBUG_DETAIL, dptr, "%s%o no go\n", dptr->name, unit); return; /* No, nop */ } uptr->CMD &= DS_ATA|DS_VV|DS_DPR|DS_MOL|DS_WRL; @@ -540,7 +322,7 @@ rs_write(int ctlr, int unit, int reg, uint32 data) { case FNC_WCHK: /* write check */ case FNC_WRITE: /* write */ case FNC_READ: /* read */ - uptr->CMD |= DS_PIP|CR_GO; + uptr->CMD |= DS_PIP|CS1_GO; uptr->DATAPTR = 0; break; @@ -549,30 +331,26 @@ rs_write(int ctlr, int unit, int reg, uint32 data) { if ((uptr->flags & UNIT_ATT) != 0) uptr->CMD |= DS_VV; uptr->CMD |= DS_DRY; - df10_setirq(df10); + rh_setirq(rhc); break; case FNC_DCLR: /* drive clear */ uptr->CMD |= DS_DRY; - uptr->CMD &= ~(DS_ATA|CR_GO); - rs_attn[ctlr] = 0; - clr_interrupt(df10->devnum); + uptr->CMD &= ~(DS_ATA|CS1_GO); + rhc->attn = 0; + clr_interrupt(rhc->devnum); for (i = 0; i < 8; i++) { - if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA) - rs_attn[ctlr] = 1; + if (dptr->units[i].CMD & DS_ATA) + rhc->attn |= 1 << i; } - if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0) - df10_setirq(df10); break; default: uptr->CMD |= DS_DRY|DS_ERR|DS_ATA; uptr->CMD |= (ER1_ILF << 16); - if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0) - df10_setirq(df10); } - if (uptr->CMD & CR_GO) + if (uptr->CMD & CS1_GO) sim_activate(uptr, 100); - sim_debug(DEBUG_DETAIL, dptr, "RSA%o AStatus=%06o\n", unit, uptr->CMD); + sim_debug(DEBUG_DETAIL, dptr, "%s%o AStatus=%06o\n", dptr->name, unit, uptr->CMD); return; case 001: /* status */ break; @@ -585,17 +363,13 @@ rs_write(int ctlr, int unit, int reg, uint32 data) { case 003: /* maintenance */ break; case 004: /* atten summary */ - rs_attn[ctlr] = 0; + rhc->attn = 0; for (i = 0; i < 8; i++) { if (data & (1<units[i].CMD &= ~DS_ATA; + if (dptr->units[i].CMD & DS_ATA) + rhc->attn |= 1 << i; } - clr_interrupt(df10->devnum); - if (((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0) || - (df10->status & PI_ENABLE)) - df10_setirq(df10); break; case 005: /* sector/track */ uptr->DA = data & 0177777; @@ -605,14 +379,13 @@ rs_write(int ctlr, int unit, int reg, uint32 data) { break; default: uptr->CMD |= (ER1_ILR<<16)|DS_ERR; - rs_rae[ctlr] &= ~(1<rae |= 1 << unit; } } uint32 -rs_read(int ctlr, int unit, int reg) { - DEVICE *dptr = rs_devs[ctlr]; - struct df10 *df10 = &rs_df10[ctlr]; +rs_read(DEVICE *dptr, struct rh_if *rhc, int reg) { + int unit = rhc->drive; UNIT *uptr = &dptr->units[unit]; uint32 temp = 0; int i; @@ -626,7 +399,7 @@ rs_read(int ctlr, int unit, int reg) { temp = uptr->CMD & 077; if (uptr->flags & UNIT_ATT) temp |= CS1_DVA; - if ((df10->status & BUSY) == 0 && (uptr->CMD & CR_GO) == 0) + if ((uptr->CMD & CS1_GO) == 0) temp |= CS1_GO; break; case 001: /* status */ @@ -637,7 +410,7 @@ rs_read(int ctlr, int unit, int reg) { break; case 004: /* atten summary */ for (i = 0; i < 8; i++) { - if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA) { + if (dptr->units[i].CMD & DS_ATA) { temp |= 1 << i; } } @@ -653,7 +426,7 @@ rs_read(int ctlr, int unit, int reg) { break; default: uptr->CMD |= (ER1_ILR<<16); - rs_rae[ctlr] &= ~(1<rae |= 1 << unit; } return temp; } @@ -661,22 +434,21 @@ rs_read(int ctlr, int unit, int reg) { t_stat rs_svc (UNIT *uptr) { - int dtype = GET_DTYPE(uptr->flags); - int ctlr = GET_CNTRL(uptr->flags); - int unit; - DEVICE *dptr; - struct df10 *df; - int da; - t_stat r; + int dtype = GET_DTYPE(uptr->flags); + int ctlr = GET_CNTRL_RH(uptr->flags); + int unit; + DEVICE *dptr; + struct rh_if *rhc; + int da; + t_stat r; /* Find dptr, and df10 */ dptr = rs_devs[ctlr]; + rhc = &rs_rh[ctlr]; unit = uptr - dptr->units; - df = &rs_df10[ctlr]; if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ uptr->CMD |= (ER1_UNS << 16) | DS_ATA|DS_ERR; /* set drive error */ - df->status &= ~BUSY; - df10_setirq(df); + rh_setirq(rhc); return (SCPE_OK); } @@ -691,26 +463,20 @@ t_stat rs_svc (UNIT *uptr) case FNC_DCLR: /* drive clear */ break; case FNC_PRESET: /* read-in preset */ - rs_attn[ctlr] = 1; uptr->CMD |= DS_DRY|DS_ATA; - uptr->CMD &= ~CR_GO; - df->status &= ~BUSY; - if (df->status & IADR_ATTN) - df10_setirq(df); - sim_debug(DEBUG_DETAIL, dptr, "RSA%o seekdone\n", unit); + uptr->CMD &= ~CS1_GO; + rh_setattn(rhc, unit); + sim_debug(DEBUG_DETAIL, dptr, "%s%o seekdone\n", dptr->name, unit); break; case FNC_SEARCH: /* search */ if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) uptr->CMD |= (ER1_IAE << 16)|DS_ERR; - rs_attn[ctlr] = 1; uptr->CMD |= DS_DRY|DS_ATA; - uptr->CMD &= ~CR_GO; - df->status &= ~BUSY; - if ((df->status & (IADR_ATTN|BUSY)) == IADR_ATTN) - df10_setirq(df); - sim_debug(DEBUG_DETAIL, dptr, "RSA%o searchdone\n", unit); + uptr->CMD &= ~CS1_GO; + rh_setattn(rhc, unit); + sim_debug(DEBUG_DETAIL, dptr, "%s%o searchdone\n", dptr->name, unit); break; case FNC_READ: /* read */ @@ -720,13 +486,12 @@ t_stat rs_svc (UNIT *uptr) if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) { uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA; - df->status &= ~BUSY; - uptr->CMD &= ~CR_GO; - sim_debug(DEBUG_DETAIL, dptr, "RSA%o readx done\n", unit); - df10_finish_op(df, 0); + uptr->CMD &= ~CS1_GO; + sim_debug(DEBUG_DETAIL, dptr, "%s%o readx done\n", dptr->name, unit); + rh_finish_op(rhc, 0); return SCPE_OK; } - sim_debug(DEBUG_DETAIL, dptr, "RSA%o read (%d,%d)\n", unit, + sim_debug(DEBUG_DETAIL, dptr, "%s%o read (%d,%d)\n", dptr->name, unit, GET_SC(uptr->DA), GET_SF(uptr->DA)); da = GET_DA(uptr->DA, dtype) * RS_NUMWD; (void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); @@ -737,10 +502,10 @@ t_stat rs_svc (UNIT *uptr) uptr->hwmark = RS_NUMWD; } - df->buf = rs_buf[ctlr][uptr->DATAPTR++]; - sim_debug(DEBUG_DATA, dptr, "RSA%o read word %d %012llo %09o %06o\n", - unit, uptr->DATAPTR, df->buf, df->cda, df->wcr); - if (df10_write(df)) { + rhc->buf = rs_buf[ctlr][uptr->DATAPTR++]; + sim_debug(DEBUG_DATA, dptr, "%s%o read word %d %012llo %09o %06o\n", + dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr); + if (rh_write(rhc)) { if (uptr->DATAPTR == uptr->hwmark) { /* Increment to next sector. Set Last Sector */ uptr->DATAPTR = 0; @@ -751,13 +516,16 @@ t_stat rs_svc (UNIT *uptr) if (GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) uptr->CMD |= DS_LST; } + if (rh_blkend(rhc)) + goto rd_end; } sim_activate(uptr, 20); } else { - sim_debug(DEBUG_DETAIL, dptr, "RSA%o read done\n", unit); +rd_end: + sim_debug(DEBUG_DETAIL, dptr, "%s%o read done\n", dptr->name, unit); uptr->CMD |= DS_DRY; - uptr->CMD &= ~CR_GO; - df10_finish_op(df, 0); + uptr->CMD &= ~CS1_GO; + rh_finish_op(rhc, 0); return SCPE_OK; } break; @@ -767,20 +535,20 @@ t_stat rs_svc (UNIT *uptr) if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) { uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA; - uptr->CMD &= ~CR_GO; - sim_debug(DEBUG_DETAIL, dptr, "RSA%o writex done\n", unit); - df10_finish_op(df, 0); + uptr->CMD &= ~CS1_GO; + sim_debug(DEBUG_DETAIL, dptr, "%s%o writex done\n", dptr->name, unit); + rh_finish_op(rhc, 0); return SCPE_OK; } } - r = df10_read(df); - rs_buf[ctlr][uptr->DATAPTR++] = df->buf; - sim_debug(DEBUG_DATA, dptr, "RSA%o write word %d %012llo %09o %06o\n", - unit, uptr->DATAPTR, df->buf, df->cda, df->wcr); + r = rh_read(rhc); + rs_buf[ctlr][uptr->DATAPTR++] = rhc->buf; + sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %09o %06o\n", + dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr); if (r == 0 || uptr->DATAPTR == RS_NUMWD) { while (uptr->DATAPTR < RS_NUMWD) rs_buf[ctlr][uptr->DATAPTR++] = 0; - sim_debug(DEBUG_DETAIL, dptr, "RSA%o write (%d,%d)\n", unit, + sim_debug(DEBUG_DETAIL, dptr, "%s%o write (%d,%d)\n", dptr->name, unit, GET_SC(uptr->DA), GET_SF(uptr->DA)); da = GET_DA(uptr->DA, dtype) * RS_NUMWD; (void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); @@ -795,15 +563,18 @@ t_stat rs_svc (UNIT *uptr) if (GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) uptr->CMD |= DS_LST; } + if (rh_blkend(rhc)) + goto wr_end; } } if (r) { sim_activate(uptr, 20); } else { - sim_debug(DEBUG_DETAIL, dptr, "RSA%o write done\n", unit); +wr_end: + sim_debug(DEBUG_DETAIL, dptr, "%s%o write done\n", dptr->name, unit); uptr->CMD |= DS_DRY; - uptr->CMD &= ~CR_GO; - df10_finish_op(df, 0); + uptr->CMD &= ~CS1_GO; + rh_finish_op(rhc, 0); return SCPE_OK; } break; @@ -831,12 +602,10 @@ rs_reset(DEVICE * rstr) { int ctlr; for (ctlr = 0; ctlr < NUM_DEVS_RS; ctlr++) { - rs_df10[ctlr].devnum = rs_dib[ctlr].dev_num; - rs_df10[ctlr].nxmerr = 19; - rs_df10[ctlr].ccw_comp = 14; - rs_df10[ctlr].status = 0; - rs_attn[ctlr] = 0; - rs_rae[ctlr] = 0; + rs_rh[ctlr].devnum = rs_dib[ctlr].dev_num; + rs_rh[ctlr].status = 0; + rs_rh[ctlr].attn = 0; + rs_rh[ctlr].rae = 0; } return SCPE_OK; } @@ -846,16 +615,16 @@ t_stat rs_boot(int32 unit_num, DEVICE * rptr) { UNIT *uptr = &rptr->units[unit_num]; - int ctlr = GET_CNTRL(uptr->flags); + int ctlr = GET_CNTRL_RH(uptr->flags); + struct rh_if *rhc; DEVICE *dptr; - struct df10 *df; uint32 addr; uint32 ptr = 0; uint64 word; int wc; - df = &rs_df10[ctlr]; dptr = rs_devs[ctlr]; + rhc = &rs_rh[ctlr]; (void)sim_fseek(uptr->fileref, 0, SEEK_SET); (void)sim_fread (&rs_buf[0][0], sizeof(uint64), RS_NUMWD, uptr->fileref); uptr->CMD |= DS_VV; @@ -873,9 +642,9 @@ rs_boot(int32 unit_num, DEVICE * rptr) addr = rs_buf[0][ptr] & RMASK; wc = (rs_buf[0][ptr++] >> 18) & RMASK; word = rs_buf[0][ptr++]; - rs_reg[ctlr] = 040; - rs_drive[ctlr] = uptr - dptr->units; - df->status |= CCW_COMP_1|PI_ENABLE; + rhc->reg = 040; + rhc->drive = uptr - dptr->units; + rhc->status |= CCW_COMP_1|PI_ENABLE; PC = word & RMASK; return SCPE_OK; @@ -905,8 +674,8 @@ t_stat rs_attach (UNIT *uptr, CONST char *cptr) uptr->CMD |= DS_DPR|DS_MOL|DS_DRY; if (uptr->flags & UNIT_WLK) uptr->CMD |= DS_WRL; - rs_df10[ctlr].status |= PI_ENABLE; - set_interrupt(dib->dev_num, rs_df10[ctlr].status); + rs_rh[ctlr].status |= PI_ENABLE; + set_interrupt(dib->dev_num, rs_rh[ctlr].status); return SCPE_OK; } diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index a7ae6e1..1840edb 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -523,12 +523,22 @@ int get_word(FILE *fileref, uint64 *word) if (sim_fread(cbuf, 1, 5, fileref) != 5) return 1; - *word = ((uint64)(cbuf[0]) << 29) | - ((uint64)(cbuf[1]) << 22) | - ((uint64)(cbuf[2]) << 15) | - ((uint64)(cbuf[3]) << 8) | - ((uint64)(cbuf[4] & 0177) << 1) | - ((uint64)(cbuf[4] & 0200) >> 7); +#if 1 + *word = ((uint64)(cbuf[0] & 0177) << 29) | + ((uint64)(cbuf[1] & 0177) << 22) | + ((uint64)(cbuf[2] & 0177) << 15) | + ((uint64)(cbuf[3] & 0177) << 8) | + ((uint64)(cbuf[4] & 0177) << 1); + if (cbuf[4] & 0200) + *word |= 1; +#endif +#if 0 + *word = ((uint64)(cbuf[0] & 0377) << 28) | + ((uint64)(cbuf[1] & 0377) << 20) | + ((uint64)(cbuf[2] & 0377) << 12) | + ((uint64)(cbuf[3] & 0377) << 4) | + (uint64)(cbuf[4] & 017); +#endif return 0; } @@ -613,7 +623,6 @@ cont = 1; do { wc = get_word(fileref, &data); -// wc = sim_fread (&data, sizeof (uint64), 1, fileref);/* read blk hdr */ if (wc != 0) /* error? */ return SCPE_FMT; bsz = (int32) ((data & RMASK) - 1); /* get count */ @@ -630,9 +639,6 @@ do { return SCPE_FMT; } ndir = bsz; -// ndir = sim_fread (dirbuf, sizeof (uint64), bsz, fileref); - // if (ndir < bsz) /* error */ - // return SCPE_FMT; break; case EXE_PDV: /* optional */ @@ -646,9 +652,6 @@ do { if (get_word(fileref, &entbuf[i])) return SCPE_FMT; } -// entvec = sim_fread (entbuf, sizeof (uint64), bsz, fileref); - // if (entvec < 2) /* error? */ - // return SCPE_FMT; entvec = bsz; cont = 0; /* stop */ break; @@ -673,24 +676,22 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */ (void)sim_fseek (fileref, (fpage << PAG_V_PN) * 5, SEEK_SET); for (k = 0; k < PAG_SIZE; k++) { if (get_word(fileref, &pagbuf[k])) - return SCPE_FMT; + break; } -// wc = sim_fread (pagbuf, sizeof (uint64), PAG_SIZE, fileref); - // if (wc < PAG_SIZE) - // return SCPE_FMT; fpage++; } ma = mpage << PAG_V_PN; /* mem addr */ for (k = 0; k < PAG_SIZE; k++, ma++) { /* copy buf to mem */ if (ma > MEMSIZE) return SCPE_NXM; -fprintf(stderr, "M %06o %012llo\n", ma, pagbuf[k]); M[ma] = fpage? (pagbuf[k] & FMASK): 0; } /* end copy */ } /* end rpt */ } /* end directory */ if (entvec && entbuf[1]) PC = (int32) (entbuf[1] & RMASK); /* start addr */ +else if (entvec == 0) + PC = (int32) (M[0120] & RMASK); return SCPE_OK; } diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index 2870106..34fb4ef 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -39,69 +39,12 @@ /* Flags in the unit flags word */ #define TU_UNIT UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE -#define CNTRL_V_CTYPE (MTUF_V_UF) -#define CNTRL_M_CTYPE 7 -#define GET_CNTRL(x) (((x) >> CNTRL_V_CTYPE) & CNTRL_M_CTYPE) -#define CNTRL(x) (((x) & CNTRL_M_CTYPE) << CNTRL_V_CTYPE) - -/* CONI Flags */ -#define IADR_ATTN 0000000000040LL /* Interrupt on attention */ -#define IARD_RAE 0000000000100LL /* Interrupt on register access error */ -#define DIB_CBOV 0000000000200LL /* Control bus overrun */ -#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */ -#define CXR_ILC 0000000004000LL /* Illegal function code */ -#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */ -#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */ -#define CCW_COMP_1 0000000040000LL /* Control word written. */ -#define CXR_CHAN_ER 0000000100000LL /* Channel Error */ -#define CXR_EXC 0000000200000LL /* Error in drive transfer */ -#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */ -#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */ -#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */ -#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */ -#define CXR_SD_RAE 0000200000000LL /* Register access error */ -#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */ -#define B22_FLAG 0004000000000LL /* 22 bit channel */ -#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */ -#define CC_CHAN_ACT 0020000000000LL /* Channel in use */ -#define CC_INH 0040000000000LL /* Disconnect channel */ -#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */ -#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */ - -/* CONO Flags */ -#define ATTN_EN 0000000000040LL /* enable attention interrupt. */ -#define REA_EN 0000000000100LL /* enable register error interrupt */ -#define CBOV_CLR 0000000000200LL /* Clear CBOV */ -#define CONT_RESET 0000000002000LL /* Clear All error bits */ -#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */ -#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */ -#define OVER_CLR 0000000020000LL /* Clear DTC overrun */ -#define WRT_CW 0000000040000LL /* Write control word */ -#define CHN_CLR 0000000100000LL /* Clear Channel Error */ -#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */ -#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */ - -/* DATAO/DATAI */ -#define CR_REG 0770000000000LL /* Register number */ -#define LOAD_REG 0004000000000LL /* Load register */ -#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */ -#define CR_DRIVE 0000007000000LL -#define CR_GEN_EVD 0000000400000LL /* Enable Parity */ -#define CR_DXES 0000000200000LL /* Disable DXES errors */ -#define CR_INAD 0000000077600LL -#define CR_WTEVM 0000000000100LL /* Verify Parity */ -#define CR_FUNC 0000000000076LL -#define CR_GO 0000000000001LL - -#define IRQ_VECT 0000000000177LL /* Interupt vector */ -#define IRQ_KI10 0000002000000LL -#define IRQ_KA10 0000001000000LL #define CMD u3 /* u3 low */ /* TUC - 00 - control */ -#define CS1_GO CR_GO /* go */ +#define CS1_GO 1 /* go */ #define CS1_V_FNC 1 /* function pos */ #define CS1_M_FNC 037 /* function mask */ #define CS1_FNC (CS1_M_FNC << CS1_V_FNC) @@ -213,23 +156,15 @@ #define CPOS u4 #define DATAPTR u6 -struct df10 tu_df10[NUM_DEVS_TU]; -int tu_xfer_drive[NUM_DEVS_TU]; +struct rh_if tu_rh[NUM_DEVS_TU]; uint8 tu_buf[NUM_DEVS_TU][TU_NUMFR]; -int tu_reg[NUM_DEVS_TU]; -int tu_ivect[NUM_DEVS_TU]; -int tu_imode[NUM_DEVS_TU]; -int tu_drive[NUM_DEVS_TU]; -int tu_rae[NUM_DEVS_TU]; -int tu_attn[NUM_DEVS_TU]; uint16 tu_frame[NUM_DEVS_TU]; uint16 tu_tcr[NUM_DEVS_TU]; static uint64 tu_boot_buffer; -t_stat tu_devio(uint32 dev, uint64 *data); -int tu_devirq(uint32 dev, int addr); -void tu_write(int ctlr, int unit, int reg, uint32 data); -uint32 tu_read(int ctlr, int unit, int reg); +void tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data); +uint32 tu_read(DEVICE *dptr, struct rh_if *rhc, int reg); +void tu_rst(DEVICE *dptr); t_stat tu_srv(UNIT *); t_stat tu_boot(int32, DEVICE *); void tu_ini(UNIT *, t_bool); @@ -243,21 +178,31 @@ const char *tu_description (DEVICE *dptr); UNIT tu_unit[] = { /* Controller 1 */ - { UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) }, - { UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) }, - { UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) }, - { UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) }, - { UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) }, - { UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) }, - { UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) }, - { UDATA (&tu_srv, TU_UNIT+CNTRL(0), 0) }, + { UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) }, + { UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) }, + { UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) }, + { UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) }, + { UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) }, + { UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) }, + { UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) }, + { UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) }, +}; + +struct rh_if tu_rh[] = { + { &tu_write, &tu_read} }; DIB tu_dib[] = { - {RH10_DEV, 1, &tu_devio, &tu_devirq} + {RH10_DEV, 1, &rh_devio, &rh_devirq, &tu_rh[0]} }; MTAB tu_mod[] = { +#if KL + {MTAB_XTD|MTAB_VDV, TYPE_RH10, NULL, "RH10", &rh_set_type, NULL, + NULL, "Sets controller to RH10" }, + {MTAB_XTD|MTAB_VDV, TYPE_RH20, "RH20", "RH20", &rh_set_type, &rh_show_type, + NULL, "Sets controller to RH20"}, +#endif {MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL}, {MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL}, {MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", @@ -270,24 +215,22 @@ MTAB tu_mod[] = { }; REG tua_reg[] = { - {ORDATA(IVECT, tu_ivect[0], 18)}, - {FLDATA(IMODE, tu_imode[0], 0)}, + {ORDATA(IVECT, tu_rh[0].ivect, 18)}, + {FLDATA(IMODE, tu_rh[0].imode, 0)}, {ORDATA(FRAME, tu_frame[0], 16)}, {ORDATA(TCR, tu_tcr[0], 16)}, - {ORDATA(XFER, tu_xfer_drive[0], 3), REG_HRO}, - {ORDATA(DRIVE, tu_drive[0], 3), REG_HRO}, - {ORDATA(REG, tu_reg[0], 6), REG_RO}, - {ORDATA(RAE, tu_rae[0], 8), REG_RO}, - {ORDATA(ATTN, tu_attn[0], 8), REG_RO}, - {ORDATA(STATUS, tu_df10[0].status, 18), REG_RO}, - {ORDATA(CIA, tu_df10[0].cia, 18)}, - {ORDATA(CCW, tu_df10[0].ccw, 18)}, - {ORDATA(WCR, tu_df10[0].wcr, 18)}, - {ORDATA(CDA, tu_df10[0].cda, 18)}, - {ORDATA(DEVNUM, tu_df10[0].devnum, 9), REG_HRO}, - {ORDATA(BUF, tu_df10[0].buf, 36), REG_HRO}, - {ORDATA(NXM, tu_df10[0].nxmerr, 8), REG_HRO}, - {ORDATA(COMP, tu_df10[0].ccw_comp, 8), REG_HRO}, + {ORDATA(XFER, tu_rh[0].xfer_drive, 3), REG_HRO}, + {ORDATA(DRIVE, tu_rh[0].drive, 3), REG_HRO}, + {ORDATA(REG, tu_rh[0].reg, 6), REG_RO}, + {ORDATA(RAE, tu_rh[0].rae, 8), REG_RO}, + {ORDATA(ATTN, tu_rh[0].attn, 8), REG_RO}, + {ORDATA(STATUS, tu_rh[0].status, 18), REG_RO}, + {ORDATA(CIA, tu_rh[0].cia, 18)}, + {ORDATA(CCW, tu_rh[0].ccw, 18)}, + {ORDATA(WCR, tu_rh[0].wcr, 18)}, + {ORDATA(CDA, tu_rh[0].cda, 18)}, + {ORDATA(DEVNUM, tu_rh[0].devnum, 9), REG_HRO}, + {ORDATA(BUF, tu_rh[0].buf, 36), REG_HRO}, {BRDATA(BUFF, &tu_buf[0][0], 16, 64, TU_NUMFR), REG_HRO}, {0} }; @@ -305,196 +248,22 @@ DEVICE *tu_devs[] = { &tua_dev, }; - -t_stat tu_devio(uint32 dev, uint64 *data) { - int ctlr = -1; - DEVICE *dptr = NULL; - struct df10 *df10; - int drive; - - for (drive = 0; rh[drive].dev_num != 0; drive++) { - if (rh[drive].dev_num == (dev & 0774)) { - dptr = rh[drive].dev; - break; - } - } - - if (dptr == NULL) - return SCPE_OK; - ctlr = GET_CNTRL(dptr->units[0].flags); - df10 = &tu_df10[ctlr]; - df10->devnum = dev; - switch(dev & 3) { - case CONI: - *data = df10->status & ~(IADR_ATTN|IARD_RAE); - if (tu_attn[ctlr] != 0 && (df10->status & IADR_ATTN)) - *data |= IADR_ATTN; - if (tu_rae[ctlr] != 0 && (df10->status & IARD_RAE)) - *data |= IARD_RAE; -#if KI_22BIT - *data |= B22_FLAG; -#endif - sim_debug(DEBUG_CONI, dptr, "TU %03o CONI %06o PC=%o %o\n", - dev, (uint32)*data, PC, tu_attn[ctlr]); - return SCPE_OK; - - case CONO: - clr_interrupt(dev); - df10->status &= ~07LL; - df10->status |= *data & (07LL|IADR_ATTN|IARD_RAE); - /* Clear flags */ - if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)) - df10->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)); - if (*data & OVER_CLR) - df10->status &= ~(DTC_OVER); - if (*data & CBOV_CLR) - df10->status &= ~(DIB_CBOV); - if (*data & CXR_ILC) - df10->status &= ~(CXR_ILFC|CXR_SD_RAE); - if (*data & WRT_CW) - df10_writecw(df10); - if (*data & PI_ENABLE) - df10->status &= ~PI_ENABLE; - if (df10->status & PI_ENABLE) - set_interrupt(dev, df10->status); - if ((df10->status & IADR_ATTN) != 0 && tu_attn[ctlr] != 0) - set_interrupt(dev, df10->status); - sim_debug(DEBUG_CONO, dptr, "TU %03o CONO %06o %d PC=%06o %06o\n", - dev, (uint32)*data, ctlr, PC, df10->status); - return SCPE_OK; - - case DATAI: - *data = 0; - if (df10->status & BUSY && tu_reg[ctlr] != 04) { - df10->status |= CC_CHAN_ACT; - return SCPE_OK; - } - if (tu_reg[ctlr] == 040) { - *data = (uint64)(tu_read(ctlr, tu_drive[ctlr], 0) & 077); - *data |= ((uint64)(df10->cia)) << 6; - *data |= ((uint64)(tu_xfer_drive[ctlr])) << 18; - } else if (tu_reg[ctlr] == 044) { - *data = (uint64)tu_ivect[ctlr]; - if (tu_imode[ctlr]) - *data |= IRQ_KI10; - else - *data |= IRQ_KA10; - } else if (tu_reg[ctlr] == 054) { - *data = (uint64)(tu_rae[ctlr]); - } else if ((tu_reg[ctlr] & 040) == 0) { - *data = (uint64)(tu_read(ctlr, tu_drive[ctlr], tu_reg[ctlr]) & 0177777); - *data |= ((uint64)(tu_drive[ctlr])) << 18; - } - *data |= ((uint64)(tu_reg[ctlr])) << 30; - sim_debug(DEBUG_DATAIO, dptr, "TU %03o DATI %012llo, %d %d PC=%06o\n", - dev, *data, ctlr, tu_drive[ctlr], PC); - return SCPE_OK; - - case DATAO: - sim_debug(DEBUG_DATAIO, dptr, "TU %03o DATO %012llo, %d PC=%06o %06o\n", - dev, *data, ctlr, PC, df10->status); - tu_reg[ctlr] = ((int)(*data >> 30)) & 077; - if (tu_reg[ctlr] < 040 && tu_reg[ctlr] != 04) { - tu_drive[ctlr] = (int)(*data >> 18) & 07; - } - if (*data & LOAD_REG) { - if (tu_reg[ctlr] == 040) { - if ((*data & 1) == 0) { - return SCPE_OK; - } - if (df10->status & BUSY) { - df10->status |= CC_CHAN_ACT; - sim_debug(DEBUG_DATAIO, dptr, - "TU %03o command busy %012llo, %d[%d] PC=%06o %06o\n", - dev, *data, ctlr, tu_drive[ctlr], PC, df10->status); - return SCPE_OK; - } - - df10->status &= ~(1 << df10->ccw_comp); - df10->status &= ~PI_ENABLE; - if (((*data >> 1) & 077) < FNC_XFER) { - df10->status |= CXR_ILC; - df10_setirq(df10); - sim_debug(DEBUG_DATAIO, dptr, - "TU %03o command abort %012llo, %d[%d] PC=%06o %06o\n", - dev, *data, ctlr, tu_drive[ctlr], PC, df10->status); - return SCPE_OK; - } - /* Check if access error */ - if (tu_rae[ctlr] & (1 << tu_drive[ctlr])) { - return SCPE_OK; - } - - /* Start command */ - df10_setup(df10, (uint32)(*data >> 6)); - tu_xfer_drive[ctlr] = (int)(*data >> 18) & 07; - tu_write(ctlr, tu_drive[ctlr], 0, (uint32)(*data & 077)); - sim_debug(DEBUG_DATAIO, dptr, - "TU %03o command %012llo, %d[%d] PC=%06o %06o\n", - dev, *data, ctlr, tu_drive[ctlr], PC, df10->status); - } else if (tu_reg[ctlr] == 044) { - /* Set KI10 Irq vector */ - tu_ivect[ctlr] = (int)(*data & IRQ_VECT); - tu_imode[ctlr] = (*data & IRQ_KI10) != 0; - } else if (tu_reg[ctlr] == 050) { - ; /* Diagnostic access to mass bus. */ - } else if (tu_reg[ctlr] == 054) { - /* clear flags */ - tu_rae[ctlr] &= ~(*data & 0377); - if (tu_rae[ctlr] == 0) - clr_interrupt(dev); - } else if ((tu_reg[ctlr] & 040) == 0) { - tu_drive[ctlr] = (int)(*data >> 18) & 07; - /* Check if access error */ - if (tu_rae[ctlr] & (1 << tu_drive[ctlr])) { - return SCPE_OK; - } - tu_drive[ctlr] = (int)(*data >> 18) & 07; - tu_write(ctlr, tu_drive[ctlr], tu_reg[ctlr] & 037, - (int)(*data & 0777777)); - } - } - return SCPE_OK; - } - return SCPE_OK; /* Unreached */ -} - -/* Handle KI and KL style interrupt vectors */ -int -tu_devirq(uint32 dev, int addr) { - DEVICE *dptr = NULL; - int drive; - - for (drive = 0; rh[drive].dev_num != 0; drive++) { - if (rh[drive].dev_num == (dev & 0774)) { - dptr = rh[drive].dev; - break; - } - } - if (dptr != NULL) { - drive = GET_CNTRL(dptr->units[0].flags); - return (tu_imode[drive] ? tu_ivect[drive] : addr); - } - return addr; -} - void -tu_write(int ctlr, int unit, int reg, uint32 data) { - UNIT *uptr = &tu_unit[(ctlr * 8) + (tu_tcr[ctlr] & 07)]; - DEVICE *dptr = tu_devs[ctlr]; - struct df10 *df10 = &tu_df10[ctlr]; +tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { + int ctlr = GET_CNTRL_RH(dptr->units[0].flags); + int unit = tu_tcr[ctlr] & 07; + UNIT *uptr = &dptr->units[unit]; int i; - if (uptr->CMD & CR_GO) { + if (uptr->CMD & CS1_GO) { uptr->STATUS |= (ER1_RMR); return; } switch(reg) { case 000: /* control */ - sim_debug(DEBUG_DETAIL, dptr, "TUA%o %d Status=%06o\n", - unit, ctlr, uptr->STATUS); - df10->status &= ~(1 << df10->ccw_comp); + sim_debug(DEBUG_DETAIL, dptr, "%s%o %d Status=%06o\n", + dptr->name, unit, ctlr, uptr->STATUS); if ((data & 01) != 0 && (uptr->flags & UNIT_ATT) != 0) { uptr->CMD = data & 076; switch (GET_FNC(data)) { @@ -516,34 +285,28 @@ tu_write(int ctlr, int unit, int reg, uint32 data) { case FNC_REWIND: /* rewind */ case FNC_UNLOAD: /* unload */ case FNC_WCHKREV: /* write w/ headers */ - uptr->CMD |= CS_PIP|CR_GO; + uptr->CMD |= CS_PIP|CS1_GO; uptr->CMD &= ~CS_TM; CLR_BUF(uptr); uptr->DATAPTR = 0; - df10->status &= ~PI_ENABLE; sim_activate(uptr, 100); break; case FNC_DCLR: /* drive clear */ - uptr->CMD &= ~(CS_ATA|CR_GO|CS_TM); + uptr->CMD &= ~(CS_ATA|CS1_GO|CS_TM); uptr->STATUS = 0; - tu_attn[ctlr] = 0; - clr_interrupt(df10->devnum); + rhc->attn = 0; for (i = 0; i < 8; i++) { - if (tu_unit[(ctlr * 8) + i].CMD & CS_ATA) - tu_attn[ctlr] = 1; + if (dptr->units[i].CMD & CS_ATA) + rhc->attn = 1; } - if ((df10->status & IADR_ATTN) != 0 && tu_attn[ctlr] != 0) - df10_setirq(df10); break; default: uptr->STATUS |= (ER1_ILF); uptr->CMD |= CS_ATA; - tu_attn[ctlr] = 1; - if ((df10->status & IADR_ATTN) != 0) - df10_setirq(df10); + rhc->attn = 1; } - sim_debug(DEBUG_DETAIL, dptr, "TUA%o AStatus=%06o\n", unit, + sim_debug(DEBUG_DETAIL, dptr, "%s%o AStatus=%06o\n", dptr->name, unit, uptr->CMD); } return; @@ -556,17 +319,13 @@ tu_write(int ctlr, int unit, int reg, uint32 data) { case 003: /* maintenance */ break; case 004: /* atten summary */ - tu_attn[ctlr] = 0; + rhc->attn = 0; for (i = 0; i < 8; i++) { if (data & (1<units[i].CMD &= ~CS_ATA; + if (dptr->units[i].CMD & CS_ATA) + rhc->attn = 1; } - clr_interrupt(df10->devnum); - if (((df10->status & IADR_ATTN) != 0 && tu_attn[ctlr] != 0) || - (df10->status & PI_ENABLE)) - df10_setirq(df10); break; case 005: /* frame count */ tu_frame[ctlr] = data & 0177777; @@ -579,31 +338,30 @@ tu_write(int ctlr, int unit, int reg, uint32 data) { default: uptr->STATUS |= ER1_ILR; uptr->CMD |= CS_ATA; - tu_attn[ctlr] = 1; - tu_rae[ctlr] |= (1<status & IADR_ATTN) != 0) - df10_setirq(df10); + rhc->attn = 1; + rhc->rae = 1; } } uint32 -tu_read(int ctlr, int unit, int reg) { - UNIT *uptr = &tu_unit[(ctlr * 8) + (tu_tcr[ctlr] & 07)]; - struct df10 *df10 = &tu_df10[ctlr]; - uint32 temp = 0; - int i; +tu_read(DEVICE *dptr, struct rh_if *rhc, int reg) { + int ctlr = GET_CNTRL_RH(dptr->units[0].flags); + int unit = tu_tcr[ctlr] & 07; + UNIT *uptr = &dptr->units[unit]; + uint32 temp = 0; + int i; switch(reg) { case 000: /* control */ temp = uptr->CMD & 076; if (uptr->flags & UNIT_ATT) temp |= CS1_DVA; - if (df10->status & BUSY || uptr->CMD & CR_GO) + if (uptr->CMD & CS1_GO) temp |= CS1_GO; break; case 001: /* status */ temp = DS_DPR; - if (tu_attn[ctlr] != 0) + if (rhc->attn != 0) temp |= DS_ATA; if (uptr->CMD & CS_CHANGE) temp |= DS_SSC; @@ -615,7 +373,7 @@ tu_read(int ctlr, int unit, int reg) { temp |= DS_TM; if (uptr->flags & MTUF_WLK) temp |= DS_WRL; - if ((uptr->CMD & (CS_MOTION|CS_PIP|CR_GO)) == 0) + if ((uptr->CMD & (CS_MOTION|CS_PIP|CS1_GO)) == 0) temp |= DS_DRY; if (sim_tape_bot(uptr)) temp |= DS_BOT; @@ -632,7 +390,7 @@ tu_read(int ctlr, int unit, int reg) { break; case 004: /* atten summary */ for (i = 0; i < 8; i++) { - if (tu_unit[(ctlr * 8) + i].CMD & CS_ATA) { + if (dptr->units[i].CMD & CS_ATA) { temp |= 1 << i; } } @@ -655,10 +413,8 @@ tu_read(int ctlr, int unit, int reg) { default: uptr->STATUS |= (ER1_ILR); uptr->CMD |= CS_ATA; - tu_attn[ctlr] = 1; - tu_rae[ctlr] |= (1<status & IADR_ATTN) != 0) - df10_setirq(df10); + rhc->attn = 1; + rhc->rae = 1; } return temp; } @@ -667,8 +423,9 @@ tu_read(int ctlr, int unit, int reg) { /* Map simH errors into machine errors */ void tu_error(UNIT * uptr, t_stat r) { - int ctlr = GET_CNTRL(uptr->flags); - DEVICE *dptr = tu_devs[ctlr]; + int ctlr = GET_CNTRL_RH(uptr->flags); + DEVICE *dptr = tu_devs[ctlr]; + struct rh_if *rhc = &tu_rh[ctlr]; switch (r) { case MTSE_OK: /* no error */ @@ -706,66 +463,61 @@ void tu_error(UNIT * uptr, t_stat r) } if (uptr->CMD & CS_ATA) { - tu_attn[ctlr] = 1; + rh_setattn(rhc, 0); +// rhc->attn = 1; } - uptr->CMD &= ~(CS_MOTION|CS_PIP|CR_GO); + uptr->CMD &= ~(CS_MOTION|CS_PIP|CS1_GO); sim_debug(DEBUG_EXP, dptr, "Setting status %d\n", r); } /* Handle processing of tape requests. */ t_stat tu_srv(UNIT * uptr) { - int ctlr = GET_CNTRL(uptr->flags); - int unit; - DEVICE *dptr; - struct df10 *df; - t_stat r; - t_mtrlnt reclen; - uint8 ch; - int cc; - int cc_max; + int ctlr = GET_CNTRL_RH(uptr->flags); + int unit; + struct rh_if *rhc; + DEVICE *dptr; + t_stat r; + t_mtrlnt reclen; + uint8 ch; + int cc; + int cc_max; /* Find dptr, and df10 */ dptr = tu_devs[ctlr]; + rhc = &tu_rh[ctlr]; unit = uptr - dptr->units; - df = &tu_df10[ctlr]; cc_max = (4 + ((tu_tcr[ctlr] & TC_FMTSEL) == 0)); if ((uptr->flags & UNIT_ATT) == 0) { tu_error(uptr, MTSE_UNATT); /* attached? */ - df10_setirq(df); + rh_setirq(rhc); return SCPE_OK; } switch (GET_FNC(uptr->CMD)) { case FNC_NOP: case FNC_DCLR: - sim_debug(DEBUG_DETAIL, dptr, "TU%o nop\n", unit); + sim_debug(DEBUG_DETAIL, dptr, "%s%o nop\n", dptr->name, unit); tu_error(uptr, MTSE_OK); /* Nop */ - df10_setirq(df); + rh_setirq(rhc); return SCPE_OK; case FNC_REWIND: - sim_debug(DEBUG_DETAIL, dptr, "TU%o rewind\n", unit); - if (uptr->CMD & CR_GO) { + sim_debug(DEBUG_DETAIL, dptr, "%s%o rewind\n", dptr->name, unit); + if (uptr->CMD & CS1_GO) { sim_activate(uptr,40000); uptr->CMD |= CS_MOTION; - uptr->CMD &= ~(CR_GO); + uptr->CMD &= ~(CS1_GO); } else { uptr->CMD &= ~(CS_MOTION|CS_PIP); uptr->CMD |= CS_CHANGE|CS_ATA; - tu_attn[ctlr] = 1; - if ((df->status & IADR_ATTN) != 0) - df10_setirq(df); tu_error(uptr, sim_tape_rewind(uptr)); } return SCPE_OK; case FNC_UNLOAD: - sim_debug(DEBUG_DETAIL, dptr, "TU%o unload\n", unit); - uptr->CMD &= ~(CR_GO); + sim_debug(DEBUG_DETAIL, dptr, "%s%o unload\n", dptr->name, unit); + uptr->CMD &= ~(CS1_GO); uptr->CMD |= CS_CHANGE|CS_ATA; - tu_attn[ctlr] = 1; - if ((df->status & IADR_ATTN) != 0) - df10_setirq(df); tu_error(uptr, sim_tape_detach(uptr)); return SCPE_OK; @@ -775,18 +527,18 @@ t_stat tu_srv(UNIT * uptr) uptr->CMD &= ~CS_PIP; if ((r = sim_tape_rdrecr(uptr, &tu_buf[ctlr][0], &reclen, TU_NUMFR)) != MTSE_OK) { - sim_debug(DEBUG_DETAIL, dptr, "TU%o read error %d\n", unit, r); + sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r); if (r == MTSE_BOT) uptr->STATUS |= ER1_NEF; tu_error(uptr, r); - df10_finish_op(df, 0); + rh_finish_op(rhc, 0); } else { - sim_debug(DEBUG_DETAIL, dptr, "TU%o read %d\n", unit, reclen); + sim_debug(DEBUG_DETAIL, dptr, "%s%o read %d\n", dptr->name, unit, reclen); uptr->CMD |= CS_MOTION; uptr->hwmark = reclen; uptr->DATAPTR = uptr->hwmark-1; uptr->CPOS = cc_max; - df->buf = 0; + rhc->buf = 0; sim_activate(uptr, 100); } return SCPE_OK; @@ -796,26 +548,27 @@ t_stat tu_srv(UNIT * uptr) cc = (8 * (3 - uptr->CPOS)) + 4; ch = tu_buf[ctlr][uptr->DATAPTR]; if (cc < 0) - df->buf |= (uint64)(ch & 0x0f); + rhc->buf |= (uint64)(ch & 0x0f); else - df->buf |= (uint64)(ch & 0xff) << cc; + rhc->buf |= (uint64)(ch & 0xff) << cc; uptr->DATAPTR--; uptr->CPOS--; if (uptr->CPOS == 0) { uptr->CPOS = cc_max; - if (GET_FNC(uptr->CMD) == FNC_READREV && - df10_write(df) == 0) { + if (GET_FNC(uptr->CMD) == FNC_READREV && rh_write(rhc) == 0) { tu_error(uptr, MTSE_OK); return SCPE_OK; } - sim_debug(DEBUG_DATA, dptr, "TU%o readrev %012llo\n", - unit, df->buf); - df->buf = 0; + sim_debug(DEBUG_DATA, dptr, "%s%o readrev %012llo\n", + dptr->name, unit, rhc->buf); + rhc->buf = 0; } } else { if (uptr->CPOS != cc_max) - df10_write(df); + rh_write(rhc); + (void)rh_blkend(rhc); tu_error(uptr, MTSE_OK); + rh_finish_op(rhc, 0); return SCPE_OK; } break; @@ -827,15 +580,15 @@ t_stat tu_srv(UNIT * uptr) uptr->CMD |= CS_MOTION; if ((r = sim_tape_rdrecf(uptr, &tu_buf[ctlr][0], &reclen, TU_NUMFR)) != MTSE_OK) { - sim_debug(DEBUG_DETAIL, dptr, "TU%o read error %d\n", unit, r); + sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r); tu_error(uptr, r); - df10_finish_op(df, 0); + rh_finish_op(rhc, 0); } else { - sim_debug(DEBUG_DETAIL, dptr, "TU%o read %d\n", unit, reclen); + sim_debug(DEBUG_DETAIL, dptr, "%s%o read %d %d\n", dptr->name, unit, reclen, uptr->pos); uptr->hwmark = reclen; uptr->DATAPTR = 0; uptr->CPOS = 0; - df->buf = 0; + rhc->buf = 0; sim_activate(uptr, 100); } return SCPE_OK; @@ -845,30 +598,30 @@ t_stat tu_srv(UNIT * uptr) cc = (8 * (3 - uptr->CPOS)) + 4; ch = tu_buf[ctlr][uptr->DATAPTR]; if (cc < 0) - df->buf |= (uint64)(ch & 0x0f); + rhc->buf |= (uint64)(ch & 0x0f); else - df->buf |= (uint64)(ch & 0xff) << cc; + rhc->buf |= (uint64)(ch & 0xff) << cc; uptr->DATAPTR++; uptr->CPOS++; if (uptr->CPOS == cc_max) { uptr->CPOS = 0; - if (GET_FNC(uptr->CMD) == FNC_READ && - df10_write(df) == 0) { + if (GET_FNC(uptr->CMD) == FNC_READ && rh_write(rhc) == 0) { tu_error(uptr, MTSE_OK); return SCPE_OK; } - sim_debug(DEBUG_DATA, dptr, "TU%o read %012llo\n", - unit, df->buf); - df->buf = 0; + sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo\n", + dptr->name, unit, rhc->buf); + rhc->buf = 0; } } else { if (uptr->CPOS != 0) { - sim_debug(DEBUG_DATA, dptr, "TU%o read %012llo\n", - unit, df->buf); - df10_write(df); + sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo\n", + dptr->name, unit, rhc->buf); + rh_write(rhc); } tu_error(uptr, MTSE_OK); - df10_finish_op(df, 0); + (void)rh_blkend(rhc); + rh_finish_op(rhc, 0); return SCPE_OK; } break; @@ -878,38 +631,38 @@ t_stat tu_srv(UNIT * uptr) uptr->CMD &= ~CS_PIP; if (tu_frame[ctlr] == 0) { uptr->STATUS |= ER1_NEF; - uptr->CMD &= ~(CR_GO); + uptr->CMD &= ~(CS1_GO); uptr->CMD |= CS_ATA; - tu_attn[ctlr] = 1; + rhc->attn = 1; tu_error(uptr, MTSE_OK); - df10_finish_op(df, 0); + rh_finish_op(rhc, 0); return SCPE_OK; } if ((uptr->flags & MTUF_WLK) != 0) { tu_error(uptr, MTSE_WRP); - df10_finish_op(df, 0); + rh_finish_op(rhc, 0); return SCPE_OK; } uptr->CMD |= CS_MOTION; - sim_debug(DEBUG_EXP, dptr, "TU%o Init write\n", unit); + sim_debug(DEBUG_EXP, dptr, "%s%o Init write\n", dptr->name, unit); uptr->hwmark = 0; uptr->CPOS = 0; uptr->DATAPTR = 0; - df->buf = 0; + rhc->buf = 0; } - if (tu_frame[ctlr] != 0 && uptr->CPOS == 0 && df10_read(df) == 0) + if (tu_frame[ctlr] != 0 && uptr->CPOS == 0 && rh_read(rhc) == 0) uptr->CPOS |= 010; if ((uptr->CMD & CS_MOTION) != 0) { if (uptr->CPOS == 0) - sim_debug(DEBUG_DATA, dptr, "TU%o write %012llo\n", - unit, df->buf); + sim_debug(DEBUG_DATA, dptr, "%s%o write %012llo\n", + dptr->name, unit, rhc->buf); /* Write next char out */ cc = (8 * (3 - (uptr->CPOS & 07))) + 4; if (cc < 0) - ch = df->buf & 0x0f; + ch = rhc->buf & 0x0f; else - ch = (df->buf >> cc) & 0xff; + ch = (rhc->buf >> cc) & 0xff; tu_buf[ctlr][uptr->DATAPTR] = ch; uptr->DATAPTR++; uptr->hwmark = uptr->DATAPTR; @@ -925,52 +678,44 @@ t_stat tu_srv(UNIT * uptr) /* Write out the block */ reclen = uptr->hwmark; r = sim_tape_wrrecf(uptr, &tu_buf[ctlr][0], reclen); - sim_debug(DEBUG_DETAIL, dptr, "TU%o Write %d %d\n", - unit, reclen, uptr->CPOS); + sim_debug(DEBUG_DETAIL, dptr, "%s%o Write %d %d\n", + dptr->name, unit, reclen, uptr->CPOS); uptr->DATAPTR = 0; uptr->hwmark = 0; - df10_finish_op(df,0 ); + (void)rh_blkend(rhc); tu_error(uptr, r); /* Record errors */ + rh_finish_op(rhc,0 ); return SCPE_OK; } break; case FNC_WTM: + uptr->CMD |= CS_ATA; if ((uptr->flags & MTUF_WLK) != 0) { tu_error(uptr, MTSE_WRP); } else { tu_error(uptr, sim_tape_wrtmk(uptr)); } - uptr->CMD |= CS_ATA; - tu_attn[ctlr] = 1; - sim_debug(DEBUG_DETAIL, dptr, "TU%o WTM\n", unit); - if ((df->status & IADR_ATTN) != 0) - df10_setirq(df); + sim_debug(DEBUG_DETAIL, dptr, "%s%o WTM\n", dptr->name, unit); return SCPE_OK; case FNC_ERASE: + uptr->CMD |= CS_ATA; if ((uptr->flags & MTUF_WLK) != 0) { tu_error(uptr, MTSE_WRP); } else { tu_error(uptr, sim_tape_wrgap(uptr, 35)); } - uptr->CMD |= CS_ATA; - tu_attn[ctlr] = 1; - sim_debug(DEBUG_DETAIL, dptr, "TU%o ERG\n", unit); - if ((df->status & IADR_ATTN) != 0) - df10_setirq(df); + sim_debug(DEBUG_DETAIL, dptr, "%s%o ERG\n", dptr->name, unit); return SCPE_OK; case FNC_SPACEF: case FNC_SPACEB: - sim_debug(DEBUG_DETAIL, dptr, "TU%o space %o\n", unit, GET_FNC(uptr->CMD)); + sim_debug(DEBUG_DETAIL, dptr, "%s%o space %o\n", dptr->name, unit, GET_FNC(uptr->CMD)); if (tu_frame[ctlr] == 0) { uptr->STATUS |= ER1_NEF; uptr->CMD |= CS_ATA; - tu_attn[ctlr] = 1; tu_error(uptr, MTSE_OK); - if ((df->status & IADR_ATTN) != 0) - df10_setirq(df); return SCPE_OK; } uptr->CMD |= CS_MOTION; @@ -991,26 +736,22 @@ t_stat tu_srv(UNIT * uptr) case MTSE_EOM: /* end of medium */ if (tu_frame[ctlr] != 0) uptr->STATUS |= ER1_FCE; - uptr->CMD &= ~(CR_GO); + uptr->CMD &= ~(CS1_GO); uptr->CMD |= CS_ATA; - tu_attn[ctlr] = 1; /* Stop motion if we recieve any of these */ tu_error(uptr, r); - if ((df->status & IADR_ATTN) != 0) - df10_setirq(df); return SCPE_OK; } tu_frame[ctlr] = 0177777 & (tu_frame[ctlr] + 1); if (tu_frame[ctlr] == 0) { + uptr->CMD |= CS_ATA; tu_error(uptr, MTSE_OK); - if ((df->status & IADR_ATTN) != 0) - df10_setirq(df); return SCPE_OK; } else sim_activate(uptr, 5000); return SCPE_OK; } - sim_activate(uptr, 200); + sim_activate(uptr, 100); return SCPE_OK; } @@ -1022,11 +763,9 @@ tu_reset(DEVICE * dptr) { int ctlr; for (ctlr = 0; ctlr < NUM_DEVS_TU; ctlr++) { - tu_df10[ctlr].devnum = tu_dib[ctlr].dev_num; - tu_df10[ctlr].nxmerr = 19; - tu_df10[ctlr].ccw_comp = 14; - tu_attn[ctlr] = 0; - tu_rae[ctlr] = 0; + tu_rh[ctlr].devnum = tu_dib[ctlr].dev_num; + tu_rh[ctlr].attn = 0; + tu_rh[ctlr].rae = 0; } return SCPE_OK; } @@ -1100,20 +839,17 @@ tu_boot(int32 unit_num, DEVICE * dptr) t_stat tu_attach(UNIT * uptr, CONST char *file) { t_stat r; - int ctlr = GET_CNTRL(uptr->flags); - struct df10 *df; - - /* Find df10 */ - df = &tu_df10[ctlr]; + int ctlr = GET_CNTRL_RH(uptr->flags); + struct rh_if *rhc = &tu_rh[ctlr]; uptr->CMD = 0; uptr->STATUS = 0; r = sim_tape_attach_ex(uptr, file, 0, 0); if (r == SCPE_OK) { uptr->CMD = CS_ATA|CS_CHANGE; - tu_attn[ctlr] = 1; - if ((df->status & IADR_ATTN) != 0) - df10_setirq(df); + rhc->attn = 1; + if ((rhc->status & IADR_ATTN) != 0) + rh_setirq(rhc); } return r; } @@ -1121,16 +857,15 @@ tu_attach(UNIT * uptr, CONST char *file) t_stat tu_detach(UNIT * uptr) { - int ctlr = GET_CNTRL(uptr->flags); - struct df10 *df; + int ctlr = GET_CNTRL_RH(uptr->flags); + struct rh_if *rhc = &tu_rh[ctlr]; /* Find df10 */ - df = &tu_df10[ctlr]; uptr->STATUS = 0; uptr->CMD = CS_ATA|CS_CHANGE; - tu_attn[ctlr] = 1; - if ((df->status & IADR_ATTN) != 0) - df10_setirq(df); + rhc->attn = 1; + if ((rhc->status & IADR_ATTN) != 0) + rh_setirq(rhc); return sim_tape_detach(uptr); } diff --git a/README.md b/README.md index 979d60d..63798b9 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,6 @@ The PDP6 runs TOPS 10 4.5 off Dectape. The KA10 sim has successfully run Tops 10 4.5, 5.03 and Tops 10 6.03, ITS and WAITS. The KI10 sim has successfully run Tops 10 6.03 with VMSER. The KL10 sim has successfully run Tops 10 6.03 with VMSER and ITS. -KL10 extended addressing support is still in development. Disk * RC10 RD10/RM10 diff --git a/makefile b/makefile index f32920e..e645ce4 100644 --- a/makefile +++ b/makefile @@ -1232,13 +1232,13 @@ KA10 = ${KA10D}/kx10_cpu.c ${KA10D}/kx10_sys.c ${KA10D}/kx10_df.c \ ${KA10D}/kx10_rp.c ${KA10D}/kx10_rc.c ${KA10D}/kx10_dt.c \ ${KA10D}/kx10_dk.c ${KA10D}/kx10_cr.c ${KA10D}/kx10_cp.c \ ${KA10D}/kx10_tu.c ${KA10D}/kx10_rs.c ${KA10D}/ka10_pd.c \ - ${KA10D}/kx10_imp.c ${KA10D}/ka10_tk10.c ${KA10D}/ka10_mty.c \ - ${KA10D}/ka10_imx.c ${KA10D}/ka10_ch10.c ${KA10D}/ka10_stk.c \ - ${KA10D}/ka10_ten11.c ${KA10D}/ka10_auxcpu.c $(KA10D)/ka10_pmp.c \ - ${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c ${KA10D}/pdp6_dtc.c \ - ${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c ${KA10D}/pdp6_dcs.c \ - ${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c ${PDP10D}/ka10_ai.c \ - ${KA10D}/ka10_iii.c ${DISPLAYL} $(DISPLAY340) + ${KA10D}/kx10_rh.c ${KA10D}/kx10_imp.c ${KA10D}/ka10_tk10.c \ + ${KA10D}/ka10_mty.c ${KA10D}/ka10_imx.c ${KA10D}/ka10_ch10.c \ + ${KA10D}/ka10_stk.c ${KA10D}/ka10_ten11.c ${KA10D}/ka10_auxcpu.c \ + $(KA10D)/ka10_pmp.c ${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c \ + ${KA10D}/pdp6_dtc.c ${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c \ + ${KA10D}/pdp6_dcs.c ${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c \ + ${PDP10D}/ka10_ai.c ${KA10D}/ka10_iii.c ${DISPLAYL} $(DISPLAY340) KA10_OPT = -DKA=1 -DUSE_INT64 -I $(KA10D) -DUSE_SIM_CARD ${NETWORK_OPT} $(DISPLAY_OPT) $(KA10_DISPLAY_OPT) ifneq ($(PANDA_LIGHTS),) # ONLY for Panda display. @@ -1254,10 +1254,10 @@ endif KI10 = ${KI10D}/kx10_cpu.c ${KI10D}/kx10_sys.c ${KI10D}/kx10_df.c \ ${KI10D}/kx10_dp.c ${KI10D}/kx10_mt.c ${KI10D}/kx10_cty.c \ ${KI10D}/kx10_lp.c ${KI10D}/kx10_pt.c ${KI10D}/kx10_dc.c \ - ${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c ${KI10D}/kx10_dt.c \ - ${KI10D}/kx10_dk.c ${KI10D}/kx10_cr.c ${KI10D}/kx10_cp.c \ - ${KI10D}/kx10_tu.c ${KI10D}/kx10_rs.c ${KI10D}/kx10_imp.c \ - ${KI10D}/kx10_dpy.c ${DISPLAYL} $(DISPLAY340) + ${KI10D}/kx10_rh.c ${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c \ + ${KI10D}/kx10_dt.c ${KI10D}/kx10_dk.c ${KI10D}/kx10_cr.c \ + ${KI10D}/kx10_cp.c ${KI10D}/kx10_tu.c ${KI10D}/kx10_rs.c \ + ${KI10D}/kx10_imp.c ${KI10D}/kx10_dpy.c ${DISPLAYL} $(DISPLAY340) KI10_OPT = -DKI=1 -DUSE_INT64 -I $(KI10D) -DUSE_SIM_CARD ${NETWORK_OPT} $(DISPLAY_OPT) $(KI10_DISPLAY_OPT) ifneq ($(PANDA_LIGHTS),) # ONLY for Panda display. @@ -1268,9 +1268,10 @@ endif KL10D = PDP10 KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \ - ${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rp.c \ - ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c ${KL10D}/kx10_imp.c \ - ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c ${KL10D}/ka10_ch10.c + ${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rh.c \ + ${KL10D}/kx10_rp.c ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c \ + ${KL10D}/kx10_imp.c ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c \ + ${KL10D}/ka10_ch10.c KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT} PDP1D = PDP1 From f0cc9bd94bebd6b4d0796bfcbbe61ba699ed0427 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 16 Oct 2019 08:49:11 -0400 Subject: [PATCH 25/98] KA10: Fixed ITS support. --- PDP10/kx10_rh.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index b337018..913d974 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -495,7 +495,9 @@ rh_devirq(uint32 dev, int addr) { void rh_setattn(struct rh_if *rhc, int unit) { rhc->attn |= 1<status & IADR_ATTN) != 0) + if (rhc->imode != 2 && rhc->status & BUSY) + return; + if ((rhc->status & IADR_ATTN) != 0) rh_setirq(rhc); } From dc2e0fb7bf0d002c31a2237b09f67253becd07da Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 16 Oct 2019 20:24:13 -0400 Subject: [PATCH 26/98] KA10: Added sector counter to RP06 drives. --- PDP10/kx10_rp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index 9c421f6..28c93d2 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -133,7 +133,7 @@ /* RPDT - 06 - drive type */ /* RPLA - 07 - look ahead register */ - +#define LA_REG us9 #define LA_V_SC 6 /* sector pos */ /* RPER2 - 10 - error status 2 - drive unsafe conditions - unimplemented */ @@ -713,6 +713,10 @@ rp_read(DEVICE *dptr, struct rh_if *rhc, int reg) { temp = uptr->ERR3; break; case 007: /* look ahead */ + uptr->LA_REG += 0100; + uptr->LA_REG &= 07700; + temp = uptr->LA_REG; + break; case 016: /* ecc position */ case 017: /* ecc pattern */ break; From 1b2e0468b53e8f6979d127a5b671a9c8d26d5f28 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 17 Oct 2019 09:10:03 -0400 Subject: [PATCH 27/98] KA10: Fixed ITS one-proceed for KL10 --- PDP10/kx10_cpu.c | 62 +++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index d8e6f9d..78d1212 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1174,7 +1174,6 @@ t_stat dev_pi(uint32 dev, uint64 *data) { if (dev & 040) { /* SBDIAG */ AB = (AB + 1) & RMASK; res = 0; -// fprintf(stderr, "SBDIAG %012llo\n\r", *data); if (((*data >> 31) & 037) == 010) { switch(*data & 037) { case 0: res = 06000000000LL; break; @@ -1182,7 +1181,6 @@ t_stat dev_pi(uint32 dev, uint64 *data) { case 2: res = 0; break; default: res = 0; break; } - // fprintf(stderr, "SBDIAG return %012llo\n\r", res); } MB = res; (void)Mem_write(0, 0); @@ -3950,7 +3948,7 @@ int flag1; int flag3; int instr_count = 0; /* Number of instructions to execute */ uint32 IA; -#if ITS +#if ITS | KL_ITS char one_p_arm = 0; /* One proceed arm */ #endif @@ -3985,10 +3983,14 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ set_quantum(); } #endif - watch_stop = 0; +#if KL_ITS + if (QITS) + one_p_arm = 0; +#endif + watch_stop = 0; - while ( reason == 0) { /* loop until ABORT */ - if (sim_interval <= 0) { /* check clock queue */ + while ( reason == 0) { /* loop until ABORT */ + if (sim_interval <= 0) { /* check clock queue */ if ((reason = sim_process_event()) != SCPE_OK) {/* error? stop sim */ #if ITS if (QITS) @@ -4045,7 +4047,6 @@ fetch: } } #endif - if (Mem_read(pi_cycle | uuo_cycle, 1, 1)) { pi_rq = check_irq_level(); if (pi_rq) @@ -4073,21 +4074,21 @@ no_fetch: #if KI | KL /* Handle page fault and traps */ if (page_enable && trap_flag == 0 && (FLAGS & (TRP1|TRP2))) { + if (FLAGS & ADRFLT) { #if KL_ITS - if (QITS && (FLAGS & (ADRFLT|BYTI)) == ADRFLT) { - FLAGS &= ~ADRFLT; + if (QITS && (FLAGS & (TRP1|TRP2|ADRFLT)) == (TRP1|TRP2|ADRFLT)) + one_p_arm = 1; +#endif + FLAGS &= ~ADRFLT; } else { -#endif - AB = 0420 + ((FLAGS & (TRP1|TRP2)) >> 2); - trap_flag = FLAGS & (TRP1|TRP2); - FLAGS &= ~(TRP1|TRP2); - pi_cycle = 1; - AB += (FLAGS & USER) ? ub_ptr : eb_ptr; - Mem_read_nopage(); - goto no_fetch; -#if KL_ITS + AB = 0420 + ((FLAGS & (TRP1|TRP2)) >> 2); + trap_flag = FLAGS & (TRP1|TRP2); + FLAGS &= ~(TRP1|TRP2); + pi_cycle = 1; + AB += (FLAGS & USER) ? ub_ptr : eb_ptr; + Mem_read_nopage(); + goto no_fetch; } -#endif } #endif @@ -5766,7 +5767,7 @@ unasign: } FE = 36 - (adjb * SC) - ((36 - FE) % SC); /* New P */ #if KLB - if (f) { + if (QKLB && f) { /* Short pointer */ f = (AR >> 30) & 077; /* P */ AR = (((uint64)((f + adjb) & 077)) << 30) | /* Make new BP */ @@ -5856,8 +5857,8 @@ unasign: goto last; AB = (AB - 1) & RMASK; } else - AR = (AR & LMASK) | ((AR + 1) & RMASK); #endif + AR = (AR & LMASK) | ((AR + 1) & RMASK); #elif KI AR = (AR & LMASK) | ((AR + 1) & RMASK); #else @@ -5912,6 +5913,12 @@ ldb_ptr: f_load_pc = 0; f_inst_fetch = 0; f_pc_inh = 1; +#if KL_ITS + if (QITS && one_p_arm) { + FLAGS |= ADRFLT; + one_p_arm = 0; + } +#endif FLAGS |= BYTI; BYF5 = 1; #if KL @@ -7131,6 +7138,12 @@ left: FLAGS |= ONEP; one_p_arm = 0; } +#endif +#if KL_ITS + if (QITS && one_p_arm) { + FLAGS |= ADRFLT; + one_p_arm = 0; + } #endif } #if KL @@ -7378,6 +7391,12 @@ jrstf: FLAGS |= ONEP; one_p_arm = 0; } +#endif +#if ITS + if (QITS && one_p_arm) { + FLAGS |= ADRFLT; + one_p_arm = 0; + } #endif break; @@ -8360,7 +8379,6 @@ fetch_opr: AR = MB; } dev_tab[d](040|DATAO|(d<<2), &AR); -if (d == 1) fprintf(stderr, "SBDIAG return %012llo\n\r", AR); } else { dev_tab[d](040|DATAI|(d<<2), &AR); MB = AR; From 6d016fb17c9575b474fe1df2dc54f5ec5cf18ca5 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 17 Oct 2019 23:18:20 -0400 Subject: [PATCH 28/98] KA10: Fixed ITS build, cleanup trailing blanks. --- PDP10/kx10_cpu.c | 215 +++++++++++++++++++++++------------------------ PDP10/kx10_rh.c | 28 +++--- 2 files changed, 120 insertions(+), 123 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 78d1212..d3b59cf 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -885,37 +885,37 @@ int opflags[] = { #endif #if KL & KLB -struct { +struct { int p; int s; - int n; + int n; int l; } _byte_adj[] = { - { /* 37 */ 36, 6, 38, 0 }, - { /* 38 */ 30, 6, 39, 0 }, - { /* 39 */ 24, 6, 40, 0 }, - { /* 40 */ 18, 6, 41, 0 }, - { /* 41 */ 12, 6, 42, 0 }, - { /* 42 */ 6, 6, 43, 0 }, - { /* 43 */ 0, 6, 37, 1 }, - { /* 44 */ 36, 8, 45, 0 }, - { /* 45 */ 28, 8, 46, 0 }, - { /* 46 */ 20, 8, 47, 0 }, - { /* 47 */ 12, 8, 48, 0 }, - { /* 48 */ 4, 8, 44, 1 }, - { /* 49 */ 36, 7, 50, 0 }, - { /* 50 */ 29, 7, 51, 0 }, - { /* 51 */ 22, 7, 52, 0 }, - { /* 52 */ 15, 7, 53, 0 }, - { /* 53 */ 8, 7, 54, 0 }, - { /* 54 */ 1, 7, 49, 1 }, - { /* 55 */ 36, 9, 56, 0 }, - { /* 56 */ 27, 9, 57, 0 }, - { /* 57 */ 18, 9, 58, 0 }, - { /* 58 */ 9, 9, 59, 0 }, - { /* 59 */ 0, 9, 55, 1 }, - { /* 60 */ 36,18, 61, 0 }, - { /* 61 */ 18,18, 62, 0 }, + { /* 37 */ 36, 6, 38, 0 }, + { /* 38 */ 30, 6, 39, 0 }, + { /* 39 */ 24, 6, 40, 0 }, + { /* 40 */ 18, 6, 41, 0 }, + { /* 41 */ 12, 6, 42, 0 }, + { /* 42 */ 6, 6, 43, 0 }, + { /* 43 */ 0, 6, 37, 1 }, + { /* 44 */ 36, 8, 45, 0 }, + { /* 45 */ 28, 8, 46, 0 }, + { /* 46 */ 20, 8, 47, 0 }, + { /* 47 */ 12, 8, 48, 0 }, + { /* 48 */ 4, 8, 44, 1 }, + { /* 49 */ 36, 7, 50, 0 }, + { /* 50 */ 29, 7, 51, 0 }, + { /* 51 */ 22, 7, 52, 0 }, + { /* 52 */ 15, 7, 53, 0 }, + { /* 53 */ 8, 7, 54, 0 }, + { /* 54 */ 1, 7, 49, 1 }, + { /* 55 */ 36, 9, 56, 0 }, + { /* 56 */ 27, 9, 57, 0 }, + { /* 57 */ 18, 9, 58, 0 }, + { /* 58 */ 9, 9, 59, 0 }, + { /* 59 */ 0, 9, 55, 1 }, + { /* 60 */ 36,18, 61, 0 }, + { /* 61 */ 18,18, 62, 0 }, { /* 62 */ 0,18, 60, 1 } }; #endif @@ -1297,7 +1297,7 @@ t_stat dev_pag(uint32 dev, uint64 *data) { prev_ctx = (res >> 20) & 0160; } #if KLB - if (res & BIT1) { + if (QKLB && (res & BIT1) != 0) { /* Load previous section */ prev_sect = (res >> 18) & 037; } @@ -1427,16 +1427,16 @@ t_stat dev_apr(uint32 dev, uint64 *data) { #if KL_ITS if (QITS) AR |= 00020000000000LL; -#endif +#endif /* Bit 18 50hz */ /* Bit 19 Cache */ /* Bit 20 Channel? */ /* Bit 21 Extended KL10 */ /* Bit 22 Master Osc */ -#if KLB +#if KLB if (QKLB) AR |= BIT1|040000; -#endif +#endif AR |= (uint64)((apr_serial == -1) ? DEF_SERIAL : apr_serial); sim_debug(DEBUG_DATAIO, &cpu_dev, "APRID BLKI %012llo\n", MB); } else { @@ -1998,7 +1998,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) data &= RMASK; pg = 0; switch(data >> 16) { - case 0: + case 0: fault_data = 033LL << 30 |((uf)?SMASK:0); page_fault = 1; return 0; /* No access */ @@ -2481,8 +2481,7 @@ int Mem_read(int flag, int cur_context, int fetch) { return 0; } - if ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1)) && AB < 020) || - (!QKLB && AB < 020)) { + if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { #else if (AB < 020) { #endif @@ -2528,8 +2527,7 @@ int Mem_write(int flag, int cur_context) { return 0; } - if ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1)) && AB < 020) || - (!QKLB && AB < 020)) { + if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { #else if (AB < 020) { #endif @@ -4019,11 +4017,10 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ trap_flag = 0; #if KL #if KLB - if (QKLB) + if (QKLB) { sect = cur_sect = pc_sect; - else - sect = cur_sect = 0; - glb_sect = 0; + glb_sect = 0; + } #endif extend = 0; ptr_flg = 0; @@ -4064,7 +4061,8 @@ no_fetch: AD = MB; /* Save for historical sake */ IA = AB; #if KL & KLB - glb_sect = (cur_sect != 0); + if (QKLB) + glb_sect = (cur_sect != 0); #endif i_flags = opflags[IR]; @@ -4093,7 +4091,8 @@ no_fetch: #endif #if KLB - glb_sect = 0; + if (QKLB) + glb_sect = 0; #endif /* Handle indirection repeat until no longer indirect */ @@ -4139,8 +4138,10 @@ no_fetch: } else glb_sect = 0; #endif + /* For KL */ AR = MB = (AB + AR) & FMASK; #else + /* For KA & KI */ AR = MB = (AB + get_reg(ix)) & FMASK; #endif AB = MB & RMASK; @@ -4157,7 +4158,6 @@ in_loop: #if KL & KLB /* Check if extended indexing */ if (QKLB && cur_sect != 0) { -// fprintf(stderr, "Ind %06o %012llo\n\r", AB, MB); if (MB & SMASK) { /* Instruction format IFIW */ if (MB & BIT1) { /* Illegal index word */ fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | @@ -4189,9 +4189,8 @@ in_loop: AB = AR & RMASK; if (!glb_sect && AB < 020) /* Map to global AC */ sect = cur_sect = 1; -//fprintf(stderr, "IFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); } else { /* Extended index EFIW */ - ind = (MB & BIT1) != 0; + ind = (MB & BIT1) != 0; ix = (MB >> 30) & 017; AB = MB & (SECTM|RMASK); if (ix) { @@ -4215,7 +4214,7 @@ in_loop: } if (ind) goto in_loop; - } + } #endif } /* Handle events during a indirect loop */ @@ -4248,8 +4247,8 @@ st_pi: pi_hold = 0; pi_ov = 0; AB = 040 | (pi_enc << 1) | maoff; -#if KI | KL xct_flag = 0; +#if KI | KL #if KL #if KLB if (QKLB) @@ -4413,14 +4412,16 @@ muuo: #endif unasign: /* Save Opcode */ + AB = ub_ptr | 0424; #if KL & KLB + if (!QKLB && t20_page) + AB = AB + 1; if (QKLB && t20_page) { AR = (((uint64)cur_sect) << 18) | (uint64)AB; /* Save address */ MB = (((uint64)((IR << 9) | (AC << 5))) | ((uint64)(FLAGS) << 23)) & FMASK; } else #endif MB = ((uint64)(IR) << 27) | ((uint64)(AC) << 23) | (uint64)(AB); - AB = ub_ptr | 0424; Mem_write_nopage(); /* Save flags */ AB++; @@ -4449,12 +4450,12 @@ unasign: MB = SMASK|BIT1 | ((uint64)(fm_sel & 0160) << 23) | ((uint64)(prev_ctx & 0160) << 20) | -#if KLB - ((uint64)(prev_sect & 037) << 18) | -#endif (ub_ptr >> 9); #if KLB - prev_sect = pc_sect; + if (QKLB && t20_page) { + MB |= ((uint64)(prev_sect & 037) << 18); + prev_sect = pc_sect; + } #endif Mem_write_nopage(); #endif @@ -4507,7 +4508,7 @@ unasign: /* Now save like MUUO */ AB = MB & RMASK; sect = (MB >> 18) & 07777; - MB = (((uint64)((IR << 9) | (AC << 5))) | ((uint64)(FLAGS) << 23)) & FMASK; + MB = (((uint64)((IR << 9) | (AC << 5))) | ((uint64)(FLAGS) << 23)) & FMASK; if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; @@ -4627,7 +4628,7 @@ unasign: #if KL case 0105: /* ADJSP */ BR = get_reg(AC); -#if KLB +#if KLB if (QKLB && pc_sect != 0 && (BR & SMASK) == 0 && (BR & SECTM) != 0) { AD = (((AR & RSIGN)?(LMASK|AR):AR) + BR) & (SECTM|RMASK); AD |= BR & ~(SECTM|RMASK); @@ -4635,7 +4636,7 @@ unasign: #endif AD = (BR + AR) & RMASK; AD |= (BR & LMASK) + ((AR << 18) & LMASK); -#if KLB +#if KLB if (QKLB && pc_sect == 0) #endif if (((BR ^ AD) & SMASK) != 0) @@ -5774,7 +5775,7 @@ unasign: ((AR + adjw) & (SECTM|RMASK)); set_reg(AC, AR); break; - } else if (QKLB && pc_sect != 0 && (AR & BIT12) != 0) { + } else if (QKLB && pc_sect != 0 && (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; if (Mem_read(0, 0, 0)) @@ -5789,7 +5790,7 @@ unasign: goto last; } BR = (MB + adjw) & RMASK | (MB & LMASK); - } else + } else BR = (MB + adjw) & (SECTM|RMASK) | (MB & ~(SECTM|RMASK)); set_reg(AC, AR); set_reg(AC+1, BR); @@ -5851,7 +5852,7 @@ unasign: goto last; } MB = (MB + 1) & RMASK | (MB & LMASK); - } else + } else MB = (MB + 1) & (SECTM|RMASK) | (MB & ~(SECTM|RMASK)); if (Mem_write(0,0)) goto last; @@ -7224,7 +7225,7 @@ jrstf: case 007: /* XPCW */ #if KLB - if (QKLB) { +// if (QKLB) { MB = (((uint64)FLAGS) << 23) | (prev_sect & 037); if (Mem_write(0, 0)) goto last; @@ -7234,20 +7235,20 @@ jrstf: goto last; AB = (AB + 1) & RMASK; goto xjrstf; - } + // } #endif - goto muuo; +// goto muuo; case 014: /* SFM */ #if KLB - if (QKLB) { +// if (QKLB) { MB = ((((uint64)FLAGS) << 23) | (uint64)(prev_sect & 037)) & FMASK; //fprintf(stderr, "SFM %012llo\n\r", MB); (void)Mem_write(0, 0); goto last; - } + // } #endif - goto muuo; + // goto muuo; case 003: /* Invalid */ case 011: /* Invalid */ @@ -7508,16 +7509,15 @@ jrstf: #endif #endif BR = AB; -#if KL +#if KL BYF5 = 1; #if KLB if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - AR++; - // glb_sect = 1; + AR = (AR + 1) & FMASK; sect = (AR >> 18) & 07777; } else -#endif -#endif +#endif +#endif AR = AOB(AR); AB = AR & RMASK; if (Mem_write(uuo_cycle | pi_cycle, 0)) @@ -7558,18 +7558,18 @@ jrstf: break; case 0261: /* PUSH */ -#if KL +#if KL BYF5 = 1; #if KLB if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - AR++; + AR = (AR + 1) & FMASK; sect = (AR >> 18) & 07777; - // glb_sect = 1; } else -#endif -#endif +#endif +#endif AR = AOB(AR); AB = AR & RMASK; + MB = BR; #if KLB flag1 = glb_sect; if (QKLB) { @@ -7582,10 +7582,10 @@ jrstf: sect = (AR >> 18) & 07777; glb_sect = 1; } - } else - f = 0; -//fprintf(stderr, "Pop %o %o %06o %06o %06o %012llo %012llo\n\r", f, xct_flag, prev_sect, sect, cur_sect, AR, BR); - if (QKLB && !f) + if (Mem_write(0, 0)) + goto last; + break; + } #endif if (AR & C1) { #if KI | KL @@ -7596,13 +7596,12 @@ jrstf: check_apr_irq(); #endif } - MB = BR; if (Mem_write(0, 0)) goto last; break; case 0262: /* POP */ -#if KL +#if KL BYF5 = 1; /* Tell PXCT that this is stack */ #if KLB flag1 = glb_sect; @@ -7628,21 +7627,21 @@ jrstf: #if KL BYF5 = 0; /* Now back to data */ #if KLB - sect = cur_sect; - glb_sect = flag1; + if (QKLB) { + sect = cur_sect; + glb_sect = flag1; + } #endif #endif if (Mem_write(0, 0)) goto last; #if KL & KLB - if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - AR = AR - 1; - } else -#endif - AR = SOB(AR); -#if KLB - if (QKLB && !f) + if (QKLB && f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR = (AR - 1) & FMASK; + break; + } #endif + AR = SOB(AR); if ((AR & C1) == 0) { #if KI | KL if (!pi_cycle) @@ -7656,7 +7655,7 @@ jrstf: case 0263: /* POPJ */ AB = AR & RMASK; -#if KL +#if KL BYF5 = 1; /* Tell PXCT that this is stack */ #if KLB if (QKLB) { @@ -7671,8 +7670,8 @@ jrstf: } } else f = 0; -#endif -#endif +#endif +#endif if (Mem_read(0, 0, 0)) goto last; #if ITS | KL_ITS @@ -7686,16 +7685,14 @@ jrstf: #if KL BYF5 = 0; /* Tell PXCT that this is stack */ #if KLB - if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + if (QKLB && f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { pc_sect = (MB >> 18) & 07777; - AR = AR - 1; - } else -#endif + AR = (AR - 1) & FMASK; + break; + } +#endif #endif AR = SOB(AR); -#if KLB - if (QKLB && !f) -#endif if ((AR & C1) == 0) { #if KI | KL if (!pi_cycle) @@ -8694,7 +8691,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) int np; int ix; int ind; - + /* Get pointer */ val1 = get_reg(n+1); val2 = get_reg(n+2); @@ -8729,7 +8726,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) val2 = (val2 & LMASK) | ((val2 + 1) & RMASK); else val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); - } + } if (val2 & SMASK) { if (val2 & BIT1) { fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | @@ -8747,7 +8744,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) glb_sect = 0; //fprintf(stderr, "Load_byte1 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } else { - ind = (val2 & BIT1) != 0; + ind = (val2 & BIT1) != 0; ix = (val2 >> 30) & 017; MB = val2 & (SECTM|RMASK); sect = (MB >> 18) & 07777; @@ -8769,7 +8766,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) glb_sect = 0; //fprintf(stderr, "Load_byte3 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } - } else + } else #endif { if (np & 0400) { @@ -8846,7 +8843,7 @@ inx: AB = temp & RMASK; //fprintf(stderr, "IFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); } else { /* Extended index EFIW */ - ind = (MB & BIT1) != 0; + ind = (MB & BIT1) != 0; ix = (MB >> 30) & 017; AB = MB & (SECTM|RMASK); if (ix) { @@ -8933,7 +8930,7 @@ load_byte(int n, uint64 *data, uint64 fill, int cnt) } /* Fetch Pointer word */ - if (do_byte_setup(n, 0, &p, &s)) + if (do_byte_setup(n, 0, &p, &s)) goto back; /* Generate mask for given size */ @@ -8968,7 +8965,7 @@ store_byte(int n, uint64 data, int cnt) int s, p, addr, ind, np, ix; /* Fetch Pointer word */ - if (do_byte_setup(n, 1, &p, &s)) + if (do_byte_setup(n, 1, &p, &s)) goto back; /* Generate mask for given size */ @@ -9048,7 +9045,7 @@ adj_byte(int n) if (np & 0400) val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); } - } else + } else #endif { if (np & 0400) @@ -9110,7 +9107,7 @@ adv_byte(int n) } else np = p; } - } else + } else #endif { p = (p + (0777 ^ s) + 1) & 0777; @@ -9498,7 +9495,7 @@ do_extend(uint32 ia) MB = get_reg(ext_ac+4); #if KLB /* Make sure byte pointers are same size */ - if (QKLB && (MB & BIT12) != (BR & BIT12)) + if (QKLB && (MB & BIT12) != (BR & BIT12)) return 0; #endif if (Mem_write(0, 0)) diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index 913d974..cf7de14 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -139,7 +139,7 @@ 77 Status (tra,cb test, bar test, ev par, r/w, exc,ebl, 0, attn, sclk */ -/* +/* * CCW 000..... New channel comand list pointer HALT. 010..... Next CCW Address JUMP 1xycount-address. x=halt last xfer, y=reverse @@ -155,7 +155,7 @@ t_stat rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { DEVICE *dptr; - DIB *dibp; + DIB *dibp; dptr = find_dev_from_unit (uptr); if (dptr == NULL) return SCPE_IERR; @@ -211,7 +211,7 @@ t_stat rh_devio(uint32 dev, uint64 *data) { sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n", dptr->name, dev, (uint32)*data, PC, rhc->attn); return SCPE_OK; - + case CONO: clr_interrupt(dev); rhc->status &= ~(07LL|IADR_ATTN|RH20_MASS_EN); @@ -230,13 +230,13 @@ t_stat rh_devio(uint32 dev, uint64 *data) { rhc->rae = 0; if (*data & PI_ENABLE) rhc->status &= ~PI_ENABLE; - if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) + if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) || (rhc->status & PI_ENABLE)) set_interrupt(rhc->devnum, rhc->status); sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n", dptr->name, dev, (uint32)*data, PC, rhc->status); return SCPE_OK; - + case DATAI: *data = 0; if (rhc->status & BUSY && rhc->reg != 04) { @@ -272,7 +272,7 @@ t_stat rh_devio(uint32 dev, uint64 *data) { sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n", dptr->name, dev, *data, rhc->drive, PC); return SCPE_OK; - + case DATAO: sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n", dptr->name, dev, *data, PC, rhc->status); @@ -290,19 +290,19 @@ t_stat rh_devio(uint32 dev, uint64 *data) { return SCPE_OK; } rhc->rh_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); - if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) + if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) || (rhc->status & PI_ENABLE)) set_interrupt(rhc->devnum, rhc->status); /* Check if access error */ if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0) set_interrupt(rhc->devnum, rhc->status); - else + else rhc->rae &= ~(1 << rhc->drive); } else if ((rhc->reg & 070) != 070) { if ((*data & BIT9) == 0) { rhc->rae = (1 << rhc->drive); set_interrupt(rhc->devnum, rhc->status); - } + } } else { switch(rhc->reg & 07) { case 0: @@ -329,7 +329,7 @@ t_stat rh_devio(uint32 dev, uint64 *data) { if ((rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL)) rh20_setup(rhc); return SCPE_OK; - } + } #endif switch(dev & 3) { case CONI: @@ -464,7 +464,7 @@ t_stat rh_devio(uint32 dev, uint64 *data) { } } clr_interrupt(dev); - if (((rhc->status & (IADR_ATTN|BUSY)) == IADR_ATTN && rhc->attn != 0) + if (((rhc->status & (IADR_ATTN|BUSY)) == IADR_ATTN && rhc->attn != 0) || (rhc->status & PI_ENABLE)) set_interrupt(rhc->devnum, rhc->status); return SCPE_OK; @@ -497,7 +497,7 @@ void rh_setattn(struct rh_if *rhc, int unit) rhc->attn |= 1<imode != 2 && rhc->status & BUSY) return; - if ((rhc->status & IADR_ATTN) != 0) + if ((rhc->status & IADR_ATTN) != 0) rh_setirq(rhc); } @@ -551,7 +551,7 @@ void rh_writecw(struct rh_if *rhc, int nxm) { return; } #endif - if (nxm) + if (nxm) rhc->status |= CXR_NXM; rhc->status |= CCW_COMP_1; if (rhc->wcr != 0) @@ -568,7 +568,7 @@ void rh_finish_op(struct rh_if *rhc, int nxm) { rh_writecw(rhc, nxm); rh_setirq(rhc); #if KL - if (rhc->imode == 2 && + if (rhc->imode == 2 && (rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL)) rh20_setup(rhc); #endif From 8b99d318464ab16c9ed54587f038ad06099f0bfc Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 18 Oct 2019 08:15:36 -0400 Subject: [PATCH 29/98] KA10: Fixed ITS build issue. --- PDP10/kx10_cpu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index d3b59cf..e8d0385 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -4412,16 +4412,18 @@ muuo: #endif unasign: /* Save Opcode */ - AB = ub_ptr | 0424; #if KL & KLB - if (!QKLB && t20_page) - AB = AB + 1; if (QKLB && t20_page) { AR = (((uint64)cur_sect) << 18) | (uint64)AB; /* Save address */ MB = (((uint64)((IR << 9) | (AC << 5))) | ((uint64)(FLAGS) << 23)) & FMASK; } else #endif MB = ((uint64)(IR) << 27) | ((uint64)(AC) << 23) | (uint64)(AB); + AB = ub_ptr | 0424; +#if KL & KLB + if (!QKLB && !QITS && t20_page) + AB = AB + 1; +#endif Mem_write_nopage(); /* Save flags */ AB++; From 4d0724b21d5611d667d929c82f8e95d08ade0e66 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 20 Oct 2019 22:50:21 -0400 Subject: [PATCH 30/98] KA10: Added core dump/binary fill switch to load. --- PDP10/kx10_sys.c | 63 +++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index 1840edb..abed9ba 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -517,29 +517,28 @@ return SCPE_OK; } -int get_word(FILE *fileref, uint64 *word) +int get_word(FILE *fileref, uint64 *word, int ftype) { - char cbuf[5]; + char cbuf[5]; - if (sim_fread(cbuf, 1, 5, fileref) != 5) + if (sim_fread(cbuf, 1, 5, fileref) != 5) return 1; -#if 1 - *word = ((uint64)(cbuf[0] & 0177) << 29) | - ((uint64)(cbuf[1] & 0177) << 22) | - ((uint64)(cbuf[2] & 0177) << 15) | - ((uint64)(cbuf[3] & 0177) << 8) | - ((uint64)(cbuf[4] & 0177) << 1); - if (cbuf[4] & 0200) - *word |= 1; -#endif -#if 0 - *word = ((uint64)(cbuf[0] & 0377) << 28) | - ((uint64)(cbuf[1] & 0377) << 20) | - ((uint64)(cbuf[2] & 0377) << 12) | - ((uint64)(cbuf[3] & 0377) << 4) | - (uint64)(cbuf[4] & 017); -#endif - return 0; + if (ftype) { + *word = ((uint64)(cbuf[0] & 0177) << 29) | + ((uint64)(cbuf[1] & 0177) << 22) | + ((uint64)(cbuf[2] & 0177) << 15) | + ((uint64)(cbuf[3] & 0177) << 8) | + ((uint64)(cbuf[4] & 0177) << 1); + if (cbuf[4] & 0200) + *word |= 1; + } else { + *word = ((uint64)(cbuf[0] & 0377) << 28) | + ((uint64)(cbuf[1] & 0377) << 20) | + ((uint64)(cbuf[2] & 0377) << 12) | + ((uint64)(cbuf[3] & 0377) << 4) | + (uint64)(cbuf[4] & 017); + } + return 0; } /* SAV file loader @@ -555,14 +554,14 @@ int get_word(FILE *fileref, uint64 *word) JRST start */ -t_stat load_sav (FILE *fileref) +t_stat load_sav (FILE *fileref, int ftype) { uint64 data; uint32 pa; int32 wc; for ( ;; ) { /* loop */ - if (get_word(fileref, &data)) + if (get_word(fileref, &data, ftype)) return SCPE_OK; wc = (int32)(data >> 18); pa = (uint32) (data & RMASK); @@ -576,7 +575,7 @@ t_stat load_sav (FILE *fileref) pa &= RMASK; wc++; wc &= RMASK; - if (get_word(fileref, &data)) + if (get_word(fileref, &data, ftype)) return SCPE_FMT; M[pa] = data; } /* end if count*/ @@ -611,7 +610,7 @@ t_stat load_sav (FILE *fileref) #define PAG_V_PN 9 #define DIRSIZ (2 * PAG_SIZE) -t_stat load_exe (FILE *fileref) +t_stat load_exe (FILE *fileref, int ftype) { uint64 data, dirbuf[DIRSIZ], pagbuf[PAG_SIZE], entbuf[2]; int32 ndir, entvec, i, j, k, cont, bsz, bty, rpt, wc; @@ -622,7 +621,7 @@ ndir = entvec = 0; /* no dir, entvec */ cont = 1; do { - wc = get_word(fileref, &data); + wc = get_word(fileref, &data, ftype); if (wc != 0) /* error? */ return SCPE_FMT; bsz = (int32) ((data & RMASK) - 1); /* get count */ @@ -635,7 +634,7 @@ do { if (ndir != 0) /* got one */ return SCPE_FMT; for (i = 0; i < bsz; i++) { - if (get_word(fileref, &dirbuf[i])) + if (get_word(fileref, &dirbuf[i], ftype)) return SCPE_FMT; } ndir = bsz; @@ -649,7 +648,7 @@ do { if (bsz != 2) /* must be 2 wds */ return SCPE_FMT; for (i = 0; i < bsz; i++) { - if (get_word(fileref, &entbuf[i])) + if (get_word(fileref, &entbuf[i], ftype)) return SCPE_FMT; } entvec = bsz; @@ -675,7 +674,7 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */ if (fpage) { /* file pages? */ (void)sim_fseek (fileref, (fpage << PAG_V_PN) * 5, SEEK_SET); for (k = 0; k < PAG_SIZE; k++) { - if (get_word(fileref, &pagbuf[k])) + if (get_word(fileref, &pagbuf[k], ftype)) break; } fpage++; @@ -701,9 +700,13 @@ t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) { uint64 data; int32 wc, fmt; +int ftype; extern int32 sim_switches; fmt = 0; /* no fmt */ +ftype = 0; +if (sim_switches & SWMASK ('C')) /* -c? core dump */ + ftype = 1; if (sim_switches & SWMASK ('R')) /* -r? */ fmt = FMT_R; else if (sim_switches & SWMASK ('S')) /* -s? */ @@ -741,10 +744,10 @@ switch (fmt) { /* case fmt */ return load_rim (fileref); case FMT_S: /* SAV */ - return load_sav (fileref); + return load_sav (fileref, ftype); case FMT_E: /* EXE */ - return load_exe (fileref); + return load_exe (fileref, ftype); case FMT_D: /* DMP */ return load_dmp (fileref); From 851f477700a5beeae9d2e89b25ead01398f0f40a Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 20 Oct 2019 22:52:46 -0400 Subject: [PATCH 31/98] KA10: RH20 fixes to allow Tops 10 7.03 to start. --- PDP10/kx10_defs.h | 6 +- PDP10/kx10_rh.c | 79 +++++----- PDP10/kx10_rp.c | 19 ++- PDP10/kx10_tu.c | 362 +++++++++++++++++++++++----------------------- 4 files changed, 241 insertions(+), 225 deletions(-) diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 6ba7e7d..0a30c86 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -464,9 +464,9 @@ struct df10 { /* RH10/RH20 Interface */ struct rh_if { - void (*rh_write)(DEVICE *dptr, struct rh_if *rh, int reg, uint32 data); - uint32 (*rh_read)(DEVICE *dptr, struct rh_if *rh, int reg); - void (*rh_reset)(DEVICE *dptr); + void (*dev_write)(DEVICE *dptr, struct rh_if *rh, int reg, uint32 data); + uint32 (*dev_read)(DEVICE *dptr, struct rh_if *rh, int reg); + void (*dev_reset)(DEVICE *dptr); t_uint64 buf; /* Data buffer */ uint32 status; /* DF10 status word */ uint32 cia; /* Initial transfer address */ diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index cf7de14..30521aa 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -119,7 +119,7 @@ /* RH20 channel status flags */ #define RH20_MEM_PAR 00200000000000LL /* Memory parity error */ -#define RH20_ADR_PAR 00100000000000LL /* Address parity error */ +#define RH20_NADR_PAR 00100000000000LL /* Address parity error */ #define RH20_NOT_WC0 00040000000000LL /* Word count not zero */ #define RH20_NXM_ERR 00020000000000LL /* Non existent memory */ #define RH20_LAST_ERR 00000400000000LL /* Last transfer error */ @@ -206,8 +206,6 @@ t_stat rh_devio(uint32 dev, uint64 *data) { *data |= RH20_ATTN; if (rhc->rae != 0) *data |= RH20_RAE; - if ((rhc->status & PI_ENABLE) == 0) - *data |= RH20_CHAN_RDY; sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n", dptr->name, dev, (uint32)*data, PC, rhc->attn); return SCPE_OK; @@ -218,8 +216,8 @@ t_stat rh_devio(uint32 dev, uint64 *data) { rhc->status |= *data & (07LL|IADR_ATTN|RH20_MASS_EN); /* Clear flags */ if (*data & RH20_CLR_MBC) { - if (rhc->rh_reset != NULL) - rhc->rh_reset(dptr); + if (rhc->dev_reset != NULL) + rhc->dev_reset(dptr); rhc->imode = 2; } if (*data & RH20_DELETE_SCR) @@ -245,12 +243,12 @@ t_stat rh_devio(uint32 dev, uint64 *data) { } if (rhc->reg < 040) { int parity; - *data = (uint64)(rhc->rh_read(dptr, rhc, rhc->reg) & 0177777); + *data = (uint64)(rhc->dev_read(dptr, rhc, rhc->reg) & 0177777); parity = (int)((*data >> 8) ^ *data); parity = (parity >> 4) ^ parity; parity = (parity >> 2) ^ parity; parity = ((parity >> 1) ^ parity) & 1; - *data |= ((uint64)(parity ^ 1)) << 17; + *data |= ((uint64)(!parity)) << 16; *data |= ((uint64)(rhc->drive)) << 18; *data |= BIT10; } else if ((rhc->reg & 070) != 070) { @@ -278,9 +276,8 @@ t_stat rh_devio(uint32 dev, uint64 *data) { dptr->name, dev, *data, PC, rhc->status); rhc->reg = ((int)(*data >> 30)) & 077; rhc->imode |= 2; - if (rhc->reg < 040 && rhc->reg != 04) { - rhc->drive = (int)(*data >> 18) & 07; - } + if (rhc->reg < 040) + rhc->drive = (int)(*data >> 18) & 07; if (*data & LOAD_REG) { if (rhc->reg < 040) { clr_interrupt(dev); @@ -289,7 +286,7 @@ t_stat rh_devio(uint32 dev, uint64 *data) { set_interrupt(rhc->devnum, rhc->status); return SCPE_OK; } - rhc->rh_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); + rhc->dev_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) || (rhc->status & PI_ENABLE)) set_interrupt(rhc->devnum, rhc->status); @@ -350,8 +347,8 @@ t_stat rh_devio(uint32 dev, uint64 *data) { rhc->status &= ~(07LL|IADR_ATTN|IARD_RAE); rhc->status |= *data & (07LL|IADR_ATTN|IARD_RAE); /* Clear flags */ - if (*data & CONT_RESET && rhc->rh_reset != NULL) - rhc->rh_reset(dptr); + if (*data & CONT_RESET && rhc->dev_reset != NULL) + rhc->dev_reset(dptr); if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)) rhc->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)); if (*data & OVER_CLR) @@ -379,7 +376,7 @@ t_stat rh_devio(uint32 dev, uint64 *data) { return SCPE_OK; } if (rhc->reg == 040) { - *data = (uint64)(rhc->rh_read(dptr, rhc, 0) & 077); + *data = (uint64)(rhc->dev_read(dptr, rhc, 0) & 077); *data |= ((uint64)(rhc->cia)) << 6; *data |= ((uint64)(rhc->xfer_drive)) << 18; } else if (rhc->reg == 044) { @@ -392,7 +389,7 @@ t_stat rh_devio(uint32 dev, uint64 *data) { *data = (uint64)(rhc->rae); } else if ((rhc->reg & 040) == 0) { int parity; - *data = (uint64)(rhc->rh_read(dptr, rhc, rhc->reg) & 0177777); + *data = (uint64)(rhc->dev_read(dptr, rhc, rhc->reg) & 0177777); parity = (int)((*data >> 8) ^ *data); parity = (parity >> 4) ^ parity; parity = (parity >> 2) ^ parity; @@ -439,7 +436,7 @@ t_stat rh_devio(uint32 dev, uint64 *data) { /* Start command */ rh_setup(rhc, (uint32)(*data >> 6)); rhc->xfer_drive = (int)(*data >> 18) & 07; - rhc->rh_write(dptr, rhc, 0, (uint32)(*data & 077)); + rhc->dev_write(dptr, rhc, 0, (uint32)(*data & 077)); sim_debug(DEBUG_DATAIO, dptr, "%s %03o command %012llo, %d PC=%06o %06o\n", dptr->name, dev, *data, rhc->drive, PC, rhc->status); @@ -460,7 +457,7 @@ t_stat rh_devio(uint32 dev, uint64 *data) { if (rhc->rae & (1 << rhc->drive)) { return SCPE_OK; } - rhc->rh_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); + rhc->dev_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); } } clr_interrupt(dev); @@ -506,7 +503,8 @@ int rh_blkend(struct rh_if *rhc) { #if KL if (rhc->imode == 2) { - rhc->cia = (rhc->cia + 1) & RH20_WMASK; +//fprintf(stderr, "RH blkend %o\n\r", rhc->cia); + rhc->cia = (rhc->cia + 1) & 01777; if (rhc->cia == 0) { rhc->status |= RH20_XEND; return 1; @@ -527,25 +525,31 @@ void rh_writecw(struct rh_if *rhc, int nxm) { #if KL if (rhc->imode == 2) { uint32 chan = (rhc->devnum - 0540); - if (rhc->ptcr & BIT10) { - int wc = (rhc->wcr ^ RH20_WMASK) + 1; + int wc = ((rhc->wcr ^ RH20_WMASK) + 1) & RH20_WMASK; + rhc->status |= RH20_CHAN_RDY; + if (wc != 0 || (rhc->status & RH20_XEND) == 0 || + (rhc->ptcr & BIT10) != 0) { uint64 wrd1 = SMASK|(uint64)(rhc->ccw); - if (nxm) + if (nxm) { wrd1 |= RH20_NXM_ERR; + rhc->status |= RH20_CHAN_ERR; + } if (wc != 0) { wrd1 |= RH20_NOT_WC0; if (rhc->status & RH20_XEND) { wrd1 |= RH20_LONG_STS; - rhc->status |= RH20_LONG_WC; + rhc->status |= RH20_LONG_WC|RH20_CHAN_ERR; } } else if ((rhc->status & RH20_XEND) == 0) { wrd1 |= RH20_SHRT_STS; - rhc->status |= RH20_SHRT_WC; + rhc->status |= RH20_SHRT_WC|RH20_CHAN_ERR; } + wrd1 |= RH20_NADR_PAR; M[eb_ptr|chan|1] = wrd1; - M[eb_ptr|chan|2] = ((uint64)rhc->cop << 30) | - (((uint64)wc & RH20_WMASK) << CSHIFT) | - ((uint64)(rhc->cda) & AMASK); + M[eb_ptr|chan|2] = ((uint64)rhc->cop << 33) | + (((uint64)wc) << CSHIFT) | + ((uint64)(rhc->cda) & AMASK); +//fprintf(stderr, "RH20 final %012llo %012llo %06o\n\r", M[eb_ptr|chan|1], M[eb_ptr|chan|2], wc); } rhc->status &= ~(RH20_PCR_FULL); return; @@ -575,7 +579,6 @@ void rh_finish_op(struct rh_if *rhc, int nxm) { } #if KL - /* Set up for a RH20 transfer */ void rh20_setup(struct rh_if *rhc) { @@ -596,12 +599,12 @@ void rh20_setup(struct rh_if *rhc) rhc->drive = (rhc->ptcr >> 18) & 07; rhc->status &= ~(RH20_SCR_FULL|PI_ENABLE|RH20_XEND); rhc->status |= RH20_PCR_FULL; - reg = rhc->rh_read(dptr, rhc, 1); + reg = rhc->dev_read(dptr, rhc, 1); if ((reg & (DS_DRY|DS_DPR|DS_ERR)) != (DS_DRY|DS_DPR)) return; if (rhc->status & RH20_SBAR) { rhc->drive = (rhc->pbar >> 18) & 07; - rhc->rh_write(dptr, rhc, 5, (rhc->pbar & 0177777)); + rhc->dev_write(dptr, rhc, 5, (rhc->pbar & 0177777)); rhc->status &= ~RH20_SBAR; } if (rhc->ptcr & BIT7) { /* If RCPL reset I/O pointers */ @@ -609,9 +612,13 @@ void rh20_setup(struct rh_if *rhc) rhc->wcr = 0; } /* Hold block count in cia */ - rhc->cia = (rhc->ptcr >> 6); - rhc->rh_write(dptr, rhc, 0, (rhc->ptcr & 077)); + rhc->drive = (rhc->ptcr >> 18) & 07; + rhc->cia = (rhc->ptcr >> 6) & 01777; + rhc->dev_write(dptr, rhc, 0, (rhc->ptcr & 077)); rhc->cop = 0; + rhc->wcr = 0; + rhc->status &= ~RH20_CHAN_RDY; +//fprintf(stderr, "RH setup %06o %06o %o\n\r", rhc->ptcr, rhc->ccw, rhc->cia); } #endif @@ -630,7 +637,7 @@ int rh_fetch(struct rh_if *rhc) { uint64 data; #if KL if (rhc->imode == 2 && (rhc->cop & 2) != 0) { - rh_finish_op(rhc, 0); +// rh_finish_op(rhc, 0); return 0; } #endif @@ -641,17 +648,19 @@ int rh_fetch(struct rh_if *rhc) { data = M[rhc->ccw]; #if KL if (rhc->imode == 2) { +//fprintf(stderr, "RH20 fetch %06o %012llo\n\r", rhc->ccw, data); while((data & RH20_XFER) == 0) { rhc->ccw = (uint32)(data & AMASK); if ((data & (BIT1|BIT2)) == 0) { - rh_finish_op(rhc, 0); - break; +// rh_finish_op(rhc, 0); + return 0; } if (rhc->ccw > MEMSIZE) { rh_finish_op(rhc, 1); return 0; } data = M[rhc->ccw]; +//fprintf(stderr, "RH20 fetch2 %06o %012llo\n\r", rhc->ccw, data); } rhc->wcr = (((data >> CSHIFT) & RH20_WMASK) ^ WMASK) + 1; rhc->cda = (data & AMASK); @@ -662,7 +671,7 @@ int rh_fetch(struct rh_if *rhc) { #endif while((data & (WMASK << CSHIFT)) == 0) { if ((data & AMASK) == 0 || (uint32)(data & AMASK) == rhc->ccw) { - rh_finish_op(rhc,0); + rh_finish_op(rhc, 0); return 0; } rhc->ccw = (uint32)(data & AMASK); diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index 28c93d2..56bdeba 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -738,6 +738,7 @@ t_stat rp_svc (UNIT *uptr) struct rh_if *rhc; int diff, da; t_stat r; + int sts; dptr = rp_devs[ctlr]; rhc = &rp_rh[ctlr]; @@ -887,7 +888,7 @@ t_stat rp_svc (UNIT *uptr) } } if (rh_blkend(rhc)) - goto rd_end; + goto rd_end; } sim_activate(uptr, 10); } else { @@ -930,13 +931,15 @@ rd_end: uptr->DATAPTR = 0; uptr->hwmark = 0; } - r = rh_read(rhc); + sts = rh_read(rhc); sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %06o\n", dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->wcr); rp_buf[ctlr][uptr->DATAPTR++] = rhc->buf; - if (r == 0 || uptr->DATAPTR == RP_NUMWD) { + if (sts == 0) { while (uptr->DATAPTR < RP_NUMWD) rp_buf[ctlr][uptr->DATAPTR++] = 0; + } + if (uptr->DATAPTR == RP_NUMWD) { sim_debug(DEBUG_DETAIL, dptr, "%s%o write (%d,%d,%d)\n", dptr->name, unit, cyl, GET_SF(uptr->DA), GET_SC(uptr->DA)); da = GET_DA(uptr->DA, dtype) * RP_NUMWD; @@ -945,7 +948,7 @@ rd_end: uptr->fileref); uptr->DATAPTR = 0; CLR_BUF(uptr); - if (r) { + if (sts) { uptr->DA += 1 << DA_V_SC; if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect) { uptr->DA &= (DA_M_SF << DA_V_SF) | (DC_M_CY << DC_V_CY); @@ -956,11 +959,11 @@ rd_end: uptr->CMD |= DS_PIP; } } - if (rh_blkend(rhc)) - goto wr_end; - } + } + if (rh_blkend(rhc)) + goto wr_end; } - if (r) { + if (sts) { sim_activate(uptr, 10); } else { wr_end: diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index 34fb4ef..f6f17a2 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -233,7 +233,7 @@ REG tua_reg[] = { {ORDATA(BUF, tu_rh[0].buf, 36), REG_HRO}, {BRDATA(BUFF, &tu_buf[0][0], 16, 64, TU_NUMFR), REG_HRO}, {0} -}; +}; DEVICE tua_dev = { "TUA", tu_unit, NULL, tu_mod, @@ -496,135 +496,139 @@ t_stat tu_srv(UNIT * uptr) switch (GET_FNC(uptr->CMD)) { case FNC_NOP: case FNC_DCLR: - sim_debug(DEBUG_DETAIL, dptr, "%s%o nop\n", dptr->name, unit); - tu_error(uptr, MTSE_OK); /* Nop */ - rh_setirq(rhc); - return SCPE_OK; + sim_debug(DEBUG_DETAIL, dptr, "%s%o nop\n", dptr->name, unit); + tu_error(uptr, MTSE_OK); /* Nop */ + rh_setirq(rhc); + return SCPE_OK; case FNC_REWIND: - sim_debug(DEBUG_DETAIL, dptr, "%s%o rewind\n", dptr->name, unit); - if (uptr->CMD & CS1_GO) { - sim_activate(uptr,40000); - uptr->CMD |= CS_MOTION; - uptr->CMD &= ~(CS1_GO); - } else { + sim_debug(DEBUG_DETAIL, dptr, "%s%o rewind\n", dptr->name, unit); + if (uptr->CMD & CS1_GO) { + sim_activate(uptr,40000); + uptr->CMD |= CS_MOTION; + uptr->CMD &= ~(CS1_GO); + } else { uptr->CMD &= ~(CS_MOTION|CS_PIP); uptr->CMD |= CS_CHANGE|CS_ATA; tu_error(uptr, sim_tape_rewind(uptr)); - } - return SCPE_OK; + } + return SCPE_OK; case FNC_UNLOAD: - sim_debug(DEBUG_DETAIL, dptr, "%s%o unload\n", dptr->name, unit); - uptr->CMD &= ~(CS1_GO); - uptr->CMD |= CS_CHANGE|CS_ATA; - tu_error(uptr, sim_tape_detach(uptr)); - return SCPE_OK; + sim_debug(DEBUG_DETAIL, dptr, "%s%o unload\n", dptr->name, unit); + uptr->CMD &= ~(CS1_GO); + uptr->CMD |= CS_CHANGE|CS_ATA; + tu_error(uptr, sim_tape_detach(uptr)); + return SCPE_OK; case FNC_WCHKREV: case FNC_READREV: - if (BUF_EMPTY(uptr)) { - uptr->CMD &= ~CS_PIP; - if ((r = sim_tape_rdrecr(uptr, &tu_buf[ctlr][0], &reclen, - TU_NUMFR)) != MTSE_OK) { - sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r); - if (r == MTSE_BOT) - uptr->STATUS |= ER1_NEF; - tu_error(uptr, r); - rh_finish_op(rhc, 0); - } else { - sim_debug(DEBUG_DETAIL, dptr, "%s%o read %d\n", dptr->name, unit, reclen); - uptr->CMD |= CS_MOTION; - uptr->hwmark = reclen; - uptr->DATAPTR = uptr->hwmark-1; - uptr->CPOS = cc_max; - rhc->buf = 0; - sim_activate(uptr, 100); - } - return SCPE_OK; - } - if (uptr->DATAPTR >= 0) { - tu_frame[ctlr]++; - cc = (8 * (3 - uptr->CPOS)) + 4; - ch = tu_buf[ctlr][uptr->DATAPTR]; - if (cc < 0) - rhc->buf |= (uint64)(ch & 0x0f); - else - rhc->buf |= (uint64)(ch & 0xff) << cc; - uptr->DATAPTR--; - uptr->CPOS--; - if (uptr->CPOS == 0) { - uptr->CPOS = cc_max; - if (GET_FNC(uptr->CMD) == FNC_READREV && rh_write(rhc) == 0) { - tu_error(uptr, MTSE_OK); - return SCPE_OK; - } - sim_debug(DEBUG_DATA, dptr, "%s%o readrev %012llo\n", - dptr->name, unit, rhc->buf); - rhc->buf = 0; - } - } else { - if (uptr->CPOS != cc_max) + if (BUF_EMPTY(uptr)) { + uptr->CMD &= ~CS_PIP; + if ((r = sim_tape_rdrecr(uptr, &tu_buf[ctlr][0], &reclen, + TU_NUMFR)) != MTSE_OK) { + sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r); + if (r == MTSE_BOT) + uptr->STATUS |= ER1_NEF; + tu_error(uptr, r); + rh_finish_op(rhc, 0); + } else { + sim_debug(DEBUG_DETAIL, dptr, "%s%o read %d\n", dptr->name, unit, reclen); + uptr->CMD |= CS_MOTION; + uptr->hwmark = reclen; + uptr->DATAPTR = uptr->hwmark-1; + uptr->CPOS = cc_max; + rhc->buf = 0; + sim_activate(uptr, 100); + } + return SCPE_OK; + } + if (uptr->DATAPTR >= 0) { + tu_frame[ctlr]++; + cc = (8 * (3 - uptr->CPOS)) + 4; + ch = tu_buf[ctlr][uptr->DATAPTR]; + if (cc < 0) + rhc->buf |= (uint64)(ch & 0x0f); + else + rhc->buf |= (uint64)(ch & 0xff) << cc; + uptr->DATAPTR--; + uptr->CPOS--; + if (uptr->CPOS == 0) { + uptr->CPOS = cc_max; + if (GET_FNC(uptr->CMD) == FNC_READREV && rh_write(rhc) == 0) { + tu_error(uptr, MTSE_OK); + rh_finish_op(rhc, 0); + return SCPE_OK; + } + sim_debug(DEBUG_DATA, dptr, "%s%o readrev %012llo\n", + dptr->name, unit, rhc->buf); + rhc->buf = 0; + } + } else { + if (uptr->CPOS != cc_max) rh_write(rhc); - (void)rh_blkend(rhc); - tu_error(uptr, MTSE_OK); + (void)rh_blkend(rhc); + tu_error(uptr, MTSE_OK); rh_finish_op(rhc, 0); - return SCPE_OK; - } - break; + return SCPE_OK; + } + break; case FNC_WCHK: case FNC_READ: - if (BUF_EMPTY(uptr)) { - uptr->CMD &= ~CS_PIP; - uptr->CMD |= CS_MOTION; - if ((r = sim_tape_rdrecf(uptr, &tu_buf[ctlr][0], &reclen, - TU_NUMFR)) != MTSE_OK) { - sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r); - tu_error(uptr, r); - rh_finish_op(rhc, 0); - } else { - sim_debug(DEBUG_DETAIL, dptr, "%s%o read %d %d\n", dptr->name, unit, reclen, uptr->pos); - uptr->hwmark = reclen; - uptr->DATAPTR = 0; - uptr->CPOS = 0; - rhc->buf = 0; - sim_activate(uptr, 100); - } - return SCPE_OK; - } - if ((uint32)uptr->DATAPTR < uptr->hwmark) { - tu_frame[ctlr]++; - cc = (8 * (3 - uptr->CPOS)) + 4; - ch = tu_buf[ctlr][uptr->DATAPTR]; - if (cc < 0) - rhc->buf |= (uint64)(ch & 0x0f); - else - rhc->buf |= (uint64)(ch & 0xff) << cc; - uptr->DATAPTR++; - uptr->CPOS++; - if (uptr->CPOS == cc_max) { - uptr->CPOS = 0; - if (GET_FNC(uptr->CMD) == FNC_READ && rh_write(rhc) == 0) { - tu_error(uptr, MTSE_OK); - return SCPE_OK; - } - sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo\n", - dptr->name, unit, rhc->buf); - rhc->buf = 0; - } - } else { - if (uptr->CPOS != 0) { - sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo\n", - dptr->name, unit, rhc->buf); - rh_write(rhc); - } - tu_error(uptr, MTSE_OK); - (void)rh_blkend(rhc); - rh_finish_op(rhc, 0); - return SCPE_OK; - } - break; + if (BUF_EMPTY(uptr)) { + uptr->CMD &= ~CS_PIP; + uptr->CMD |= CS_MOTION; + if ((r = sim_tape_rdrecf(uptr, &tu_buf[ctlr][0], &reclen, + TU_NUMFR)) != MTSE_OK) { + sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r); + tu_error(uptr, r); + rh_finish_op(rhc, 0); + } else { + sim_debug(DEBUG_DETAIL, dptr, "%s%o read %d %d\n", dptr->name, unit, reclen, uptr->pos); + uptr->hwmark = reclen; + uptr->DATAPTR = 0; + uptr->CPOS = 0; + rhc->buf = 0; + sim_activate(uptr, 100); + } + return SCPE_OK; + } + if ((uint32)uptr->DATAPTR < uptr->hwmark) { + tu_frame[ctlr]++; + cc = (8 * (3 - uptr->CPOS)) + 4; + ch = tu_buf[ctlr][uptr->DATAPTR]; + if (cc < 0) + rhc->buf |= (uint64)(ch & 0x0f); + else + rhc->buf |= (uint64)(ch & 0xff) << cc; + uptr->DATAPTR++; + uptr->CPOS++; + if (uptr->CPOS == cc_max) { + uptr->CPOS = 0; + if (GET_FNC(uptr->CMD) == FNC_READ && rh_write(rhc) == 0) { + tu_error(uptr, MTSE_OK); + if (uptr->DATAPTR == uptr->hwmark) + (void)rh_blkend(rhc); + rh_finish_op(rhc, 0); + return SCPE_OK; + } + sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo\n", + dptr->name, unit, rhc->buf); + rhc->buf = 0; + } + } else { + if (uptr->CPOS != 0) { + sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo\n", + dptr->name, unit, rhc->buf); + rh_write(rhc); + } + tu_error(uptr, MTSE_OK); + (void)rh_blkend(rhc); + rh_finish_op(rhc, 0); + return SCPE_OK; + } + break; case FNC_WRITE: if (BUF_EMPTY(uptr)) { @@ -675,81 +679,81 @@ t_stat tu_srv(UNIT * uptr) uptr->CPOS = 010; } if (uptr->CPOS == 010) { - /* Write out the block */ - reclen = uptr->hwmark; - r = sim_tape_wrrecf(uptr, &tu_buf[ctlr][0], reclen); - sim_debug(DEBUG_DETAIL, dptr, "%s%o Write %d %d\n", - dptr->name, unit, reclen, uptr->CPOS); - uptr->DATAPTR = 0; - uptr->hwmark = 0; - (void)rh_blkend(rhc); - tu_error(uptr, r); /* Record errors */ - rh_finish_op(rhc,0 ); - return SCPE_OK; + /* Write out the block */ + reclen = uptr->hwmark; + r = sim_tape_wrrecf(uptr, &tu_buf[ctlr][0], reclen); + sim_debug(DEBUG_DETAIL, dptr, "%s%o Write %d %d\n", + dptr->name, unit, reclen, uptr->CPOS); + uptr->DATAPTR = 0; + uptr->hwmark = 0; + (void)rh_blkend(rhc); + tu_error(uptr, r); /* Record errors */ + rh_finish_op(rhc,0 ); + return SCPE_OK; } break; case FNC_WTM: - uptr->CMD |= CS_ATA; - if ((uptr->flags & MTUF_WLK) != 0) { - tu_error(uptr, MTSE_WRP); - } else { - tu_error(uptr, sim_tape_wrtmk(uptr)); - } - sim_debug(DEBUG_DETAIL, dptr, "%s%o WTM\n", dptr->name, unit); - return SCPE_OK; + uptr->CMD |= CS_ATA; + if ((uptr->flags & MTUF_WLK) != 0) { + tu_error(uptr, MTSE_WRP); + } else { + tu_error(uptr, sim_tape_wrtmk(uptr)); + } + sim_debug(DEBUG_DETAIL, dptr, "%s%o WTM\n", dptr->name, unit); + return SCPE_OK; case FNC_ERASE: - uptr->CMD |= CS_ATA; - if ((uptr->flags & MTUF_WLK) != 0) { - tu_error(uptr, MTSE_WRP); - } else { - tu_error(uptr, sim_tape_wrgap(uptr, 35)); - } - sim_debug(DEBUG_DETAIL, dptr, "%s%o ERG\n", dptr->name, unit); - return SCPE_OK; + uptr->CMD |= CS_ATA; + if ((uptr->flags & MTUF_WLK) != 0) { + tu_error(uptr, MTSE_WRP); + } else { + tu_error(uptr, sim_tape_wrgap(uptr, 35)); + } + sim_debug(DEBUG_DETAIL, dptr, "%s%o ERG\n", dptr->name, unit); + return SCPE_OK; case FNC_SPACEF: case FNC_SPACEB: - sim_debug(DEBUG_DETAIL, dptr, "%s%o space %o\n", dptr->name, unit, GET_FNC(uptr->CMD)); - if (tu_frame[ctlr] == 0) { - uptr->STATUS |= ER1_NEF; - uptr->CMD |= CS_ATA; - tu_error(uptr, MTSE_OK); - return SCPE_OK; - } - uptr->CMD |= CS_MOTION; - /* Always skip at least one record */ - if (GET_FNC(uptr->CMD) == FNC_SPACEF) - r = sim_tape_sprecf(uptr, &reclen); - else - r = sim_tape_sprecr(uptr, &reclen); - switch (r) { - case MTSE_OK: /* no error */ - break; + sim_debug(DEBUG_DETAIL, dptr, "%s%o space %o\n", dptr->name, unit, GET_FNC(uptr->CMD)); + if (tu_frame[ctlr] == 0) { + uptr->STATUS |= ER1_NEF; + uptr->CMD |= CS_ATA; + tu_error(uptr, MTSE_OK); + return SCPE_OK; + } + uptr->CMD |= CS_MOTION; + /* Always skip at least one record */ + if (GET_FNC(uptr->CMD) == FNC_SPACEF) + r = sim_tape_sprecf(uptr, &reclen); + else + r = sim_tape_sprecr(uptr, &reclen); + switch (r) { + case MTSE_OK: /* no error */ + break; - case MTSE_BOT: /* beginning of tape */ - uptr->STATUS |= ER1_NEF; - /* Fall Through */ + case MTSE_BOT: /* beginning of tape */ + uptr->STATUS |= ER1_NEF; + /* Fall Through */ - case MTSE_TMK: /* tape mark */ - case MTSE_EOM: /* end of medium */ - if (tu_frame[ctlr] != 0) - uptr->STATUS |= ER1_FCE; - uptr->CMD &= ~(CS1_GO); - uptr->CMD |= CS_ATA; - /* Stop motion if we recieve any of these */ - tu_error(uptr, r); - return SCPE_OK; - } - tu_frame[ctlr] = 0177777 & (tu_frame[ctlr] + 1); - if (tu_frame[ctlr] == 0) { - uptr->CMD |= CS_ATA; - tu_error(uptr, MTSE_OK); - return SCPE_OK; - } else - sim_activate(uptr, 5000); - return SCPE_OK; + case MTSE_TMK: /* tape mark */ + case MTSE_EOM: /* end of medium */ + if (tu_frame[ctlr] != 0) + uptr->STATUS |= ER1_FCE; + uptr->CMD &= ~(CS1_GO); + uptr->CMD |= CS_ATA; + /* Stop motion if we recieve any of these */ + tu_error(uptr, r); + return SCPE_OK; + } + tu_frame[ctlr] = 0177777 & (tu_frame[ctlr] + 1); + if (tu_frame[ctlr] == 0) { + uptr->CMD |= CS_ATA; + tu_error(uptr, MTSE_OK); + return SCPE_OK; + } else + sim_activate(uptr, 5000); + return SCPE_OK; } sim_activate(uptr, 100); return SCPE_OK; From eea9b1a9a2c457852cfd3d9ade63ae25f58bad5a Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 20 Oct 2019 22:53:26 -0400 Subject: [PATCH 32/98] KA10: Changes to fix issues with Tops 10 and Tops 20 on KL10B. --- PDP10/kx10_cpu.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index e8d0385..9957e1c 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2362,14 +2362,14 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch (!fetch || (M[*loc] & 00777740000000LL) != 0254040000000LL)) { /* Handle public violation */ fault_data = ((uint64)addr) | 021LL << 30 | BIT8 |((uf)?SMASK:0); -//fprintf(stderr, "Public fault %012llo %06o\n\r", fault_data, FLAGS << 5); +//fprintf(stderr, "Public fault %012llo %06o %06o\n\r", fault_data, FLAGS << 5, PC); page_fault = 1; return 0; } /* Check for access error */ if ((data & RSIGN) == 0 || (wr & ((data & 0100000) == 0))) { -//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); +//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data, PC); fault_data = BIT8 | (uint64)addr; #if KLB if (QKLB) @@ -4189,6 +4189,7 @@ in_loop: AB = AR & RMASK; if (!glb_sect && AB < 020) /* Map to global AC */ sect = cur_sect = 1; +//fprintf(stderr, "LFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); } else { /* Extended index EFIW */ ind = (MB & BIT1) != 0; ix = (MB >> 30) & 017; @@ -7240,6 +7241,19 @@ jrstf: // } #endif // goto muuo; + case 015: /* XJRST */ + if (Mem_read(0, 0, 0)) + goto last; + AR = MB; /* Get PC. */ +#if KLB + if (QKLB) { + pc_sect = (AR >> 18) & 07777; + if ((FLAGS & USER) == 0 && ((BR >> 23) & USER) == 0) + prev_sect = BR & 037; +//fprintf(stderr, "XJRST %06o %06o %06o %012llo\r\n", pc_sect, prev_sect, FLAGS, BR); + } +#endif + break; case 014: /* SFM */ #if KLB @@ -7255,7 +7269,6 @@ jrstf: case 003: /* Invalid */ case 011: /* Invalid */ case 013: /* Invalid */ - case 015: /* Invalid */ case 016: /* Invalid */ goto muuo; @@ -7510,7 +7523,7 @@ jrstf: } #endif #endif - BR = AB; +// BR = AB; #if KL BYF5 = 1; #if KLB @@ -7551,8 +7564,8 @@ jrstf: } #endif #if KL & KLB - if (QKLB && pc_sect != 0) - pc_sect = (BR >> 18) & 07777; + if (QKLB && pc_sect != 0 && glb_sect) + pc_sect = cur_sect; #endif PC = BR & RMASK; PC_CHANGE @@ -7687,10 +7700,12 @@ jrstf: #if KL BYF5 = 0; /* Tell PXCT that this is stack */ #if KLB - if (QKLB && f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + if (QKLB && f) { pc_sect = (MB >> 18) & 07777; - AR = (AR - 1) & FMASK; - break; + if ((AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR = (AR - 1) & FMASK; + break; + } } #endif #endif From 17307ec1c8bb64ea69458cff7ae32426d753c5a9 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 22 Oct 2019 22:05:55 -0400 Subject: [PATCH 33/98] KA10: More update to KL10B, converted addresses to t_addr. --- PDP10/ka10_auxcpu.c | 4 +- PDP10/ka10_ten11.c | 8 +- PDP10/kl10_fe.c | 6 +- PDP10/kx10_cpu.c | 392 +++++++++++++++++++++++++------------------- PDP10/kx10_defs.h | 12 +- PDP10/kx10_imp.c | 6 +- PDP10/kx10_rh.c | 9 +- PDP10/kx10_rp.c | 2 + PDP10/kx10_tu.c | 9 +- 9 files changed, 258 insertions(+), 190 deletions(-) diff --git a/PDP10/ka10_auxcpu.c b/PDP10/ka10_auxcpu.c index ca310d9..0ef22df 100644 --- a/PDP10/ka10_auxcpu.c +++ b/PDP10/ka10_auxcpu.c @@ -246,7 +246,7 @@ static int transaction (unsigned char *request, unsigned char *response) return 0; } -int auxcpu_read (int addr, t_uint64 *data) +int auxcpu_read (t_addr addr, t_uint64 *data) { unsigned char request[12]; unsigned char response[12]; @@ -292,7 +292,7 @@ int auxcpu_read (int addr, t_uint64 *data) return 0; } -int auxcpu_write (int addr, t_uint64 data) +int auxcpu_write (t_addr addr, t_uint64 data) { unsigned char request[12]; unsigned char response[12]; diff --git a/PDP10/ka10_ten11.c b/PDP10/ka10_ten11.c index 3f23c57..23ae2bf 100644 --- a/PDP10/ka10_ten11.c +++ b/PDP10/ka10_ten11.c @@ -244,7 +244,7 @@ static int transaction (unsigned char *request, unsigned char *response) return 0; } -static int read_word (int addr, int *data) +static int read_word (t_addr addr, int *data) { unsigned char request[8]; unsigned char response[8]; @@ -290,7 +290,7 @@ static int read_word (int addr, int *data) return 0; } -int ten11_read (int addr, uint64 *data) +int ten11_read (t_addr addr, uint64 *data) { int offset = addr & 01777; int word1, word2; @@ -333,7 +333,7 @@ int ten11_read (int addr, uint64 *data) return 0; } -static int write_word (int addr, uint16 data) +static int write_word (t_addr addr, uint16 data) { unsigned char request[8]; unsigned char response[8]; @@ -371,7 +371,7 @@ static int write_word (int addr, uint16 data) return 0; } -int ten11_write (int addr, uint64 data) +int ten11_write (t_addr addr, uint64 data) { int offset = addr & 01777; diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 13e900d..1902984 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -176,7 +176,7 @@ extern int32 tmxr_poll; t_stat dte_devio(uint32 dev, uint64 *data); -int dte_devirq(uint32 dev, int addr); +t_addr dte_devirq(uint32 dev, t_addr addr); void dte_second(UNIT *uptr); void dte_primary(UNIT *uptr); #if KL_ITS @@ -472,8 +472,8 @@ sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n"); } /* Handle KL style interrupt vectors */ -int -dte_devirq(uint32 dev, int addr) { +t_addr +dte_devirq(uint32 dev, t_addr addr) { return 0142; } diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 9957e1c..71ab362 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -122,8 +122,8 @@ uint64 MQ; /* Extension to AR */ uint64 BR; /* Secondary operand */ uint64 AD; /* Address Data */ uint64 MB; /* Memory Bufer Register */ -uint32 AB; /* Memory address buffer */ -uint32 PC; /* Program counter */ +t_addr AB; /* Memory address buffer */ +t_addr PC; /* Program counter */ uint32 IR; /* Instruction register */ uint64 MI; /* Monitor lights */ uint32 FLAGS; /* Flags */ @@ -169,8 +169,8 @@ int xct_flag; /* XCT flags */ uint64 ARX; /* Extension to AR */ uint64 BRX; /* Extension to BR */ uint64 ADX; /* Extension to AD */ -uint32 ub_ptr; /* User base pointer */ -uint32 eb_ptr; /* Executive base pointer */ +t_addr ub_ptr; /* User base pointer */ +t_addr eb_ptr; /* Executive base pointer */ uint8 fm_sel; /* User fast memory block */ int32 apr_serial = -1; /* CPU Serial number */ int inout_fail; /* In out fail flag */ @@ -250,7 +250,7 @@ int maoff = 0; /* Offset for traps */ uint16 dev_irq[128]; /* Pending irq by device */ t_stat (*dev_tab[128])(uint32 dev, uint64 *data); -int (*dev_irqv[128])(uint32 dev, int addr); +t_addr (*dev_irqv[128])(uint32 dev, t_addr addr); t_stat rtc_srv(UNIT * uptr); int32 rtc_tps = 60; #if ITS @@ -1423,7 +1423,9 @@ t_stat dev_apr(uint32 dev, uint64 *data) { /* Bit 0 for TOPS-20 paging */ /* Bit 1 for extended addressing */ /* Bit 2 Exotic microcode */ - /* Bit 4 for ITS Style Paging */ + /* Bit 3 KL10B */ + /* Bit 4 PMOVE/PMOVEM or ITS Style Paging */ + /* Bit 5 Tops-20 R5 microcode */ #if KL_ITS if (QITS) AR |= 00020000000000LL; @@ -1435,7 +1437,7 @@ t_stat dev_apr(uint32 dev, uint64 *data) { /* Bit 22 Master Osc */ #if KLB if (QKLB) - AR |= BIT1|040000; + AR |= BIT1|BIT4|040000; #endif AR |= (uint64)((apr_serial == -1) ? DEF_SERIAL : apr_serial); sim_debug(DEBUG_DATAIO, &cpu_dev, "APRID BLKI %012llo\n", MB); @@ -1629,8 +1631,8 @@ t_stat dev_tim(uint32 dev, uint64 *data) { return SCPE_OK; } -int -tim_irq(uint32 dev, int addr) +t_addr +tim_irq(uint32 dev, t_addr addr) { return 0514; } @@ -2029,19 +2031,21 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) #endif #define PG_PUB 0040000 #define PG_WRT 0020000 +#define PG_KEP 0010000 #define PG_CAC 0004000 -#define PG_STG 0000037 +#define PG_STG 0000077 #define PG_IDX 0000777 #define PG_MASK 0000003777777LL #define PG_AGE 0770000000000LL -#define PG_PAG 0007777 +#define PG_PAG 0017777 if (t20_page) { /* Start with full access */ - int acc_bits = PG_PUB|PG_WRT|PG_CAC; + int acc_bits = PG_PUB|PG_WRT|PG_KEP|PG_CAC; uint64 spt = FM[(06<<4)|3] & PG_MASK; uint64 cst = FM[(06<<4)|2] & PG_MASK; uint64 cst_msk = FM[(06<<4)|0]; uint64 cst_dat = FM[(06<<4)|1]; + uint64 cst_val; int index; int match = 0; int pg; @@ -2067,106 +2071,121 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) data = M[eb_ptr + base]; //fprintf(stderr, "Map %06o %03o %012llo %012llo %012llo\n\r", base, sect, data, spt, cst); /* Find correct page table */ - do { - switch ((data >> 33) & 07) { - default: /* Invalid page */ - fault_data = 024LL << 30; - page_fault = 1; - return 0; - case 1: /* Direct page */ - /* Bit 4 = execute */ - /* Bit 3 = Write */ - /* Bit 2 = Read */ - acc_bits &= (data >> 18) & RMASK; - match = 1; - break; +sect_loop: + switch ((data >> 33) & 07) { + default: /* Invalid page */ + fault_data = (wr)? BIT5:0; + page_fault = 1; + return 0; + case 1: /* Direct page */ + /* Bit 4 = execute */ + /* Bit 3 = Write */ + /* Bit 2 = Read */ + acc_bits &= (data >> 18) & RMASK; + break; - case 2: /* Shared page */ - acc_bits &= (data >> 18) & RMASK; - data = M[(data & RMASK) + spt]; - match = 1; - break; + case 2: /* Shared page */ + acc_bits &= (data >> 18) & RMASK; + data = M[(data & RMASK) + spt]; + break; - case 3: /* Indirect page */ - acc_bits &= (data >> 18) & RMASK; - index = (data >> 18) & PG_IDX; - data = M[(data & RMASK) + spt]; - if ((data >> 18) & PG_STG) { + case 3: /* Indirect page */ + acc_bits &= (data >> 18) & RMASK; + index = (data >> 18) & PG_IDX; + data = M[(data & RMASK) + spt]; + if (((data >> 18) & PG_STG) != 0) { + fault_data = 0; + page_fault = 1; + return 0; + } + pg = data & PG_PAG; + if (cst) { + cst_val = M[cst + pg]; + if ((cst_val & PG_AGE) == 0) { +//fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); if (trap) { fault_data = 0; page_fault = 1; } return 0; - } - data = M[(data & RMASK) + index]; - break; - + } + M[cst + pg] = (cst_val & cst_msk) | cst_dat; } - } while (!match); + data = M[(pg << 9) | index]; + goto sect_loop; + } + if (((data >> 18) & PG_STG) != 0) { + fault_data = 0; + page_fault = 1; + return 0; + } //fprintf(stderr, "XMap %012llo\n\r", data); + pg = data & PG_PAG; - match = 0; - /* Now look up address of final table entry */ - do { - if ((data >> 18) & PG_STG) { -//fprintf(stderr, "ZMap %012llo not in stg\n\r", data); - if (trap) { - fault_data = 0; - page_fault = 1; - } - return 0; - } - pg = data & PG_PAG; - /* Check outside of memory */ - /* Update CST entry if needed */ - if (cst) { - uint64 c = M[cst + pg]; - if ((c & PG_AGE) == 0) { -//fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); - if (trap) { - fault_data = 0; - page_fault = 1; - } - return 0; - } - M[cst + pg] = (c & cst_msk) | cst_dat; + /* Update CST entry if needed */ + if (cst) { + cst_val = M[cst + pg]; +//fprintf(stderr, "ZMap %08o %012llo %012llo age\n\r", cst+pg, data, cst_val); + if ((cst_val & PG_AGE) == 0) { + if (trap) { + fault_data = 0; + page_fault = 1; + } + return 0; } + M[cst + pg] = (cst_val & cst_msk) | cst_dat; + } - /* Get address of page */ - data = M[(pg << 9) + page]; + /* Get address of page */ + data = M[(pg << 9) | page]; //fprintf(stderr, "YMap %012llo %o %o\n\r", data, pg << 9, page); +pg_loop: - /* Decode map pointer */ - switch ((data >> 33) & 07) { - default: /* Invalid page */ - if (trap) { - fault_data = 024LL << 30; - page_fault = 1; - } + /* Decode map pointer */ + switch ((data >> 33) & 07) { + default: /* Invalid page */ + fault_data = (wr)? BIT5:0; + page_fault = 1; + return 0; + case 1: /* Direct page */ + /* Bit 4 = execute */ + /* Bit 3 = Write */ + /* Bit 2 = Read */ + acc_bits &= (data >> 18) & RMASK; + break; + + case 2: /* Shared page */ + acc_bits &= (data >> 18) & RMASK; + data = M[(data & RMASK) + spt]; + break; + + case 3: /* Indirect page */ + acc_bits &= (data >> 18) & RMASK; + index = (data >> 18) & PG_IDX; + data = M[(data & RMASK) + spt]; +//fprintf(stderr, "IMap %012llo %o %o %o\n\r", data, pg << 9, index, page); + if (((data >> 18) & PG_STG) != 0) { + fault_data = 0; + page_fault = 1; return 0; - case 1: /* Direct page */ - /* Bit 4 = execute */ - /* Bit 3 = Write */ - /* Bit 2 = Read */ - acc_bits &= (data >> 18) & RMASK; - match = 1; - break; - - case 2: /* Shared page */ - acc_bits &= (data >> 18) & RMASK; - data = M[(data & RMASK) + spt]; - match = 1; - break; - - case 3: /* Indirect page */ - acc_bits &= (data >> 18) & RMASK; - page = (data >> 18) & PG_IDX; - data = M[(data & RMASK) + spt]; -//fprintf(stderr, "IMap %012llo %o %o\n\r", data, pg << 9, page); - break; - - } - } while (!match); + } + pg = data & RMASK; + if (cst) { + cst_val = M[cst + pg]; +//fprintf(stderr, "ZMap %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); + if ((cst_val & PG_AGE) == 0) { + if (trap) { + fault_data = 0; + page_fault = 1; + } + return 0; + } + M[cst + pg] = (cst_val & cst_msk) | cst_dat; + } + data = M[(pg << 9) | index]; +//fprintf(stderr, "JMap %012llo %o %o %o\n\r", data, pg << 9, index, page); + goto pg_loop; + } /* Now have final page */ if ((data >> 18) & PG_STG) { @@ -2178,8 +2197,9 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) /* Check outside of memory */ /* Update CST entry if needed */ if (cst) { - uint64 c = M[cst + pg]; - if ((c & PG_AGE) == 0) { + cst_val = M[cst + pg]; +//fprintf(stderr, "ZMap %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); + if ((cst_val & PG_AGE) == 0) { if (trap) { fault_data = 0; page_fault = 1; @@ -2188,16 +2208,17 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) } if (acc_bits & PG_WRT) { if (wr) - c |= 1; + cst_val |= 1; acc_bits |= 1; } else if (wr) { /* Trying to write and not writable */ +//fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, cst_val); if (trap) { fault_data = 0 /* Write fault */; page_fault = 1; } return 0; } - M[cst + pg] = (c & cst_msk) | cst_dat; + M[cst + pg] = (cst_val & cst_msk) | cst_dat; } else { if (acc_bits & PG_WRT) acc_bits |= 1; @@ -2213,7 +2234,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) data |= 0200000; if (acc_bits & PG_WRT) data |= 0100000; - if (acc_bits & 1) + if (acc_bits & PG_KEP) data |= 0040000; /* Set M bit (S) */ if (acc_bits & PG_CAC) data |= 0020000; @@ -2226,6 +2247,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) u_tlb[page] = data; else e_tlb[page] = data; +//fprintf(stderr, "Page %03o %08o %o\r\n", page, data, uf); } else { /* Map the page */ @@ -2244,7 +2266,6 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) data = e_tlb[page]; } } -//fprintf(stderr, "Page %03o %08o %o\r\n", page, data, uf); return (int)(data); } @@ -2258,7 +2279,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) * cur_context is set when access should ignore xct_flag * fetch is set for instruction fetches. */ -int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch) { +int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fetch) { int data; int base = 0; int page = (RMASK & addr) >> 9; @@ -2467,7 +2488,7 @@ int Mem_write_nopage() { } int Mem_read(int flag, int cur_context, int fetch) { - int addr; + t_addr addr; sim_interval--; #if KLB @@ -2513,7 +2534,7 @@ int Mem_read(int flag, int cur_context, int fetch) { } int Mem_write(int flag, int cur_context) { - int addr; + t_addr addr; sim_interval--; #if KLB @@ -2559,7 +2580,7 @@ int Mem_write(int flag, int cur_context) { } /* executive page table lookup */ -int exec_page_lookup(int addr, int wr, int *loc) +int exec_page_lookup(t_addr addr, int wr, int *loc) { int data; int page = (RMASK & addr) >> 9; @@ -2595,7 +2616,7 @@ int exec_page_lookup(int addr, int wr, int *loc) } int Mem_examine_word(int n, int wrd, uint64 *data) { - int addr = 0144 + (8 * n) + eb_ptr; + t_addr addr = 0144 + (8 * n) + eb_ptr; int base = 0; if (addr >= MEMSIZE) @@ -2611,7 +2632,7 @@ int Mem_examine_word(int n, int wrd, uint64 *data) { } int Mem_deposit_word(int n, int wrd, uint64 *data) { - int addr = 0146 + (8 * n) + eb_ptr; + t_addr addr = 0146 + (8 * n) + eb_ptr; int base = 0; if (addr >= MEMSIZE) @@ -2630,7 +2651,7 @@ int Mem_deposit_word(int n, int wrd, uint64 *data) { * Read in 16 bits of data from a byte pointer. */ int Mem_read_byte(int n, uint16 *data, int byte) { - int addr; + t_addr addr; uint64 val; uint64 msk; int p, s, np; @@ -2675,7 +2696,7 @@ int Mem_read_byte(int n, uint16 *data, int byte) { } int Mem_write_byte(int n, uint16 *data) { - int addr; + t_addr addr; uint64 val; uint64 msk; int p, s, np; @@ -2787,7 +2808,7 @@ load_tlb(int uf, int page) * cur_context is set when access should ignore xct_flag * fetch is set for instruction fetches. */ -int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch) { +int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fetch) { int data; int base = 0; int page = (RMASK & addr) >> 9; @@ -2932,7 +2953,7 @@ int Mem_write_nopage() { } int Mem_read(int flag, int cur_context, int fetch) { - int addr; + t_addr addr; sim_interval--; if (AB < 020) { @@ -2968,7 +2989,7 @@ read: } int Mem_write(int flag, int cur_context) { - int addr; + t_addr addr; sim_interval--; if (AB < 020) { @@ -3052,7 +3073,7 @@ int its_load_tlb(uint32 reg, int page, uint32 *tlb) { * Translation logic for KA10 */ -int page_lookup_its(int addr, int flag, int *loc, int wr, int cur_context, int fetch) { +int page_lookup_its(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fetch) { uint64 data; int base = 0; int page = (RMASK & addr) >> 10; @@ -3184,7 +3205,7 @@ fault: * Return of 0 if successful, 1 if there was an error. */ int Mem_read_its(int flag, int cur_context, int fetch) { - int addr; + t_addr addr; sim_interval--; if (AB < 020) { @@ -3231,7 +3252,7 @@ int Mem_read_its(int flag, int cur_context, int fetch) { * Return of 0 if successful, 1 if there was an error. */ int Mem_write_its(int flag, int cur_context) { - int addr; + t_addr addr; sim_interval--; if (AB < 020) { @@ -3274,7 +3295,7 @@ int Mem_write_its(int flag, int cur_context) { #endif #if BBN -int page_lookup_bbn(int addr, int flag, int *loc, int wr, int cur_context, int fetch) { +int page_lookup_bbn(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fetch) { /* Group 0, 01 = 00 bit 2 = Age 00x 0100000 bit 3 = Age 02x 0040000 @@ -3536,7 +3557,7 @@ fault_bbn: * Return of 0 if successful, 1 if there was an error. */ int Mem_read_bbn(int flag, int cur_context, int fetch) { - int addr; + t_addr addr; sim_interval--; /* If not doing any special access, just access register */ @@ -3566,7 +3587,7 @@ int Mem_read_bbn(int flag, int cur_context, int fetch) { * Return of 0 if successful, 1 if there was an error. */ int Mem_write_bbn(int flag, int cur_context) { - int addr; + t_addr addr; sim_interval--; /* If not doing any special access, just access register */ @@ -3592,7 +3613,7 @@ int Mem_write_bbn(int flag, int cur_context) { #endif #if WAITS -int page_lookup_waits(int addr, int flag, int *loc, int wr, int cur_context, int fetch) { +int page_lookup_waits(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fetch) { int uf = (FLAGS & USER) != 0; /* If this is modify instruction use write access */ @@ -3630,7 +3651,7 @@ int page_lookup_waits(int addr, int flag, int *loc, int wr, int cur_context, int } int Mem_read_waits(int flag, int cur_context, int fetch) { - int addr; + t_addr addr; sim_interval--; if (AB < 020 && ((xct_flag == 0 || fetch || cur_context || (FLAGS & USER) != 0))) { @@ -3656,7 +3677,7 @@ int Mem_read_waits(int flag, int cur_context, int fetch) { */ int Mem_write_waits(int flag, int cur_context) { - int addr; + t_addr addr; sim_interval--; /* If not doing any special access, just access register */ @@ -3677,7 +3698,7 @@ int Mem_write_waits(int flag, int cur_context) { } #endif -int page_lookup_ka(int addr, int flag, int *loc, int wr, int cur_context, int fetch) { +int page_lookup_ka(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fetch) { if (!flag && (FLAGS & USER) != 0) { if (addr <= Pl) { *loc = (addr + Rl) & RMASK; @@ -3699,7 +3720,7 @@ int page_lookup_ka(int addr, int flag, int *loc, int wr, int cur_context, int fe } int Mem_read_ka(int flag, int cur_context, int fetch) { - int addr; + t_addr addr; sim_interval--; if (AB < 020) { @@ -3725,7 +3746,7 @@ int Mem_read_ka(int flag, int cur_context, int fetch) { */ int Mem_write_ka(int flag, int cur_context) { - int addr; + t_addr addr; sim_interval--; if (AB < 020) { @@ -3850,7 +3871,7 @@ t_stat dev_apr(uint32 dev, uint64 *data) { #define get_reg(reg) FM[(reg) & 017] #define set_reg(reg, value) FM[(reg) & 017] = value -int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch) { +int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fetch) { if (!flag && (FLAGS & USER) != 0) { if (addr <= Pl) { *loc = (addr + Rl) & RMASK; @@ -3865,7 +3886,7 @@ int page_lookup(int addr, int flag, int *loc, int wr, int cur_context, int fetch } int Mem_read(int flag, int cur_context, int fetch) { - int addr; + t_addr addr; sim_interval--; if (AB < 020) { @@ -3891,7 +3912,7 @@ int Mem_read(int flag, int cur_context, int fetch) { */ int Mem_write(int flag, int cur_context) { - int addr; + t_addr addr; sim_interval--; if (AB < 020) { @@ -4300,7 +4321,7 @@ st_pi: } /* Update history */ - if (hst_lnt && PC > 017) { + if (hst_lnt /*&& PC > 017*/) { hst_p = hst_p + 1; if (hst_p >= hst_lnt) { hst_p = 0; @@ -4387,11 +4408,32 @@ st_pi: /* Process the instruction */ switch (IR) { +#if KL & KLB + case 0052: + case 0053: + if (QKLB & t20_page) { + if (Mem_read(0, 0, 0)) + goto last; + AB = MB & (SECTM|RMASK); + if (IR & 1) { + AR = get_reg(AC); + if (Mem_write_nopage()) + goto last; + } else { + if (Mem_read_nopage()) + goto last; + set_reg(AC, MB); + } + break; + } +#else + case 0052: case 0053: +#endif muuo: case 0000: /* UUO */ case 0040: case 0041: case 0042: case 0043: case 0044: case 0045: case 0046: case 0047: - case 0050: case 0051: case 0052: case 0053: + case 0050: case 0051: case 0054: case 0055: case 0056: case 0057: case 0060: case 0061: case 0062: case 0063: case 0064: case 0065: case 0066: case 0067: @@ -7135,22 +7177,15 @@ left: break; case 0254: /* JRST */ /* AR Frm PC */ - if (uuo_cycle | pi_cycle) { - FLAGS &= ~USER; /* Clear USER */ -#if ITS - if (QITS && one_p_arm) { - FLAGS |= ONEP; - one_p_arm = 0; - } -#endif +#if KL #if KL_ITS + if (uuo_cycle | pi_cycle) { if (QITS && one_p_arm) { FLAGS |= ADRFLT; one_p_arm = 0; } -#endif } -#if KL +#endif switch (AC) { case 000: /* JRST */ break; @@ -7171,7 +7206,6 @@ xjrstf: pc_sect = (AR >> 18) & 07777; if ((FLAGS & USER) == 0 && ((BR >> 23) & USER) == 0) prev_sect = BR & 037; -//fprintf(stderr, "XJRST %06o %06o %06o %012llo\r\n", pc_sect, prev_sect, FLAGS, BR); } #endif BR = BR >> 23; /* Move flags into position */ @@ -7214,6 +7248,7 @@ jrstf: FLAGS |= f; #endif check_apr_irq(); +//fprintf(stderr, "XJRST %06o %06o %06o %06o %012llo\r\n", pc_sect, PC, prev_sect, FLAGS << 5, BR); break; case 017: /* Invalid */ @@ -7227,9 +7262,12 @@ jrstf: goto muuo; case 007: /* XPCW */ -#if KLB -// if (QKLB) { +//fprintf(stderr, "XPCW %06o %06o %06o %06o\r\n", pc_sect, AB, PC, FLAGS << 5); MB = (((uint64)FLAGS) << 23) | (prev_sect & 037); + if (uuo_cycle | pi_cycle) { + FLAGS &= ~(USER|PUBLIC); /* Clear USER */ + } + sect = 0; if (Mem_write(0, 0)) goto last; AB = (AB + 1) & RMASK; @@ -7238,9 +7276,7 @@ jrstf: goto last; AB = (AB + 1) & RMASK; goto xjrstf; - // } -#endif -// goto muuo; + case 015: /* XJRST */ if (Mem_read(0, 0, 0)) goto last; @@ -7301,6 +7337,15 @@ jrstf: pc_sect = (AR >> 18) & 07777; #endif #else + if (uuo_cycle | pi_cycle) { + FLAGS &= ~USER; /* Clear USER */ +#if ITS + if (QITS && one_p_arm) { + FLAGS |= ONEP; + one_p_arm = 0; + } +#endif + } /* JEN */ if (AC & 010) { /* Restore interrupt level. */ #if KI @@ -7523,13 +7568,17 @@ jrstf: } #endif #endif -// BR = AB; #if KL BYF5 = 1; #if KLB - if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - AR = (AR + 1) & FMASK; - sect = (AR >> 18) & 07777; + if (QKLB) { + if (pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR = (AR + 1) & FMASK; + sect = (AR >> 18) & 07777; + } else { + sect = pc_sect; + AR = AOB(AR); + } } else #endif #endif @@ -7576,9 +7625,14 @@ jrstf: #if KL BYF5 = 1; #if KLB - if (QKLB && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - AR = (AR + 1) & FMASK; - sect = (AR >> 18) & 07777; + if (QKLB) { + if (pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR = (AR + 1) & FMASK; + sect = (AR >> 18) & 07777; + } else { + sect = pc_sect; + AR = AOB(AR); + } } else #endif #endif @@ -7622,6 +7676,7 @@ jrstf: flag1 = glb_sect; if (QKLB) { f = (pc_sect != 0); + sect = pc_sect; if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) { sect = prev_sect; f = (prev_sect != 0); @@ -7675,6 +7730,7 @@ jrstf: #if KLB if (QKLB) { f = (pc_sect != 0); + sect = pc_sect; if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) { f = (prev_sect != 0); sect = prev_sect; @@ -7758,8 +7814,10 @@ jrstf: #if KL & KLB if (QKLB) { AR = AR + 1; + if (AR & BIT17) + cur_sect++; if (glb_sect) - pc_sect = (AR >> 18) & 07777; + pc_sect = cur_sect; PC = AR & RMASK; } else #endif @@ -7798,7 +7856,7 @@ jrstf: PC_CHANGE #if KL & KLB if (QKLB && glb_sect) - pc_sect = (AR >> 18) & 07777; + pc_sect = cur_sect; #endif PC = AR & RMASK; AR = AD; @@ -7820,7 +7878,7 @@ jrstf: PC_CHANGE #if KL & KLB if (QKLB && glb_sect) - pc_sect = (AR >> 18) & 07777; + pc_sect = cur_sect; #endif PC = AR & RMASK; AR = BR; @@ -8490,7 +8548,7 @@ fetch_opr: } if (hst_lnt && PC >= 020) { - hst[hst_p].fmb = AR; + hst[hst_p].fmb = MB; } last: @@ -8515,35 +8573,35 @@ last: BYF5 = 0; #if KL_ITS if (QITS) { - AB = eb_ptr + 0500; + AB = eb_ptr | 0500; FM[(6<<4)|0] = fault_data; } else #endif - AB = ub_ptr + 0500; + AB = ub_ptr | 0500; +#if KLB + if (!QKLB && !QITS && t20_page) + AB++; +#endif MB = fault_data; Mem_write_nopage(); AB++; FLAGS |= trap_flag & (TRP1|TRP2); trap_flag = (TRP1|TRP2); -#if KLB - if (QKLB) + if (QKLB /*|| (!QITS && t20_page)*/) MB = (((uint64)(FLAGS) << 23) & LMASK); else -#endif - MB = (((uint64)(FLAGS) << 23) & LMASK) | (PC & RMASK); + MB = (((uint64)(FLAGS) << 23) & LMASK) | (PC & RMASK); if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; } Mem_write_nopage(); AB++; -#if KLB - if (QKLB) { + if (QKLB /*|| (!QITS && t20_page)*/) { MB = (((uint64)pc_sect) << 18) | (PC & RMASK); Mem_write_nopage(); AB++; } -#endif flag1 = flag3 = 0; if (FLAGS & PUBLIC) flag3 = 1; diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 0a30c86..8608b1b 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -493,7 +493,7 @@ struct pdp_dib { uint32 dev_num; /* device address */ uint32 num_devs; /* length */ t_stat (*io)(uint32 dev, t_uint64 *data); - int (*irq)(uint32 dev, int addr); + t_addr (*irq)(uint32 dev, t_addr addr); struct rh_if *rh; }; @@ -524,7 +524,7 @@ int dct_is_connect(int u); t_stat rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat rh_devio(uint32 dev, t_uint64 *data); -int rh_devirq(uint32 dev, int addr); +t_addr rh_devirq(uint32 dev, t_addr addr); void rh_setattn(struct rh_if *rh, int unit); int rh_blkend(struct rh_if *rh); void rh_setirq(struct rh_if *rh) ; @@ -532,8 +532,8 @@ void rh_finish_op(struct rh_if *rh, int flags); int rh_read(struct rh_if *rh); int rh_write(struct rh_if *rh); -int ten11_read (int addr, t_uint64 *data); -int ten11_write (int addr, t_uint64 data); +int ten11_read (t_addr addr, t_uint64 *data); +int ten11_write (t_addr addr, t_uint64 data); /* Console lights. */ extern void ka10_lights_init (void); @@ -541,8 +541,8 @@ extern void ka10_lights_main (t_uint64); extern void ka10_lights_set_aux (int); extern void ka10_lights_clear_aux (int); -int auxcpu_read (int addr, t_uint64 *); -int auxcpu_write (int addr, t_uint64); +int auxcpu_read (t_addr addr, t_uint64 *); +int auxcpu_write (t_addr addr, t_uint64); /* I/O system parameters */ #define NUM_DEVS_LP 1 diff --git a/PDP10/kx10_imp.c b/PDP10/kx10_imp.c index 46367a2..19249fe 100644 --- a/PDP10/kx10_imp.c +++ b/PDP10/kx10_imp.c @@ -451,7 +451,7 @@ static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff}; static CONST in_addr_T broadcast_ipaddr = {0xffffffff}; t_stat imp_devio(uint32 dev, uint64 *data); -t_stat imp_devirq(uint32 dev, int addr); +t_addr imp_devirq(uint32 dev, t_addr addr); t_stat imp_srv(UNIT *); t_stat imp_eth_srv(UNIT *); t_stat imp_tim_srv(UNIT *); @@ -741,8 +741,8 @@ t_stat imp_devio(uint32 dev, uint64 *data) #if KL /* Handle KL style interrupt vectors for ITS */ -int -imp_devirq(uint32 dev, int addr) { +t_addr +imp_devirq(uint32 dev, t_addr addr) { if ((cpu_unit[0].flags & UNIT_ITSPAGE) != 0 && (imp_data.pia & 7) == 1) { if (imp_unit[0].STATUS & IMPID && (imp_unit[0].STATUS & IMPLW) == 0) return 070|RSIGN; diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index 30521aa..d6a414d 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -212,14 +212,15 @@ t_stat rh_devio(uint32 dev, uint64 *data) { case CONO: clr_interrupt(dev); - rhc->status &= ~(07LL|IADR_ATTN|RH20_MASS_EN); - rhc->status |= *data & (07LL|IADR_ATTN|RH20_MASS_EN); /* Clear flags */ if (*data & RH20_CLR_MBC) { if (rhc->dev_reset != NULL) rhc->dev_reset(dptr); rhc->imode = 2; + rhc->status = 0; } + rhc->status &= ~(07LL|IADR_ATTN|RH20_MASS_EN); + rhc->status |= *data & (07LL|IADR_ATTN|RH20_MASS_EN); if (*data & RH20_DELETE_SCR) rhc->status &= ~(RH20_SBAR|RH20_SCR_FULL); if (*data & (RH20_RCLP|RH20_CLR_MBC)) @@ -470,8 +471,8 @@ t_stat rh_devio(uint32 dev, uint64 *data) { } /* Handle KI and KL style interrupt vectors */ -int -rh_devirq(uint32 dev, int addr) { +t_addr +rh_devirq(uint32 dev, t_addr addr) { DEVICE *dptr = NULL; struct rh_if *rhc = NULL; int drive; diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index 56bdeba..9feac0c 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -896,6 +896,8 @@ rd_end: sim_debug(DEBUG_DETAIL, dptr, "%s%o read done\n", dptr->name, unit); uptr->CMD |= DS_DRY; uptr->CMD &= ~CS1_GO; + if (uptr->DATAPTR == RP_NUMWD) + (void)rh_blkend(rhc); rh_finish_op(rhc, 0); return SCPE_OK; } diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index f6f17a2..0c4bcd6 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -255,6 +255,9 @@ tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { UNIT *uptr = &dptr->units[unit]; int i; + if (rhc->drive != 0) /* Only one unit at 0 */ + return; + if (uptr->CMD & CS1_GO) { uptr->STATUS |= (ER1_RMR); return; @@ -295,6 +298,7 @@ tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { case FNC_DCLR: /* drive clear */ uptr->CMD &= ~(CS_ATA|CS1_GO|CS_TM); uptr->STATUS = 0; + rhc->status &= ~PI_ENABLE; rhc->attn = 0; for (i = 0; i < 8; i++) { if (dptr->units[i].CMD & CS_ATA) @@ -351,6 +355,9 @@ tu_read(DEVICE *dptr, struct rh_if *rhc, int reg) { uint32 temp = 0; int i; + if (rhc->drive != 0) /* Only one unit at 0 */ + return 0; + switch(reg) { case 000: /* control */ temp = uptr->CMD & 076; @@ -399,7 +406,7 @@ tu_read(DEVICE *dptr, struct rh_if *rhc, int reg) { temp = tu_frame[ctlr]; break; case 006: /* drive type */ - temp = 040054; + temp = 042054; break; case 011: /* tape control register */ temp = tu_tcr[ctlr]; From c2af65a7faef9381a0816c5695ecaa35b32f78c6 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 24 Oct 2019 22:31:41 -0400 Subject: [PATCH 34/98] KA10: More support for Tops 20. Fixed Coverity error. --- PDP10/ka10_iii.c | 1 + PDP10/kl10_fe.c | 112 +++++++++++++++++++++++++++++++++++------------ PDP10/kx10_cpu.c | 49 +++++++++++++-------- 3 files changed, 114 insertions(+), 48 deletions(-) diff --git a/PDP10/ka10_iii.c b/PDP10/ka10_iii.c index 59a73c8..6671e04 100644 --- a/PDP10/ka10_iii.c +++ b/PDP10/ka10_iii.c @@ -524,6 +524,7 @@ iii_svc (UNIT *uptr) uptr->MAR &= RMASK; sim_activate(uptr, 10); } + return SCPE_OK; } diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 1902984..301edc1 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -34,6 +34,12 @@ #define UNIT_DUMMY (1 << UNIT_V_UF) #define DTE_DEVNUM 0200 +#define DEV_V_OS (DEV_V_UF + 1) /* Type RSX10/RSX20 */ +#define DEV_M_OS (1 << DEV_V_OS) +#define TYPE_RSX10 (0 << DEV_V_OS) +#define TYPE_RSX20 (1 << DEV_V_OS) + + /* DTE10 CONI bits */ @@ -45,7 +51,7 @@ #define DTE_11DN 00000100 /* TO 11 transfer done */ #define DTE_10DN 00000040 /* TO 10 transfer done */ #define DTE_10ER 00000020 /* Error during TO10 transfer */ -#define DTE_PIE 00000010 /* DTE PI enabled */ +#define DTE_PIE 00000010 /* PIO enabled */ #define DTE_PIA 00000007 /* PI channel assigment */ /* internal flags */ @@ -191,6 +197,8 @@ t_stat dtei_svc (UNIT *uptr); t_stat dte_svc (UNIT *uptr); t_stat dteo_svc (UNIT *uptr); t_stat dtertc_srv(UNIT * uptr); +t_stat dte_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat dte_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat dte_reset (DEVICE *dptr); t_stat dte_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); @@ -256,6 +264,10 @@ MTAB dte_mod[] = { { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode }, + {MTAB_XTD|MTAB_VDV, TYPE_RSX10, NULL, "RSX10", &dte_set_type, NULL, + NULL, "Sets DTE to RSX10 mode"}, + {MTAB_XTD|MTAB_VDV, TYPE_RSX20, "RSX20", "RSX20", &dte_set_type, &dte_show_type, + NULL, "Sets DTE to RSX20 mode"}, { 0 } }; @@ -453,8 +465,7 @@ sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n"); dte_unit[0].STATUS |= DTE_11DB; sim_activate(&dte_unit[0], 200); } - if (dte_unit[0].STATUS & DTE_PIE && - dte_unit[0].STATUS & (DTE_10DB|DTE_11DN|DTE_10DN|DTE_11ER|DTE_10ER)) + if (dte_unit[0].STATUS & (DTE_10DB|DTE_11DN|DTE_10DN|DTE_11ER|DTE_10ER)) set_interrupt(dev, dte_unit[0].STATUS); sim_debug(DEBUG_CONO, &dte_dev, "CTY %03o CONO %06o %06o\n", dev, (uint32)*data, PC); break; @@ -523,17 +534,19 @@ void dte_second(UNIT *uptr) { switch(word & SEC_CMDMSK) { default: case SEC_MONO: /* Ouput character in monitor mode */ + ch = (int32)(word & 0177); if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) { - sim_activate(uptr, 1000); + sim_activate(uptr, 200); return; } - ch = (int32)(word & 0177); - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - cty_out.buff[cty_out.in_ptr] = (char)(word & 0x7f); - cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + if (ch != 0) { + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + cty_out.buff[cty_out.in_ptr] = (char)(word & 0x7f); + cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + sim_activate(&dte_unit[1], 200); + } M[SEC_DTCHR + base] = ch; M[SEC_DTMTD + base] = FMASK; - sim_activate(&dte_unit[1], 100); break; case SEC_SETPRI: enter_pri: @@ -550,6 +563,11 @@ enter_pri: dte_in_cmd = dte_out_res = 0; cty_done = 0; /* Start input process */ + M[SEC_DTCMD + base] = 0; + M[SEC_DTFLG + base] = FMASK; +// uptr->STATUS |= DTE_10DB; + uptr->STATUS &= ~DTE_11DB; +return; break; case SEC_SETDDT: /* Read character from console */ if (cty_in.in_ptr == cty_in.out_ptr) { @@ -594,6 +612,8 @@ enter_pri: break; case SEC_CLKWT: rtc_wait = (uint16)(M[SEC_DTT11 + base] & 0177777); + /* Fall Through */ + case SEC_CLKON: dte_unit[3].STATUS |= SEC_CLK; rtc_tick = 0; @@ -607,8 +627,11 @@ enter_pri: /* Acknowledge command */ M[SEC_DTCMD + base] = 0; M[SEC_DTFLG + base] = FMASK; - uptr->STATUS |= DTE_10DB; uptr->STATUS &= ~DTE_11DB; + if (dte_dev.flags & TYPE_RSX20) { + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); + } } #if KL_ITS @@ -663,8 +686,7 @@ void dte_its(UNIT *uptr) { } M[ITS_DTEOUT] = FMASK; uptr->STATUS |= DTE_11DN; - if (uptr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, uptr->STATUS); + set_interrupt(DTE_DEVNUM, uptr->STATUS); sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word); } /* Check for line speed */ @@ -792,8 +814,7 @@ done: if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) goto error; uptr->STATUS |= DTE_11DN; - if (uptr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, uptr->STATUS); + set_interrupt(DTE_DEVNUM, uptr->STATUS); dte_function(uptr); } @@ -1068,8 +1089,7 @@ void dte_transfer(UNIT *uptr) { dte_out_ptr = (dte_out_ptr + 1) & 0x1f; done: uptr->STATUS |= DTE_10DN; - if (uptr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, uptr->STATUS); + set_interrupt(DTE_DEVNUM, uptr->STATUS); error: return; } @@ -1113,8 +1133,7 @@ dte_input() M[ITS_DTEODN] = word; /* Tell 10 something is ready */ uptr->STATUS |= DTE_10DB; - if (uptr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, uptr->STATUS); + set_interrupt(DTE_DEVNUM, uptr->STATUS); sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo\n", word); } } @@ -1148,8 +1167,7 @@ dte_input() M[ITS_DTETYI] = word; /* Tell 10 something is ready */ uptr->STATUS |= DTE_10DB; - if (uptr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, uptr->STATUS); + set_interrupt(DTE_DEVNUM, uptr->STATUS); sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); } } @@ -1172,8 +1190,7 @@ dte_input() if ((word & SMASK) == 0) { M[ITS_DTEHNG] = word; uptr->STATUS |= DTE_10DB; - if (uptr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, uptr->STATUS); + set_interrupt(DTE_DEVNUM, uptr->STATUS); sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEHNG = %012llo\n", word); } } @@ -1297,8 +1314,7 @@ dte_start(UNIT *uptr) error: /* If we can't read it, go back to secondary */ uptr->STATUS |= DTE_SEC|DTE_10ER; - if (uptr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, uptr->STATUS); + set_interrupt(DTE_DEVNUM, uptr->STATUS); return 0; } /* If in middle of transfer hold off */ @@ -1313,8 +1329,7 @@ error: goto error; /* Tell 10 something is ready */ uptr->STATUS |= DTE_10DB; - if (uptr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, uptr->STATUS); + set_interrupt(DTE_DEVNUM, uptr->STATUS); return 1; } @@ -1362,9 +1377,10 @@ t_stat dtei_svc (UNIT *uptr) cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; M[SEC_DTF11 + base] = ch; M[SEC_DTMTI + base] = FMASK; - optr->STATUS |= DTE_10DB; - if (optr->STATUS & DTE_PIE) - set_interrupt(DTE_DEVNUM, optr->STATUS); + if (dte_dev.flags & TYPE_RSX20) { + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); + } } return SCPE_OK; } @@ -1372,6 +1388,15 @@ t_stat dtei_svc (UNIT *uptr) /* Handle output of characters to CTY. Started whenever there is output pending */ t_stat dteo_svc (UNIT *uptr) { + uint32 base = 0; + UNIT *optr = &dte_unit[0]; + +#if KI_22BIT +#if KL_ITS + if (!QITS) +#endif + base = eb_ptr; +#endif /* Flush out any pending CTY output */ while(cty_out.in_ptr != cty_out.out_ptr) { char ch = cty_out.buff[cty_out.out_ptr]; @@ -1471,6 +1496,35 @@ t_stat dte_reset (DEVICE *dptr) return SCPE_OK; } + +t_stat +dte_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + DEVICE *dptr; + dptr = find_dev_from_unit (uptr); + if (dptr == NULL) + return SCPE_IERR; + dptr->flags &= ~DEV_M_OS; + dptr->flags |= val; + return SCPE_OK; +} + +t_stat +dte_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + DEVICE *dptr; + + if (uptr == NULL) + return SCPE_IERR; + + dptr = find_dev_from_unit(uptr); + if (dptr == NULL) + return SCPE_IERR; + fprintf (st, "%s", (dptr->flags & TYPE_RSX20) ? "RSX20" : "RSX10"); + return SCPE_OK; +} + + /* Stop operating system */ t_stat dte_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 71ab362..178663f 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -7263,7 +7263,7 @@ jrstf: case 007: /* XPCW */ //fprintf(stderr, "XPCW %06o %06o %06o %06o\r\n", pc_sect, AB, PC, FLAGS << 5); - MB = (((uint64)FLAGS) << 23) | (prev_sect & 037); + MB = ((((uint64)FLAGS) << 23) | (prev_sect & 037)) & FMASK; if (uuo_cycle | pi_cycle) { FLAGS &= ~(USER|PUBLIC); /* Clear USER */ } @@ -7480,8 +7480,12 @@ jrstf: goto muuo; /* Figure out if this is a user space access */ - if (xct_flag & 4) + if (xct_flag & 4) { flag1 = (FLAGS & USERIO) != 0; +#if KLB + sect = prev_sect; +#endif + } /* Check if Paging Enabled */ if (!page_enable || AB < 020) { @@ -10214,6 +10218,7 @@ DEVICE *dptr; DIB *dibp; uint32 i, j, d; int rh20; +int rh_idx; /* Set trap offset based on MAOFF flag */ maoff = (cpu_unit[0].flags & UNIT_MAOFF)? 0100 : 0; @@ -10269,33 +10274,31 @@ if (QBBN) /* Assign all RH10 & RH20 devices */ rh20 = 0540; -for (j = i = 0; (dptr = rh_devs[i]) != NULL; i++) { +rh_idx = 0; +for (i = 0; (dptr = rh_devs[i]) != NULL; i++) { dibp = (DIB *) dptr->ctxt; if (dibp && !(dptr->flags & DEV_DIS)) { /* enabled? */ d = dibp->dev_num; /* Check type */ if (d & RH10_DEV) { /* Skip RH10 devices */ - d = rh_nums[j]; - if (d == 0) - break; + d = rh_nums[rh_idx]; + if (d == 0) { + sim_printf ("To many RH10 devices %s\n", sim_dname (dptr)); + return TRUE; + } } else if (d & RH20_DEV) { /* RH20, grab next device */ - d = rh20; - rh20 += 4; + continue; +// d = rh20; + // rh20 += 4; } dev_tab[(d >> 2)] = dibp->io; dev_irqv[(d >> 2)] = dibp->irq; - rh[j].dev_num = d; - rh[j].dev = dptr; - rh[j].rh = dibp->rh; - j++; + rh[rh_idx].dev_num = d; + rh[rh_idx].dev = dptr; + rh[rh_idx].rh = dibp->rh; + rh_idx++; } } -/* Make sure all are assigned */ -if (j == 4 && rh_devs[i] != NULL) { - sim_printf ("To many RH10 devices %s\n", sim_dname (dptr)); - return TRUE; -} - /* Assign all remaining devices */ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { dibp = (DIB *) dptr->ctxt; @@ -10303,8 +10306,16 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { for (j = 0; j < dibp->num_devs; j++) { /* loop thru disp */ if (dibp->io) { /* any dispatch? */ d = dibp->dev_num; - if (d & (RH10_DEV|RH20_DEV)) /* Skip RH10 & RH20 devices */ + if (d & (RH10_DEV)) /* Skip RH10 & RH20 devices */ continue; + if (d & (RH20_DEV)) { + d = rh20; + rh20 += 4; + rh[rh_idx].dev_num = d; + rh[rh_idx].dev = dptr; + rh[rh_idx].rh = dibp->rh; + rh_idx++; + } if (dev_tab[(d >> 2) + j] != &null_dev) { /* already filled? */ sim_printf ("%s device number conflict at %02o\n", From 6f9ecd3cdd5a6c2c9ba59625f0437d374c89c508 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 27 Oct 2019 12:07:26 -0400 Subject: [PATCH 35/98] KA10: Added Return Date and Indirect reply messages to KL10 FE. --- PDP10/kl10_fe.c | 162 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 114 insertions(+), 48 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 301edc1..d145f3b 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -129,6 +129,7 @@ #define PRI_CMT_11IC 0000377LL /* TO11 IC for queued transfers */ #define PRI_CMTW_CNT 3 /* Queue Count */ #define PRI_CMTW_KAC 5 /* Keep alive count */ +#define PRI_IND_FLG 0100000 /* Flag function as indirect */ #define PRI_EM2EI 001 /* Initial message to 11 */ #define PRI_EM2TI 002 /* Replay to initial message. */ @@ -206,7 +207,7 @@ t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cpt const char *dte_description (DEVICE *dptr); extern uint64 SW; /* Switch register */ -char *pri_name[] = { "(0)", "EM2EI", "EM2TI", "EMSTR", "EMLNC", "EMRDS", "(6)", +char *pri_name[] = { "(0)", "EM2EI", "EM2TI", "EMSTR", "EMLNC", "EMRDS", "(6)", "EMHDS", "(10)", "EMRDT", "EMHDR", "EMFLO", "EMSNA", "EMDSC", "EMHUD", "EMACK", "EMXOF", "EMXON", "EMHLS", "EMHLA", "EMRBI", "EMAKA", "EMTDO", "EMEDR", "EMLDR", "EMLDV" }; @@ -450,10 +451,12 @@ t_stat dte_devio(uint32 dev, uint64 *data) { dte_unit[0].STATUS &= ~(DTE_PIA|DTE_PIE); dte_unit[0].STATUS |= res & (DTE_PIA|DTE_PIE); } - if (res & DTE_CO11CL) + if (res & DTE_CO11CL) dte_unit[0].STATUS &= ~(DTE_11DN|DTE_11ER); - if (res & DTE_CO10CL) + if (res & DTE_CO10CL) { dte_unit[0].STATUS &= ~(DTE_10DN|DTE_10ER); + dte_start(&dte_unit[0]); + } if (res & DTE_CO10DB) dte_unit[0].STATUS &= ~(DTE_10DB); if (res & DTE_CO11CR) @@ -485,7 +488,7 @@ sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n"); /* Handle KL style interrupt vectors */ t_addr dte_devirq(uint32 dev, t_addr addr) { - return 0142; + return 0142; } /* Handle TO11 interrupts */ @@ -520,7 +523,7 @@ void dte_second(UNIT *uptr) { #endif base = eb_ptr; #endif - /* read command */ + /* read command */ word = M[SEC_DTCMD + base]; #if KL_ITS if (word == 0 && QITS && (uptr->STATUS & ITS_ON) != 0) { @@ -660,7 +663,7 @@ void dte_its(UNIT *uptr) { if (ln < 0) { if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) return; - if (!Mem_read_byte(0, &data, 1)) + if (!Mem_read_byte(0, &data, 1)) return; ch = data & 0177; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %x\n", ch); @@ -674,7 +677,7 @@ void dte_its(UNIT *uptr) { struct _buffer *otty = &tty_out[ln]; if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) return; - if (!Mem_read_byte(0, &data, 1)) + if (!Mem_read_byte(0, &data, 1)) return; ch = data & 0177; sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln); @@ -719,7 +722,7 @@ void dte_primary(UNIT *uptr) { int cnt; struct _dte_queue *in; uint16 data1, data2, *dp; - + if ((uptr->STATUS & DTE_11DB) == 0) return; @@ -733,14 +736,30 @@ void dte_primary(UNIT *uptr) { clr_interrupt(DTE_DEVNUM); /* Check status word to see if valid */ if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word)) { + uint32 base; error: + base = 0; +#if KI_22BIT +#if KL_ITS + if (!QITS) +#endif + base = eb_ptr; +#endif +fprintf(stderr, "DTE going to secondary %012llo error\n\r", word); /* If we can't read it, go back to secondary */ + M[SEC_DTFLG + base] = FMASK; uptr->STATUS |= DTE_SEC; + uptr->STATUS &= ~DTE_11DB; + if (dte_dev.flags & TYPE_RSX20) { + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); + } return; } if ((word & PRI_CMT_QP) == 0) { - uptr->STATUS |= DTE_SEC; +fprintf(stderr, "DTE going to secondary %012llo No QP\n\r", word); + goto error; } in = &dte_in[dte_in_ptr]; /* Check if indirect */ @@ -751,17 +770,17 @@ error: return; } /* Get size of transfer */ - if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_CNT, &iword)) + if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_CNT, &iword)) goto error; sim_debug(DEBUG_EXP, &dte_dev, "DTE: count: %012llo\n", iword); in->dcnt = (uint16)(iword & 0177777); /* Read in data */ - dp = &in->data[0]; + dp = &in->data[0]; for (cnt = in->dcnt; cnt >= 0; cnt -=2) { /* Read in data */ if (!Mem_read_byte(0, dp, 0)) goto error; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o %06o\n", + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o %06o\n", *dp, *dp >> 8, *dp & 0377, ((*dp & 0377) << 8) | ((*dp >> 8) & 0377)); dp++; } @@ -787,10 +806,10 @@ error: goto error; in->spare = data1; cnt -= 2; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read CMD: %o %o %s %o\n", - in->cnt, in->func, + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read CMD: %o c=%o f=%o %s d=%o\n", + dte_in_ptr, in->cnt, in->func, ((in->func & 0377) > PRI_EMLDV)?"***":pri_name[in->func & 0377], in->dev); - dp = &in->data[0]; + dp = &in->data[0]; for (; cnt > 0; cnt -=2) { /* Read in data */ if (!Mem_read_byte(0, dp, 0)) @@ -799,11 +818,11 @@ error: *dp, *dp >> 8, *dp & 0377); dp++; } - if (in->func & 0100000) { + if (in->func & PRI_IND_FLG) { uptr->STATUS |= DTE_IND; in->sdev = in->dcnt = in->data[0]; word |= PRI_CMT_TOT; - if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) + if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) goto error; } else { dte_in_ptr = (dte_in_ptr + 1) & 0x1f; @@ -811,7 +830,7 @@ error: } done: word &= ~PRI_CMT_TOT; - if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) + if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) goto error; uptr->STATUS |= DTE_11DN; set_interrupt(DTE_DEVNUM, uptr->STATUS); @@ -827,8 +846,7 @@ dte_function(UNIT *uptr) struct _dte_queue *cmd; t_stat r; int func; - - + /* Check if queue is empty */ while (dte_in_cmd != dte_in_ptr) { if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { @@ -838,8 +856,8 @@ dte_function(UNIT *uptr) } cmd = &dte_in[dte_in_cmd]; func = cmd->func & 0377; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: func %02o %s dev %o cnt %d dcnt %d\n", func, - (func > PRI_EMLDV) ? "***" : pri_name[func], + sim_debug(DEBUG_DATA, &dte_dev, "DTE: func %o %02o %s dev %o cnt %d dcnt %d\n", + dte_in_cmd, func, (func > PRI_EMLDV) ? "***" : pri_name[func], cmd->dev, cmd->dcnt, cmd->dptr ); switch (func) { case PRI_EM2EI: /* Initial message to 11 */ @@ -855,12 +873,33 @@ dte_function(UNIT *uptr) if (dte_queue(PRI_EMAKA, PRI_EMCLK, 0, data1) == 0) return; break; - + case PRI_EM2TI: /* Replay to initial message. */ case PRI_EMACK: /* Acknowledge line */ /* Should never get these */ break; - + case PRI_EMHDR: /* Here is date and time */ + /* Ignore this function */ + break; + case PRI_EMRDT: /* Request Date/Time */ + { + time_t t = time(NULL); + struct tm *tm = localtime(&t); + int yr = tm->tm_year + 1900; + int tim = (((tm->tm_hour * 60) + tm->tm_min) * 60) + + tm->tm_sec; + data1[0] = 0177777; + data1[1] = ((yr & 0377) << 8) | ((yr >> 8) & 0377); + data1[2] = (tm->tm_mon) + ((tm->tm_mday - 1) << 8); + data1[3] = (((tm->tm_wday + 6) % 7)) + + (tm->tm_isdst ? 0200 << 8 : 0); + tim >>= 1; + data1[4] = ((tim & 0377) << 8) | ((tim >> 8) & 0377); + if (dte_queue(PRI_EMHDR | PRI_IND_FLG, PRI_EMCLK, 6, data1) == 0) + return; + } + break; + case PRI_EMSTR: /* String data */ #if (NUM_DEVS_LP > 0) @@ -915,7 +954,7 @@ dte_function(UNIT *uptr) #endif /* Fall through */ case PRI_EMSNA: /* Send all (ttys) */ - if (cmd->dev != PRI_EMCTY) + if (cmd->dev != PRI_EMCTY) break; cty: sim_activate(&dte_unit[1], 100); @@ -936,15 +975,33 @@ cty: if (cmd->dptr != cmd->dcnt) return; break; - + case PRI_EMLNC: /* Line-Char */ /* Send by DTE only? */ break; case PRI_EMRDS: /* Request device status */ - case PRI_EMHDS: /* Here is device status */ - case PRI_EMRDT: /* Request Date/Time */ - case PRI_EMHDR: /* Here is date and time */ +#if (NUM_DEVS_LP > 0) + if (cmd->dev == PRI_EMLPT) { + data1[0] = 0; + if (dte_queue(PRI_EMHDS, PRI_EMLPT, 1, data1) == 0) + return; + } +#endif + if (cmd->dev == PRI_EMCTY) { + data1[0] = 0; + if (dte_queue(PRI_EMHDS, PRI_EMCTY, 1, data1) == 0) + return; + } + if (cmd->dev == PRI_EMDH1) { + data1[0] = 0; + if (dte_queue(PRI_EMHDS, PRI_EMDH1, 1, data1) == 0) + return; + } break; + + case PRI_EMHDS: /* Here is device status */ + break; + #if (NUM_DEVS_TTY > 0) case PRI_EMFLO: /* Flush output */ if ((cmd->dev & 0377) == PRI_EMDLS) { @@ -1036,7 +1093,7 @@ void dte_transfer(UNIT *uptr) { /* Check if indirect */ if ((uptr->STATUS & DTE_SIND) != 0) { /* Transfer indirect */ - cnt = out->dcnt+2; + cnt = out->dcnt; dp = &out->data[0]; if (cnt > scnt) /* Only send as much as we are allowed */ cnt = scnt; @@ -1045,16 +1102,19 @@ void dte_transfer(UNIT *uptr) { *dp, *dp >> 8, *dp & 0377); if (Mem_write_byte(0, dp) == 0) goto error; + dp++; } uptr->STATUS &= ~DTE_SIND; } else { - sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d send CMD: %o %o %o\n", + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d send CMD: %o %o %o\n", dte_out_ptr, dte_out_res, out->cnt, out->func, out->dev); /* Get size of packet */ - cnt = out->cnt + out->dcnt; + cnt = out->cnt; + if ((out->func & PRI_IND_FLG) == 0) + cnt += out->dcnt; /* If it will not fit, request indirect */ if (cnt > scnt) { /* If not enough space request indirect */ - out->func |= 0100000; + out->func |= PRI_IND_FLG; cnt = scnt; } /* Write out header */ @@ -1069,7 +1129,8 @@ void dte_transfer(UNIT *uptr) { if (!Mem_write_byte(0, &out->spare)) goto error; cnt -= 2; - if (out->func & 0100000) { + if (out->func & PRI_IND_FLG) { +sim_debug(DEBUG_DATA, &dte_dev, "DTE: Indirect %o %o\n", cnt, out->dcnt); if (!Mem_write_byte(0, &out->dcnt)) goto error; uptr->STATUS |= DTE_SIND; @@ -1156,7 +1217,7 @@ dte_input() } ln++; if (ln >= tty_desc.lines) - ln = 0; + ln = 0; if (ln == uptr->CNT) break; } @@ -1213,7 +1274,7 @@ dte_input() cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY recieve %02x\n", ch); dataq[n++] = (PRI_CTYDV << 8) | ch; - } + } if (n > 0 && dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) { /* Restore the input pointer */ cty_in.out_ptr = save_ptr; @@ -1281,8 +1342,8 @@ dte_queue(int func, int dev, int dcnt, uint16 *data) out->dev = dev; out->dcnt = (dcnt-1)*2; out->spare = 0; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d queue resp: %o %o %s %o\n", - dte_out_ptr, dte_out_res, out->cnt, out->func, + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d queue resp: %o %o %s %o\n", + dte_out_ptr, dte_out_res, out->cnt, out->func, (out->func > PRI_EMLDV)? "***":pri_name[out->func], out->dev); for (dp = &out->data[0]; dcnt > 0; dcnt--) { *dp++ = *data++; @@ -1308,7 +1369,7 @@ dte_start(UNIT *uptr) return 1; /* If there is interrupt pending, just return */ - if ((uptr->STATUS & (DTE_IND|DTE_10DB|DTE_11DB)) != 0) + if ((uptr->STATUS & (DTE_IND|DTE_10DB|DTE_11DB)) != 0) return 1; if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word)) { error: @@ -1317,17 +1378,22 @@ error: set_interrupt(DTE_DEVNUM, uptr->STATUS); return 0; } - /* If in middle of transfer hold off */ - if (word & PRI_CMT_TOT) - return 1; /* Bump count of messages sent */ word = (word & ~(PRI_CMT_10IC|PRI_CMT_IP)) | ((word + 0400) & PRI_CMT_10IC); + if ((uptr->STATUS & DTE_SIND) != 0) + word |= PRI_CMT_IP; if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) goto error; - word = (uint64)(dte_out[dte_out_ptr].cnt + dte_out[dte_out_ptr].dcnt); + dcnt = dte_out[dte_out_ptr].cnt; + if ((dte_out[dte_out_ptr].func & PRI_IND_FLG) == 0) + dcnt += dte_out[dte_out_ptr].dcnt; + /* Tell 10 something is ready */ + word = (uint64)dcnt; + if ((uptr->STATUS & DTE_SIND) != 0) { + word = (uint64)(dte_out[dte_out_ptr].dcnt); + } if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_CNT, &word)) goto error; - /* Tell 10 something is ready */ uptr->STATUS |= DTE_10DB; set_interrupt(DTE_DEVNUM, uptr->STATUS); return 1; @@ -1592,7 +1658,7 @@ lpt_printline(UNIT *uptr, int nl) { } else if (nl < 0 && uptr->LINE >= (int32)uptr->capac) { uptr->LINE = 0; } - + sim_fwrite(&lpt_buffer, 1, uptr->POS, uptr->fileref); uptr->pos += uptr->POS; uptr->COL = 0; @@ -1800,7 +1866,7 @@ t_stat ttyi_svc (UNIT *uptr) tty_ldsc[ln].rcve = 1; sim_debug(DEBUG_DETAIL, &tty_dev, "TTY line connect %d\n", ln); } - + tmxr_poll_tx(&tty_desc); tmxr_poll_rx(&tty_desc); @@ -1822,7 +1888,7 @@ t_stat ttyi_svc (UNIT *uptr) } else flg = 0; } - } + } return SCPE_OK; } @@ -1846,7 +1912,7 @@ t_stat ttyo_svc (UNIT *uptr) lp = &tty_ldsc[ln]; if (lp->conn == 0) continue; - if (optr->out_ptr == optr->in_ptr) + if (optr->out_ptr == optr->in_ptr) continue; while (optr->out_ptr != optr->in_ptr) { int32 ch = optr->buff[optr->out_ptr]; From 3b96138fecc24cd85f47a4d7e25b3bab6b89f423 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 27 Oct 2019 12:08:20 -0400 Subject: [PATCH 36/98] KA10: Minor changes to RH10/RH20 definitions. --- PDP10/kx10_cpu.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 178663f..8315c0b 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2232,10 +2232,11 @@ pg_loop: data = pg | RSIGN; if (acc_bits & PG_PUB) data |= 0200000; - if (acc_bits & PG_WRT) - data |= 0100000; - if (acc_bits & PG_KEP) - data |= 0040000; /* Set M bit (S) */ + if (acc_bits & PG_WRT) { + if (wr) + data |= 0040000; /* Set M bit (S) */ + data |= 0100000; /* Set W bit */ + } if (acc_bits & PG_CAC) data |= 0020000; #if KLB @@ -2709,6 +2710,8 @@ int Mem_write_byte(int n, uint16 *data) { if (addr >= MEMSIZE) return 0; val = M[addr]; + if (val == 0) + return 1; // fprintf(stderr, "Write: %06o %012llo -> ", addr, val); s = (val >> 24) & 077; p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; @@ -4523,10 +4526,12 @@ unasign: #endif FLAGS = (MB >> 23) & 017777; /* If transistioning from user to executive adjust flags */ - if ((FLAGS & USER) == 0 && (AB & 4) != 0) - FLAGS |= USERIO; - if ((FLAGS & USER) == 0 && (AB & 2 || (FLAGS & OVR) != 0)) - FLAGS |= PRV_PUB|OVR; + if ((FLAGS & USER) == 0) { + if ((AB & 4) != 0) + FLAGS |= USERIO; + if ((AB & 2 || (FLAGS & OVR) != 0)) + FLAGS |= PRV_PUB|OVR; + } PC = MB & RMASK; f_pc_inh = 1; break; @@ -10286,9 +10291,8 @@ for (i = 0; (dptr = rh_devs[i]) != NULL; i++) { return TRUE; } } else if (d & RH20_DEV) { /* RH20, grab next device */ - continue; -// d = rh20; - // rh20 += 4; + d = rh20; + rh20 += 4; } dev_tab[(d >> 2)] = dibp->io; dev_irqv[(d >> 2)] = dibp->irq; @@ -10306,16 +10310,8 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { for (j = 0; j < dibp->num_devs; j++) { /* loop thru disp */ if (dibp->io) { /* any dispatch? */ d = dibp->dev_num; - if (d & (RH10_DEV)) /* Skip RH10 & RH20 devices */ + if (d & (RH10_DEV|RH20_DEV)) /* Skip RH10 & RH20 devices */ continue; - if (d & (RH20_DEV)) { - d = rh20; - rh20 += 4; - rh[rh_idx].dev_num = d; - rh[rh_idx].dev = dptr; - rh[rh_idx].rh = dibp->rh; - rh_idx++; - } if (dev_tab[(d >> 2) + j] != &null_dev) { /* already filled? */ sim_printf ("%s device number conflict at %02o\n", From 0e54edd06ef039f3dcce521aa650bc0ae4006459 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 30 Oct 2019 20:59:07 -0400 Subject: [PATCH 37/98] SCP: Updated to current. --- scp.c | 50 +++++++++++++++++++------------------------------- sim_defs.h | 4 ++-- sim_fio.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/scp.c b/scp.c index a032c5c..ba15f05 100644 --- a/scp.c +++ b/scp.c @@ -1651,6 +1651,8 @@ static const char simh_help[] = "++%%~pI%% - expands the value of %%I%% to a path only\n" "++%%~nI%% - expands the value of %%I%% to a file name only\n" "++%%~xI%% - expands the value of %%I%% to a file extension only\n\n" + "++%%~tI%% - expands the value of %%I%% to date/time of file\n\n" + "++%%~zI%% - expands the value of %%I%% to size of file\n\n" " The modifiers can be combined to get compound results:\n\n" "++%%~pnI%% - expands the value of %%I%% to a path and name only\n" "++%%~nxI%% - expands the value of %%I%% to a file name and extension only\n\n" @@ -3125,7 +3127,7 @@ if (dptr->modifiers) { if ((!mptr->disp) || (!mptr->pstring) || !(*mptr->pstring)) continue; fprint_header (st, &found, header); - sprintf (buf, "show %s %s%s", sim_dname (dptr), mptr->pstring, MODMASK(mptr,MTAB_SHP) ? "=arg" : ""); + sprintf (buf, "show %s %s%s", sim_dname (dptr), mptr->pstring, MODMASK(mptr,MTAB_SHP) ? "{=arg}" : ""); fprintf (st, "%-30s\t%s\n", buf, mptr->help ? mptr->help : ""); } } @@ -3383,7 +3385,7 @@ if (*cptr) { } } else { - if (dptr->flags & DEV_DISABLE) + if (dptr->flags & DEV_DIS) sim_printf ("Device %s is currently disabled\n", dptr->name); r = help_dev_help (stdout, dptr, uptr, flag, cptr); if (sim_log) @@ -4210,7 +4212,7 @@ for (; *ip && (op < oend); ) { if (*ip == '~') { expand_it = TRUE; ++ip; - for (i=0; (i < (sizeof (parts) - 1)) && (strchr ("fpnx", *ip)); i++, ip++) { + for (i=0; (i < (sizeof (parts) - 1)) && (strchr ("fpnxtz", *ip)); i++, ip++) { parts[i] = *ip; parts[i + 1] = '\0'; } @@ -5310,11 +5312,6 @@ while (*cptr != 0) { /* do all mods */ } else if (!mptr->desc) /* value desc? */ break; -// else if (mptr->mask & MTAB_VAL) { /* take a value? */ -// if (!cvptr) return SCPE_MISVAL; /* none? error */ -// r = dep_reg (0, cvptr, (REG *) mptr->desc, 0); -// if (r != SCPE_OK) return r; -// } else if (cvptr) /* = value? */ return SCPE_ARG; else *((int32 *) mptr->desc) = mptr->match; @@ -5529,9 +5526,9 @@ if ((dptr = find_dev (gbuf))) { /* device match? */ } else if ((dptr = find_unit (gbuf, &uptr))) { /* unit match? */ if (uptr == NULL) /* invalid unit */ - return SCPE_NXUN; + return sim_messagef (SCPE_NXUN, "Non-existent unit: %s\n", gbuf); if (uptr->flags & UNIT_DIS) /* disabled? */ - return SCPE_UDIS; + return sim_messagef (SCPE_UDIS, "Unit disabled: %s\n", gbuf); shtb = show_unit_tab; /* global table */ lvl = MTAB_VUN; /* unit match */ GET_SWITCHES (cptr); /* get more switches */ @@ -5544,7 +5541,7 @@ else { if (sim_dflt_dev->modifiers) { if ((cvptr = strchr (gbuf, '='))) /* = value? */ *cvptr++ = 0; - for (mptr = sim_dflt_dev->modifiers; mptr->mask != 0; mptr++) { + for (mptr = sim_dflt_dev->modifiers; mptr && (mptr->mask != 0); mptr++) { if ((((mptr->mask & MTAB_VDV) == MTAB_VDV) && (mptr->pstring && (MATCH_CMD (gbuf, mptr->pstring) == 0))) || (!(mptr->mask & MTAB_VDV) && (mptr->mstring && (MATCH_CMD (gbuf, mptr->mstring) == 0)))) { @@ -5561,7 +5558,7 @@ else { if ((shptr = find_shtab (show_dev_tab, gbuf))) /* global match? */ return shptr->action (ofile, sim_dflt_dev, uptr, shptr->arg, cptr); else - return SCPE_NXDEV; /* no match */ + return sim_messagef (SCPE_NXDEV, "Non-existent device: %s\n", gbuf);/* no match */ } } @@ -5581,13 +5578,9 @@ while (*cptr != 0) { /* do all mods */ ((mptr->mask & lvl) == lvl): (MTAB_VUN & lvl)) && ((mptr->disp && mptr->pstring && /* named disp? */ (MATCH_CMD (gbuf, mptr->pstring) == 0)) - // || - // ((mptr->mask & MTAB_VAL) && /* named value? */ - // mptr->mstring && - // (MATCH_CMD (gbuf, mptr->mstring) == 0))) )) { - if (cvptr && !(mptr->mask & MTAB_SHP)) - return SCPE_ARG; + if (cvptr && !MODMASK(mptr,MTAB_SHP)) + return sim_messagef (SCPE_ARG, "Invalid Argument: %s=%s\n", gbuf, cvptr); show_one_mod (ofile, dptr, uptr, mptr, cvptr, 1); break; } /* end if */ @@ -5600,10 +5593,12 @@ while (*cptr != 0) { /* do all mods */ if (r != SCPE_OK) return r; } - else if (!dptr->modifiers) /* no modifiers? */ - return SCPE_NOPARAM; - else - return SCPE_NXPAR; + else { + if (!dptr->modifiers) /* no modifiers? */ + return sim_messagef (SCPE_NOPARAM, "%s device has no parameters\n", dptr->name); + else + return sim_messagef (SCPE_NXPAR, "Non-existent parameter: %s\n", gbuf); + } } /* end if */ } /* end while */ return SCPE_OK; @@ -6255,18 +6250,11 @@ t_stat show_one_mod (FILE *st, DEVICE *dptr, UNIT *uptr, MTAB *mptr, CONST char *cptr, int32 flag) { t_stat r = SCPE_OK; -//t_value val; if (mptr->disp) r = mptr->disp (st, uptr, mptr->match, (CONST void *)(cptr? cptr: mptr->desc)); -//else if ((mptr->mask & MTAB_XTD) && (mptr->mask & MTAB_VAL)) { -// REG *rptr = (REG *) mptr->desc; -// fprintf (st, "%s=", mptr->pstring); -// val = get_rval (rptr, 0); -// fprint_val (st, val, rptr->radix, rptr->width, -// rptr->flags & REG_FMT); -// } -else fputs (mptr->pstring, st); +else + fputs (mptr->pstring, st); if ((r == SCPE_OK) && (flag && !((mptr->mask & MTAB_XTD) && MODMASK(mptr,MTAB_NMO)))) fputc ('\n', st); return r; diff --git a/sim_defs.h b/sim_defs.h index a92433d..e400c6e 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -749,8 +749,8 @@ struct MTAB { t_stat (*disp)(FILE *st, UNIT *up, int32 v, CONST void *dp); /* display routine */ void *desc; /* value descriptor */ - /* REG * if MTAB_VAL */ - /* int * if not */ + /* pointer to something needed by */ + /* the validation and/or display routines */ const char *help; /* help string */ }; diff --git a/sim_fio.c b/sim_fio.c index cc43e2c..97c1c0c 100644 --- a/sim_fio.c +++ b/sim_fio.c @@ -742,6 +742,8 @@ char *fullpath = NULL, *result = NULL; char *c, *name, *ext; char chr; const char *p; +char filesizebuf[32] = ""; +char filedatetimebuf[32] = ""; if (((*filepath == '\'') || (*filepath == '"')) && (filepath[strlen (filepath) - 1] == *filepath)) { @@ -812,6 +814,20 @@ if (ext == NULL) tot_size = 0; if (*parts == '\0') /* empty part specifier means strip only quotes */ tot_size = strlen (tempfilepath); +if (strchr (parts, 't') || strchr (parts, 'z')) { + struct stat filestat; + struct tm *tm; + + memset (&filestat, 0, sizeof (filestat)); + (void)stat (fullpath, &filestat); + if (sizeof (filestat.st_size) == 4) + sprintf (filesizebuf, "%ld ", filestat.st_size); + else + sprintf (filesizebuf, "%" LL_FMT "d ", (LL_TYPE)filestat.st_size); + tm = localtime (&filestat.st_mtime); + sprintf (filedatetimebuf, "%02d/%02d/%04d %02d:%02d %cM ", 1 + tm->tm_mon, tm->tm_mday, 1900 + tm->tm_year, + tm->tm_hour % 12, tm->tm_min, (0 == (tm->tm_hour % 12)) ? 'A' : 'P'); + } for (p = parts; *p; p++) { switch (*p) { case 'f': @@ -826,6 +842,12 @@ for (p = parts; *p; p++) { case 'x': tot_size += strlen (ext); break; + case 't': + tot_size += strlen (filedatetimebuf); + break; + case 'z': + tot_size += strlen (filesizebuf); + break; } } result = (char *)malloc (1 + tot_size); @@ -852,6 +874,12 @@ for (p = parts; *p; p++) { case 'x': strlcat (result, ext, 1 + tot_size); break; + case 't': + strlcat (result, filedatetimebuf, 1 + tot_size); + break; + case 'z': + strlcat (result, filesizebuf, 1 + tot_size); + break; } } free (fullpath); From 824a25644a346c0feda985657557dee5404873b5 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 30 Oct 2019 20:59:26 -0400 Subject: [PATCH 38/98] KA10: Added support to load .EXB files. --- PDP10/kx10_sys.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index abed9ba..9489c79 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -239,6 +239,7 @@ DEBTAB crd_debug[] = { #define FMT_E 3 /* EXE */ #define FMT_D 4 /* WAITS DMP */ #define FMT_I 5 /* ITS SBLK */ +#define FMT_B 6 /* EXB format */ #define EXE_DIR 01776 /* EXE directory */ #define EXE_VEC 01775 /* EXE entry vec */ @@ -694,6 +695,86 @@ else if (entvec == 0) return SCPE_OK; } +static int exb_pos = -1; +int get_exb_byte (FILE *fileref, int *byt, int ftype) +{ + static uint64 word; + + exb_pos++; + switch(exb_pos & 3) { + case 0: if (get_word(fileref, &word, ftype)) + return 1; + *byt = ((word >> 18) & 0377); + break; + case 1: *byt = ((word >> 26) & 0377); + break; + case 2: *byt = ((word >> 0) & 0377); + break; + case 3: *byt = ((word >> 8) & 0377); + break; + } + return 0; +} + +t_stat load_exb (FILE *fileref, int ftype) +{ + int odd = 0; + int pos = 0; + int wc; + int byt; + uint64 word; + t_addr addr; + + exb_pos = -1; + for ( ;; ) { + int byt; + /* All records start on even byte */ + if (odd && get_exb_byte (fileref, &byt, ftype)) + return SCPE_FMT; + if (get_exb_byte(fileref, &byt, ftype)) + return SCPE_FMT; + wc = byt; + if (get_exb_byte(fileref, &byt, ftype)) + return SCPE_FMT; + wc |= byt << 8; + wc -= 4; + odd = wc & 1; + if (get_exb_byte(fileref, &byt, ftype)) + return SCPE_FMT; + addr = byt; + if (get_exb_byte(fileref, &byt, ftype)) + return SCPE_FMT; + addr |= byt << 8; + if (get_exb_byte(fileref, &byt, ftype)) + return SCPE_FMT; + addr |= byt << 16; + if (get_exb_byte(fileref, &byt, ftype)) + return SCPE_FMT; + addr |= byt << 24; + /* Empty record gives start address */ + if (wc == 0) { + PC = addr; + return SCPE_OK; + } + pos = 0; + for (; wc > 0; wc--, pos++) { + if (get_exb_byte(fileref, &byt, ftype)) + return SCPE_FMT; + switch(pos) { + case 0: word = ((uint64)byt); break; + case 1: word |= ((uint64)byt) << 8; break; + case 2: word |= ((uint64)byt) << 16; break; + case 3: word |= ((uint64)byt) << 24; break; + case 4: word |= ((uint64)(byt & 017)) << 32; + M[addr++] = word; + pos = -1; + break; + } + } + } + return SCPE_FMT; +} + /* Master loader */ t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) @@ -717,12 +798,16 @@ else if (sim_switches & SWMASK ('D')) /* -d? */ fmt = FMT_D; else if (sim_switches & SWMASK ('I')) /* -i? */ fmt = FMT_I; +else if (sim_switches & SWMASK ('B')) /* -b? */ + fmt = FMT_B; else if (match_ext (fnam, "RIM")) /* .RIM? */ fmt = FMT_R; else if (match_ext (fnam, "SAV")) /* .SAV? */ fmt = FMT_S; else if (match_ext (fnam, "EXE")) /* .EXE? */ fmt = FMT_E; +else if (match_ext (fnam, "EXB")) /* .EXB? */ + fmt = FMT_B; else if (match_ext (fnam, "DMP")) /* .DMP? */ fmt = FMT_D; else if (match_ext (fnam, "BIN")) /* .BIN? */ @@ -754,6 +839,9 @@ switch (fmt) { /* case fmt */ case FMT_I: /* SBLK */ return load_sblk (fileref); + + case FMT_B: /* EXB */ + return load_exb (fileref, ftype); } printf ("Can't determine load file format\n"); From 5969ce355325d1d0d7c6c7218b8584d7e0ae215f Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 30 Oct 2019 21:00:09 -0400 Subject: [PATCH 39/98] KA10: Fixed bugs in interrupt vector for RH10/RH20. --- PDP10/kx10_rh.c | 7 +++++-- PDP10/kx10_rp.c | 2 -- PDP10/kx10_rs.c | 43 ++++++++++++++++++++++--------------------- PDP10/kx10_tu.c | 2 +- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index d6a414d..1a3450d 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -99,7 +99,7 @@ #define CR_FUNC 0000000000076LL #define CR_GO 0000000000001LL -#define IRQ_VECT 0000000000177LL /* Interupt vector */ +#define IRQ_VECT 0000000000777LL /* Interupt vector */ #define IRQ_KI10 0000002000000LL #define IRQ_KA10 0000001000000LL #define FNC_XFER 024 /* >=? data xfr */ @@ -484,7 +484,10 @@ rh_devirq(uint32 dev, t_addr addr) { } } if (rhc != NULL) { - return (rhc->imode ? rhc->ivect : addr); + if (rhc->imode == 1) /* KI10 Style */ + addr = RSIGN | rhc->ivect; + else if (rhc->imode == 2) /* RH20 style */ + addr = rhc->ivect; } return addr; } diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index 9feac0c..63319f4 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -32,7 +32,6 @@ #define CLR_BUF(u) u->hwmark = 0xFFFFFFFF #define RP_NUMWD 128 /* 36bit words/sec */ -#define RP_DEVNUM 0270 /* First device number */ #define NUM_UNITS_RP 8 /* Flags in the unit flags word */ @@ -1084,7 +1083,6 @@ t_stat rp_attach (UNIT *uptr, CONST char *cptr) if (rh[ctlr].dev == rptr) break; } - ctlr = dib->dev_num & 014; uptr->DA = 0; uptr->CMD &= ~DS_VV; uptr->CMD |= DS_DPR|DS_MOL|DS_DRY; diff --git a/PDP10/kx10_rs.c b/PDP10/kx10_rs.c index cb7ab6d..1124bb5 100644 --- a/PDP10/kx10_rs.c +++ b/PDP10/kx10_rs.c @@ -28,6 +28,8 @@ #endif #if (NUM_DEVS_RS > 0) +#define BUF_EMPTY(u) (u->hwmark == 0xFFFFFFFF) +#define CLR_BUF(u) u->hwmark = 0xFFFFFFFF #define RS_NUMWD 128 /* 36bit words/sec */ #define NUM_UNITS_RS 8 @@ -170,18 +172,7 @@ struct drvtyp rs_drv_tab[] = { }; -//struct df10 rs_df10[NUM_DEVS_RS]; -//uint32 rs_xfer_drive[NUM_DEVS_RS]; uint64 rs_buf[NUM_DEVS_RS][RS_NUMWD]; -//int rs_reg[NUM_DEVS_RS]; -//int rs_ivect[NUM_DEVS_RS]; -//int rs_imode[NUM_DEVS_RS]; -//int rs_drive[NUM_DEVS_RS]; -//int rs_rae[NUM_DEVS_RS]; -//int rs_attn[NUM_DEVS_RS]; - -//t_stat rs_devio(uint32 dev, uint64 *data); -//int rs_devirq(uint32 dev, int addr); void rs_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data); uint32 rs_read(DEVICE *dptr, struct rh_if *rhc, int reg); void rs_rst(DEVICE *dptr); @@ -323,6 +314,7 @@ rs_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { case FNC_WRITE: /* write */ case FNC_READ: /* read */ uptr->CMD |= DS_PIP|CS1_GO; + CLR_BUF(uptr); uptr->DATAPTR = 0; break; @@ -441,6 +433,7 @@ t_stat rs_svc (UNIT *uptr) struct rh_if *rhc; int da; t_stat r; + int sts; /* Find dptr, and df10 */ dptr = rs_devs[ctlr]; @@ -481,7 +474,7 @@ t_stat rs_svc (UNIT *uptr) case FNC_READ: /* read */ case FNC_WCHK: /* write check */ - if (uptr->DATAPTR == 0) { + if (BUF_EMPTY(uptr)) { int wc; if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) { @@ -500,15 +493,17 @@ t_stat rs_svc (UNIT *uptr) while (wc < RS_NUMWD) rs_buf[ctlr][wc++] = 0; uptr->hwmark = RS_NUMWD; + uptr->DATAPTR = 0; } rhc->buf = rs_buf[ctlr][uptr->DATAPTR++]; sim_debug(DEBUG_DATA, dptr, "%s%o read word %d %012llo %09o %06o\n", dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr); if (rh_write(rhc)) { - if (uptr->DATAPTR == uptr->hwmark) { + if (uptr->DATAPTR == RS_NUMWD) { /* Increment to next sector. Set Last Sector */ uptr->DATAPTR = 0; + CLR_BUF(uptr); uptr->DA += 1 << DA_V_SC; if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect) { uptr->DA &= (DA_M_SF << DA_V_SF); @@ -525,13 +520,15 @@ rd_end: sim_debug(DEBUG_DETAIL, dptr, "%s%o read done\n", dptr->name, unit); uptr->CMD |= DS_DRY; uptr->CMD &= ~CS1_GO; + if (uptr->DATAPTR == RS_NUMWD) + (void)rh_blkend(rhc); rh_finish_op(rhc, 0); return SCPE_OK; } break; case FNC_WRITE: /* write */ - if (uptr->DATAPTR == 0) { + if (BUF_EMPTY(uptr)) { if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect || GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) { uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA; @@ -540,14 +537,18 @@ rd_end: rh_finish_op(rhc, 0); return SCPE_OK; } + uptr->DATAPTR = 0; + uptr->hwmark = 0; } - r = rh_read(rhc); + sts = rh_read(rhc); rs_buf[ctlr][uptr->DATAPTR++] = rhc->buf; sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %09o %06o\n", dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr); - if (r == 0 || uptr->DATAPTR == RS_NUMWD) { + if (sts == 0) { while (uptr->DATAPTR < RS_NUMWD) rs_buf[ctlr][uptr->DATAPTR++] = 0; + } + if (uptr->DATAPTR == RS_NUMWD) { sim_debug(DEBUG_DETAIL, dptr, "%s%o write (%d,%d)\n", dptr->name, unit, GET_SC(uptr->DA), GET_SF(uptr->DA)); da = GET_DA(uptr->DA, dtype) * RS_NUMWD; @@ -555,7 +556,8 @@ rd_end: (void)sim_fwrite (&rs_buf[ctlr][0], sizeof(uint64), RS_NUMWD, uptr->fileref); uptr->DATAPTR = 0; - if (r) { + CLR_BUF(uptr); + if (sts) { uptr->DA += 1 << DA_V_SC; if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect) { uptr->DA &= (DA_M_SF << DA_V_SF); @@ -563,11 +565,11 @@ rd_end: if (GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) uptr->CMD |= DS_LST; } - if (rh_blkend(rhc)) - goto wr_end; } + if (rh_blkend(rhc)) + goto wr_end; } - if (r) { + if (sts) { sim_activate(uptr, 20); } else { wr_end: @@ -668,7 +670,6 @@ t_stat rs_attach (UNIT *uptr, CONST char *cptr) if (rstr == 0) return SCPE_OK; dib = (DIB *) rstr->ctxt; - ctlr = dib->dev_num & 014; uptr->DA = 0; uptr->CMD &= ~DS_VV; uptr->CMD |= DS_DPR|DS_MOL|DS_DRY; diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index 0c4bcd6..ce91300 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -236,7 +236,7 @@ REG tua_reg[] = { }; DEVICE tua_dev = { - "TUA", tu_unit, NULL, tu_mod, + "TUA", tu_unit, tua_reg, tu_mod, NUM_UNITS_TU, 8, 18, 1, 8, 36, NULL, NULL, &tu_reset, &tu_boot, &tu_attach, &tu_detach, &tu_dib[0], DEV_DISABLE | DEV_DEBUG | DEV_TAPE, 0, dev_debug, From 5dbbbe8245d3a369caef0135376b16c01debbdb7 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 30 Oct 2019 21:00:47 -0400 Subject: [PATCH 40/98] KA10: KL10B now passes DFKEC and DFKED. --- PDP10/kx10_cpu.c | 126 ++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 68 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 8315c0b..691011e 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -4086,9 +4086,8 @@ no_fetch: IA = AB; #if KL & KLB if (QKLB) - glb_sect = (cur_sect != 0); + glb_sect = 0; #endif - i_flags = opflags[IR]; BYF5 = 0; } @@ -4114,12 +4113,20 @@ no_fetch: } #endif -#if KLB - if (QKLB) - glb_sect = 0; -#endif - /* Handle indirection repeat until no longer indirect */ +#if KL && KLB + /* If we are doing a PXCT with E1 or E2 set, change section */ + if (QKLB) { + if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || + ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) + sect = cur_sect = prev_sect; + /* Short cut for extended pointer address */ + if (ptr_flg && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { /* Full pointer */ + ind = 1; /* Allow us to read word, xDB has already bumped AB */ + goto in_loop; + } + } +#endif do { if ((!pi_cycle) & pi_pending #if KI | KL @@ -4128,23 +4135,10 @@ no_fetch: ) { pi_rq = check_irq_level(); } -#if KLB - if (QKLB && ptr_flg && pc_sect != 0 && (AR & BIT12) != 0) { /* Full pointer */ - ind = 1; - goto in_loop; - } -#endif ind = TST_IND(MB) != 0; AR = MB; AB = MB & RMASK; ix = GET_XR(MB); -#if KLB - if (QKLB) { - if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || - ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) - sect = cur_sect = prev_sect; - } -#endif if (ix) { #if KL if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || @@ -4171,9 +4165,6 @@ no_fetch: AB = MB & RMASK; } #if KL & KLB - else /* No index so become local */ - glb_sect = 0; - in_loop: #endif if (ind & !pi_rq) { @@ -4181,15 +4172,15 @@ in_loop: goto last; #if KL & KLB /* Check if extended indexing */ - if (QKLB && cur_sect != 0) { - if (MB & SMASK) { /* Instruction format IFIW */ - if (MB & BIT1) { /* Illegal index word */ + if (QKLB && (cur_sect != 0 || glb_sect)) { + if (MB & SMASK || cur_sect == 0) { /* Instruction format IFIW */ + if (MB & BIT1 && cur_sect != 0) { /* Illegal index word */ +//fprintf(stderr, "Illegal fault %06o %012llo\n\r", PC, MB); fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | (AR & RMASK) | ((uint64)cur_sect << 18); page_fault = 1; goto last; } - glb_sect = 0; ind = TST_IND(MB) != 0; ix = GET_XR(MB); AB = MB & RMASK; @@ -4200,20 +4191,25 @@ in_loop: else AR = get_reg(ix); /* Check if extended indexing */ - if ((AR & SMASK) != 0 || (AR & SECTM) == 0) { /* Local index word */ + if (cur_sect == 0 || (AR & SMASK) != 0 || (AR & SECTM) == 0) { + /* Local index word */ AR = (AR + AB) & RMASK; + glb_sect = 0; } else { AR = (AR + AB) & FMASK; glb_sect = 1; sect = cur_sect = (AR >> 18) & 07777; } MB = AR; - } else + } else { + if (((xct_flag & 014) != 014 || (FLAGS & USER) != 0)) + glb_sect = 0; + if ((MB & RMASK) < 020) + sect = cur_sect = 1; AR = MB; + } AB = AR & RMASK; - if (!glb_sect && AB < 020) /* Map to global AC */ - sect = cur_sect = 1; -//fprintf(stderr, "LFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); +//fprintf(stderr, "LFIW %012llo %o %02o %06o %06o %o\n\r", MB, ind, ix, cur_sect, AB, glb_sect); } else { /* Extended index EFIW */ ind = (MB & BIT1) != 0; ix = (MB >> 30) & 017; @@ -4235,7 +4231,7 @@ in_loop: sect = cur_sect = (AR >> 18) & 07777; AB = AR & RMASK; glb_sect = 1; -//fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); +//fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", AR, ind, ix, cur_sect, AB); } if (ind) goto in_loop; @@ -4324,7 +4320,7 @@ st_pi: } /* Update history */ - if (hst_lnt /*&& PC > 017*/) { + if (hst_lnt && PC > 017) { hst_p = hst_p + 1; if (hst_p >= hst_lnt) { hst_p = 0; @@ -5975,7 +5971,7 @@ ldb_ptr: #if KL ptr_flg = 1; #if KLB - if (QKLB && pc_sect != 0 && (AR & BIT12) != 0) { + if (QKLB && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; //fprintf(stderr, "LBP %o %o %06o %012llo\n\r", SC, SCAD, AB, MB); @@ -7207,7 +7203,7 @@ xjrstf: goto last; AR = MB; /* Get PC. */ #if KLB - if (QKLB) { + if (QKLB && t20_page) { pc_sect = (AR >> 18) & 07777; if ((FLAGS & USER) == 0 && ((BR >> 23) & USER) == 0) prev_sect = BR & 037; @@ -7272,7 +7268,6 @@ jrstf: if (uuo_cycle | pi_cycle) { FLAGS &= ~(USER|PUBLIC); /* Clear USER */ } - sect = 0; if (Mem_write(0, 0)) goto last; AB = (AB + 1) & RMASK; @@ -7587,6 +7582,8 @@ jrstf: } else { sect = pc_sect; AR = AOB(AR); + if (pc_sect != 0 && (AR & RMASK) < 020) + sect = 1; } } else #endif @@ -7622,7 +7619,7 @@ jrstf: } #endif #if KL & KLB - if (QKLB && pc_sect != 0 && glb_sect) + if (QKLB && glb_sect) pc_sect = cur_sect; #endif PC = BR & RMASK; @@ -7634,7 +7631,7 @@ jrstf: #if KL BYF5 = 1; #if KLB - if (QKLB) { + if (QKLB && t20_page) { if (pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { AR = (AR + 1) & FMASK; sect = (AR >> 18) & 07777; @@ -7648,23 +7645,6 @@ jrstf: AR = AOB(AR); AB = AR & RMASK; MB = BR; -#if KLB - flag1 = glb_sect; - if (QKLB) { - f = (pc_sect != 0); - if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) { - sect = prev_sect; - f = (prev_sect != 0); - } - if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - sect = (AR >> 18) & 07777; - glb_sect = 1; - } - if (Mem_write(0, 0)) - goto last; - break; - } -#endif if (AR & C1) { #if KI | KL if (!pi_cycle) @@ -7674,6 +7654,16 @@ jrstf: check_apr_irq(); #endif } +#if KLB + if (QKLB && t20_page) { + if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) + sect = prev_sect; + if (sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + sect = (AR >> 18) & 07777; + glb_sect = 1; + } + } +#endif if (Mem_write(0, 0)) goto last; break; @@ -7683,7 +7673,7 @@ jrstf: BYF5 = 1; /* Tell PXCT that this is stack */ #if KLB flag1 = glb_sect; - if (QKLB) { + if (QKLB && t20_page) { f = (pc_sect != 0); sect = pc_sect; if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) { @@ -7706,7 +7696,7 @@ jrstf: #if KL BYF5 = 0; /* Now back to data */ #if KLB - if (QKLB) { + if (QKLB && t20_page) { sect = cur_sect; glb_sect = flag1; } @@ -7737,7 +7727,7 @@ jrstf: #if KL BYF5 = 1; /* Tell PXCT that this is stack */ #if KLB - if (QKLB) { + if (QKLB && t20_page) { f = (pc_sect != 0); sect = pc_sect; if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) { @@ -8557,7 +8547,7 @@ fetch_opr: } if (hst_lnt && PC >= 020) { - hst[hst_p].fmb = MB; + hst[hst_p].fmb = (i_flags & SAC) ? AR: MB; } last: @@ -8596,7 +8586,7 @@ last: AB++; FLAGS |= trap_flag & (TRP1|TRP2); trap_flag = (TRP1|TRP2); - if (QKLB /*|| (!QITS && t20_page)*/) + if (QKLB & t20_page) MB = (((uint64)(FLAGS) << 23) & LMASK); else MB = (((uint64)(FLAGS) << 23) & LMASK) | (PC & RMASK); @@ -8606,7 +8596,7 @@ last: } Mem_write_nopage(); AB++; - if (QKLB /*|| (!QITS && t20_page)*/) { + if (QKLB && t20_page) { MB = (((uint64)pc_sect) << 18) | (PC & RMASK); Mem_write_nopage(); AB++; @@ -9941,7 +9931,7 @@ do_extend(uint32 ia) while (reg != 0) { if (reg & SMASK) { val1 = (val1 - 1) & (SECTM|RMASK); - sect = (val1 >> 18) & 07777; + sect = (val1 >> 18) & 00037; AB = val1 & RMASK; ptr_flg = 1; if (Mem_read(0, 0, 0)) { @@ -9950,7 +9940,7 @@ do_extend(uint32 ia) } //fprintf(stderr, " XBLT: D=%012llo 1-%012llo 2-%012llo\n\r", MB, val1, val2); val2 = (val2 - 1) & (SECTM|RMASK); - sect = (val2 >> 18) & 07777; + sect = (val2 >> 18) & 00037; AB = val2 & RMASK; ptr_flg = 0; BYF5 = 1; @@ -9962,13 +9952,13 @@ do_extend(uint32 ia) BYF5 = 0; reg = (reg + 1) & FMASK; } else { - sect = (val1 >> 18) & 07777; + sect = (val1 >> 18) & 00037; AB = val1 & RMASK; ptr_flg = 1; if (Mem_read(0, 0, 0)) goto xblt_done; //fprintf(stderr, " XBLT: D=%012llo 1-%012llo 2-%012llo\n\r", MB, val1, val2); - sect = (val2 >> 18) & 07777; + sect = (val2 >> 18) & 00037; AB = val2 & RMASK; ptr_flg = 0; BYF5 = 1; @@ -10416,7 +10406,7 @@ for (k = 0; k < lnt; k++) { /* print specified */ #if KL #if KLB if (QKLB) - fprintf(st, "%09o ", h->pc & 0777777777); + fprintf(st, "%08o ", h->pc & 0777777777); else #endif #endif @@ -10426,7 +10416,7 @@ for (k = 0; k < lnt; k++) { /* print specified */ #if KL #if KLB if (QKLB) - fprintf(st, "%09o ", h->ea & 0777777777); + fprintf(st, "%08o ", h->ea & 0777777777); else #endif #endif From 7015ff72bbad109f0279163143501e1c2e2b21b0 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 3 Nov 2019 00:55:59 -0400 Subject: [PATCH 41/98] SCP: Updated to current. --- sim_ether.c | 8 +++++--- sim_sock.c | 8 ++++---- sim_tape.c | 24 ++++++++++++++++++++---- sim_tmxr.c | 2 +- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/sim_ether.c b/sim_ether.c index 7d56f7b..f242e90 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -1572,10 +1572,10 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname) memset(command, 0, sizeof(command)); /* try to force an otherwise unused interface to be turned on */ - snprintf(command, sizeof(command)-1, "ifconfig %s up", devname); + snprintf(command, sizeof(command)-1, "ifconfig %.*s up", (int)(sizeof(command) - 14), devname); (void)system(command); for (i=0; patterns[i] && (0 == dev->have_host_nic_phy_addr); ++i) { - snprintf(command, sizeof(command)-1, "ifconfig %s | %s >NIC.hwaddr", devname, patterns[i]); + snprintf(command, sizeof(command)-1, "ifconfig %.*s | %s >NIC.hwaddr", (int)(sizeof(command) - (26 + strlen(patterns[i]))), devname, patterns[i]); (void)system(command); if (NULL != (f = fopen("NIC.hwaddr", "r"))) { while (0 == dev->have_host_nic_phy_addr) { @@ -2118,7 +2118,9 @@ else { /* !tap: */ while (isspace(*devname)) ++devname; - if ((*handle = (void*) sim_slirp_open(devname, opaque, &_slirp_callback, dptr, dbit, errbuf, PCAP_ERRBUF_SIZE))) { + if (!(*handle = (void*) sim_slirp_open(devname, opaque, &_slirp_callback, dptr, dbit, errbuf, PCAP_ERRBUF_SIZE))) + strlcpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE); + else { *eth_api = ETH_API_NAT; *fd_handle = 0; } diff --git a/sim_sock.c b/sim_sock.c index 858a74b..4235cea 100644 --- a/sim_sock.c +++ b/sim_sock.c @@ -1045,7 +1045,7 @@ int keepalive = 1; defined (__APPLE__) || defined (__OpenBSD__) || \ defined(__NetBSD__) || defined(__FreeBSD__) || \ (defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED)) || \ - defined (__HAIKU__) + defined (__HAIKU__) || defined(__CYGWIN__) socklen_t size; #elif defined (_WIN32) || defined (__EMX__) || \ (defined (__ALPHA) && defined (__unix__)) || \ @@ -1111,7 +1111,7 @@ struct sockaddr_storage peername; defined (__APPLE__) || defined (__OpenBSD__) || \ defined(__NetBSD__) || defined(__FreeBSD__) || \ (defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED)) || \ - defined (__HAIKU__) + defined (__HAIKU__) || defined(__CYGWIN__) socklen_t peernamesize = (socklen_t)sizeof(peername); #elif defined (_WIN32) || defined (__EMX__) || \ (defined (__ALPHA) && defined (__unix__)) || \ @@ -1147,7 +1147,7 @@ static int _sim_getaddrname (struct sockaddr *addr, size_t addrsize, char *hostn defined (__APPLE__) || defined (__OpenBSD__) || \ defined(__NetBSD__) || defined(__FreeBSD__) || \ (defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED)) || \ - defined (__HAIKU__) + defined (__HAIKU__) || defined(__CYGWIN__) socklen_t size = (socklen_t)addrsize; #elif defined (_WIN32) || defined (__EMX__) || \ (defined (__ALPHA) && defined (__unix__)) || \ @@ -1181,7 +1181,7 @@ struct sockaddr_storage sockname, peername; defined (__APPLE__) || defined (__OpenBSD__) || \ defined(__NetBSD__) || defined(__FreeBSD__) || \ (defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED)) || \ - defined (__HAIKU__) + defined (__HAIKU__) || defined(__CYGWIN__) socklen_t socknamesize = (socklen_t)sizeof(sockname); socklen_t peernamesize = (socklen_t)sizeof(peername); #elif defined (_WIN32) || defined (__EMX__) || \ diff --git a/sim_tape.c b/sim_tape.c index 312731c..8729a89 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -3353,6 +3353,8 @@ uint32 tapemark_total = 0; uint32 record_total = 0; uint32 unique_record_sizes = 0; uint32 remaining_data = 0; +uint32 gaps = 0; +uint32 gap_bytes = 0; uint32 *rec_sizes = NULL; t_stat r = SCPE_OK; t_stat r_f; @@ -3429,9 +3431,15 @@ while (r == SCPE_OK) { memset (buf_f, 0, bc_f); memset (buf_r, 0, bc_r); if (pos_f != pos_r) { - sim_printf ("Unexpected tape file position between forward and reverse record read: (%" T_ADDR_FMT "u, %" T_ADDR_FMT "u)\n", pos_f, pos_r); - r = MTSE_RECE; - break; + if (MT_GET_FMT (uptr) == MTUF_F_STD) { + ++gaps; + gap_bytes += (uint32)(pos_r - pos_f); + } + else { + sim_printf ("Unexpected tape file position between forward and reverse record read: (%" T_ADDR_FMT "u, %" T_ADDR_FMT "u)\n", pos_f, pos_r); + r = MTSE_RECE; + break; + } } r_s = sim_tape_sprecf (uptr, &bc_s); pos_sa = uptr->pos; @@ -3479,8 +3487,10 @@ if ((!stop_cpu) && sim_messagef (SCPE_OK, "Comprising %d different sized records (in record size order):\n", unique_record_sizes); for (bc = 0; bc <= max; bc++) { if (rec_sizes[bc]) - sim_messagef (SCPE_OK, "%8u %u byte records\n", rec_sizes[bc], (uint32)bc); + sim_messagef (SCPE_OK, "%8u %u byte record%s\n", rec_sizes[bc], (uint32)bc, (rec_sizes[bc] != 1) ? "s" : ""); } + if (gaps) + sim_messagef (SCPE_OK, "%8u gap%s totalling %u bytes %s seen\n", gaps, (gaps != 1) ? "s" : "", gap_bytes, (gaps != 1) ? "were" : "was"); } if (r != MTSE_EOM) sim_messagef (SCPE_OK, "Read Tape Record Returned Unexpected Status: %s\n", sim_tape_error_text (r)); @@ -3848,6 +3858,12 @@ for (i=0; ilines; i++) { /* check each line in se ++mp->sessions; /* count the new session */ if (lp->destination) { /* Virtual Null Modem Cable? */ - char host[CBUFSIZE]; + char host[sizeof(msg) - 64]; if (sim_parse_addr (lp->destination, host, sizeof(host), NULL, NULL, 0, NULL, address)) { tmxr_msg (newsock, "Rejecting connection from unexpected source\r\n"); From ec771f3398fd24075361978e48a3d5edcfbca324 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 3 Nov 2019 00:56:24 -0400 Subject: [PATCH 42/98] KA10: More changes to make Tops 20 happy. --- PDP10/kl10_fe.c | 68 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index d145f3b..f1f5802 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -235,6 +235,7 @@ struct _dte_queue { uint16 dcnt; /* Data count */ uint16 data[256]; /* Data packet */ uint16 sdev; /* Secondary device code */ + uint16 sz; /* Byte size */ } dte_in[32], dte_out[32]; int dte_in_ptr; @@ -476,10 +477,15 @@ sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n"); sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAI %06o\n", dev, (uint32)*data); break; case DATAO: + sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAO %06o\n", dev, (uint32)*data); + if (*data == 01365) { + dte_unit[0].STATUS |= DTE_SEC|DTE_10ER; + dte_unit[0].STATUS &= ~(DTE_10DB); + break; + } dte_unit[0].CNT = (*data & (DTE_TO10IB|DTE_TO10BC)); dte_unit[0].STATUS |= DTE_TO11; sim_activate(&dte_unit[0], 10); - sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAO %06o\n", dev, (uint32)*data); break; } return SCPE_OK; @@ -671,7 +677,7 @@ void dte_its(UNIT *uptr) { cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; cnt--; if (! sim_is_active(&dte_unit[1])) - sim_activate(&dte_unit[1], 100); + sim_activate(&dte_unit[1], 50); #if (NUM_DEVS_TTY > 0) } else { struct _buffer *otty = &tty_out[ln]; @@ -745,7 +751,6 @@ error: #endif base = eb_ptr; #endif -fprintf(stderr, "DTE going to secondary %012llo error\n\r", word); /* If we can't read it, go back to secondary */ M[SEC_DTFLG + base] = FMASK; uptr->STATUS |= DTE_SEC; @@ -758,7 +763,6 @@ fprintf(stderr, "DTE going to secondary %012llo error\n\r", word); } if ((word & PRI_CMT_QP) == 0) { -fprintf(stderr, "DTE going to secondary %012llo No QP\n\r", word); goto error; } in = &dte_in[dte_in_ptr]; @@ -776,19 +780,24 @@ fprintf(stderr, "DTE going to secondary %012llo No QP\n\r", word); in->dcnt = (uint16)(iword & 0177777); /* Read in data */ dp = &in->data[0]; - for (cnt = in->dcnt; cnt >= 0; cnt -=2) { + for (cnt = in->dcnt; cnt >= 0; cnt --) { /* Read in data */ - if (!Mem_read_byte(0, dp, 0)) + s = Mem_read_byte(0, dp, 0); + if (s == 0) goto error; + in->sz = s; sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o %06o\n", *dp, *dp >> 8, *dp & 0377, ((*dp & 0377) << 8) | ((*dp >> 8) & 0377)); dp++; + if (s <= 8) + cnt--; } uptr->STATUS &= ~DTE_IND; dte_in_ptr = (dte_in_ptr + 1) & 0x1f; } else { /* Transfer from 10 */ in->dptr = 0; + in->dcnt = 0; /* Read in count */ if (!Mem_read_byte(0, &data1, 0)) goto error; @@ -817,6 +826,7 @@ fprintf(stderr, "DTE going to secondary %012llo No QP\n\r", word); sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read data: %06o %03o %03o\n", *dp, *dp >> 8, *dp & 0377); dp++; + in->dcnt += 2; } if (in->func & PRI_IND_FLG) { uptr->STATUS |= DTE_IND; @@ -870,7 +880,7 @@ dte_function(UNIT *uptr) return; #endif data1[0] = 0; - if (dte_queue(PRI_EMAKA, PRI_EMCLK, 0, data1) == 0) + if (dte_queue(PRI_EMAKA, PRI_EMCLK, 1, data1) == 0) return; break; @@ -935,6 +945,8 @@ dte_function(UNIT *uptr) if (ln > 0 && ln >= tty_desc.lines) break; otty = &tty_out[ln]; + if (cmd->sz > 8) + cmd->dcnt += cmd->dcnt; while (cmd->dptr < cmd->dcnt) { if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) return; @@ -942,9 +954,11 @@ dte_function(UNIT *uptr) if ((cmd->dptr & 1) == 0) ch >>= 8; ch &= 0177; - sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %o %d\n", ch, ln); - otty->buff[otty->in_ptr] = ch; - otty->in_ptr = (otty->in_ptr + 1) & 0xff; + if (ch != 0) { + sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %o %d\n", ch, ln); + otty->buff[otty->in_ptr] = ch; + otty->in_ptr = (otty->in_ptr + 1) & 0xff; + } cmd->dptr++; } if (cmd->dptr != cmd->dcnt) @@ -959,6 +973,8 @@ dte_function(UNIT *uptr) cty: sim_activate(&dte_unit[1], 100); data1[0] = 0; + if (cmd->sz > 8) + cmd->dcnt += cmd->dcnt; while (cmd->dptr < cmd->dcnt) { if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) return; @@ -966,10 +982,12 @@ cty: if ((cmd->dptr & 1) == 0) ch >>= 8; ch &= 0177; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); - cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + if (ch != 0) { + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); + cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + } cmd->dptr++; } if (cmd->dptr != cmd->dcnt) @@ -977,8 +995,28 @@ cty: break; case PRI_EMLNC: /* Line-Char */ - /* Send by DTE only? */ + if (cmd->dev == PRI_EMDLS) { + sim_activate(&dte_unit[1], 100); + while (cmd->dptr < cmd->dcnt) { + int ln; + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) + return; + ch = (int32)(cmd->data[cmd->dptr >> 1]); + ln = (ch >> 8); + ch &= 0177; + if (ch != 0 && ln == 0) { + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); + cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + } + cmd->dptr+=2; + } + if (cmd->dptr != cmd->dcnt) + return; + } break; + case PRI_EMRDS: /* Request device status */ #if (NUM_DEVS_LP > 0) if (cmd->dev == PRI_EMLPT) { From a408e53f73a2ad0689be016e7fbf4dd05b658471 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 3 Nov 2019 00:56:57 -0400 Subject: [PATCH 43/98] KA10: Changes to make TM03 behave on RH20. --- PDP10/kx10_rh.c | 15 +++++++-------- PDP10/kx10_tu.c | 34 ++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index 1a3450d..da0ec3e 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -496,10 +496,8 @@ rh_devirq(uint32 dev, t_addr addr) { void rh_setattn(struct rh_if *rhc, int unit) { rhc->attn |= 1<imode != 2 && rhc->status & BUSY) - return; - if ((rhc->status & IADR_ATTN) != 0) - rh_setirq(rhc); + if ((rhc->status & BUSY) == 0 && (rhc->status & IADR_ATTN) != 0) + set_interrupt(rhc->devnum, rhc->status); } /* Decrement block count for RH20, nop for RH10 */ @@ -601,11 +599,12 @@ void rh20_setup(struct rh_if *rhc) rhc->ptcr = rhc->stcr; /* Read drive status */ rhc->drive = (rhc->ptcr >> 18) & 07; - rhc->status &= ~(RH20_SCR_FULL|PI_ENABLE|RH20_XEND); + rhc->status &= ~(RH20_DATA_OVR|RH20_CHAN_RDY|RH20_DR_RESP|RH20_CHAN_ERR|RH20_SHRT_WC|\ + RH20_LONG_WC|RH20_DR_EXC|RH20_SCR_FULL|PI_ENABLE|RH20_XEND); rhc->status |= RH20_PCR_FULL; - reg = rhc->dev_read(dptr, rhc, 1); - if ((reg & (DS_DRY|DS_DPR|DS_ERR)) != (DS_DRY|DS_DPR)) - return; +// reg = rhc->dev_read(dptr, rhc, 1); + // if ((reg & (DS_DRY|DS_DPR|DS_ERR)) != (DS_DRY|DS_DPR)) + // return; if (rhc->status & RH20_SBAR) { rhc->drive = (rhc->pbar >> 18) & 07; rhc->dev_write(dptr, rhc, 5, (rhc->pbar & 0177777)); diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index ce91300..ebb0e94 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -122,7 +122,7 @@ /* TUDT - 06 - drive type */ -/* TULA - 07 - look ahead register */ +/* TULA - 07 - Check Character */ /* TUSN - 10 - serial number */ @@ -338,6 +338,10 @@ tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { case 007: /* look ahead */ case 011: /* tape control register */ tu_tcr[ctlr] = data & 0177777 ; + if ((tu_tcr[ctlr] & TC_DENS) == TC_1600) + uptr->STATUS |= DS_PES; + else + uptr->STATUS &= ~DS_PES; break; default: uptr->STATUS |= ER1_ILR; @@ -469,10 +473,8 @@ void tu_error(UNIT * uptr, t_stat r) break; } - if (uptr->CMD & CS_ATA) { + if (uptr->CMD & CS_ATA) rh_setattn(rhc, 0); -// rhc->attn = 1; - } uptr->CMD &= ~(CS_MOTION|CS_PIP|CS1_GO); sim_debug(DEBUG_EXP, dptr, "Setting status %d\n", r); } @@ -517,13 +519,13 @@ t_stat tu_srv(UNIT * uptr) } else { uptr->CMD &= ~(CS_MOTION|CS_PIP); uptr->CMD |= CS_CHANGE|CS_ATA; - tu_error(uptr, sim_tape_rewind(uptr)); + rh_setattn(rhc, 0); + (void)sim_tape_rewind(uptr); } return SCPE_OK; case FNC_UNLOAD: sim_debug(DEBUG_DETAIL, dptr, "%s%o unload\n", dptr->name, unit); - uptr->CMD &= ~(CS1_GO); uptr->CMD |= CS_CHANGE|CS_ATA; tu_error(uptr, sim_tape_detach(uptr)); return SCPE_OK; @@ -642,7 +644,6 @@ t_stat tu_srv(UNIT * uptr) uptr->CMD &= ~CS_PIP; if (tu_frame[ctlr] == 0) { uptr->STATUS |= ER1_NEF; - uptr->CMD &= ~(CS1_GO); uptr->CMD |= CS_ATA; rhc->attn = 1; tu_error(uptr, MTSE_OK); @@ -701,6 +702,7 @@ t_stat tu_srv(UNIT * uptr) break; case FNC_WTM: + uptr->CMD &= ~CS_PIP; uptr->CMD |= CS_ATA; if ((uptr->flags & MTUF_WLK) != 0) { tu_error(uptr, MTSE_WRP); @@ -711,6 +713,7 @@ t_stat tu_srv(UNIT * uptr) return SCPE_OK; case FNC_ERASE: + uptr->CMD &= ~CS_PIP; uptr->CMD |= CS_ATA; if ((uptr->flags & MTUF_WLK) != 0) { tu_error(uptr, MTSE_WRP); @@ -723,6 +726,7 @@ t_stat tu_srv(UNIT * uptr) case FNC_SPACEF: case FNC_SPACEB: sim_debug(DEBUG_DETAIL, dptr, "%s%o space %o\n", dptr->name, unit, GET_FNC(uptr->CMD)); + uptr->CMD &= ~CS_PIP; if (tu_frame[ctlr] == 0) { uptr->STATUS |= ER1_NEF; uptr->CMD |= CS_ATA; @@ -735,6 +739,7 @@ t_stat tu_srv(UNIT * uptr) r = sim_tape_sprecf(uptr, &reclen); else r = sim_tape_sprecr(uptr, &reclen); + tu_frame[ctlr] = 0177777 & (tu_frame[ctlr] + 1); switch (r) { case MTSE_OK: /* no error */ break; @@ -744,22 +749,23 @@ t_stat tu_srv(UNIT * uptr) /* Fall Through */ case MTSE_TMK: /* tape mark */ + /* Position just after mark */ + if (GET_FNC(uptr->CMD) == FNC_SPACEB && r == MTSE_TMK) + sim_tape_sprecf(uptr, &reclen); case MTSE_EOM: /* end of medium */ if (tu_frame[ctlr] != 0) uptr->STATUS |= ER1_FCE; - uptr->CMD &= ~(CS1_GO); uptr->CMD |= CS_ATA; /* Stop motion if we recieve any of these */ tu_error(uptr, r); return SCPE_OK; } - tu_frame[ctlr] = 0177777 & (tu_frame[ctlr] + 1); if (tu_frame[ctlr] == 0) { uptr->CMD |= CS_ATA; tu_error(uptr, MTSE_OK); return SCPE_OK; } else - sim_activate(uptr, 5000); + sim_activate(uptr, reclen * 100); return SCPE_OK; } sim_activate(uptr, 100); @@ -858,9 +864,7 @@ tu_attach(UNIT * uptr, CONST char *file) r = sim_tape_attach_ex(uptr, file, 0, 0); if (r == SCPE_OK) { uptr->CMD = CS_ATA|CS_CHANGE; - rhc->attn = 1; - if ((rhc->status & IADR_ATTN) != 0) - rh_setirq(rhc); + rh_setattn(rhc, 0); } return r; } @@ -874,9 +878,7 @@ tu_detach(UNIT * uptr) /* Find df10 */ uptr->STATUS = 0; uptr->CMD = CS_ATA|CS_CHANGE; - rhc->attn = 1; - if ((rhc->status & IADR_ATTN) != 0) - rh_setirq(rhc); + rh_setattn(rhc, 0); return sim_tape_detach(uptr); } From 3621d71639d8af0696cac97af9e1dbb662150476 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 3 Nov 2019 00:57:57 -0400 Subject: [PATCH 44/98] KA10: Fixes to get Tops 10 and Tops 20 running on KL10B. --- PDP10/kx10_cpu.c | 455 +++++++++++++++++++++++++--------------------- PDP10/kx10_defs.h | 19 ++ 2 files changed, 262 insertions(+), 212 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 691011e..7ad0236 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -110,13 +110,11 @@ uint64 M[MAXMEMSIZE]; /* Memory */ #if KL uint64 FM[128]; /* Fast memory register */ -#else -#if KI +#elif KI uint64 FM[64]; /* Fast memory register */ #else uint64 FM[16]; /* Fast memory register */ #endif -#endif uint64 AR; /* Primary work register */ uint64 MQ; /* Extension to AR */ uint64 BR; /* Secondary operand */ @@ -312,8 +310,6 @@ InstHistory *hst = NULL; /* instruction history */ /* Forward and external declarations */ #if KL -int Mem_read(int flag, int cur_context, int fetch); -int Mem_write(int flag, int cur_context); int do_extend(uint32 IA); #endif t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); @@ -330,6 +326,13 @@ t_stat cpu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); const char *cpu_description (DEVICE *dptr); void set_ac_display (uint64 *acbase); +#if KA +int (*Mem_read)(int flag, int cur_context, int fetch); +int (*Mem_write)(int flag, int cur_context); +#else +int Mem_read(int flag, int cur_context, int fetch); +int Mem_write(int flag, int cur_context); +#endif t_bool build_dev_tab (void); @@ -371,12 +374,10 @@ REG cpu_reg[] = { { ORDATA (FM17, FM[017], 36) }, #if KL { BRDATA (FM, &FM[0], 8, 36, 128)}, -#else -#if KI +#elif KI { BRDATA (FM, &FM[0], 8, 36, 64)}, #else { BRDATA (FM, &FM[0], 8, 36, 16)}, -#endif #endif { ORDATAD (PIR, PIR, 8, "Priority Interrupt Request") }, { ORDATAD (PIH, PIH, 8, "Priority Interrupt Hold") }, @@ -1496,7 +1497,9 @@ t_stat dev_mtr(uint32 dev, uint64 *data) { /* RDMACT */ /* Read memory accounting */ if (page_enable) { + sim_interval--; res = M[ub_ptr + 0506]; + sim_interval--; BR = (M[ub_ptr + 0507] & CMASK); } else { res = 0 << 12; @@ -1512,7 +1515,9 @@ t_stat dev_mtr(uint32 dev, uint64 *data) { update_times(t); rtc_tim = ((int)us); if (page_enable) { + sim_interval--; res = M[ub_ptr + 0504]; + sim_interval--; BR = (M[ub_ptr + 0505] & CMASK); } else { res = 0; @@ -1588,7 +1593,9 @@ t_stat dev_tim(uint32 dev, uint64 *data) { update_times(t); rtc_tim = ((int)us); if (page_enable) { + sim_interval--; res = (M[ub_ptr + 0504]); + sim_interval--; BR = M[ub_ptr + 0505]; } else { res = 0 << 12; @@ -1603,7 +1610,9 @@ t_stat dev_tim(uint32 dev, uint64 *data) { update_times(t); rtc_tim = ((int)us); if (page_enable) { + sim_interval--; res = (M[eb_ptr + 0510]); + sim_interval--; BR = M[eb_ptr + 0511]; } else { res = 0; @@ -1804,11 +1813,13 @@ t_stat dev_pag(uint32 dev, uint64 *data) { case 0: /* Clear page tables, reload from 71 & 72 */ for (i = 0; i < 512; i++) e_tlb[i] = u_tlb[i] = 0; + sim_interval--; res = M[071]; mon_base_reg = (res & 03777) << 9; ac_stack = (res >> 9) & 0760; user_base_reg = (res >> 9) & 03777000; user_limit = page_limit[(res >> 30) & 07]; + sim_interval--; pur = M[072]; break; @@ -1988,6 +1999,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) dbr = (uf)? ((page & 0400) ? dbr2 : dbr1) : ((page & 0400) ? dbr3 : dbr4) ; pg = (page & 0377) >> 2; /* 2 1024 word page entries */ + sim_interval--; data = M[dbr + pg]; //fprintf(stderr, "Load page %06o dbr%012llo pg%06o data=%012llo -> ", page, dbr, pg, data); if ((page & 02) == 0) @@ -2001,19 +2013,19 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) pg = 0; switch(data >> 16) { case 0: - fault_data = 033LL << 30 |((uf)?SMASK:0); + fault_data = 033LL << 30; page_fault = 1; return 0; /* No access */ case 1: /* Read Only */ case 2: /* R/W First */ if (wr) { - fault_data = 024LL << 30 |((uf)?SMASK:0); + fault_data = 024LL << 30; page_fault = 1; return 0; } - pg = RSIGN; + pg = KL_PAG_A; break; - case 3: pg = RSIGN|0100000; break; /* R/W */ + case 3: pg = KL_PAG_A|KL_PAG_W; break; /* R/W */ } pg |= (data & 017777) << 1; /* Create 2 page table entries. */ @@ -2045,9 +2057,8 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) uint64 cst = FM[(06<<4)|2] & PG_MASK; uint64 cst_msk = FM[(06<<4)|0]; uint64 cst_dat = FM[(06<<4)|1]; - uint64 cst_val; + uint64 cst_val = 0; int index; - int match = 0; int pg; #if EPT440 int base = 0440; @@ -2065,6 +2076,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) base += (sect & 037); } #endif + sim_interval--; if (uf) data = M[ub_ptr + base]; else @@ -2074,7 +2086,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) sect_loop: switch ((data >> 33) & 07) { default: /* Invalid page */ - fault_data = (wr)? BIT5:0; + fault_data = 0; page_fault = 1; return 0; case 1: /* Direct page */ @@ -2086,12 +2098,14 @@ sect_loop: case 2: /* Shared page */ acc_bits &= (data >> 18) & RMASK; + sim_interval--; data = M[(data & RMASK) + spt]; break; case 3: /* Indirect page */ acc_bits &= (data >> 18) & RMASK; index = (data >> 18) & PG_IDX; + sim_interval--; data = M[(data & RMASK) + spt]; if (((data >> 18) & PG_STG) != 0) { fault_data = 0; @@ -2100,6 +2114,7 @@ sect_loop: } pg = data & PG_PAG; if (cst) { + sim_interval--; cst_val = M[cst + pg]; if ((cst_val & PG_AGE) == 0) { //fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); @@ -2111,6 +2126,7 @@ sect_loop: } M[cst + pg] = (cst_val & cst_msk) | cst_dat; } + sim_interval--; data = M[(pg << 9) | index]; goto sect_loop; } @@ -2124,6 +2140,7 @@ sect_loop: /* Update CST entry if needed */ if (cst) { + sim_interval--; cst_val = M[cst + pg]; //fprintf(stderr, "ZMap %08o %012llo %012llo age\n\r", cst+pg, data, cst_val); if ((cst_val & PG_AGE) == 0) { @@ -2137,6 +2154,7 @@ sect_loop: } /* Get address of page */ + sim_interval--; data = M[(pg << 9) | page]; //fprintf(stderr, "YMap %012llo %o %o\n\r", data, pg << 9, page); pg_loop: @@ -2144,7 +2162,7 @@ pg_loop: /* Decode map pointer */ switch ((data >> 33) & 07) { default: /* Invalid page */ - fault_data = (wr)? BIT5:0; + fault_data = 0; page_fault = 1; return 0; case 1: /* Direct page */ @@ -2156,12 +2174,14 @@ pg_loop: case 2: /* Shared page */ acc_bits &= (data >> 18) & RMASK; + sim_interval--; data = M[(data & RMASK) + spt]; break; case 3: /* Indirect page */ acc_bits &= (data >> 18) & RMASK; index = (data >> 18) & PG_IDX; + sim_interval--; data = M[(data & RMASK) + spt]; //fprintf(stderr, "IMap %012llo %o %o %o\n\r", data, pg << 9, index, page); if (((data >> 18) & PG_STG) != 0) { @@ -2171,6 +2191,7 @@ pg_loop: } pg = data & RMASK; if (cst) { + sim_interval--; cst_val = M[cst + pg]; //fprintf(stderr, "ZMap %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); if ((cst_val & PG_AGE) == 0) { @@ -2182,6 +2203,7 @@ pg_loop: } M[cst + pg] = (cst_val & cst_msk) | cst_dat; } + sim_interval--; data = M[(pg << 9) | index]; //fprintf(stderr, "JMap %012llo %o %o %o\n\r", data, pg << 9, index, page); goto pg_loop; @@ -2197,6 +2219,7 @@ pg_loop: /* Check outside of memory */ /* Update CST entry if needed */ if (cst) { + sim_interval--; cst_val = M[cst + pg]; //fprintf(stderr, "ZMap %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); if ((cst_val & PG_AGE) == 0) { @@ -2209,7 +2232,6 @@ pg_loop: if (acc_bits & PG_WRT) { if (wr) cst_val |= 1; - acc_bits |= 1; } else if (wr) { /* Trying to write and not writable */ //fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, cst_val); if (trap) { @@ -2220,8 +2242,9 @@ pg_loop: } M[cst + pg] = (cst_val & cst_msk) | cst_dat; } else { - if (acc_bits & PG_WRT) - acc_bits |= 1; + if (acc_bits & PG_WRT) { + cst_val = 1; + } } /* Now construct a TBL entry */ /* A = accessable */ @@ -2229,16 +2252,16 @@ pg_loop: /* W = writable */ /* S = user */ /* C = cache */ - data = pg | RSIGN; + data = pg | KL_PAG_A; if (acc_bits & PG_PUB) - data |= 0200000; + data |= KL_PAG_P; /* P */ if (acc_bits & PG_WRT) { - if (wr) - data |= 0040000; /* Set M bit (S) */ - data |= 0100000; /* Set W bit */ + if (cst_val & 1) + data |= KL_PAG_W; /* Set Modified page */ + data |= KL_PAG_S; /* Set Writeable bit */ } if (acc_bits & PG_CAC) - data |= 0020000; + data |= KL_PAG_C; #if KLB if (QKLB) data |= (((flag) ? 0: sect) & 037) << 18; @@ -2252,6 +2275,7 @@ pg_loop: } else { /* Map the page */ + sim_interval--; if (uf | upmp) { data = M[ub_ptr + (page >> 1)]; u_tlb[page & 01776] = (uint32)(RMASK & (data >> 18)); @@ -2358,21 +2382,38 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int data = load_tlb(uf, page, upmp, wr, 1, flag); if (data == 0 && page_fault) { fault_data |= ((uint64)addr); - if (uf) /* U */ - fault_data |= SMASK; /* BIT0 */ -#if KLB - if (QKLB) - fault_data = (((uint64)sect) << 18); -#endif -//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data); /* Ignore faults if flag set */ if (FLAGS & ADRFLT) { page_fault = 0; return 1; } + if (uf) /* U */ + fault_data |= SMASK; +#if KL_ITS + if (QITS) + return 0; +#endif + fault_data |= BIT8; +#if KLB + if (QKLB) + fault_data |= (((uint64)sect) << 18); +#endif + if (fault_data & BIT1) + return 0; + if (wr) /* T */ + fault_data |= BIT5; /* BIT5 */ +//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o d=%012llo\n\r", addr, (data & KL_PAG_A) == 0, wr, (data & KL_PAG_W) == 0, data, fault_data); return 0; } } + + /* Check if we need to modify TLB entry for TOPS 20 */ + if (t20_page && (data & KL_PAG_A) && (wr & ((data & KL_PAG_W) == 0)) && (data & KL_PAG_S)) { + /* Try and reload TLB and modify the CST */ + data = load_tlb(uf, page, upmp, wr, 0, flag); + } + + /* create location. */ *loc = ((data & 017777) << 9) + (addr & 0777); /* Ignore faults if flag set */ @@ -2380,8 +2421,8 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int return 1; /* If PUBLIC and private page, make sure we are fetching a Portal */ - if ((data & RSIGN) && !flag && pub && ((data & 0200000) == 0) && - (!fetch || (M[*loc] & 00777740000000LL) != 0254040000000LL)) { + if ((data & KL_PAG_A) && !flag && pub && ((data & KL_PAG_P) == 0) && + (!fetch || !OP_PORTAL(M[*loc]))) { /* Handle public violation */ fault_data = ((uint64)addr) | 021LL << 30 | BIT8 |((uf)?SMASK:0); //fprintf(stderr, "Public fault %012llo %06o %06o\n\r", fault_data, FLAGS << 5, PC); @@ -2389,9 +2430,26 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int return 0; } + /* Check for access error */ - if ((data & RSIGN) == 0 || (wr & ((data & 0100000) == 0))) { -//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o %06o\n\r", addr, (data & RSIGN) == 0, wr, (data & 0100000) == 0, data, PC); + if ((data & KL_PAG_A) == 0 || (wr & ((data & KL_PAG_W) == 0))) { +#if KL_ITS + if (QITS) { + /* Remap the flag bits */ + if (uf) { /* U */ + u_tlb[page] = 0; + } else { + e_tlb[page] = 0; + } + if ((data & KL_PAG_A) == 0) { + fault_data = ((uint64)addr) | 033LL << 30 |((uf)?SMASK:0); + } else { + fault_data = ((uint64)addr) | 024LL << 30 |((uf)?SMASK:0); + } + page_fault = 1; + return 0; + } +#endif fault_data = BIT8 | (uint64)addr; #if KLB if (QKLB) @@ -2404,37 +2462,26 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int } else { e_tlb[page] = 0; } - if (data & 0020000LL) /* C */ + if (data & KL_PAG_C) /* C */ fault_data |= BIT7; /* BIT7 */ - if (data & 0200000LL) /* P */ + if (data & KL_PAG_P) /* P */ fault_data |= BIT6; /* BIT6 */ -#if KL_ITS - if (QITS) { - if ((data & RSIGN) == 0) { - fault_data = ((uint64)addr) | 033LL << 30 |((uf)?SMASK:0); - page_fault = 1; - } else {// if (wr & ((data & 0100000) == 0)) { - fault_data = ((uint64)addr) | 024LL << 30 |((uf)?SMASK:0); - page_fault = 1; - } - return 0; - } -#endif if (wr) /* T */ fault_data |= BIT5; /* BIT5 */ - if (data & 0040000LL) /* S */ + if (data & KL_PAG_S) /* S */ fault_data |= BIT4; /* BIT4 */ - if (data & 0100000LL) /* W */ + if (data & KL_PAG_W) /* W */ fault_data |= BIT3; /* BIT3 */ - if (data & 0400000LL) /* A */ + if (data & KL_PAG_A) /* A */ fault_data |= BIT2; /* BIT2 */ +//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o %06o %012llo\n\r", addr, (data & KL_PAG_A) == 0, wr, (data & KL_PAG_W) == 0, data, PC, fault_data); page_fault = 1; return 0; } /* If fetching from public page, set public flag */ - if (fetch && ((data & 0200000) != 0)) + if (fetch && ((data & KL_PAG_P) != 0)) FLAGS |= PUBLIC; return 1; } @@ -2450,52 +2497,13 @@ void set_reg(int reg, uint64 value) { FM[fm_sel|(reg & 017)] = value; } -/* - * Read a location directly from memory. - * - * Return of 0 if successful, 1 if there was an error. - */ -int Mem_read_nopage() { - sim_interval--; - if (AB < 020) { - MB = FM[fm_sel|AB]; - } else { - if (AB >= (int)MEMSIZE) { - irq_flags |= 02000; - return 1; - } - MB = M[AB]; - } - return 0; -} - -/* - * Write a directly to a location in memory. - * - * Return of 0 if successful, 1 if there was an error. - */ -int Mem_write_nopage() { - sim_interval--; - if (AB < 020) { - FM[fm_sel|AB] = MB; - } else { - if (AB >= (int)MEMSIZE) { - irq_flags |= 02000; - return 1; - } - M[AB] = MB; - } - return 0; -} - int Mem_read(int flag, int cur_context, int fetch) { t_addr addr; - sim_interval--; #if KLB /* Check if invalid section */ if (QKLB && t20_page && !flag && (sect & 07740) != 0) { - fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); + fault_data = (027LL << 30) | (uint64)AB | (((uint64)sect) << 18); if (USER==0) /* U */ fault_data |= SMASK; /* BIT0 */ //fprintf(stderr, "Invalid section %012llo\n\r", fault_data); @@ -2529,6 +2537,7 @@ int Mem_read(int flag, int cur_context, int fetch) { } if (sim_brk_summ && sim_brk_test(AB, SWMASK('R'))) watch_stop = 1; + sim_interval--; MB = M[addr]; } return 0; @@ -2537,11 +2546,10 @@ int Mem_read(int flag, int cur_context, int fetch) { int Mem_write(int flag, int cur_context) { t_addr addr; - sim_interval--; #if KLB /* Check if invalid section */ if (QKLB && t20_page && !flag && (sect & 07740) != 0) { - fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); + fault_data = (027LL << 30) | (uint64)AB | (((uint64)sect) << 18); if (USER==0) /* U */ fault_data |= SMASK; /* BIT0 */ //fprintf(stderr, "Invalid section %012llo\n\r", fault_data); @@ -2575,6 +2583,7 @@ int Mem_write(int flag, int cur_context) { } if (sim_brk_summ && sim_brk_test(AB, SWMASK('W'))) watch_stop = 1; + sim_interval--; M[addr] = MB; } return 0; @@ -2693,7 +2702,7 @@ int Mem_read_byte(int n, uint16 *data, int byte) { *data |= val << need; // fprintf(stderr, " %012llo %06o \n\r", val, *data); } - return 1; + return s; } int Mem_write_byte(int n, uint16 *data) { @@ -2740,7 +2749,7 @@ int Mem_write_byte(int n, uint16 *data) { // fprintf(stderr, " %012llo %06o \n\r", val, dat); need -= s; } - return 1; + return s; } #endif @@ -2769,7 +2778,7 @@ load_tlb(int uf, int page) /* Pages 000-037 direct map */ } else { /* Return what MAP wants to see */ - return (RSIGN | 020000 | page); + return (KI_PAG_A | KI_PAG_X | page); } } /* Map the page */ @@ -2873,12 +2882,12 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int *loc = ((data & 017777) << 9) + (addr & 0777); /* Check for access error */ - if ((data & RSIGN) == 0 || (wr & ((data & 0100000) == 0))) { + if ((data & KI_PAG_A) == 0 || (wr & ((data & KI_PAG_W) == 0))) { page = (RMASK & addr) >> 9; fault_data = ((((uint64)(page))<<18) | ((uint64)(uf) << 27)) & LMASK; - fault_data |= (data & 0400000) ? 010LL : 0LL; /* A */ - fault_data |= (data & 0100000) ? 004LL : 0LL; /* W */ - fault_data |= (data & 0040000) ? 002LL : 0LL; /* S */ + fault_data |= (data & KI_PAG_A) ? 010LL : 0LL; /* A */ + fault_data |= (data & KI_PAG_W) ? 004LL : 0LL; /* W */ + fault_data |= (data & KI_PAG_S) ? 002LL : 0LL; /* S */ fault_data |= wr; page_fault = 1; return 0; @@ -2886,8 +2895,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int pub: /* If PUBLIC and private page, make sure we are fetching a Portal */ - if (!flag && pub && ((data & 0200000) == 0) && - (!fetch || (M[*loc] & 00777040000000LL) != 0254040000000LL)) { + if (!flag && pub && ((data & KI_PAG_P) == 0) && (!fetch || !OP_PORTAL(M[*loc]))) { /* Handle public violation */ fault_data = (((uint64)(page))<<18) | ((uint64)(uf) << 27) | 021LL; page_fault = 1; @@ -2895,7 +2903,7 @@ pub: } /* If fetching from public page, set public flag */ - if (fetch && ((data & 0200000) != 0)) + if (fetch && ((data & KI_PAG_P) != 0)) FLAGS |= PUBLIC; return 1; } @@ -2917,48 +2925,9 @@ void set_reg(int reg, uint64 value) { FM[reg & 017] = value; } -/* - * Read a location directly from memory. - * - * Return of 0 if successful, 1 if there was an error. - */ -int Mem_read_nopage() { - sim_interval--; - if (AB < 020) { - MB = FM[AB]; - } else { - if (AB >= (int)MEMSIZE) { - nxm_flag = 1; - return 1; - } - MB = M[AB]; - } - return 0; -} - -/* - * Write a directly to a location in memory. - * - * Return of 0 if successful, 1 if there was an error. - */ -int Mem_write_nopage() { - sim_interval--; - if (AB < 020) { - FM[AB] = MB; - } else { - if (AB >= (int)MEMSIZE) { - nxm_flag = 1; - return 1; - } - M[AB] = MB; - } - return 0; -} - int Mem_read(int flag, int cur_context, int fetch) { t_addr addr; - sim_interval--; if (AB < 020) { if (FLAGS & USER) { MB = get_reg(AB); @@ -2986,6 +2955,7 @@ read: } if (sim_brk_summ && sim_brk_test(AB, SWMASK('R'))) watch_stop = 1; + sim_interval--; MB = M[addr]; } return 0; @@ -2994,7 +2964,6 @@ read: int Mem_write(int flag, int cur_context) { t_addr addr; - sim_interval--; if (AB < 020) { if (FLAGS & USER) { set_reg(AB, MB); @@ -3025,6 +2994,7 @@ write: } if (sim_brk_summ && sim_brk_test(AB, SWMASK('W'))) watch_stop = 1; + sim_interval--; M[addr] = MB; } return 0; @@ -3210,7 +3180,6 @@ fault: int Mem_read_its(int flag, int cur_context, int fetch) { t_addr addr; - sim_interval--; if (AB < 020) { if ((xct_flag & 1) != 0 && !cur_context && (FLAGS & USER) == 0) { MB = M[(ac_stack & 01777777) + AB]; @@ -3244,6 +3213,7 @@ int Mem_read_its(int flag, int cur_context, int fetch) { } if (sim_brk_summ && sim_brk_test(AB, SWMASK('R'))) watch_stop = 1; + sim_interval--; MB = M[addr]; } return 0; @@ -3257,7 +3227,6 @@ int Mem_read_its(int flag, int cur_context, int fetch) { int Mem_write_its(int flag, int cur_context) { t_addr addr; - sim_interval--; if (AB < 020) { if ((xct_flag & 2) != 0 && !cur_context && (FLAGS & USER) == 0) { M[(ac_stack & 01777777) + AB] = MB; @@ -3291,6 +3260,7 @@ int Mem_write_its(int flag, int cur_context) { } if (sim_brk_summ && sim_brk_test(AB, SWMASK('W'))) watch_stop = 1; + sim_interval--; M[addr] = MB; } return 0; @@ -3562,7 +3532,6 @@ fault_bbn: int Mem_read_bbn(int flag, int cur_context, int fetch) { t_addr addr; - sim_interval--; /* If not doing any special access, just access register */ if (AB < 020 && ((xct_flag == 0 || fetch || cur_context || (FLAGS & USER) != 0))) { MB = get_reg(AB); @@ -3580,6 +3549,7 @@ int Mem_read_bbn(int flag, int cur_context, int fetch) { } if (sim_brk_summ && sim_brk_test(AB, SWMASK('R'))) watch_stop = 1; + sim_interval--; MB = M[addr]; return 0; } @@ -3592,7 +3562,6 @@ int Mem_read_bbn(int flag, int cur_context, int fetch) { int Mem_write_bbn(int flag, int cur_context) { t_addr addr; - sim_interval--; /* If not doing any special access, just access register */ if (AB < 020 && ((xct_flag == 0 || cur_context || (FLAGS & USER) != 0))) { set_reg(AB, MB); @@ -3610,6 +3579,7 @@ int Mem_write_bbn(int flag, int cur_context) { } if (sim_brk_summ && sim_brk_test(AB, SWMASK('W'))) watch_stop = 1; + sim_interval--; M[addr] = MB; return 0; } @@ -3656,7 +3626,6 @@ int page_lookup_waits(t_addr addr, int flag, t_addr *loc, int wr, int cur_contex int Mem_read_waits(int flag, int cur_context, int fetch) { t_addr addr; - sim_interval--; if (AB < 020 && ((xct_flag == 0 || fetch || cur_context || (FLAGS & USER) != 0))) { MB = get_reg(AB); return 0; @@ -3669,6 +3638,7 @@ int Mem_read_waits(int flag, int cur_context, int fetch) { } if (sim_brk_summ && sim_brk_test(AB, SWMASK('R'))) watch_stop = 1; + sim_interval--; MB = M[addr]; return 0; } @@ -3682,7 +3652,6 @@ int Mem_read_waits(int flag, int cur_context, int fetch) { int Mem_write_waits(int flag, int cur_context) { t_addr addr; - sim_interval--; /* If not doing any special access, just access register */ if (AB < 020 && ((xct_flag == 0 || cur_context || (FLAGS & USER) != 0))) { set_reg(AB, MB); @@ -3696,6 +3665,7 @@ int Mem_write_waits(int flag, int cur_context) { } if (sim_brk_summ && sim_brk_test(AB, SWMASK('W'))) watch_stop = 1; + sim_interval--; M[addr] = MB; return 0; } @@ -3725,7 +3695,6 @@ int page_lookup_ka(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int Mem_read_ka(int flag, int cur_context, int fetch) { t_addr addr; - sim_interval--; if (AB < 020) { MB = get_reg(AB); } else { @@ -3737,6 +3706,7 @@ int Mem_read_ka(int flag, int cur_context, int fetch) { } if (sim_brk_summ && sim_brk_test(AB, SWMASK('R'))) watch_stop = 1; + sim_interval--; MB = M[addr]; } return 0; @@ -3751,7 +3721,6 @@ int Mem_read_ka(int flag, int cur_context, int fetch) { int Mem_write_ka(int flag, int cur_context) { t_addr addr; - sim_interval--; if (AB < 020) { set_reg(AB, MB); } else { @@ -3763,13 +3732,12 @@ int Mem_write_ka(int flag, int cur_context) { } if (sim_brk_summ && sim_brk_test(AB, SWMASK('W'))) watch_stop = 1; + sim_interval--; M[addr] = MB; } return 0; } -int (*Mem_read)(int flag, int cur_context, int fetch); -int (*Mem_write)(int flag, int cur_context); #endif #if PDP6 @@ -3935,6 +3903,53 @@ int Mem_write(int flag, int cur_context) { } #endif +/* + * Read a location directly from memory. + * + * Return of 0 if successful, 1 if there was an error. + */ +int Mem_read_nopage() { + if (AB < 020) { + MB = get_reg(AB); + } else { + if (AB >= (int)MEMSIZE) { +#if KL + irq_flags |= 02000; +#else + nxm_flag = 1; +#endif + return 1; + } + sim_interval--; + MB = M[AB]; + } + return 0; +} + +/* + * Write a directly to a location in memory. + * + * Return of 0 if successful, 1 if there was an error. + */ +int Mem_write_nopage() { + if (AB < 020) { + set_reg(AB, MB); + } else { + if (AB >= (int)MEMSIZE) { +#if KL + irq_flags |= 02000; +#else + nxm_flag = 1; +#endif + return 1; + } + sim_interval--; + M[AB] = MB; + } + return 0; +} + + /* * Function to determine number of leading zero bits in a work */ @@ -4012,6 +4027,7 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ watch_stop = 0; while ( reason == 0) { /* loop until ABORT */ + AIO_CHECK_EVENT; /* queue async events */ if (sim_interval <= 0) { /* check clock queue */ if ((reason = sim_process_event()) != SCPE_OK) {/* error? stop sim */ #if ITS @@ -4041,10 +4057,8 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ trap_flag = 0; #if KL #if KLB - if (QKLB) { - sect = cur_sect = pc_sect; - glb_sect = 0; - } + sect = cur_sect = pc_sect; + glb_sect = 0; #endif extend = 0; ptr_flg = 0; @@ -4085,8 +4099,7 @@ no_fetch: AD = MB; /* Save for historical sake */ IA = AB; #if KL & KLB - if (QKLB) - glb_sect = 0; + glb_sect = 0; #endif i_flags = opflags[IR]; BYF5 = 0; @@ -4239,6 +4252,7 @@ in_loop: #endif } /* Handle events during a indirect loop */ + AIO_CHECK_EVENT; /* queue async events */ if (sim_interval-- <= 0) { if ((reason = sim_process_event()) != SCPE_OK) { return reason; @@ -4272,8 +4286,7 @@ st_pi: #if KI | KL #if KL #if KLB - if (QKLB) - sect = cur_sect = 0; + sect = cur_sect = 0; #endif extend = 0; #endif @@ -4408,9 +4421,9 @@ st_pi: /* Process the instruction */ switch (IR) { #if KL & KLB - case 0052: + case 0052: case 0053: - if (QKLB & t20_page) { + if (QKLB && t20_page) { if (Mem_read(0, 0, 0)) goto last; AB = MB & (SECTM|RMASK); @@ -4432,7 +4445,7 @@ muuo: case 0000: /* UUO */ case 0040: case 0041: case 0042: case 0043: case 0044: case 0045: case 0046: case 0047: - case 0050: case 0051: + case 0050: case 0051: case 0054: case 0055: case 0056: case 0057: case 0060: case 0061: case 0062: case 0063: case 0064: case 0065: case 0066: case 0067: @@ -5791,6 +5804,7 @@ unasign: f = 1; SC = _byte_adj[(FE - 37)].s; FE = _byte_adj[(FE - 37)].p; +fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); } #endif left = (36 - FE) / SC; /* Number bytes left (36 - P)/S */ @@ -5870,9 +5884,20 @@ unasign: #if KL & KLB if (QKLB && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; - if (_byte_adj[i].l) - AR = (AR + 1) & (SECTM|RMASK); - AR |= ((uint64)_byte_adj[i].n) << 30; +//fprintf(stderr, "ILDB %012llo %d %d -> %d %d %d\n\r", AR, SCAD, i, _byte_adj[i].p, _byte_adj[i].s,_byte_adj[i].n); + SC = _byte_adj[i].s; + SCAD = (_byte_adj[i].p + (0777 ^ SC) + 1) & 0777; + i++; + if (SCAD & 0400) { + SCAD = ((0777 ^ SC) + 044 + 1) & 0777; + AR++; + for(i = 0; i < 28; i++) { + if (_byte_adj[i].s == SC && _byte_adj[i].p == SCAD) + break; + } + } + AR &= (SECTM|RMASK); + AR |= ((uint64)(i + 37)) << 30; MB = AR; if (Mem_write(0, 0)) goto last; @@ -5882,7 +5907,7 @@ unasign: SC = (AR >> 24) & 077; SCAD = (SCAD + (0777 ^ SC) + 1) & 0777; if (SCAD & 0400) { - SC = ((0777 ^ SC) + 044 + 1) & 0777; + SCAD = ((0777 ^ SC) + 044 + 1) & 0777; #if KL #if KLB if (QKLB && pc_sect != 0 && (AR & BIT12) != 0) { /* Full pointer */ @@ -5911,10 +5936,9 @@ unasign: #else AR = (AR + 1) & FMASK; #endif - } else - SC = SCAD; + } AR &= PMASK; - AR |= (uint64)(SC & 077) << 30; + AR |= (uint64)(SCAD & 077) << 30; MB = AR; #if KL if (Mem_write(0, 0)) @@ -5938,24 +5962,20 @@ unasign: #endif goto last; AR = MB; -#if KL & KLB -ld_ptr: + SC = (AR >> 24) & 077; SCAD = (AR >> 30) & 077; +#if KL & KLB if (QKLB && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; - SC = _byte_adj[i].p; - MQ = (uint64)(1) << _byte_adj[i].s; - MQ -= 1; + SC = _byte_adj[i].s; + SCAD = _byte_adj[i].p; +ld_ptr: sect = (AR >> 18) & 07777; AB = AR & RMASK; - BYF5 = 1; - FLAGS |= BYTI; - goto ex_byte; } #endif ldb_ptr: - SC = (AR >> 30) & 077; - MQ = (uint64)(1) << ( 077 & (AR >> 24)); + MQ = (uint64)(1) << SC; MQ -= 1; f_load_pc = 0; f_inst_fetch = 0; @@ -5971,7 +5991,7 @@ ldb_ptr: #if KL ptr_flg = 1; #if KLB - if (QKLB && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { + if (QKLB && (SC < 36) && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; //fprintf(stderr, "LBP %o %o %06o %012llo\n\r", SC, SCAD, AB, MB); @@ -5985,9 +6005,6 @@ ldb_ptr: #endif } else { #if KL -#if KLB -ex_byte: -#endif ptr_flg = 0; #endif AB = AR & RMASK; @@ -5997,13 +6014,13 @@ ex_byte: goto last; AR = MB; if ((IR & 06) == 4) { - AR = AR >> SC; + AR = AR >> SCAD; AR &= MQ; set_reg(AC, AR); } else { BR = get_reg(AC); - BR = BR << SC; - MQ = MQ << SC; + BR = BR << SCAD; + MQ = MQ << SCAD; AR &= CM(MQ); AR |= BR & MQ; MB = AR & FMASK; @@ -7076,6 +7093,7 @@ left: case 0251: /* BLT */ BR = AB; do { + AIO_CHECK_EVENT; /* queue async events */ if (sim_interval <= 0) { sim_process_event(); } @@ -7278,16 +7296,13 @@ jrstf: goto xjrstf; case 015: /* XJRST */ - if (Mem_read(0, 0, 0)) - goto last; - AR = MB; /* Get PC. */ + if (Mem_read(0, 0, 0)) + goto last; + AR = MB; /* Get PC. */ #if KLB - if (QKLB) { - pc_sect = (AR >> 18) & 07777; - if ((FLAGS & USER) == 0 && ((BR >> 23) & USER) == 0) - prev_sect = BR & 037; -//fprintf(stderr, "XJRST %06o %06o %06o %012llo\r\n", pc_sect, prev_sect, FLAGS, BR); - } + if (QKLB && t20_page) { + pc_sect = (AR >> 18) & 07777; + } #endif break; @@ -7508,18 +7523,18 @@ jrstf: page_fault = 0; /* Incase error during lookup */ BR = AR; /* Remap the flag bits */ - if (BR & 0400000LL) { /* A */ + if (BR & KL_PAG_A) { /* A */ AR = ((AR & 017777LL) << 9) + (AB & 0777); if (flag1) /* U */ AR |= SMASK; /* BIT0 */ AR |= BIT2; /* BIT2 */ - if (BR & 0200000LL) /* P */ + if (BR & KL_PAG_P) /* P */ AR |= BIT6; /* BIT6 */ - if (BR & 0100000LL) /* W */ + if (BR & KL_PAG_W) /* W */ AR |= BIT3; /* BIT3 */ - if (BR & 0040000LL) /* S */ + if (BR & KL_PAG_S) /* S */ AR |= BIT4; /* BIT4 */ - if (BR & 0020000LL) /* C */ + if (BR & KL_PAG_C) /* C */ AR |= BIT7; /* BIT7 */ } else AR = (f & 01740) ? 0 : 0377777LL; @@ -7575,7 +7590,7 @@ jrstf: #if KL BYF5 = 1; #if KLB - if (QKLB) { + if (QKLB && t20_page) { if (pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { AR = (AR + 1) & FMASK; sect = (AR >> 18) & 07777; @@ -8586,9 +8601,11 @@ last: AB++; FLAGS |= trap_flag & (TRP1|TRP2); trap_flag = (TRP1|TRP2); - if (QKLB & t20_page) - MB = (((uint64)(FLAGS) << 23) & LMASK); +#if KLB + if (QKLB && t20_page) + MB = (((uint64)(FLAGS) << 23) & LMASK) | (uint64)(pc_sect & 037); else +#endif MB = (((uint64)(FLAGS) << 23) & LMASK) | (PC & RMASK); if ((FLAGS & USER) == 0) { MB &= ~SMASK; @@ -8615,7 +8632,7 @@ last: FLAGS |= PRV_PUB|OVR; PC = MB & RMASK; #if KLB - if (QKLB) + if (QKLB && t20_page) pc_sect = (MB >> 18) & 07777; #endif xct_flag = 0; @@ -8776,10 +8793,10 @@ do_byte_setup(int n, int wr, int *pos, int *sz) /* Advance pointer */ //fprintf(stderr, "%s %012llo %012llo %2o %2o %03o\n\r", (wr)?"store":"load", val1, val2, s, p, np); #if KLB - if (QKLB) { + if (QKLB & t20_page) { if (p > 36) { /* Extended pointer */ int i = p - 37; - s = _byte_adj[i].s; + *sz = s = _byte_adj[i].s; p = _byte_adj[i].p; np = p = (p + (0777 ^ s) + 1) & 0777; val2 = val1 & (SECTM|RMASK); /* Convert to long pointer */ @@ -8866,7 +8883,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) temp = get_reg(ix); #if KLB /* Check if extended indexing */ - if (QKLB && glb_sect != 0 && (temp & SMASK) == 0 && (temp & SECTM) != 0) { + if (QKLB && t20_page && glb_sect != 0 && (temp & SMASK) == 0 && (temp & SECTM) != 0) { //fprintf(stderr, "Index %06o %012llo %06o\n\r", AB, temp, sect); temp = (temp + MB) & (SECTM|RMASK); sect = (temp >> 18) & 07777; @@ -10051,6 +10068,19 @@ tim_srv(UNIT * uptr) } #endif +/* + * This sequence of instructions is a mix that hopefully + * represents a resonable instruction set that is a close + * estimate to the normal calibrated result. + */ + +static const char *pdp10_clock_precalibrate_commands[] = { + "-m 100 ADDM 0,110", + "-m 101 ADDI 0,1", + "-m 102 JRST 100", + "PC 100", + NULL}; + /* Reset routine */ t_stat cpu_reset (DEVICE *dptr) @@ -10090,6 +10120,7 @@ exec_map = 0; for(i=0; i < 128; dev_irq[i++] = 0); sim_brk_types = SWMASK('E') | SWMASK('W') | SWMASK('R'); sim_brk_dflt = SWMASK ('E'); +sim_clock_precalibrate_commands = pdp10_clock_precalibrate_commands; sim_rtcn_init_unit (&cpu_unit[0], cpu_unit[0].wait, TMR_RTC); sim_activate(&cpu_unit[0], 10000); #if ITS diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 8608b1b..c00c7f6 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -224,6 +224,7 @@ extern DEBTAB crd_debug[]; #define LRZ(x) (((x) >> 18) & RMASK) #define JRST1 (((uint64)OP_JRST << 27) + 1) +#define OP_PORTAL(x) (((x) & 00777740000000LL) == 0254040000000LL) #if PDP6 #define NODIV 000000 @@ -340,6 +341,24 @@ extern DEBTAB crd_debug[]; #define BBN_MERGE 0161740000000LL #endif +#if KL +/* KL10 TLB paging bits */ +#define KL_PAG_A 0400000 /* Access */ +#define KL_PAG_P 0200000 /* Public */ +#define KL_PAG_W 0100000 /* Writable (M Tops 20) */ +#define KL_PAG_S 0040000 /* Software (W Writable Tops 20) */ +#define KL_PAG_C 0020000 /* Cacheable */ +#endif + +#if KI +/* KI10 TLB paging bits */ +#define KI_PAG_A 0400000 /* Access */ +#define KI_PAG_P 0200000 /* Public */ +#define KI_PAG_W 0100000 /* Writable */ +#define KI_PAG_S 0040000 /* Software */ +#define KI_PAG_X 0020000 /* Reserved */ +#endif + /* Flags for CPU unit */ #define UNIT_V_MSIZE (UNIT_V_UF + 0) #define UNIT_MSIZE (0177 << UNIT_V_MSIZE) From 09aae6d5c15b93e8586bd78f12847eb4c4f7424d Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 3 Nov 2019 13:24:34 -0500 Subject: [PATCH 45/98] KA10: Fixed compile warnings on Windows. --- PDP10/ka10_iii.c | 2 +- PDP10/kl10_fe.c | 23 ++--------------------- PDP10/kx10_cpu.c | 25 ++++++++++--------------- PDP10/kx10_rp.c | 17 +++++++---------- PDP10/kx10_rs.c | 5 ++++- PDP10/kx10_sys.c | 1 - 6 files changed, 24 insertions(+), 49 deletions(-) diff --git a/PDP10/ka10_iii.c b/PDP10/ka10_iii.c index 6671e04..b57c56d 100644 --- a/PDP10/ka10_iii.c +++ b/PDP10/ka10_iii.c @@ -145,7 +145,7 @@ uint8 map[128][18] = { { V(3,6), M(0,7), V(3,10), V(0,13) }, { M(0,7), V(6,7), M(6,9), V(0,9), M(0,11), V(6,11) }, { M(0,11), V(3,8), V(6,11) }, - { }, + { 0, }, { M(2,6), V(2,7), M(2,8), V(2,13) }, { M(2,12), V(2,14), M(4,14), V(4,12) }, { M(2,7), V(2,13), M(4,13), V(4,7), M(6,9), V(0,9), M(0,11), V(6,11) }, diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index f1f5802..9e7be88 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -500,8 +500,6 @@ dte_devirq(uint32 dev, t_addr addr) { /* Handle TO11 interrupts */ t_stat dte_svc (UNIT *uptr) { - t_stat r; - /* Did the 10 knock? */ if (uptr->STATUS & DTE_11DB) { /* If in secondary mode, do that protocol */ @@ -521,7 +519,6 @@ void dte_second(UNIT *uptr) { uint64 word; int32 ch; uint32 base = 0; - t_stat r; #if KI_22BIT #if KL_ITS @@ -574,7 +571,6 @@ enter_pri: /* Start input process */ M[SEC_DTCMD + base] = 0; M[SEC_DTFLG + base] = FMASK; -// uptr->STATUS |= DTE_10DB; uptr->STATUS &= ~DTE_11DB; return; break; @@ -651,7 +647,6 @@ void dte_its(UNIT *uptr) { uint16 data; int cnt; int ln; - t_stat r; /* Check for input Start */ word = M[ITS_DTEINP]; @@ -727,7 +722,7 @@ void dte_primary(UNIT *uptr) { int s; int cnt; struct _dte_queue *in; - uint16 data1, data2, *dp; + uint16 data1, *dp; if ((uptr->STATUS & DTE_11DB) == 0) return; @@ -838,7 +833,6 @@ error: dte_in_ptr = (dte_in_ptr + 1) & 0x1f; } } -done: word &= ~PRI_CMT_TOT; if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) goto error; @@ -854,7 +848,6 @@ dte_function(UNIT *uptr) uint16 data1[32]; int32 ch; struct _dte_queue *cmd; - t_stat r; int func; /* Check if queue is empty */ @@ -1111,12 +1104,10 @@ cty: * Send to 10 when requested. */ void dte_transfer(UNIT *uptr) { - uint64 word; - int s; uint16 cnt; uint16 scnt; struct _dte_queue *out; - uint16 data1, data2, *dp; + uint16 *dp; /* Check if Queue empty */ if (dte_out_res == dte_out_ptr) @@ -1203,7 +1194,6 @@ dte_input() int ln; int save_ptr; char ch; - int flg; UNIT *uptr = &dte_unit[0]; #if KL_ITS @@ -1365,7 +1355,6 @@ dte_input() int dte_queue(int func, int dev, int dcnt, uint16 *data) { - uint64 word; uint16 *dp; struct _dte_queue *out; @@ -1444,8 +1433,6 @@ t_stat dtei_svc (UNIT *uptr) int32 ch; uint32 base = 0; UNIT *optr = &dte_unit[0]; - uint16 data1; - int f; #if KI_22BIT #if KL_ITS @@ -1524,7 +1511,6 @@ t_stat dteo_svc (UNIT *uptr) t_stat dtertc_srv(UNIT * uptr) { - int32 t; UNIT *optr = &dte_unit[0]; sim_activate_after(uptr, 1000000/rtc_tps); @@ -1725,8 +1711,6 @@ lpt_output(UNIT *uptr, char c) { t_stat lpt_svc (UNIT *uptr) { char c; - int pos; - int cpos; uint16 data1 = 0; if ((uptr->flags & UNIT_ATT) == 0) @@ -1818,8 +1802,6 @@ t_stat lpt_reset (DEVICE *dptr) t_stat lpt_attach (UNIT *uptr, CONST char *cptr) { - t_stat reason; - return attach_unit (uptr, cptr); } @@ -1938,7 +1920,6 @@ t_stat ttyo_svc (UNIT *uptr) int32 ln; int n = 0; TMLN *lp; - uint16 data1[32]; if ((tty_unit[0].flags & UNIT_ATT) == 0) /* attached? */ return SCPE_OK; diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 7ad0236..77c6d16 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -134,7 +134,7 @@ int SC; /* Shift count */ int SCAD; /* Shift count extension */ int FE; /* Exponent */ #if KA | PDP6 -int Pl, Ph, Rl, Rh, Pflag; /* Protection registers */ +t_addr Pl, Ph, Rl, Rh, Pflag; /* Protection registers */ int push_ovf; /* Push stack overflow */ int mem_prot; /* Memory protection flag */ #endif @@ -2268,9 +2268,9 @@ pg_loop: #endif /* And save it */ if (uf) - u_tlb[page] = data; + u_tlb[page] = data & (SECTM|RMASK); else - e_tlb[page] = data; + e_tlb[page] = data & (SECTM|RMASK); //fprintf(stderr, "Page %03o %08o %o\r\n", page, data, uf); } else { @@ -2893,7 +2893,6 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int return 0; } -pub: /* If PUBLIC and private page, make sure we are fetching a Portal */ if (!flag && pub && ((data & KI_PAG_P) == 0) && (!fetch || !OP_PORTAL(M[*loc]))) { /* Handle public violation */ @@ -8906,7 +8905,6 @@ do_byte_setup(int n, int wr, int *pos, int *sz) #if KLB /* Check if extended indexing */ if (QKLB && sect != 0) { -inx: if (MB & SMASK) { /* Instruction format IFIW */ if (MB & BIT1) { /* Illegal index word */ fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | @@ -9010,8 +9008,8 @@ inx: int load_byte(int n, uint64 *data, uint64 fill, int cnt) { - uint64 val1, val2, msk; - int s, p, addr, ind, np, ix; + uint64 val1, msk; + int s, p; /* Check if should return fill */ val1 = get_reg(n); @@ -9052,8 +9050,8 @@ back: int store_byte(int n, uint64 data, int cnt) { - uint64 val1, val2, msk; - int s, p, addr, ind, np, ix; + uint64 val1, msk; + int s, p; /* Fetch Pointer word */ if (do_byte_setup(n, 1, &p, &s)) @@ -9222,8 +9220,8 @@ adv_byte(int n) void bak_byte(int n, int cnt) { - uint64 val, msk; - int s, p, addr, ind, np; + uint64 val; + int s, p; /* Increment count */ if (cnt) { @@ -9675,7 +9673,7 @@ do_extend(uint32 ia) case 011: /* CVTDBT */ #if KLB if (QKLB && pc_sect != 0 && glb_sect) - xlat_sect = (val2 >> 18) & 07777; + xlat_sect = (AR >> 18) & 07777; else xlat_sect = cur_sect; #endif @@ -10016,9 +10014,6 @@ t_stat rtc_srv(UNIT * uptr) { int32 t; -#if KL - uint64 temp; -#endif t = sim_rtcn_calb (rtc_tps, TMR_RTC); sim_activate_after(uptr, 1000000/rtc_tps); tmxr_poll = t/2; diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index 63319f4..7506b87 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -736,7 +736,6 @@ t_stat rp_svc (UNIT *uptr) DEVICE *dptr; struct rh_if *rhc; int diff, da; - t_stat r; int sts; dptr = rp_devs[ctlr]; @@ -1013,15 +1012,12 @@ rp_boot(int32 unit_num, DEVICE * rptr) { UNIT *uptr = &rptr->units[unit_num]; int ctlr = GET_CNTRL_RH(uptr->flags); - DEVICE *dptr; - struct rh_if *rhc; + struct rh_if *rhc = &rp_rh[ctlr]; + DEVICE *dptr = rp_devs[ctlr]; uint32 addr; uint32 ptr = 0; - uint64 word; int wc; - - rhc = &rp_rh[ctlr]; - dptr = rp_devs[ctlr]; + uint64 word; #if KL int sect; /* KL does not support readin, so fake it by reading in sectors 4 to 7 */ @@ -1032,10 +1028,11 @@ rp_boot(int32 unit_num, DEVICE * rptr) (void)sim_fread (&rp_buf[0][0], sizeof(uint64), RP_NUMWD, uptr->fileref); ptr = 0; for(wc = RP_NUMWD; wc > 0; wc--) { - M[addr++] = rp_buf[0][ptr++]; + word = rp_buf[0][ptr++]; + M[addr++] = word; } } - PC = (MEMSIZE - 512) & RMASK; + word = (MEMSIZE - 512) & RMASK; #else (void)sim_fseek(uptr->fileref, 0, SEEK_SET); (void)sim_fread (&rp_buf[0][0], sizeof(uint64), RP_NUMWD, uptr->fileref); @@ -1053,8 +1050,8 @@ rp_boot(int32 unit_num, DEVICE * rptr) addr = rp_buf[0][ptr] & RMASK; wc = (rp_buf[0][ptr++] >> 18) & RMASK; word = rp_buf[0][ptr++]; - PC = word & RMASK; #endif + PC = word & RMASK; uptr->CMD |= DS_VV; rhc->reg = 040; rhc->drive = uptr - dptr->units; diff --git a/PDP10/kx10_rs.c b/PDP10/kx10_rs.c index 1124bb5..e8b58e8 100644 --- a/PDP10/kx10_rs.c +++ b/PDP10/kx10_rs.c @@ -432,7 +432,6 @@ t_stat rs_svc (UNIT *uptr) DEVICE *dptr; struct rh_if *rhc; int da; - t_stat r; int sts; /* Find dptr, and df10 */ @@ -670,6 +669,10 @@ t_stat rs_attach (UNIT *uptr, CONST char *cptr) if (rstr == 0) return SCPE_OK; dib = (DIB *) rstr->ctxt; + for (ctlr = 0; rh[ctlr].dev_num != 0; ctlr++) { + if (rh[ctlr].dev == rstr) + break; + } uptr->DA = 0; uptr->CMD &= ~DS_VV; uptr->CMD |= DS_DPR|DS_MOL|DS_DRY; diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index 9489c79..cc923c8 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -727,7 +727,6 @@ t_stat load_exb (FILE *fileref, int ftype) exb_pos = -1; for ( ;; ) { - int byt; /* All records start on even byte */ if (odd && get_exb_byte (fileref, &byt, ftype)) return SCPE_FMT; From 5e96ee7e751492646aec6983b7472c0d1a963363 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 3 Nov 2019 13:25:11 -0500 Subject: [PATCH 46/98] KA10: Updated Visual Studio Project for KL10. --- Visual Studio Projects/PDP10-KA.vcproj | 8 + Visual Studio Projects/PDP10-KI.vcproj | 4 + Visual Studio Projects/PDP10-KL.vcproj | 557 +++++++++++++++++++++++++ 3 files changed, 569 insertions(+) create mode 100644 Visual Studio Projects/PDP10-KL.vcproj diff --git a/Visual Studio Projects/PDP10-KA.vcproj b/Visual Studio Projects/PDP10-KA.vcproj index ef4df83..a20c066 100644 --- a/Visual Studio Projects/PDP10-KA.vcproj +++ b/Visual Studio Projects/PDP10-KA.vcproj @@ -213,6 +213,10 @@ RelativePath="..\PDP10\ka10_dpk.c" > + + @@ -301,6 +305,10 @@ RelativePath="..\PDP10\kx10_rc.c" > + + diff --git a/Visual Studio Projects/PDP10-KI.vcproj b/Visual Studio Projects/PDP10-KI.vcproj index 97ded4f..e59f8e6 100644 --- a/Visual Studio Projects/PDP10-KI.vcproj +++ b/Visual Studio Projects/PDP10-KI.vcproj @@ -253,6 +253,10 @@ RelativePath="..\PDP10\kx10_rc.c" > + + diff --git a/Visual Studio Projects/PDP10-KL.vcproj b/Visual Studio Projects/PDP10-KL.vcproj new file mode 100644 index 0000000..3e0c09f --- /dev/null +++ b/Visual Studio Projects/PDP10-KL.vcproj @@ -0,0 +1,557 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 8254121c6d2b6bd78dfb1094f1564f408151a9d4 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 3 Nov 2019 14:52:22 -0500 Subject: [PATCH 47/98] KA10: Cleanup coverity errors. --- PDP10/kx10_cpu.c | 1 + PDP10/kx10_tu.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 77c6d16..cdf58c1 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -4437,6 +4437,7 @@ st_pi: } break; } + /* Fall through */ #else case 0052: case 0053: #endif diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index ebb0e94..614c610 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -752,6 +752,8 @@ t_stat tu_srv(UNIT * uptr) /* Position just after mark */ if (GET_FNC(uptr->CMD) == FNC_SPACEB && r == MTSE_TMK) sim_tape_sprecf(uptr, &reclen); + /* Fall Through */ + case MTSE_EOM: /* end of medium */ if (tu_frame[ctlr] != 0) uptr->STATUS |= ER1_FCE; From ce56a29cedd4e7efc470a091b8934bc89969f437 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Mon, 4 Nov 2019 23:42:35 -0500 Subject: [PATCH 48/98] KA10: Fixed TU to read correctly. --- PDP10/kx10_defs.h | 9 +++++---- PDP10/kx10_rh.c | 16 ++++++++++++---- PDP10/kx10_tu.c | 11 ++--------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index c00c7f6..f76979f 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -526,9 +526,9 @@ struct rh_dev { typedef struct pdp_dib DIB; -void df10_setirq(struct df10 *df) ; -void df10_writecw(struct df10 *df) ; -void df10_finish_op(struct df10 *df, int flags) ; +void df10_setirq(struct df10 *df); +void df10_writecw(struct df10 *df); +void df10_finish_op(struct df10 *df, int flags); void df10_setup(struct df10 *df, uint32 addr); int df10_fetch(struct df10 *df); int df10_read(struct df10 *df); @@ -545,8 +545,9 @@ t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat rh_devio(uint32 dev, t_uint64 *data); t_addr rh_devirq(uint32 dev, t_addr addr); void rh_setattn(struct rh_if *rh, int unit); +void rh_error(struct rh_if *rh); int rh_blkend(struct rh_if *rh); -void rh_setirq(struct rh_if *rh) ; +void rh_setirq(struct rh_if *rh); void rh_finish_op(struct rh_if *rh, int flags); int rh_read(struct rh_if *rh); int rh_write(struct rh_if *rh); diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index da0ec3e..c2e5d84 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -500,6 +500,12 @@ void rh_setattn(struct rh_if *rhc, int unit) set_interrupt(rhc->devnum, rhc->status); } +void rh_error(struct rh_if *rhc) +{ + if (rhc->imode == 2) + rhc->status |= RH20_DR_EXC; +} + /* Decrement block count for RH20, nop for RH10 */ int rh_blkend(struct rh_if *rhc) { @@ -529,12 +535,15 @@ void rh_writecw(struct rh_if *rhc, int nxm) { uint32 chan = (rhc->devnum - 0540); int wc = ((rhc->wcr ^ RH20_WMASK) + 1) & RH20_WMASK; rhc->status |= RH20_CHAN_RDY; + rhc->status &= ~(RH20_PCR_FULL); if (wc != 0 || (rhc->status & RH20_XEND) == 0 || - (rhc->ptcr & BIT10) != 0) { + (rhc->ptcr & BIT10) != 0 || nxm) { uint64 wrd1 = SMASK|(uint64)(rhc->ccw); + if ((rhc->ptcr & BIT10) == 0 && (rhc->status & RH20_DR_EXC) != 0) + return; if (nxm) { - wrd1 |= RH20_NXM_ERR; - rhc->status |= RH20_CHAN_ERR; + wrd1 |= RH20_NXM_ERR; + rhc->status |= RH20_CHAN_ERR; } if (wc != 0) { wrd1 |= RH20_NOT_WC0; @@ -553,7 +562,6 @@ void rh_writecw(struct rh_if *rhc, int nxm) { ((uint64)(rhc->cda) & AMASK); //fprintf(stderr, "RH20 final %012llo %012llo %06o\n\r", M[eb_ptr|chan|1], M[eb_ptr|chan|2], wc); } - rhc->status &= ~(RH20_PCR_FULL); return; } #endif diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index 614c610..ac238e2 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -338,10 +338,6 @@ tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { case 007: /* look ahead */ case 011: /* tape control register */ tu_tcr[ctlr] = data & 0177777 ; - if ((tu_tcr[ctlr] & TC_DENS) == TC_1600) - uptr->STATUS |= DS_PES; - else - uptr->STATUS &= ~DS_PES; break; default: uptr->STATUS |= ER1_ILR; @@ -475,6 +471,8 @@ void tu_error(UNIT * uptr, t_stat r) } if (uptr->CMD & CS_ATA) rh_setattn(rhc, 0); + if (uptr->CMD & (CS_ATA | CS_TM)) + rh_error(rhc); uptr->CMD &= ~(CS_MOTION|CS_PIP|CS1_GO); sim_debug(DEBUG_EXP, dptr, "Setting status %d\n", r); } @@ -749,11 +747,6 @@ t_stat tu_srv(UNIT * uptr) /* Fall Through */ case MTSE_TMK: /* tape mark */ - /* Position just after mark */ - if (GET_FNC(uptr->CMD) == FNC_SPACEB && r == MTSE_TMK) - sim_tape_sprecf(uptr, &reclen); - /* Fall Through */ - case MTSE_EOM: /* end of medium */ if (tu_frame[ctlr] != 0) uptr->STATUS |= ER1_FCE; From c0fa747b5f2cc8c9a3adffa155c659e6d5804fd7 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 5 Nov 2019 23:32:12 -0500 Subject: [PATCH 49/98] KA10: Fixed RH20 so that Tops 20 can work. --- PDP10/kx10_rh.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index c2e5d84..414acf4 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -549,11 +549,15 @@ void rh_writecw(struct rh_if *rhc, int nxm) { wrd1 |= RH20_NOT_WC0; if (rhc->status & RH20_XEND) { wrd1 |= RH20_LONG_STS; - rhc->status |= RH20_LONG_WC|RH20_CHAN_ERR; + rhc->status |= RH20_CHAN_ERR; + if ((rhc->ptcr & 010) == 0) /* Write command */ + rhc->status |= RH20_LONG_WC; } } else if ((rhc->status & RH20_XEND) == 0) { wrd1 |= RH20_SHRT_STS; - rhc->status |= RH20_SHRT_WC|RH20_CHAN_ERR; + rhc->status |= RH20_CHAN_ERR; + if ((rhc->ptcr & 010) == 0) /* Write command */ + rhc->status |= RH20_SHRT_WC; } wrd1 |= RH20_NADR_PAR; M[eb_ptr|chan|1] = wrd1; From 9e05e6dd9b02a4c1e94591f52a6690885eab36fe Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 5 Nov 2019 23:33:45 -0500 Subject: [PATCH 50/98] KA10: Fixed some diagnostics errors. --- PDP10/kx10_cpu.c | 196 +++++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 91 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index cdf58c1..172040e 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2395,7 +2395,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int #endif fault_data |= BIT8; #if KLB - if (QKLB) + if (QKLB && t20_page) fault_data |= (((uint64)sect) << 18); #endif if (fault_data & BIT1) @@ -4529,7 +4529,7 @@ unasign: #if KL & KLB if (QKLB && t20_page) { - pc_sect = (MB >> 18) & 07777; + pc_sect = (MB >> 18) & 00037; FLAGS = 0; } else #endif @@ -4703,7 +4703,8 @@ unasign: #if KLB } #endif - set_reg(AC, AD & FMASK); + i_flags = SAC; + AR = AD & FMASK; break; #endif @@ -6004,12 +6005,13 @@ ldb_ptr: } #endif } else { + AB = AR & RMASK; #if KL ptr_flg = 0; -#endif - AB = AR & RMASK; +#else if ((IR & 06) == 6) modify = 1; +#endif if (Mem_read(0, 0, 0)) goto last; AR = MB; @@ -7282,14 +7284,23 @@ jrstf: case 007: /* XPCW */ //fprintf(stderr, "XPCW %06o %06o %06o %06o\r\n", pc_sect, AB, PC, FLAGS << 5); - MB = ((((uint64)FLAGS) << 23) | (prev_sect & 037)) & FMASK; + MB = ((((uint64)FLAGS) << 23) +#if KLB + | (prev_sect & 037) +#endif + ) & FMASK; if (uuo_cycle | pi_cycle) { FLAGS &= ~(USER|PUBLIC); /* Clear USER */ } if (Mem_write(0, 0)) goto last; AB = (AB + 1) & RMASK; - MB = (((((uint64)pc_sect) << 18) | PC) + !pi_cycle) & (SECTM|RMASK); +#if KLB + if (QKLB && t20_page) + MB = (((((uint64)pc_sect) << 18) | PC) + !pi_cycle) & (SECTM|RMASK); + else +#endif + MB = (PC + !pi_cycle) & (RMASK); if (Mem_write(0, 0)) goto last; AB = (AB + 1) & RMASK; @@ -8613,11 +8624,13 @@ last: } Mem_write_nopage(); AB++; +#if KLB if (QKLB && t20_page) { MB = (((uint64)pc_sect) << 18) | (PC & RMASK); Mem_write_nopage(); AB++; } +#endif flag1 = flag3 = 0; if (FLAGS & PUBLIC) flag3 = 1; @@ -8793,7 +8806,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) /* Advance pointer */ //fprintf(stderr, "%s %012llo %012llo %2o %2o %03o\n\r", (wr)?"store":"load", val1, val2, s, p, np); #if KLB - if (QKLB & t20_page) { + if (QKLB && t20_page) { if (p > 36) { /* Extended pointer */ int i = p - 37; *sz = s = _byte_adj[i].s; @@ -8810,6 +8823,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) MB = val2 & (SECTM|RMASK); sect = (MB >> 18) & 07777; glb_sect = 1; +//fprintf(stderr, "Load_bytex %012llo %012llo %06 %2o %2o\n\r", val1, val2, sect, s, p); } else if (pc_sect != 0 && (val1 & BIT12) != 0) { /* Full pointer */ if (np & 0400) { np = p = ((0777 ^ s) + 044 + 1) & 0777; @@ -8817,6 +8831,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) val2 = (val2 & LMASK) | ((val2 + 1) & RMASK); else val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); +//fprintf(stderr, "Load_byte0 %012llo %012llo %06 %2o %2o\n\r", val1, val2, sect, s, p); } if (val2 & SMASK) { if (val2 & BIT1) { @@ -9065,7 +9080,7 @@ store_byte(int n, uint64 data, int cnt) MB &= CM(msk); MB |= msk & ((uint64)(data) << p); //fprintf(stderr, "store_bytes %2o %2o %06o %06o %012llo\n\r", s, p, sect, AB, data); - BYF5 = 1; + BYF5 = 1; if (Mem_write(0, 0)) goto back; @@ -9113,11 +9128,11 @@ adj_byte(int n) val2 = get_reg(n+2); /* Extract index */ s = (val1 >> 24) & 077; - p = (val2 >> 30) & 077; + p = (val1 >> 30) & 077; /* Advance pointer */ np = (p + (0777 ^ s) + 1) & 0777; #if KLB - if (QKLB) { + if (QKLB && t20_page) { if (p > 36) { /* Extended pointer */ int i = p - 37; s = _byte_adj[i].s; @@ -9173,39 +9188,40 @@ adv_byte(int n) val2 = get_reg(n+2); /* Extract index */ s = (val1 >> 24) & 077; - p = (val2 >> 30) & 077; + p = (val1 >> 30) & 077; /* Advance pointer */ + np = (p + (0777 ^ s) + 1) & 0777; #if KLB - if (QKLB) { + if (QKLB && t20_page) { if (p > 36) { /* Extended pointer */ int i = p - 37; s = _byte_adj[i].s; p = _byte_adj[i].p; - p = (p + (0777 ^ s) + 1) & 0777; + np = (p + (0777 ^ s) + 1) & 0777; val2 = val1 & (SECTM|RMASK); /* Convert to long pointer */ val1 = ((uint64)s << 24) | BIT12; - if (p & 0400) { - np = p = ((0777 ^ s) + 044 + 1) & 0777; + if (np & 0400) { + np = ((0777 ^ s) + 044 + 1) & 0777; val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); - } else - np = p; + } } else if (pc_sect != 0 && (val1 & BIT12) != 0) { /* Full pointer */ - p = (p + (0777 ^ s) + 1) & 0777; - if (p & 0400) { - np = p = ((0777 ^ s) + 044 + 1) & 0777; + if (np & 0400) { + np = ((0777 ^ s) + 044 + 1) & 0777; val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); - } else - np = p; + } + } else { + if (np & 0400) { + np = ((0777 ^ s) + 044 + 1) & 0777; + val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); + } } } else #endif { - p = (p + (0777 ^ s) + 1) & 0777; - if (p & 0400) { - np = p = ((0777 ^ s) + 044 + 1) & 0777; + if (np & 0400) { + np = ((0777 ^ s) + 044 + 1) & 0777; val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); - } else - np = p; + } } np &= 077; /* Update pointer */ @@ -9691,9 +9707,8 @@ do_extend(uint32 ia) fill2 |= SMASK; set_reg(ext_ac, fill2); } -//fprintf(stderr, "CVD %04llo %012lld %012llo\n\r", val1, ARX, AR); +//fprintf(stderr, "CVD %04llo %012lld %012llo c=%012llo\n\r", val1, ARX, AR, get_reg(ext_ac)); while ((get_reg(ext_ac) & MANT) != 0) { - f = 1; if (!load_byte(ext_ac, &val1, 0, 1)) { set_reg(ext_ac+3, AR); set_reg(ext_ac+4, ARX); @@ -9706,32 +9721,32 @@ do_extend(uint32 ia) sect = xlat_sect; #endif f = do_xlate((uint32)(val2 & RMASK), val1, 017); + if (f < 0) + break; + if (f) + val1 = MB & 017; } - if (f < 0) - break; - if (f) { - if ((val1 & RSIGN) != 0 || val1 > 9) { - ARX = (ARX & CMASK) | (AR & SMASK); - set_reg(ext_ac+3, AR); - set_reg(ext_ac+4, ARX); - return 0; - } - /* Multiply by 2 */ - AR <<= 1; - ARX <<= 1; - if (ARX & SMASK) - AR |= 1; - ARX &= CMASK; - /* Compute times 4 */ - BR = (AR << 2) | ((ARX >> 33) & 03); - BRX = (ARX << 2) & CMASK; - ARX = (ARX & CMASK) + (BRX & CMASK) + val1; - f = (ARX >> 35); - AR = AR + BR + f; - ARX &= CMASK; - AR &= FMASK; + if ((val1 & RSIGN) != 0 || val1 > 9) { + ARX = (ARX & CMASK) | (AR & SMASK); + set_reg(ext_ac+3, AR); + set_reg(ext_ac+4, ARX); + return 0; + } + /* Multiply by 2 */ + AR <<= 1; + ARX <<= 1; + if (ARX & SMASK) + AR |= 1; + ARX &= CMASK; + /* Compute times 4 */ + BR = (AR << 2) | ((ARX >> 33) & 03); + BRX = (ARX << 2) & CMASK; + ARX = (ARX & CMASK) + (BRX & CMASK) + val1; + f = (ARX >> 35); + AR = AR + BR + f; + ARX &= CMASK; + AR &= FMASK; //fprintf(stderr, "CVD %04llo %012lld %012llo\n\r", val1, ARX, AR); - } } ARX &= CMASK; if ((get_reg(ext_ac) & MANT) == 0) { @@ -9750,15 +9765,16 @@ do_extend(uint32 ia) case 013: /* CVTBDT */ /* Save E1 */ if (IR == 012) - val2 = AB; - else val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); + else { + val2 = AB; #if KLB - if (QKLB && pc_sect != 0 && glb_sect) - xlat_sect = (val2 >> 18) & 07777; - else - xlat_sect = cur_sect; + if (QKLB && pc_sect != 0 && glb_sect) + xlat_sect = (AR >> 18) & 07777; + else + xlat_sect = cur_sect; #endif + } /* Get fill */ AB = (ia + 1) & RMASK; if (Mem_read(0, 1, 0)) @@ -9792,7 +9808,7 @@ do_extend(uint32 ia) return 0; /* Fill out left justify */ /* If L, fill leading zeros with fill char */ - while ((reg & SMASK) != 0 && (reg & MANT) != f) { + while ((reg & SMASK) != 0 && (reg & MANT) > f) { if (!store_byte(ext_ac + 3, fill1, 1)) return 0; reg = get_reg(ext_ac + 3); @@ -9847,53 +9863,51 @@ do_extend(uint32 ia) return 1; if (IR == 014) { val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); -#if KLB - if (QKLB && pc_sect != 0 && glb_sect) - xlat_sect = (val2 >> 18) & 07777; - else - xlat_sect = cur_sect; -#endif } else if (IR == 015) { AB = ia; +#if KLB + if (QKLB) { + if (pc_sect != 0 && glb_sect) + xlat_sect = (AR >> 18) & 07777; + else + xlat_sect = cur_sect; + } else + xlat_sect = 0; +#endif if (Mem_read(0, 1, 0)) return 0; - val2 = MB; + val2 = MB; } else { - val2 = AB; + val2 = AB; } /* Fetch filler values */ AB = (ia + 1) & RMASK; if (Mem_read(0, 1, 0)) return 0; fill1 = MB; - f = 1; while ((get_reg(ext_ac) & MANT) != 0) { if ((get_reg(ext_ac+3) & MANT) == 0) return 0; - f = 1; - if (!load_byte(ext_ac, &val1, fill1, 1)) { + if (!load_byte(ext_ac, &val1, fill1, 1)) return 0; - } if (IR == 014) { val1 = (val1 + val2) & FMASK; + /* Check if in range */ + if ((val1 & ~msk) != 0) + return 0; } else if (IR == 015) { #if KLB sect = xlat_sect; #endif f = do_xlate((uint32)(val2), val1, 07777); + if (f < 0) + return 0; + if (f) + val1 = MB & 07777; } - if (f < 0) - return 0; - if (f) { - /* Check if in range */ - if (IR == 014 && (val1 & ~msk) != 0) - return 0; - if (!store_byte(ext_ac+3, val1, 1)) { - bak_byte(ext_ac, 1); - return 0; - } - } else { - adv_byte(ext_ac+3); + if (!store_byte(ext_ac+3, val1, 1)) { + bak_byte(ext_ac, 1); + return 0; } } while ((get_reg(ext_ac+3) & MANT) != 0) { @@ -9912,19 +9926,19 @@ do_extend(uint32 ia) return 0; fill1 = MB; /* While source is larger, skip source */ - while ((get_reg(ext_ac+3) & MANT) != 0 && - (get_reg(ext_ac) & MANT) > (get_reg(ext_ac+3) & MANT)) { + val2 = get_reg(ext_ac+3); + while (val2 != 0 && get_reg(ext_ac) > val2) adv_byte(ext_ac); - } + /* While destination is larger, fill destination */ - while ((get_reg(ext_ac+3) & MANT) != 0 && - (get_reg(ext_ac) & MANT) < (get_reg(ext_ac+3) & MANT)) { + while (val2 != 0 && get_reg(ext_ac) < val2) { if (!store_byte(ext_ac+3, fill1, 1)) { return 0; } + val2 = get_reg(ext_ac+3); } /* Copy rest of string */ - while ((get_reg(ext_ac+3) & MANT) != 0) { + while (get_reg(ext_ac+3)) { if (!load_byte(ext_ac, &val1, fill1, 1)) return 0; if (!store_byte(ext_ac+3, val1, 1)) { From 6de313eb4d50246a6966ece8527fab765c7faa86 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 5 Nov 2019 23:35:00 -0500 Subject: [PATCH 51/98] KA10: Fixed file ending to CR/LF on new files. --- PDP10/ka10_iii.c | 1246 +++++++------- PDP10/kl10_fe.c | 4236 +++++++++++++++++++++++----------------------- PDP10/kx10_rh.c | 1552 ++++++++--------- 3 files changed, 3517 insertions(+), 3517 deletions(-) diff --git a/PDP10/ka10_iii.c b/PDP10/ka10_iii.c index b57c56d..2796cee 100644 --- a/PDP10/ka10_iii.c +++ b/PDP10/ka10_iii.c @@ -1,623 +1,623 @@ -/* ka10_iii.c: Triple III display processor. - - Copyright (c) 2013-2019, Richard Cornwell - - 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 - RICHARD CORNWELL 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 Richard Cornwell shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Richard Cornwell - -*/ - -#include "kx10_defs.h" -#ifndef NUM_DEVS_III -#define NUM_DEVS_III 0 -#endif - -#if NUM_DEVS_III > 0 -#include "display/display.h" - - -#define III_DEVNUM 0430 - -#define STATUS u3 -#define MAR u4 -#define PIA u5 -#define POS u6 - -/* CONO Bits */ -#define SET_PIA 000000010 /* Set if this bit is zero */ -#define STOP 000000020 /* Stop processor after instruction */ -#define CONT 000000040 /* Start execution at address */ -#define F 000000100 /* Clear flags */ -#define SET_MSK 000360000 /* Set mask */ -#define RST_MSK 007400000 /* Reset mask */ - -/* CONI Bits */ -#define PIA_MSK 000000007 -#define INST_HLT 000000010 /* Halt instruction */ -#define WRAP_ENB 000000020 /* Wrap around mask */ -#define EDGE_ENB 000000040 /* Edge interrupt mask */ -#define LIGH_ENB 000000100 /* Light pen enable mask */ -#define CLK_STOP 000000200 /* Clock stop */ -#define CLK_BIT 000001000 /* Clock */ -#define NXM_BIT 000002000 /* Non-existent memory */ -#define IRQ_BIT 000004000 /* Interrupt pending */ -#define DATAO_LK 000010000 /* PDP10 gave DATAO when running */ -#define LIGHT_FLG 000020000 /* Light pen flag */ -#define WRAP_FLG 000040000 /* Wrap around flag */ -#define EDGE_FLG 000100000 /* Edge overflow */ -#define HLT_FLG 000200000 /* Not running */ - -#define WRAP_MSK 00001 -#define EDGE_MSK 00002 -#define LIGH_MSK 00004 -#define HLT_MSK 00010 -#define WRP_FBIT 00020 -#define EDG_FBIT 00040 -#define LIT_FBIT 00100 -#define CTL_FBIT 00200 -#define HLT_FBIT 00400 -#define NXM_FLG 01000 -#define DATA_FLG 02000 -#define RUN_FLG 04000 - -#define TSS_INST 012 /* Test */ -#define LVW_INST 006 /* Long Vector */ -#define SVW_INST 002 /* Short vector */ -#define JMP_INST 000 /* Jump or Halt */ -#define JSR_INST 004 /* JSR(1) or JMS(0), SAVE(3) */ -#define RES_INST 014 /* Restore */ -#define SEL_INST 010 /* Select instruction */ - -#define CSIZE 00000000007 /* Current char size */ -#define CBRT 00000000070 /* Current brightness */ -#define POS_Y 00000377700 -#define POS_X 01777400000 -#define CSIZE_V 0 -#define CBRT_V 3 -#define POS_X_V 6 -#define POS_Y_V 16 - -/* - * Character map. - * M(x,y) moves pointer to x,y. - * V(x,y) draws a vector between current pointer and x,y. - * All characters start at 0,6 and end at 8,6. - * In the map there are up to 18 points per character. For a character a M(0,0) indicates - * that drawing is done and a move to 8,6 should be done. - */ -#define M(x,y) (x << 4)|y|0000 -#define V(x,y) (x << 4)|y|0200 - -uint8 map[128][18] = { - { 0 }, - { M(0,9), V(3,6), V(3,14), M(3,6), V(6,9) }, - { M(6,6), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(6,9) }, - { V(2,8), V(2,13), V(3,14), V(5,14), V(6,13), V(6,12), V(5,11), V(2,11), M(5,11), - V(6,10), V(6,9), V(5,8), V(3,8), V(2,9) }, - { M(0,8), V(3,11), V(6,8) }, - { M(0,10), V(6,10), V(6,7) }, - { M(3,9), V(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(2,6), V(3,7), M(2,8), V(0,8) }, - { M(0,10), V(6,10), M(4,10), V(4,6), M(2,6), V(2,10) }, - { V(3,9), M(0,11), V(1,11), V(6,6) }, - { M(0,11), V(1,12), V(2,12), V(5,9), V(5,7), V(4,6), V(3,6), V(2,7), V(2,8), V(6,12) }, - { M(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9), V(3,10), V(2,10), - V(2,12), V(4,12) }, - { M(0,7), V(1,6), V(2,6), V(3,7), V(3,12), V(4,13), V(5,13), V(6,12) }, - { M(0,9), V(4,9), M(2,11), V(2,7), M(0,7), V(4,7) }, - { M(0,8), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9), V(3,10), V(1,10), V(0,9), V(0,8), - V(4,8), M(2,10), V(2,6) }, - { M(0,10), V(1,9), V(2,9), V(4,11), V(5,11), V(6,10), V(5,9), V(4,9), V(2,11), V(1,11), - V(0,10) }, - { M(4,8), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(4,7), V(4,10), V(2,12), - V(1,12) }, - { M(3,11), V(1,11), V(0,10), V(0,8), V(1,7), V(3,7) }, - { M(0,11), V(2,11), V(3,10), V(3,8), V(2,7), V(0,7) }, - { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7) }, - { M(0,10), V(0,8), V(1,7), V(3,7), V(4,8), V(4,10) }, - { M(0,13), V(0,8), V(2,6), V(4,6), V(6,8), V(6,13), M(0,10), V(6,10) }, - { V(6,6), V(6,14), V(0,14), M(2,10), V(6,10) }, - { V(4,10), M(0,10), V(4,6), M(3,6), V(1,6), V(0,7), V(0,9), V(1,10), V(3,10), V(4,9), - V(4,7), V(3,6) }, - { M(2,8), V(0,10), V(2,12), M(0,10), V(6,10), M(4,12), V(6,10), V(4,8) }, - { M(0,5), V(6,5) }, - { M(0,10), V(6,10), M(3,13), V(6,10), V(3,7) }, - { M(0,12), V(2,14), V(4,12), V(6,14) }, - { V(6,12), M(0,10), V(6,10), M(0,8), V(6,8) }, - { V(3,6), M(3,7), V(0,10), V(3,13) }, - { V(3,6), M(0,7), V(3,10), V(0,13) }, - { M(0,7), V(6,7), M(6,9), V(0,9), M(0,11), V(6,11) }, - { M(0,11), V(3,8), V(6,11) }, - { 0, }, - { M(2,6), V(2,7), M(2,8), V(2,13) }, - { M(2,12), V(2,14), M(4,14), V(4,12) }, - { M(2,7), V(2,13), M(4,13), V(4,7), M(6,9), V(0,9), M(0,11), V(6,11) }, - { M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14), V(4,14), V(6,12), - M(4,14), V(4,6), M(2,6), V(2,14) }, - { V(6,12), V(1,12), V(0,11), V(0,10), V(1,9), V(2,9), V(3,10), V(3,11), V(2,12), M(4,9), - V(3,8), V(3,7), V(4,6), V(5,6), V(6,7), V(6,8), V(5,9), V(4,9) }, - { M(6,6), V(1,11), V(1,13), V(2,14), V(3,14), V(4,13), V(0,9), V(0,7), V(1,6), V(3,6), - V(5,8) }, - { M(2,12), V(4,14) }, - { M(2,6), V(0,8), V(0,12), V(2,14) }, - { V(2,8), V(2,12), V(0,14) }, - { M(1,8), V(5,12), M(3,13), V(3,7), M(5,8), V(1,12), M(0,10), V(6,10) }, - { M(2,7), V(2,11), M(0,9), V(4,9) }, - { M(0,7), V(1,6), V(1,5), V(0,4) }, - { M(0,9), V(4,9) }, - { M(2,6), V(3,6), V(3,7), V(2,7), V(2,6) }, - { V(6,12) }, - { M(0,7), V(6,13), M(6,12), V(4,14), V(2,14), V(0,12), V(0,8), V(2,6), V(4,6), V(6,8), - V(6,12) }, - { M(1,12), V(3,14), V(3,6) }, - { M(0,13), V(1,14), V(4,14), V(6,12), V(6,11), V(5,10), V(2,10), V(0,8), V(0,6), V(6,6) }, - { M(0,14), V(6,14), V(6,12), V(4,10), V(5,10), V(6,9), V(6,7), V(5,6), V(0,6) }, - { M(5,6), V(5,14), V(0,9), V(6,9) }, - { M(0,7), V(1,6), V(4,6), V(6,8), V(6,9), V(5,10), V(1,10), V(0,9), V(0,14), V(6,14) }, - { M(0,9), V(1,10), V(5,10), V(6,9), V(6,7), V(5,6), V(1,6), V(0,7), V(0,10), V(4,14) }, - { V(6,12), V(6,14), V(0,14) }, - { M(1,10), V(0,9), V(0,7), V(1,6), V(5,6), V(6,7), V(6,9), V(5,10), V(6,11), V(6,13), - V(5,14), V(1,14), V(0,13), V(0,11), V(1,10), V(5,10) }, - { M(2,6), V(6,10), V(6,13), V(5,14), V(1,14), V(0,13), V(0,11), V(1,10), V(5,10), - V(6,11) }, - { M(2,6), V(3,6), V(3,7), V(2,7), V(2,6), M(2,10), V(3,10), V(3,11), V(2,11), V(2,10) }, - { M(2,7), V(3,6), V(3,5), V(2,4), M(2,10), V(3,10), V(3,11), V(2,11), V(2,10) }, - { M(3,7), V(0,10), V(3,13) }, - { M(0,8), V(6,8), M(6,10), V(0,10) }, - { M(0,7), V(3,10), V(0,13) }, - { M(0,13), V(1,14), V(2,13), V(2,12), V(1,11), V(1,8), M(1,7), V(1,6) }, - { M(1,6), V(0,7), V(0,11), V(1,12), V(5,12), V(6,11), V(6,8), V(5,7), V(4,8), V(4,11), - M(4,10), V(3,11), V(2,11), V(1,10), V(1,9), V(2,8), V(3,8), V(4,9) }, - { V(0,12), V(2,14), V(4,14), V(6,12), V(6,9), V(0,9), V(6,9), V(6,6) }, - { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(5,10), V(6,9), V(6,7), V(5,6), - V(0,6) }, - { M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(5,6), V(6,7) }, - { V(0,14), V(4,14), V(6,12), V(6,8), V(4,6), V(0,6) }, - { M(6,6), V(0,6), V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) }, - { V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) }, - { M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(4,6), V(6,8), V(6,10), V(4,10) }, - { V(0,14), V(0,10), V(6,10), V(6,14), V(6,6) }, - { M(1,6), V(5,6), V(3,6), V(3,14), V(1,14), V(5,14) }, - { M(1,9), V(1,7), V(2,6), V(3,6), V(4,7), V(4,14), V(2,14), V(6,14) }, - { V(0,14), V(0,8), V(6,14), V(2,10), V(6,6) }, - { M(0,14), V(0,6), V(6,6) }, - { V(0,14), V(3,11), V(6,14), V(6,6) }, - { V(0,14), V(0,13), V(6,7), V(6,6), V(6,14) }, - { M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6), V(0,8) }, - { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10) }, - { M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6), V(0,8), M(3,9), - V(6,6) }, - { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(2,10), V(6,6) }, - { M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14), V(4,14), V(6,12) }, - { M(3,6), V(3,14), V(0,14), V(6,14) }, - { M(0,14), V(0,7), V(1,6), V(5,6), V(6,7), V(6,14) }, - { M(0,14), V(0,9), V(3,6), V(6,9), V(6,14) }, - { M(0,14), V(0,6), V(3,9), V(6,6), V(6,14) }, - { V(0,7), V(6,13), V(6,14), M(0,14), V(0,13), V(6,7), V(6,6) }, - { M(0,14), V(3,11), V(6,14), V(3,11), V(3,6) }, - { M(0,14), V(6,14), V(6,13), V(0,7), V(0,6), V(6,6) }, - { M(3,5), V(0,5), V(0,15), V(3,15) }, - { M(0,12), V(6,6) }, - { M(0,5), V(3,5), V(3,15), V(0,15) }, - { M(0,11), V(3,14), V(6,11), M(3,14), V(3,6) }, - { M(3,7), V(0,10), V(3,13), M(0,10), V(6,10) }, - { M(2,14), V(4,12) }, - { M(0,9), V(1,10), V(3,10), V(4,9), V(4,6), M(4,8), V(3,9), V(1,9), V(0,8), V(0,7), - V(1,6), V(3,6), V(4,7) }, - { V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) }, - { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7) }, - { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7), M(4,6), - V(4,13) }, - { M(4,7), V(3,6), V(1,6), V(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,8), V(0,8) }, - { M(2,6), V(2,12), V(3,13), V(4,13), V(5,12), M(0,11), V(4,11) }, - { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), M(4,10), V(4,5), - V(3,4), V(1,4), V(0,5) }, - { V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,6) }, - { M(3,12), V(3,11), M(3,10), V(3,7), V(4,6), V(5,6) }, - { M(3,12), V(3,11), M(3,10), V(3,5), V(2,4), V(1,3) }, - { V(0,13), M(0,8), V(2,10), M(0,8), V(2,6) }, - { M(2,6), V(2,13) }, - { V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6), M(3,9), V(4,10), V(5,10), V(6,9), - V(6,6) }, - { V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6) }, - { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) }, - { M(0,4), V(0,10), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) }, - { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), M(4,10), V(4,4) }, - { V(0,10), M(0,9), V(1,10), V(3,10), V(4,9) }, - { M(0,7), V(1,6), V(3,6), V(4,7), V(3,8), V(1,8), V(0,9), V(1,10), V(3,10), V(4,9) }, - { M(2,13), V(2,7), V(3,6), V(4,6), V(5,7), M(1,11), V(3,11) }, - { M(0,10), V(0,7), V(1,6), V(3,6), V(4,7), V(4,10), V(4,6) }, - { M(0,9), V(3,6), V(6,9) }, - { M(0,10), V(0,6), V(2,8), V(4,6), V(4,10) }, - { V(4,10), M(0,10), V(4,6) }, - { M(0,9), V(3,6), M(6,9), V(1,4), V(0,4) }, - { M(0,10), V(4,10), V(0,6), V(4,6) }, - { M(3,15), V(2,14), V(2,12), V(0,10), V(2,8), V(2,6), V(3,5) }, - { M(2,4), V(2,14) }, - { M(3,6), V(0,9), V(3,12), V(6,9), V(3,6) }, - { M(0,15), V(1,14), V(1,12), V(3,10), V(1,8), V(1,6), V(0,5) }, - { M(0,12), V(6,6) }, -}; - -uint64 iii_instr; /* Currently executing instruction */ -int iii_sel; /* Select mask */ - -t_stat iii_devio(uint32 dev, uint64 *data); -t_stat iii_svc(UNIT *uptr); -static void draw_point(int x, int y, int b); -static void draw_line(int x1, int y1, int x2, int y2, int b); -t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); -const char *iii_description (DEVICE *dptr); - -DIB iii_dib = { III_DEVNUM, 1, iii_devio, NULL}; - -UNIT iii_unit[] = { - {UDATA (&iii_svc, UNIT_IDLE, 0) }, - { 0 } - }; - - -MTAB iii_mod[] = { - { 0 } - }; - -DEVICE iii_dev = { - "III", iii_unit, NULL, iii_mod, - 2, 10, 31, 1, 8, 8, - NULL, NULL, NULL, - NULL, NULL, NULL, &iii_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS, 0, dev_debug, - NULL, NULL, &iii_help, NULL, NULL, &iii_description - }; - -int status; -t_stat iii_devio(uint32 dev, uint64 *data) { - UNIT *uptr = &iii_unit[0]; - switch(dev & 3) { - case CONI: - *data = (((uint64)iii_sel) << 18) | (uint64)(uptr->PIA); - if ((iii_instr & 037) == 0) - *data |= INST_HLT; - *data |= (uptr->STATUS & 07) << 4; - if (uptr->STATUS & NXM_FLG) - *data |= NXM_BIT; - if (uptr->STATUS & DATA_FLG) - *data |= DATAO_LK; - if ((uptr->STATUS & RUN_FLG) == 0) - *data |= HLT_FLG; - if (uptr->STATUS & WRP_FBIT) - *data |= WRAP_FLG; - if (uptr->STATUS & EDG_FBIT) - *data |= EDGE_FLG; - if (uptr->STATUS & LIT_FBIT) - *data |= LIGHT_FLG; - sim_debug(DEBUG_CONI, &iii_dev, "III %03o CONI %06o\n", dev, (uint32)*data); - break; - case CONO: - if (*data & SET_PIA) - uptr->PIA = (int)(*data&PIA_MSK); - if (*data & F) - uptr->STATUS &= ~(WRP_FBIT|EDG_FBIT|LIT_FBIT|DATA_FLG|NXM_FLG); - uptr->STATUS &= ~(017 & ((*data >> 14) ^ (*data >> 10))); - uptr->STATUS ^= (017 & (*data >> 10)); - if (*data & STOP) - uptr->STATUS |= RUN_FLG; - if (*data & CONT) { - uptr->STATUS &= ~RUN_FLG; - iii_instr = M[uptr->MAR]; - sim_activate(uptr, 10); - } - sim_debug(DEBUG_CONO, &iii_dev, "III %03o CONO %06o\n", dev, (uint32)*data); - break; - case DATAI: - sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAI %06o\n", dev, (uint32)*data); - break; - case DATAO: - if (uptr->STATUS & RUN_FLG) - uptr->STATUS |= DATA_FLG; - else { - iii_instr = *data; - sim_activate(uptr, 10); - } - sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAO %06o\n", dev, (uint32)*data); - break; - } - return SCPE_OK; -} - -t_stat -iii_svc (UNIT *uptr) -{ - uint64 temp; - int A; - int ox, oy, nx, ny, br, sz; - int i, j, ch; - switch(iii_instr & 017) { - case 000: /* JMP and HLT */ - if (iii_instr & 020) { - uptr->MAR = (iii_instr >> 18) & RMASK; - } else { - uptr->STATUS &= ~RUN_FLG; - } - break; - case 001: - case 003: - case 005: - case 007: - case 011: - case 013: - case 015: - case 017: /* Draw 4 characters */ - /* Extract X,Y,Bright and Size */ - sz = (uptr->POS & CSIZE) >> CSIZE_V; - br = (uptr->POS & CBRT) >> CBRT_V; - ox = (uptr->POS & POS_X) >> POS_X_V; - oy = (uptr->POS & POS_Y) >> POS_Y_V; - for (i = 29; i >= 1; i -= 7) { - /* Extract character and compute initial point */ - int cx, cy; - uint8 v; - ch = (iii_instr >> i) & 0177; - cx = ox; - cy = oy + (6 * sz); - /* Scan map and draw lines as needed */ - for(j = 0; j < 18; j++) { - v = map[i][j]; - if (v == 0) - break; - nx = cx + (((v >> 4) & 07) * sz); - ny = cy + ((v & 017) * sz); - if (v & 0200) - draw_line(cx, cy, nx, ny, br); - cx = nx; - cy = ny; - } - ox += 8 * sz; - } - /* Repack to new position. */ - uptr->POS = (POS_X & (nx << POS_X_V)) | - (POS_Y & (ny << POS_Y_V)) | - (uptr->POS & (CBRT|CSIZE)); - break; - - case 002: /* Short Vector */ - /* Extract X,Y,Bright and Size */ - sz = (uptr->POS & CSIZE) >> CSIZE_V; - br = (uptr->POS & CBRT) >> CBRT_V; - ox = (uptr->POS & POS_X) >> POS_X_V; - oy = (uptr->POS & POS_Y) >> POS_Y_V; - /* Do first point */ - nx = (iii_instr >> 29) & 077; - ny = (iii_instr >> 22) & 077; - /* Sign extend */ - if (nx & 0100) - nx |= 03700; - if (ny & 0100) - ny |= 03700; - /* Compute relative position. */ - nx += ox; - ny += oy; - if ((iii_instr & 010000000LL) == 0) { /* Check if visible */ - if ((iii_instr & 004000000LL) == 0) { /* Draw a line */ - draw_line(ox, oy, nx, ny, br); - } else { - draw_point(nx, ny, br); - } - } - /* Do second point */ - nx = (iii_instr >> 13) & 0177; - ny = (iii_instr >> 6) & 0177; - /* Sign extend */ - if (nx & 0100) - nx |= 03700; - if (ny & 0100) - ny |= 03700; - /* Compute relative position. */ - nx += ox; - ny += oy; - if ((iii_instr & 040) == 0) { /* Check if visible */ - if ((iii_instr & 020) == 0) { /* Draw a line */ - draw_line(ox, oy, nx, ny, br); - } else { - draw_point(nx, ny, br); - } - } - /* Repack to new position. */ - uptr->POS = (POS_X & (nx << POS_X_V)) | - (POS_Y & (ny << POS_Y_V)) | - (uptr->POS & (CBRT|CSIZE)); - break; - - case 004: /* JSR, JMS, SAVE */ - temp = (((uint64)uptr->MAR) << 18) | 020 /* | CPC */; - A = (iii_instr >> 18) & RMASK; - if ((iii_instr & 030) != 030) { - M[A] = temp; - A++; - } - if ((iii_instr & 020) != 020) { - temp = uptr->STATUS & 0377; - temp |= ((uint64)uptr->POS) << 8; - M[A] = temp; - A++; - } - if ((iii_instr & 030) != 030) { - uptr->MAR = A; - } - break; - - case 006: /* Long Vector */ - /* Extract X,Y,Bright and Size */ - sz = (uptr->POS & CSIZE) >> CSIZE_V; - br = (uptr->POS & CBRT) >> CBRT_V; - ox = (uptr->POS & POS_X) >> POS_X_V; - oy = (uptr->POS & POS_Y) >> POS_Y_V; - /* Update sizes if needed */ - if (((iii_instr >> 9) & CSIZE) != 0) - sz = (iii_instr >> 9) & CSIZE; - if (((iii_instr >> 12) & 7) != 0) - br = (iii_instr > 12) & 7; - nx = (iii_instr >> 25) & 03777; - ny = (iii_instr >> 15) & 03777; - if ((iii_instr & 0100) == 0) { /* Relative mode */ - nx += ox; - ny += oy; - } - if ((iii_instr & 040) == 0) { /* Check if visible */ - if ((iii_instr & 020) == 0) /* Draw a line */ - draw_line(ox, oy, nx, ny, br); - else - draw_point(nx, ny, br); - } - /* Repack to new position. */ - uptr->POS = (POS_X & (nx << POS_X_V)) | - (POS_Y & (ny << POS_Y_V)) | - (CBRT & (br << CBRT_V)) | - (CSIZE & (sz << CSIZE_V)); - break; - - case 010: /* Select instruction */ - break; - - case 012: /* Test instruction */ - A = (uptr->STATUS & (int32)(iii_instr >> 12) & 0377) != 0; - uptr->STATUS &= ~(0377 & ((iii_instr >> 28) ^ (iii_instr >> 20))); - uptr->STATUS ^= (0377 & (iii_instr >> 20)); - if (A ^ ((iii_instr & 020) != 0)) - uptr->MAR++; - break; - - case 014: /* Restore */ - A = (iii_instr >> 18) & RMASK; - temp = M[A]; - if ((iii_instr & 020) != 0) { - uptr->STATUS &= ~0377; - uptr->STATUS |= temp & 0377; - } - if ((iii_instr & 040) != 0) { - uptr->POS = (temp >> 8) & (POS_X|POS_Y|CBRT|CSIZE); - } - break; - - case 016: /* Nop */ - break; - } - if (uptr->STATUS & RUN_FLG) { - iii_instr = M[uptr->MAR]; - uptr->MAR++; - uptr->MAR &= RMASK; - sim_activate(uptr, 10); - } - return SCPE_OK; -} - - -/* Draw a point at x,y with intensity b. */ -/* X and Y runs from -512 to 512. */ -static void -draw_point(int x, int y, int b) -{ - display_point(x, y, b, 0); -} - -/* Draw a line between two points */ -static void -draw_line(int x1, int y1, int x2, int y2, int b) -{ - int dx, px; - int dy, py; - int i, p; - int minx, miny; - int maxx, maxy; - - dx = x1 - x2; - dy = y1 - y2; - if (x1 < 0) { - dx = -1; - px = -x1; - } else if (x1 > 0) { - dx = 1; - px = x1; - } else { - dx = 0; - px = 0; - } - - if (y1 < 0) { - dy = -1; - py = -y1; - } else if (y1 > 0) { - dy = 1; - py = y1; - } else { - dy = 0; - py = 0; - } - - if (dx == 0) { - /* Vertical line */ - for (i = 1; i < py; i++) { - dy += dy; - draw_point(dx, dy, b); - } - } else if (dy == 0) { - /* Horizontal line */ - for (i = 1; i < px; i++) { - dx += dx; - draw_point(dx, dy, b); - } - } else if (py > px) { - /* More horizontal */ - p = 2 * px - py; - for (i = 1; i < py; i++) { - if (p > 0) { - dx += dx; - p += (2 * px) - (2 * py); - } else { - p += 2 * px; - } - dy += dy; - draw_point(dx, dy, b); - } - } else { - /* More vertical */ - p = 2 * py - px; - for (i = 1; i < px; i++) { - if (p > 0) { - dy += dy; - p += (2 * py) - (2 * px); - } else { - p += 2 * py; - } - dx += dx; - draw_point(dx, dy, b); - } - } -} - -t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) -{ -return SCPE_OK; -} - -const char *iii_description (DEVICE *dptr) -{ - return "Triple III Display"; -} -#endif +/* ka10_iii.c: Triple III display processor. + + Copyright (c) 2013-2019, Richard Cornwell + + 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 + RICHARD CORNWELL 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 Richard Cornwell shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Richard Cornwell + +*/ + +#include "kx10_defs.h" +#ifndef NUM_DEVS_III +#define NUM_DEVS_III 0 +#endif + +#if NUM_DEVS_III > 0 +#include "display/display.h" + + +#define III_DEVNUM 0430 + +#define STATUS u3 +#define MAR u4 +#define PIA u5 +#define POS u6 + +/* CONO Bits */ +#define SET_PIA 000000010 /* Set if this bit is zero */ +#define STOP 000000020 /* Stop processor after instruction */ +#define CONT 000000040 /* Start execution at address */ +#define F 000000100 /* Clear flags */ +#define SET_MSK 000360000 /* Set mask */ +#define RST_MSK 007400000 /* Reset mask */ + +/* CONI Bits */ +#define PIA_MSK 000000007 +#define INST_HLT 000000010 /* Halt instruction */ +#define WRAP_ENB 000000020 /* Wrap around mask */ +#define EDGE_ENB 000000040 /* Edge interrupt mask */ +#define LIGH_ENB 000000100 /* Light pen enable mask */ +#define CLK_STOP 000000200 /* Clock stop */ +#define CLK_BIT 000001000 /* Clock */ +#define NXM_BIT 000002000 /* Non-existent memory */ +#define IRQ_BIT 000004000 /* Interrupt pending */ +#define DATAO_LK 000010000 /* PDP10 gave DATAO when running */ +#define LIGHT_FLG 000020000 /* Light pen flag */ +#define WRAP_FLG 000040000 /* Wrap around flag */ +#define EDGE_FLG 000100000 /* Edge overflow */ +#define HLT_FLG 000200000 /* Not running */ + +#define WRAP_MSK 00001 +#define EDGE_MSK 00002 +#define LIGH_MSK 00004 +#define HLT_MSK 00010 +#define WRP_FBIT 00020 +#define EDG_FBIT 00040 +#define LIT_FBIT 00100 +#define CTL_FBIT 00200 +#define HLT_FBIT 00400 +#define NXM_FLG 01000 +#define DATA_FLG 02000 +#define RUN_FLG 04000 + +#define TSS_INST 012 /* Test */ +#define LVW_INST 006 /* Long Vector */ +#define SVW_INST 002 /* Short vector */ +#define JMP_INST 000 /* Jump or Halt */ +#define JSR_INST 004 /* JSR(1) or JMS(0), SAVE(3) */ +#define RES_INST 014 /* Restore */ +#define SEL_INST 010 /* Select instruction */ + +#define CSIZE 00000000007 /* Current char size */ +#define CBRT 00000000070 /* Current brightness */ +#define POS_Y 00000377700 +#define POS_X 01777400000 +#define CSIZE_V 0 +#define CBRT_V 3 +#define POS_X_V 6 +#define POS_Y_V 16 + +/* + * Character map. + * M(x,y) moves pointer to x,y. + * V(x,y) draws a vector between current pointer and x,y. + * All characters start at 0,6 and end at 8,6. + * In the map there are up to 18 points per character. For a character a M(0,0) indicates + * that drawing is done and a move to 8,6 should be done. + */ +#define M(x,y) (x << 4)|y|0000 +#define V(x,y) (x << 4)|y|0200 + +uint8 map[128][18] = { + { 0 }, + { M(0,9), V(3,6), V(3,14), M(3,6), V(6,9) }, + { M(6,6), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(6,9) }, + { V(2,8), V(2,13), V(3,14), V(5,14), V(6,13), V(6,12), V(5,11), V(2,11), M(5,11), + V(6,10), V(6,9), V(5,8), V(3,8), V(2,9) }, + { M(0,8), V(3,11), V(6,8) }, + { M(0,10), V(6,10), V(6,7) }, + { M(3,9), V(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(2,6), V(3,7), M(2,8), V(0,8) }, + { M(0,10), V(6,10), M(4,10), V(4,6), M(2,6), V(2,10) }, + { V(3,9), M(0,11), V(1,11), V(6,6) }, + { M(0,11), V(1,12), V(2,12), V(5,9), V(5,7), V(4,6), V(3,6), V(2,7), V(2,8), V(6,12) }, + { M(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9), V(3,10), V(2,10), + V(2,12), V(4,12) }, + { M(0,7), V(1,6), V(2,6), V(3,7), V(3,12), V(4,13), V(5,13), V(6,12) }, + { M(0,9), V(4,9), M(2,11), V(2,7), M(0,7), V(4,7) }, + { M(0,8), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9), V(3,10), V(1,10), V(0,9), V(0,8), + V(4,8), M(2,10), V(2,6) }, + { M(0,10), V(1,9), V(2,9), V(4,11), V(5,11), V(6,10), V(5,9), V(4,9), V(2,11), V(1,11), + V(0,10) }, + { M(4,8), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(4,7), V(4,10), V(2,12), + V(1,12) }, + { M(3,11), V(1,11), V(0,10), V(0,8), V(1,7), V(3,7) }, + { M(0,11), V(2,11), V(3,10), V(3,8), V(2,7), V(0,7) }, + { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7) }, + { M(0,10), V(0,8), V(1,7), V(3,7), V(4,8), V(4,10) }, + { M(0,13), V(0,8), V(2,6), V(4,6), V(6,8), V(6,13), M(0,10), V(6,10) }, + { V(6,6), V(6,14), V(0,14), M(2,10), V(6,10) }, + { V(4,10), M(0,10), V(4,6), M(3,6), V(1,6), V(0,7), V(0,9), V(1,10), V(3,10), V(4,9), + V(4,7), V(3,6) }, + { M(2,8), V(0,10), V(2,12), M(0,10), V(6,10), M(4,12), V(6,10), V(4,8) }, + { M(0,5), V(6,5) }, + { M(0,10), V(6,10), M(3,13), V(6,10), V(3,7) }, + { M(0,12), V(2,14), V(4,12), V(6,14) }, + { V(6,12), M(0,10), V(6,10), M(0,8), V(6,8) }, + { V(3,6), M(3,7), V(0,10), V(3,13) }, + { V(3,6), M(0,7), V(3,10), V(0,13) }, + { M(0,7), V(6,7), M(6,9), V(0,9), M(0,11), V(6,11) }, + { M(0,11), V(3,8), V(6,11) }, + { 0, }, + { M(2,6), V(2,7), M(2,8), V(2,13) }, + { M(2,12), V(2,14), M(4,14), V(4,12) }, + { M(2,7), V(2,13), M(4,13), V(4,7), M(6,9), V(0,9), M(0,11), V(6,11) }, + { M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14), V(4,14), V(6,12), + M(4,14), V(4,6), M(2,6), V(2,14) }, + { V(6,12), V(1,12), V(0,11), V(0,10), V(1,9), V(2,9), V(3,10), V(3,11), V(2,12), M(4,9), + V(3,8), V(3,7), V(4,6), V(5,6), V(6,7), V(6,8), V(5,9), V(4,9) }, + { M(6,6), V(1,11), V(1,13), V(2,14), V(3,14), V(4,13), V(0,9), V(0,7), V(1,6), V(3,6), + V(5,8) }, + { M(2,12), V(4,14) }, + { M(2,6), V(0,8), V(0,12), V(2,14) }, + { V(2,8), V(2,12), V(0,14) }, + { M(1,8), V(5,12), M(3,13), V(3,7), M(5,8), V(1,12), M(0,10), V(6,10) }, + { M(2,7), V(2,11), M(0,9), V(4,9) }, + { M(0,7), V(1,6), V(1,5), V(0,4) }, + { M(0,9), V(4,9) }, + { M(2,6), V(3,6), V(3,7), V(2,7), V(2,6) }, + { V(6,12) }, + { M(0,7), V(6,13), M(6,12), V(4,14), V(2,14), V(0,12), V(0,8), V(2,6), V(4,6), V(6,8), + V(6,12) }, + { M(1,12), V(3,14), V(3,6) }, + { M(0,13), V(1,14), V(4,14), V(6,12), V(6,11), V(5,10), V(2,10), V(0,8), V(0,6), V(6,6) }, + { M(0,14), V(6,14), V(6,12), V(4,10), V(5,10), V(6,9), V(6,7), V(5,6), V(0,6) }, + { M(5,6), V(5,14), V(0,9), V(6,9) }, + { M(0,7), V(1,6), V(4,6), V(6,8), V(6,9), V(5,10), V(1,10), V(0,9), V(0,14), V(6,14) }, + { M(0,9), V(1,10), V(5,10), V(6,9), V(6,7), V(5,6), V(1,6), V(0,7), V(0,10), V(4,14) }, + { V(6,12), V(6,14), V(0,14) }, + { M(1,10), V(0,9), V(0,7), V(1,6), V(5,6), V(6,7), V(6,9), V(5,10), V(6,11), V(6,13), + V(5,14), V(1,14), V(0,13), V(0,11), V(1,10), V(5,10) }, + { M(2,6), V(6,10), V(6,13), V(5,14), V(1,14), V(0,13), V(0,11), V(1,10), V(5,10), + V(6,11) }, + { M(2,6), V(3,6), V(3,7), V(2,7), V(2,6), M(2,10), V(3,10), V(3,11), V(2,11), V(2,10) }, + { M(2,7), V(3,6), V(3,5), V(2,4), M(2,10), V(3,10), V(3,11), V(2,11), V(2,10) }, + { M(3,7), V(0,10), V(3,13) }, + { M(0,8), V(6,8), M(6,10), V(0,10) }, + { M(0,7), V(3,10), V(0,13) }, + { M(0,13), V(1,14), V(2,13), V(2,12), V(1,11), V(1,8), M(1,7), V(1,6) }, + { M(1,6), V(0,7), V(0,11), V(1,12), V(5,12), V(6,11), V(6,8), V(5,7), V(4,8), V(4,11), + M(4,10), V(3,11), V(2,11), V(1,10), V(1,9), V(2,8), V(3,8), V(4,9) }, + { V(0,12), V(2,14), V(4,14), V(6,12), V(6,9), V(0,9), V(6,9), V(6,6) }, + { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(5,10), V(6,9), V(6,7), V(5,6), + V(0,6) }, + { M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(5,6), V(6,7) }, + { V(0,14), V(4,14), V(6,12), V(6,8), V(4,6), V(0,6) }, + { M(6,6), V(0,6), V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) }, + { V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) }, + { M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(4,6), V(6,8), V(6,10), V(4,10) }, + { V(0,14), V(0,10), V(6,10), V(6,14), V(6,6) }, + { M(1,6), V(5,6), V(3,6), V(3,14), V(1,14), V(5,14) }, + { M(1,9), V(1,7), V(2,6), V(3,6), V(4,7), V(4,14), V(2,14), V(6,14) }, + { V(0,14), V(0,8), V(6,14), V(2,10), V(6,6) }, + { M(0,14), V(0,6), V(6,6) }, + { V(0,14), V(3,11), V(6,14), V(6,6) }, + { V(0,14), V(0,13), V(6,7), V(6,6), V(6,14) }, + { M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6), V(0,8) }, + { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10) }, + { M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6), V(0,8), M(3,9), + V(6,6) }, + { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(2,10), V(6,6) }, + { M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14), V(4,14), V(6,12) }, + { M(3,6), V(3,14), V(0,14), V(6,14) }, + { M(0,14), V(0,7), V(1,6), V(5,6), V(6,7), V(6,14) }, + { M(0,14), V(0,9), V(3,6), V(6,9), V(6,14) }, + { M(0,14), V(0,6), V(3,9), V(6,6), V(6,14) }, + { V(0,7), V(6,13), V(6,14), M(0,14), V(0,13), V(6,7), V(6,6) }, + { M(0,14), V(3,11), V(6,14), V(3,11), V(3,6) }, + { M(0,14), V(6,14), V(6,13), V(0,7), V(0,6), V(6,6) }, + { M(3,5), V(0,5), V(0,15), V(3,15) }, + { M(0,12), V(6,6) }, + { M(0,5), V(3,5), V(3,15), V(0,15) }, + { M(0,11), V(3,14), V(6,11), M(3,14), V(3,6) }, + { M(3,7), V(0,10), V(3,13), M(0,10), V(6,10) }, + { M(2,14), V(4,12) }, + { M(0,9), V(1,10), V(3,10), V(4,9), V(4,6), M(4,8), V(3,9), V(1,9), V(0,8), V(0,7), + V(1,6), V(3,6), V(4,7) }, + { V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) }, + { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7) }, + { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7), M(4,6), + V(4,13) }, + { M(4,7), V(3,6), V(1,6), V(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,8), V(0,8) }, + { M(2,6), V(2,12), V(3,13), V(4,13), V(5,12), M(0,11), V(4,11) }, + { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), M(4,10), V(4,5), + V(3,4), V(1,4), V(0,5) }, + { V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,6) }, + { M(3,12), V(3,11), M(3,10), V(3,7), V(4,6), V(5,6) }, + { M(3,12), V(3,11), M(3,10), V(3,5), V(2,4), V(1,3) }, + { V(0,13), M(0,8), V(2,10), M(0,8), V(2,6) }, + { M(2,6), V(2,13) }, + { V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6), M(3,9), V(4,10), V(5,10), V(6,9), + V(6,6) }, + { V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6) }, + { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) }, + { M(0,4), V(0,10), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6), V(0,7) }, + { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), M(4,10), V(4,4) }, + { V(0,10), M(0,9), V(1,10), V(3,10), V(4,9) }, + { M(0,7), V(1,6), V(3,6), V(4,7), V(3,8), V(1,8), V(0,9), V(1,10), V(3,10), V(4,9) }, + { M(2,13), V(2,7), V(3,6), V(4,6), V(5,7), M(1,11), V(3,11) }, + { M(0,10), V(0,7), V(1,6), V(3,6), V(4,7), V(4,10), V(4,6) }, + { M(0,9), V(3,6), V(6,9) }, + { M(0,10), V(0,6), V(2,8), V(4,6), V(4,10) }, + { V(4,10), M(0,10), V(4,6) }, + { M(0,9), V(3,6), M(6,9), V(1,4), V(0,4) }, + { M(0,10), V(4,10), V(0,6), V(4,6) }, + { M(3,15), V(2,14), V(2,12), V(0,10), V(2,8), V(2,6), V(3,5) }, + { M(2,4), V(2,14) }, + { M(3,6), V(0,9), V(3,12), V(6,9), V(3,6) }, + { M(0,15), V(1,14), V(1,12), V(3,10), V(1,8), V(1,6), V(0,5) }, + { M(0,12), V(6,6) }, +}; + +uint64 iii_instr; /* Currently executing instruction */ +int iii_sel; /* Select mask */ + +t_stat iii_devio(uint32 dev, uint64 *data); +t_stat iii_svc(UNIT *uptr); +static void draw_point(int x, int y, int b); +static void draw_line(int x1, int y1, int x2, int y2, int b); +t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *iii_description (DEVICE *dptr); + +DIB iii_dib = { III_DEVNUM, 1, iii_devio, NULL}; + +UNIT iii_unit[] = { + {UDATA (&iii_svc, UNIT_IDLE, 0) }, + { 0 } + }; + + +MTAB iii_mod[] = { + { 0 } + }; + +DEVICE iii_dev = { + "III", iii_unit, NULL, iii_mod, + 2, 10, 31, 1, 8, 8, + NULL, NULL, NULL, + NULL, NULL, NULL, &iii_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS, 0, dev_debug, + NULL, NULL, &iii_help, NULL, NULL, &iii_description + }; + +int status; +t_stat iii_devio(uint32 dev, uint64 *data) { + UNIT *uptr = &iii_unit[0]; + switch(dev & 3) { + case CONI: + *data = (((uint64)iii_sel) << 18) | (uint64)(uptr->PIA); + if ((iii_instr & 037) == 0) + *data |= INST_HLT; + *data |= (uptr->STATUS & 07) << 4; + if (uptr->STATUS & NXM_FLG) + *data |= NXM_BIT; + if (uptr->STATUS & DATA_FLG) + *data |= DATAO_LK; + if ((uptr->STATUS & RUN_FLG) == 0) + *data |= HLT_FLG; + if (uptr->STATUS & WRP_FBIT) + *data |= WRAP_FLG; + if (uptr->STATUS & EDG_FBIT) + *data |= EDGE_FLG; + if (uptr->STATUS & LIT_FBIT) + *data |= LIGHT_FLG; + sim_debug(DEBUG_CONI, &iii_dev, "III %03o CONI %06o\n", dev, (uint32)*data); + break; + case CONO: + if (*data & SET_PIA) + uptr->PIA = (int)(*data&PIA_MSK); + if (*data & F) + uptr->STATUS &= ~(WRP_FBIT|EDG_FBIT|LIT_FBIT|DATA_FLG|NXM_FLG); + uptr->STATUS &= ~(017 & ((*data >> 14) ^ (*data >> 10))); + uptr->STATUS ^= (017 & (*data >> 10)); + if (*data & STOP) + uptr->STATUS |= RUN_FLG; + if (*data & CONT) { + uptr->STATUS &= ~RUN_FLG; + iii_instr = M[uptr->MAR]; + sim_activate(uptr, 10); + } + sim_debug(DEBUG_CONO, &iii_dev, "III %03o CONO %06o\n", dev, (uint32)*data); + break; + case DATAI: + sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAI %06o\n", dev, (uint32)*data); + break; + case DATAO: + if (uptr->STATUS & RUN_FLG) + uptr->STATUS |= DATA_FLG; + else { + iii_instr = *data; + sim_activate(uptr, 10); + } + sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAO %06o\n", dev, (uint32)*data); + break; + } + return SCPE_OK; +} + +t_stat +iii_svc (UNIT *uptr) +{ + uint64 temp; + int A; + int ox, oy, nx, ny, br, sz; + int i, j, ch; + switch(iii_instr & 017) { + case 000: /* JMP and HLT */ + if (iii_instr & 020) { + uptr->MAR = (iii_instr >> 18) & RMASK; + } else { + uptr->STATUS &= ~RUN_FLG; + } + break; + case 001: + case 003: + case 005: + case 007: + case 011: + case 013: + case 015: + case 017: /* Draw 4 characters */ + /* Extract X,Y,Bright and Size */ + sz = (uptr->POS & CSIZE) >> CSIZE_V; + br = (uptr->POS & CBRT) >> CBRT_V; + ox = (uptr->POS & POS_X) >> POS_X_V; + oy = (uptr->POS & POS_Y) >> POS_Y_V; + for (i = 29; i >= 1; i -= 7) { + /* Extract character and compute initial point */ + int cx, cy; + uint8 v; + ch = (iii_instr >> i) & 0177; + cx = ox; + cy = oy + (6 * sz); + /* Scan map and draw lines as needed */ + for(j = 0; j < 18; j++) { + v = map[i][j]; + if (v == 0) + break; + nx = cx + (((v >> 4) & 07) * sz); + ny = cy + ((v & 017) * sz); + if (v & 0200) + draw_line(cx, cy, nx, ny, br); + cx = nx; + cy = ny; + } + ox += 8 * sz; + } + /* Repack to new position. */ + uptr->POS = (POS_X & (nx << POS_X_V)) | + (POS_Y & (ny << POS_Y_V)) | + (uptr->POS & (CBRT|CSIZE)); + break; + + case 002: /* Short Vector */ + /* Extract X,Y,Bright and Size */ + sz = (uptr->POS & CSIZE) >> CSIZE_V; + br = (uptr->POS & CBRT) >> CBRT_V; + ox = (uptr->POS & POS_X) >> POS_X_V; + oy = (uptr->POS & POS_Y) >> POS_Y_V; + /* Do first point */ + nx = (iii_instr >> 29) & 077; + ny = (iii_instr >> 22) & 077; + /* Sign extend */ + if (nx & 0100) + nx |= 03700; + if (ny & 0100) + ny |= 03700; + /* Compute relative position. */ + nx += ox; + ny += oy; + if ((iii_instr & 010000000LL) == 0) { /* Check if visible */ + if ((iii_instr & 004000000LL) == 0) { /* Draw a line */ + draw_line(ox, oy, nx, ny, br); + } else { + draw_point(nx, ny, br); + } + } + /* Do second point */ + nx = (iii_instr >> 13) & 0177; + ny = (iii_instr >> 6) & 0177; + /* Sign extend */ + if (nx & 0100) + nx |= 03700; + if (ny & 0100) + ny |= 03700; + /* Compute relative position. */ + nx += ox; + ny += oy; + if ((iii_instr & 040) == 0) { /* Check if visible */ + if ((iii_instr & 020) == 0) { /* Draw a line */ + draw_line(ox, oy, nx, ny, br); + } else { + draw_point(nx, ny, br); + } + } + /* Repack to new position. */ + uptr->POS = (POS_X & (nx << POS_X_V)) | + (POS_Y & (ny << POS_Y_V)) | + (uptr->POS & (CBRT|CSIZE)); + break; + + case 004: /* JSR, JMS, SAVE */ + temp = (((uint64)uptr->MAR) << 18) | 020 /* | CPC */; + A = (iii_instr >> 18) & RMASK; + if ((iii_instr & 030) != 030) { + M[A] = temp; + A++; + } + if ((iii_instr & 020) != 020) { + temp = uptr->STATUS & 0377; + temp |= ((uint64)uptr->POS) << 8; + M[A] = temp; + A++; + } + if ((iii_instr & 030) != 030) { + uptr->MAR = A; + } + break; + + case 006: /* Long Vector */ + /* Extract X,Y,Bright and Size */ + sz = (uptr->POS & CSIZE) >> CSIZE_V; + br = (uptr->POS & CBRT) >> CBRT_V; + ox = (uptr->POS & POS_X) >> POS_X_V; + oy = (uptr->POS & POS_Y) >> POS_Y_V; + /* Update sizes if needed */ + if (((iii_instr >> 9) & CSIZE) != 0) + sz = (iii_instr >> 9) & CSIZE; + if (((iii_instr >> 12) & 7) != 0) + br = (iii_instr > 12) & 7; + nx = (iii_instr >> 25) & 03777; + ny = (iii_instr >> 15) & 03777; + if ((iii_instr & 0100) == 0) { /* Relative mode */ + nx += ox; + ny += oy; + } + if ((iii_instr & 040) == 0) { /* Check if visible */ + if ((iii_instr & 020) == 0) /* Draw a line */ + draw_line(ox, oy, nx, ny, br); + else + draw_point(nx, ny, br); + } + /* Repack to new position. */ + uptr->POS = (POS_X & (nx << POS_X_V)) | + (POS_Y & (ny << POS_Y_V)) | + (CBRT & (br << CBRT_V)) | + (CSIZE & (sz << CSIZE_V)); + break; + + case 010: /* Select instruction */ + break; + + case 012: /* Test instruction */ + A = (uptr->STATUS & (int32)(iii_instr >> 12) & 0377) != 0; + uptr->STATUS &= ~(0377 & ((iii_instr >> 28) ^ (iii_instr >> 20))); + uptr->STATUS ^= (0377 & (iii_instr >> 20)); + if (A ^ ((iii_instr & 020) != 0)) + uptr->MAR++; + break; + + case 014: /* Restore */ + A = (iii_instr >> 18) & RMASK; + temp = M[A]; + if ((iii_instr & 020) != 0) { + uptr->STATUS &= ~0377; + uptr->STATUS |= temp & 0377; + } + if ((iii_instr & 040) != 0) { + uptr->POS = (temp >> 8) & (POS_X|POS_Y|CBRT|CSIZE); + } + break; + + case 016: /* Nop */ + break; + } + if (uptr->STATUS & RUN_FLG) { + iii_instr = M[uptr->MAR]; + uptr->MAR++; + uptr->MAR &= RMASK; + sim_activate(uptr, 10); + } + return SCPE_OK; +} + + +/* Draw a point at x,y with intensity b. */ +/* X and Y runs from -512 to 512. */ +static void +draw_point(int x, int y, int b) +{ + display_point(x, y, b, 0); +} + +/* Draw a line between two points */ +static void +draw_line(int x1, int y1, int x2, int y2, int b) +{ + int dx, px; + int dy, py; + int i, p; + int minx, miny; + int maxx, maxy; + + dx = x1 - x2; + dy = y1 - y2; + if (x1 < 0) { + dx = -1; + px = -x1; + } else if (x1 > 0) { + dx = 1; + px = x1; + } else { + dx = 0; + px = 0; + } + + if (y1 < 0) { + dy = -1; + py = -y1; + } else if (y1 > 0) { + dy = 1; + py = y1; + } else { + dy = 0; + py = 0; + } + + if (dx == 0) { + /* Vertical line */ + for (i = 1; i < py; i++) { + dy += dy; + draw_point(dx, dy, b); + } + } else if (dy == 0) { + /* Horizontal line */ + for (i = 1; i < px; i++) { + dx += dx; + draw_point(dx, dy, b); + } + } else if (py > px) { + /* More horizontal */ + p = 2 * px - py; + for (i = 1; i < py; i++) { + if (p > 0) { + dx += dx; + p += (2 * px) - (2 * py); + } else { + p += 2 * px; + } + dy += dy; + draw_point(dx, dy, b); + } + } else { + /* More vertical */ + p = 2 * py - px; + for (i = 1; i < px; i++) { + if (p > 0) { + dy += dy; + p += (2 * py) - (2 * px); + } else { + p += 2 * py; + } + dx += dx; + draw_point(dx, dy, b); + } + } +} + +t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +return SCPE_OK; +} + +const char *iii_description (DEVICE *dptr) +{ + return "Triple III Display"; +} +#endif diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 9e7be88..3031978 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -1,2118 +1,2118 @@ -/* kl10_fe.c: KL-10 front end (console terminal) simulator - - Copyright (c) 2013-2019, Richard Cornwell - - 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 - RICHARD CORNWELL 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 Richard Cornwell shall not be - used in advertising or otherwise to promote the sale, use or other dealings - in this Software without prior written authorization from Richard Cornwell - -*/ - -#include "kx10_defs.h" -#include "sim_sock.h" -#include "sim_tmxr.h" -#include - -#if KL -#define UNIT_DUMMY (1 << UNIT_V_UF) - -#define DTE_DEVNUM 0200 -#define DEV_V_OS (DEV_V_UF + 1) /* Type RSX10/RSX20 */ -#define DEV_M_OS (1 << DEV_V_OS) -#define TYPE_RSX10 (0 << DEV_V_OS) -#define TYPE_RSX20 (1 << DEV_V_OS) - - - -/* DTE10 CONI bits */ - -#define DTE_RM 00100000 /* Restricted mode */ -#define DTE_D11 00040000 /* Dead-11 */ -#define DTE_11DB 00020000 /* TO11 Door bell request */ -#define DTE_10DB 00001000 /* TO10 Door bell request */ -#define DTE_11ER 00000400 /* Error during TO11 transfer */ -#define DTE_11DN 00000100 /* TO 11 transfer done */ -#define DTE_10DN 00000040 /* TO 10 transfer done */ -#define DTE_10ER 00000020 /* Error during TO10 transfer */ -#define DTE_PIE 00000010 /* PIO enabled */ -#define DTE_PIA 00000007 /* PI channel assigment */ - -/* internal flags */ -#define DTE_11RELD 01000000 /* Reload 11. */ -#define DTE_TO11 02000000 /* Transfer to 11 */ -#define DTE_SEC 04000000 /* In secondary protocol */ -#define DTE_IND 010000000 /* Next transfer will be indirect */ -#define DTE_SIND 020000000 /* Send indirect data next */ - -/* DTE CONO bits */ -#define DTE_CO11DB 0020000 /* Set TO11 Door bell */ -#define DTE_CO11CR 0010000 /* Clear reload 11 button */ -#define DTE_CO11SR 0004000 /* Set reload 11 button */ -#define DTE_CO10DB 0001000 /* Clear TO10 Door bell */ -#define DTE_CO11CL 0000100 /* Clear TO11 done and error */ -#define DTE_CO10CL 0000040 /* Clear TO10 done and error */ -#define DTE_PIENB 0000020 /* Load PI and enable bit */ - -/* DTE DATAO */ -#define DTE_TO10IB 010000 /* Interrupt after transfer */ -#define DTE_TO10BC 007777 /* Byte count for transfer */ - -/* Secondary protocol addresses */ -#define SEC_DTFLG 0444 /* Operation complete flag */ -#define SEC_DTCLK 0445 /* Clock interrupt flag */ -#define SEC_DTCI 0446 /* Clock interrupt instruction */ -#define SEC_DTT11 0447 /* 10 to 11 argument */ -#define SEC_DTF11 0450 /* 10 from 11 argument */ -#define SEC_DTCMD 0451 /* To 11 command word */ -#define SEC_DTSEQ 0452 /* Operation sequence number */ -#define SEC_DTOPR 0453 /* Operational DTE # */ -#define SEC_DTCHR 0454 /* Last typed character */ -#define SEC_DTMTD 0455 /* Monitor tty output complete flag */ -#define SEC_DTMTI 0456 /* Monitor tty input flag */ -#define SEC_DTSWR 0457 /* 10 switch register */ - -#define SEC_PGMCTL 00400 -#define SEC_ENDPASS 00404 -#define SEC_LOOKUP 00406 -#define SEC_RDWRD 00407 -#define SEC_RDBYT 00414 -#define SEC_ESEC 00440 -#define SEC_EPRI 00500 -#define SEC_ERTM 00540 -#define SEC_CLKCTL 01000 -#define SEC_CLKOFF 01000 -#define SEC_CLKON 01001 -#define SEC_CLKWT 01002 -#define SEC_CLKRD 01003 -#define SEC_RDSW 01400 -#define SEC_CLRDDT 03000 -#define SEC_SETDDT 03400 -#define SEC_MONO 04000 -#define SEC_MONON 04400 -#define SEC_SETPRI 05000 -#define SEC_RTM 05400 -#define SEC_CMDMSK 07400 -#define DTE_MON 00000001 /* Save in unit1 STATUS */ -#define SEC_CLK 00000002 /* Clock enabled */ -#define ITS_ON 00000004 /* ITS Is alive */ - -/* Primary or Queued protocol addresses */ -#define PRI_CMTW_0 0 -#define PRI_CMTW_PPT 1 /* Pointer to com region */ -#define PRI_CMTW_STS 2 /* Status word */ -#define PRI_CMT_PWF SMASK /* Power failure */ -#define PRI_CMT_L11 BIT1 /* Load 11 */ -#define PRI_CMT_INI BIT2 /* Init */ -#define PRI_CMT_TST BIT3 /* Valid examine bit */ -#define PRI_CMT_QP 020000000LL /* Do Queued protocol */ -#define PRI_CMT_FWD 001000000LL /* Do full word transfers */ -#define PRI_CMT_IP RSIGN /* Indirect transfer */ -#define PRI_CMT_TOT 0200000LL /* TOIT bit */ -#define PRI_CMT_10IC 0177400LL /* TO10 IC for queued transfers */ -#define PRI_CMT_11IC 0000377LL /* TO11 IC for queued transfers */ -#define PRI_CMTW_CNT 3 /* Queue Count */ -#define PRI_CMTW_KAC 5 /* Keep alive count */ -#define PRI_IND_FLG 0100000 /* Flag function as indirect */ - -#define PRI_EM2EI 001 /* Initial message to 11 */ -#define PRI_EM2TI 002 /* Replay to initial message. */ -#define PRI_EMSTR 003 /* String data */ -#define PRI_EMLNC 004 /* Line-Char */ -#define PRI_EMRDS 005 /* Request device status */ -#define PRI_EMHDS 007 /* Here is device status */ -#define PRI_EMRDT 011 /* Request Date/Time */ -#define PRI_EMHDR 012 /* Here is date and time */ -#define PRI_EMFLO 013 /* Flush output */ -#define PRI_EMSNA 014 /* Send all (ttys) */ -#define PRI_EMDSC 015 /* Dataset connect */ -#define PRI_EMHUD 016 /* Hang up dataset */ -#define PRI_EMACK 017 /* Acknowledge line */ -#define PRI_EMXOF 020 /* XOFF line */ -#define PRI_EMXON 021 /* XON line */ -#define PRI_EMHLS 022 /* Here is line speeds */ -#define PRI_EMHLA 023 /* Here is line allocation */ -#define PRI_EMRBI 024 /* Reboot information */ -#define PRI_EMAKA 025 /* Ack ALL */ -#define PRI_EMTDO 026 /* Turn device On/Off */ -#define PRI_EMEDR 027 /* Enable/Disable line */ -#define PRI_EMLDR 030 /* Load LP RAM */ -#define PRI_EMLDV 031 /* Load LP VFU */ - -#define PRI_EMCTY 001 /* Device code for CTY */ -#define PRI_EMDL1 002 /* DL11 */ -#define PRI_EMDH1 003 /* DH11 #1 */ -#define PRI_EMDLS 004 /* DLS (all ttys combined) */ -#define PRI_EMLPT 005 /* Front end LPT */ -#define PRI_EMCDR 006 /* CDR */ -#define PRI_EMCLK 007 /* Clock */ -#define PRI_EMFED 010 /* Front end device */ -#define PRI_CTYDV 000 /* Line number for CTY */ - -#if KL_ITS -/* ITS Timesharing protocol locations */ -#define ITS_DTEVER 0400 /* Protocol version and number of devices */ -#define ITS_DTECHK 0401 /* Increment at 60Hz. Ten setom 2 times per second */ -#define ITS_DTEINP 0402 /* Input from 10 to 11. Line #, Count */ -#define ITS_DTEOUT 0403 /* Output from 10 to 11 Line #, Count */ -#define ITS_DTELSP 0404 /* Line # to set speed of */ -#define ITS_DTELPR 0405 /* Parameter */ -#define ITS_DTEOST 0406 /* Line # to start output on */ -#define ITS_DTETYI 0410 /* Received char (Line #, char) */ -#define ITS_DTEODN 0411 /* Output done (Line #, buffer size) */ -#define ITS_DTEHNG 0412 /* Hangup/dialup */ -#endif - -#define TMR_RTC 2 - -extern int32 tmxr_poll; -t_stat dte_devio(uint32 dev, uint64 *data); -t_addr dte_devirq(uint32 dev, t_addr addr); -void dte_second(UNIT *uptr); -void dte_primary(UNIT *uptr); -#if KL_ITS -void dte_its(UNIT *uptr); -#endif -void dte_transfer(UNIT *uptr); -void dte_function(UNIT *uptr); -void dte_input(); -int dte_start(UNIT *uptr); -int dte_queue(int func, int dev, int dcnt, uint16 *data); -t_stat dtei_svc (UNIT *uptr); -t_stat dte_svc (UNIT *uptr); -t_stat dteo_svc (UNIT *uptr); -t_stat dtertc_srv(UNIT * uptr); -t_stat dte_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); -t_stat dte_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc); -t_stat dte_reset (DEVICE *dptr); -t_stat dte_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); -const char *dte_description (DEVICE *dptr); -extern uint64 SW; /* Switch register */ - -char *pri_name[] = { "(0)", "EM2EI", "EM2TI", "EMSTR", "EMLNC", "EMRDS", "(6)", - "EMHDS", "(10)", "EMRDT", "EMHDR", "EMFLO", "EMSNA", "EMDSC", "EMHUD", - "EMACK", "EMXOF", "EMXON", "EMHLS", "EMHLA", "EMRBI", "EMAKA", "EMTDO", - "EMEDR", "EMLDR", "EMLDV" }; - -#if KL_ITS -#define QITS (cpu_unit[0].flags & UNIT_ITSPAGE) -#else -#define QITS 0 -#endif - -#define STATUS u3 -#define CNT u4 - -extern uint32 eb_ptr; -static int32 rtc_tps = 60; -uint16 rtc_tick; -uint16 rtc_wait = 0; - -struct _dte_queue { - int dptr; /* Pointer to working item */ - uint16 cnt; /* Number of bytes in packet */ - uint16 func; /* Function code */ - uint16 dev; /* Dev code */ - uint16 spare; /* Dev code */ - uint16 dcnt; /* Data count */ - uint16 data[256]; /* Data packet */ - uint16 sdev; /* Secondary device code */ - uint16 sz; /* Byte size */ -} dte_in[32], dte_out[32]; - -int dte_in_ptr; -int dte_in_cmd; -int dte_out_ptr; -int dte_out_res; -int dte_base; /* Base */ -int dte_off; /* Our offset */ -int dte_dt10_off; /* Offset to 10 deposit region */ -int dte_et10_off; /* Offset to 10 examine region */ -int dte_et11_off; /* Offset to 11 examine region */ -int dte_proc_num; /* Our processor number */ - -struct _buffer { - int in_ptr; /* Insert pointer */ - int out_ptr; /* Remove pointer */ - char buff[256]; /* Buffer */ -} cty_in, cty_out; -int cty_done; - -DIB dte_dib[] = { - { DTE_DEVNUM|000, 1, dte_devio, dte_devirq}, -}; - -MTAB dte_mod[] = { - { UNIT_DUMMY, 0, NULL, "STOP", &dte_stop_os }, - { TT_MODE, TT_MODE_UC, "UC", "UC", &tty_set_mode }, - { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, - { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, - { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode }, - {MTAB_XTD|MTAB_VDV, TYPE_RSX10, NULL, "RSX10", &dte_set_type, NULL, - NULL, "Sets DTE to RSX10 mode"}, - {MTAB_XTD|MTAB_VDV, TYPE_RSX20, "RSX20", "RSX20", &dte_set_type, &dte_show_type, - NULL, "Sets DTE to RSX20 mode"}, - { 0 } - }; - -UNIT dte_unit[] = { - { UDATA (&dte_svc, TT_MODE_7B, 0), 100}, - { UDATA (&dteo_svc, TT_MODE_7B, 0), 100}, - { UDATA (&dtei_svc, TT_MODE_7B|UNIT_DIS, 0), 1000 }, - { UDATA (&dtertc_srv, UNIT_IDLE|UNIT_DIS, 0), 1000 } - }; - - -DEVICE dte_dev = { - "CTY", dte_unit, NULL, dte_mod, - 4, 10, 31, 1, 8, 8, - NULL, NULL, &dte_reset, - NULL, NULL, NULL, &dte_dib, DEV_DEBUG, 0, dev_debug, - NULL, NULL, &dte_help, NULL, NULL, &dte_description - }; - - - -#ifndef NUM_DEVS_LP -#define NUM_DEVS_LP 0 -#endif - -#if (NUM_DEVS_LP > 0) - -#define COL u4 -#define POS u5 -#define LINE u6 - -#define MARGIN 6 - -#define UNIT_V_CT (UNIT_V_UF + 0) -#define UNIT_UC (1 << UNIT_V_CT) -#define UNIT_CT (3 << UNIT_V_CT) - - - -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, CONST char *cptr); -t_stat lpt_detach (UNIT *uptr); -t_stat lpt_setlpp(UNIT *, int32, CONST char *, void *); -t_stat lpt_getlpp(FILE *, UNIT *, int32, CONST void *); -t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, - const char *cptr); -const char *lpt_description (DEVICE *dptr); - -char lpt_buffer[134 * 3]; - -struct _buffer lpt_queue; - -/* LPT data structures - - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list -*/ - -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 66), 100 - }; - -REG lpt_reg[] = { - { BRDATA(BUFF, lpt_buffer, 16, 8, sizeof(lpt_buffer)), REG_HRO}, - { NULL } -}; - -MTAB lpt_mod[] = { - {UNIT_CT, 0, "Lower case", "LC", NULL}, - {UNIT_CT, UNIT_UC, "Upper case", "UC", NULL}, - {MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LINESPERPAGE", "LINESPERPAGE", - &lpt_setlpp, &lpt_getlpp, NULL, "Number of lines per page"}, - { 0 } -}; - -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, - 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, &lpt_detach, - NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug, - NULL, NULL, &lpt_help, NULL, NULL, &lpt_description -}; -#endif - -#ifndef NUM_DEVS_TTY -#define NUM_DEVS_TTY 0 -#endif - -#if (NUM_DEVS_TTY > 0) - -struct _buffer tty_out[NUM_LINES_TTY], tty_in[NUM_LINES_TTY]; -TMLN tty_ldsc[NUM_LINES_TTY] = { 0 }; /* Line descriptors */ -TMXR tty_desc = { NUM_LINES_TTY, 0, 0, tty_ldsc }; -int tty_connect[NUM_LINES_TTY]; -int tty_done[NUM_LINES_TTY]; -int tty_enable = 0; -extern int32 tmxr_poll; - -t_stat ttyi_svc (UNIT *uptr); -t_stat ttyo_svc (UNIT *uptr); -t_stat tty_reset (DEVICE *dptr); -t_stat tty_set_modem (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -t_stat tty_show_modem (FILE *st, UNIT *uptr, int32 val, CONST void *desc); -t_stat tty_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -t_stat tty_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -t_stat tty_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc); -t_stat tty_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc); -t_stat tty_attach (UNIT *uptr, CONST char *cptr); -t_stat tty_detach (UNIT *uptr); -t_stat tty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, - const char *cptr); -const char *tty_description (DEVICE *dptr); - -/* TTY data structures - - tty_dev TTY device descriptor - tty_unit TTY unit descriptor - tty_reg TTY register list -*/ - -UNIT tty_unit[] = { - { UDATA (&ttyi_svc, TT_MODE_7B+UNIT_IDLE+UNIT_DISABLE+UNIT_ATTABLE, 0), KBD_POLL_WAIT}, - { UDATA (&ttyo_svc, TT_MODE_7B+UNIT_IDLE+UNIT_DIS, 0), KBD_POLL_WAIT}, - }; - -REG tty_reg[] = { - { DRDATA (TIME, tty_unit[0].wait, 24), REG_NZ + PV_LEFT }, - { NULL } - }; - -MTAB tty_mod[] = { - { TT_MODE, TT_MODE_KSR, "KSR", "KSR", NULL }, - { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, - { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, - { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, - { MTAB_XTD|MTAB_VDV|MTAB_VALR, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &tty_desc, "Disconnect a specific line" }, - { UNIT_ATT, UNIT_ATT, "SUMMARY", NULL, - NULL, &tmxr_show_summ, (void *) &tty_desc, "Display a summary of line states" }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &tmxr_show_cstat, (void *) &tty_desc, "Display current connections" }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &tmxr_show_cstat, (void *) &tty_desc, "Display multiplexer statistics" }, - { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "LINES", "LINES=n", - &tty_setnl, &tmxr_show_lines, (void *) &tty_desc, "Set number of lines" }, - { MTAB_XTD|MTAB_VDV|MTAB_NC, 0, NULL, "LOG=n=file", - &tty_set_log, NULL, (void *)&tty_desc }, - { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, NULL, "NOLOG", - &tty_set_nolog, NULL, (void *)&tty_desc, "Disable logging on designated line" }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "LOG", NULL, - NULL, &tty_show_log, (void *)&tty_desc, "Display logging for all lines" }, - { 0 } - }; - -DEVICE tty_dev = { - "TTY", tty_unit, tty_reg, tty_mod, - 2, 10, 31, 1, 8, 8, - &tmxr_ex, &tmxr_dep, &tty_reset, - NULL, &tty_attach, &tty_detach, - NULL, DEV_NET | DEV_DISABLE | DEV_DEBUG, 0, dev_debug, - NULL, NULL, &tty_help, NULL, NULL, &tty_description - }; -#endif - - -t_stat dte_devio(uint32 dev, uint64 *data) { - uint32 res; - switch(dev & 3) { - case CONI: - *data = (uint64)(dte_unit[0].STATUS) & RMASK; - sim_debug(DEBUG_CONI, &dte_dev, "CTY %03o CONI %06o\n", dev, (uint32)*data); - break; - case CONO: - res = (uint32)(*data & RMASK); - clr_interrupt(dev); - if (res & DTE_PIENB) { - dte_unit[0].STATUS &= ~(DTE_PIA|DTE_PIE); - dte_unit[0].STATUS |= res & (DTE_PIA|DTE_PIE); - } - if (res & DTE_CO11CL) - dte_unit[0].STATUS &= ~(DTE_11DN|DTE_11ER); - if (res & DTE_CO10CL) { - dte_unit[0].STATUS &= ~(DTE_10DN|DTE_10ER); - dte_start(&dte_unit[0]); - } - if (res & DTE_CO10DB) - dte_unit[0].STATUS &= ~(DTE_10DB); - if (res & DTE_CO11CR) - dte_unit[0].STATUS &= ~(DTE_11RELD); - if (res & DTE_CO11SR) - dte_unit[0].STATUS |= (DTE_11RELD); - if (res & DTE_CO11DB) { -sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n"); - dte_unit[0].STATUS |= DTE_11DB; - sim_activate(&dte_unit[0], 200); - } - if (dte_unit[0].STATUS & (DTE_10DB|DTE_11DN|DTE_10DN|DTE_11ER|DTE_10ER)) - set_interrupt(dev, dte_unit[0].STATUS); - sim_debug(DEBUG_CONO, &dte_dev, "CTY %03o CONO %06o %06o\n", dev, (uint32)*data, PC); - break; - case DATAI: - sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAI %06o\n", dev, (uint32)*data); - break; - case DATAO: - sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAO %06o\n", dev, (uint32)*data); - if (*data == 01365) { - dte_unit[0].STATUS |= DTE_SEC|DTE_10ER; - dte_unit[0].STATUS &= ~(DTE_10DB); - break; - } - dte_unit[0].CNT = (*data & (DTE_TO10IB|DTE_TO10BC)); - dte_unit[0].STATUS |= DTE_TO11; - sim_activate(&dte_unit[0], 10); - break; - } - return SCPE_OK; -} - -/* Handle KL style interrupt vectors */ -t_addr -dte_devirq(uint32 dev, t_addr addr) { - return 0142; -} - -/* Handle TO11 interrupts */ -t_stat dte_svc (UNIT *uptr) -{ - /* Did the 10 knock? */ - if (uptr->STATUS & DTE_11DB) { - /* If in secondary mode, do that protocol */ - if (uptr->STATUS & DTE_SEC) - dte_second(uptr); - else - dte_primary(uptr); /* Retrieve data */ - } else if (uptr->STATUS & DTE_TO11) { - /* Does 10 want us to send it what we have? */ - dte_transfer(uptr); - } - return SCPE_OK; -} - -/* Handle secondary protocol */ -void dte_second(UNIT *uptr) { - uint64 word; - int32 ch; - uint32 base = 0; - -#if KI_22BIT -#if KL_ITS - if (!QITS) -#endif - base = eb_ptr; -#endif - /* read command */ - word = M[SEC_DTCMD + base]; -#if KL_ITS - if (word == 0 && QITS && (uptr->STATUS & ITS_ON) != 0) { - dte_its(uptr); - uptr->STATUS &= ~DTE_11DB; - return; - } -#endif - /* Do it */ - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY secondary %012llo\n", word); - switch(word & SEC_CMDMSK) { - default: - case SEC_MONO: /* Ouput character in monitor mode */ - ch = (int32)(word & 0177); - if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) { - sim_activate(uptr, 200); - return; - } - if (ch != 0) { - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - cty_out.buff[cty_out.in_ptr] = (char)(word & 0x7f); - cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; - sim_activate(&dte_unit[1], 200); - } - M[SEC_DTCHR + base] = ch; - M[SEC_DTMTD + base] = FMASK; - break; - case SEC_SETPRI: -enter_pri: - if (Mem_examine_word(0, 0, &word)) - break; - dte_proc_num = (word >> 24) & 037; - dte_base = dte_proc_num + 1; - dte_off = dte_base + (word & 0177777); - dte_dt10_off = 16; - dte_et10_off = dte_dt10_off + 16; - dte_et11_off = dte_base + 16; - uptr->STATUS &= ~DTE_SEC; - dte_in_ptr = dte_out_ptr = 0; - dte_in_cmd = dte_out_res = 0; - cty_done = 0; - /* Start input process */ - M[SEC_DTCMD + base] = 0; - M[SEC_DTFLG + base] = FMASK; - uptr->STATUS &= ~DTE_11DB; -return; - break; - case SEC_SETDDT: /* Read character from console */ - if (cty_in.in_ptr == cty_in.out_ptr) { - M[SEC_DTF11 + base] = 0; - M[SEC_DTMTI + base] = FMASK; - break; - } - ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; - M[SEC_DTF11 + base] = 0177 & ch; - M[SEC_DTMTI + base] = FMASK; - break; - case SEC_CLRDDT: /* Clear DDT input mode */ - uptr->STATUS &= ~DTE_MON; - break; - case SEC_MONON: - uptr->STATUS |= DTE_MON; - break; - case SEC_RDSW: /* Read switch register */ - M[SEC_DTSWR + base] = SW; - M[SEC_DTF11 + base] = SW; - break; - - case SEC_PGMCTL: /* Program control: Used by KLDCP */ - switch(word) { - case SEC_ENDPASS: - case SEC_LOOKUP: - case SEC_RDWRD: - case SEC_RDBYT: - break; - case SEC_ESEC: - goto enter_pri; - case SEC_EPRI: - case SEC_ERTM: - break; - } - break; - case SEC_CLKCTL: /* Clock control: Used by KLDCP */ - switch(word) { - case SEC_CLKOFF: - dte_unit[3].STATUS &= ~SEC_CLK; - break; - case SEC_CLKWT: - rtc_wait = (uint16)(M[SEC_DTT11 + base] & 0177777); - /* Fall Through */ - - case SEC_CLKON: - dte_unit[3].STATUS |= SEC_CLK; - rtc_tick = 0; - break; - case SEC_CLKRD: - M[SEC_DTF11+base] = rtc_tick; - break; - } - break; - } - /* Acknowledge command */ - M[SEC_DTCMD + base] = 0; - M[SEC_DTFLG + base] = FMASK; - uptr->STATUS &= ~DTE_11DB; - if (dte_dev.flags & TYPE_RSX20) { - uptr->STATUS |= DTE_10DB; - set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); - } -} - -#if KL_ITS -/* Process ITS Ioeleven locations */ -void dte_its(UNIT *uptr) { - uint64 word; - char ch; - uint16 data; - int cnt; - int ln; - - /* Check for input Start */ - word = M[ITS_DTEINP]; - if ((word & SMASK) == 0) { - M[ITS_DTEINP] = FMASK; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEINP = %012llo\n", word); - } - /* Check for output Start */ - word = M[ITS_DTEOUT]; - if ((word & SMASK) == 0) { - cnt = word & 017777; - ln = ((word >> 18) & 077) - 1; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word); - while (cnt > 0) { - if (ln < 0) { - if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) - return; - if (!Mem_read_byte(0, &data, 1)) - return; - ch = data & 0177; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %x\n", ch); - cty_out.buff[cty_out.in_ptr] = ch; - cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; - cnt--; - if (! sim_is_active(&dte_unit[1])) - sim_activate(&dte_unit[1], 50); -#if (NUM_DEVS_TTY > 0) - } else { - struct _buffer *otty = &tty_out[ln]; - if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) - return; - if (!Mem_read_byte(0, &data, 1)) - return; - ch = data & 0177; - sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln); - otty->buff[otty->in_ptr] = ch; - otty->in_ptr = (otty->in_ptr + 1) & 0xff; - cnt--; -#endif - } - } - M[ITS_DTEOUT] = FMASK; - uptr->STATUS |= DTE_11DN; - set_interrupt(DTE_DEVNUM, uptr->STATUS); - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word); - } - /* Check for line speed */ - word = M[ITS_DTELSP]; - if ((word & SMASK) == 0) { /* Ready? */ - M[ITS_DTELSP] = FMASK; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTELSP = %012llo %012llo\n", word, M[ITS_DTELPR]); - } - dte_input(); - /* Check for output Start */ - word = M[ITS_DTEOST]; - if ((word & SMASK) == 0) { - if (word == 0) - cty_done++; -#if (NUM_DEVS_TTY > 0) - else if (word > 0 && word < tty_desc.lines) { - tty_done[word-1] = 1; - } -#endif - M[ITS_DTEOST] = FMASK; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOST = %012llo\n", word); - } -} -#endif - -/* Handle primary protocol */ -void dte_primary(UNIT *uptr) { - uint64 word, iword; - int s; - int cnt; - struct _dte_queue *in; - uint16 data1, *dp; - - if ((uptr->STATUS & DTE_11DB) == 0) - return; - - /* Check if there is room for another packet */ - if (((dte_in_ptr + 1) & 0x1f) == dte_in_cmd) { - /* If not reschedule ourselves */ - sim_activate(uptr, 100); - return; - } - uptr->STATUS &= ~(DTE_11DB); - clr_interrupt(DTE_DEVNUM); - /* Check status word to see if valid */ - if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word)) { - uint32 base; -error: - base = 0; -#if KI_22BIT -#if KL_ITS - if (!QITS) -#endif - base = eb_ptr; -#endif - /* If we can't read it, go back to secondary */ - M[SEC_DTFLG + base] = FMASK; - uptr->STATUS |= DTE_SEC; - uptr->STATUS &= ~DTE_11DB; - if (dte_dev.flags & TYPE_RSX20) { - uptr->STATUS |= DTE_10DB; - set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); - } - return; - } - - if ((word & PRI_CMT_QP) == 0) { - goto error; - } - in = &dte_in[dte_in_ptr]; - /* Check if indirect */ - if ((word & PRI_CMT_IP) != 0) { - /* Transfer from 10 */ - if ((uptr->STATUS & DTE_IND) == 0) { - fprintf(stderr, "DTE out of sync\n\r"); - return; - } - /* Get size of transfer */ - if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_CNT, &iword)) - goto error; - sim_debug(DEBUG_EXP, &dte_dev, "DTE: count: %012llo\n", iword); - in->dcnt = (uint16)(iword & 0177777); - /* Read in data */ - dp = &in->data[0]; - for (cnt = in->dcnt; cnt >= 0; cnt --) { - /* Read in data */ - s = Mem_read_byte(0, dp, 0); - if (s == 0) - goto error; - in->sz = s; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o %06o\n", - *dp, *dp >> 8, *dp & 0377, ((*dp & 0377) << 8) | ((*dp >> 8) & 0377)); - dp++; - if (s <= 8) - cnt--; - } - uptr->STATUS &= ~DTE_IND; - dte_in_ptr = (dte_in_ptr + 1) & 0x1f; - } else { - /* Transfer from 10 */ - in->dptr = 0; - in->dcnt = 0; - /* Read in count */ - if (!Mem_read_byte(0, &data1, 0)) - goto error; - in->cnt = data1; - cnt = in->cnt-2; - if (!Mem_read_byte(0, &data1, 0)) - goto error; - in->func = data1; - cnt -= 2; - if (!Mem_read_byte(0, &data1, 0)) - goto error; - in->dev = data1; - cnt -= 2; - if (!Mem_read_byte(0, &data1, 0)) - goto error; - in->spare = data1; - cnt -= 2; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read CMD: %o c=%o f=%o %s d=%o\n", - dte_in_ptr, in->cnt, in->func, - ((in->func & 0377) > PRI_EMLDV)?"***":pri_name[in->func & 0377], in->dev); - dp = &in->data[0]; - for (; cnt > 0; cnt -=2) { - /* Read in data */ - if (!Mem_read_byte(0, dp, 0)) - goto error; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read data: %06o %03o %03o\n", - *dp, *dp >> 8, *dp & 0377); - dp++; - in->dcnt += 2; - } - if (in->func & PRI_IND_FLG) { - uptr->STATUS |= DTE_IND; - in->sdev = in->dcnt = in->data[0]; - word |= PRI_CMT_TOT; - if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) - goto error; - } else { - dte_in_ptr = (dte_in_ptr + 1) & 0x1f; - } - } - word &= ~PRI_CMT_TOT; - if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) - goto error; - uptr->STATUS |= DTE_11DN; - set_interrupt(DTE_DEVNUM, uptr->STATUS); - dte_function(uptr); -} - -/* Process primary protocol packets */ -void -dte_function(UNIT *uptr) -{ - uint16 data1[32]; - int32 ch; - struct _dte_queue *cmd; - int func; - - /* Check if queue is empty */ - while (dte_in_cmd != dte_in_ptr) { - if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { - sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n", - dte_out_res, dte_out_ptr); - return; - } - cmd = &dte_in[dte_in_cmd]; - func = cmd->func & 0377; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: func %o %02o %s dev %o cnt %d dcnt %d\n", - dte_in_cmd, func, (func > PRI_EMLDV) ? "***" : pri_name[func], - cmd->dev, cmd->dcnt, cmd->dptr ); - switch (func) { - case PRI_EM2EI: /* Initial message to 11 */ - data1[0] = PRI_CTYDV; - if (dte_queue(PRI_EM2TI, PRI_EMCTY, 1, data1) == 0) - return; -#if (NUM_DEVS_LP > 0) - data1[0] = 140; - if (dte_queue(PRI_EMHLA, PRI_EMLPT, 1, data1) == 0) - return; -#endif - data1[0] = 0; - if (dte_queue(PRI_EMAKA, PRI_EMCLK, 1, data1) == 0) - return; - break; - - case PRI_EM2TI: /* Replay to initial message. */ - case PRI_EMACK: /* Acknowledge line */ - /* Should never get these */ - break; - case PRI_EMHDR: /* Here is date and time */ - /* Ignore this function */ - break; - case PRI_EMRDT: /* Request Date/Time */ - { - time_t t = time(NULL); - struct tm *tm = localtime(&t); - int yr = tm->tm_year + 1900; - int tim = (((tm->tm_hour * 60) + tm->tm_min) * 60) + - tm->tm_sec; - data1[0] = 0177777; - data1[1] = ((yr & 0377) << 8) | ((yr >> 8) & 0377); - data1[2] = (tm->tm_mon) + ((tm->tm_mday - 1) << 8); - data1[3] = (((tm->tm_wday + 6) % 7)) + - (tm->tm_isdst ? 0200 << 8 : 0); - tim >>= 1; - data1[4] = ((tim & 0377) << 8) | ((tim >> 8) & 0377); - if (dte_queue(PRI_EMHDR | PRI_IND_FLG, PRI_EMCLK, 6, data1) == 0) - return; - } - break; - - case PRI_EMSTR: /* String data */ - -#if (NUM_DEVS_LP > 0) - /* Handle printer data */ - if (cmd->dev == PRI_EMLPT) { - if (!sim_is_active(&lpt_unit)) - sim_activate(&lpt_unit, 1000); - while (cmd->dptr < cmd->dcnt) { - if (((lpt_queue.in_ptr + 1) & 0xff) == lpt_queue.out_ptr) - return; - ch = (int32)(cmd->data[cmd->dptr >> 1]); - if ((cmd->dptr & 1) == 0) - ch >>= 8; - ch &= 0177; - lpt_queue.buff[lpt_queue.in_ptr] = ch; - lpt_queue.in_ptr = (lpt_queue.in_ptr + 1) & 0xff; - cmd->dptr++; - } - if (cmd->dptr != cmd->dcnt) - return; - break; - } -#endif - -#if (NUM_DEVS_TTY > 0) - /* Handle terminal data */ - if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377); - struct _buffer *otty; - if (ln == PRI_CTYDV) - goto cty; - ln -= 2; - if (ln > 0 && ln >= tty_desc.lines) - break; - otty = &tty_out[ln]; - if (cmd->sz > 8) - cmd->dcnt += cmd->dcnt; - while (cmd->dptr < cmd->dcnt) { - if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) - return; - ch = (int32)(cmd->data[cmd->dptr >> 1]); - if ((cmd->dptr & 1) == 0) - ch >>= 8; - ch &= 0177; - if (ch != 0) { - sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %o %d\n", ch, ln); - otty->buff[otty->in_ptr] = ch; - otty->in_ptr = (otty->in_ptr + 1) & 0xff; - } - cmd->dptr++; - } - if (cmd->dptr != cmd->dcnt) - return; - break; - } -#endif - /* Fall through */ - case PRI_EMSNA: /* Send all (ttys) */ - if (cmd->dev != PRI_EMCTY) - break; -cty: - sim_activate(&dte_unit[1], 100); - data1[0] = 0; - if (cmd->sz > 8) - cmd->dcnt += cmd->dcnt; - while (cmd->dptr < cmd->dcnt) { - if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) - return; - ch = (int32)(cmd->data[cmd->dptr >> 1]); - if ((cmd->dptr & 1) == 0) - ch >>= 8; - ch &= 0177; - if (ch != 0) { - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); - cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; - } - cmd->dptr++; - } - if (cmd->dptr != cmd->dcnt) - return; - break; - - case PRI_EMLNC: /* Line-Char */ - if (cmd->dev == PRI_EMDLS) { - sim_activate(&dte_unit[1], 100); - while (cmd->dptr < cmd->dcnt) { - int ln; - if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) - return; - ch = (int32)(cmd->data[cmd->dptr >> 1]); - ln = (ch >> 8); - ch &= 0177; - if (ch != 0 && ln == 0) { - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); - cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; - } - cmd->dptr+=2; - } - if (cmd->dptr != cmd->dcnt) - return; - } - break; - - case PRI_EMRDS: /* Request device status */ -#if (NUM_DEVS_LP > 0) - if (cmd->dev == PRI_EMLPT) { - data1[0] = 0; - if (dte_queue(PRI_EMHDS, PRI_EMLPT, 1, data1) == 0) - return; - } -#endif - if (cmd->dev == PRI_EMCTY) { - data1[0] = 0; - if (dte_queue(PRI_EMHDS, PRI_EMCTY, 1, data1) == 0) - return; - } - if (cmd->dev == PRI_EMDH1) { - data1[0] = 0; - if (dte_queue(PRI_EMHDS, PRI_EMDH1, 1, data1) == 0) - return; - } - break; - - case PRI_EMHDS: /* Here is device status */ - break; - -#if (NUM_DEVS_TTY > 0) - case PRI_EMFLO: /* Flush output */ - if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2;; - tty_out[ln].in_ptr = tty_out[ln].out_ptr = 0; - } - break; - case PRI_EMDSC: /* Dataset connect */ - break; - case PRI_EMHUD: /* Hang up dataset */ - if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2; - TMLN *lp = &tty_ldsc[ln]; - tmxr_linemsg (lp, "\r\nLine Hangup\r\n"); - tmxr_reset_ln(lp); - tty_connect[ln] = 0; - } - break; - case PRI_EMXOF: /* XOFF line */ - if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2; - tty_ldsc[ln].rcve = 0; - } - break; - case PRI_EMXON: /* XON line */ - if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2; - tty_ldsc[ln].rcve = 1; - } - break; - case PRI_EMHLS: /* Here is line speeds */ - if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2; - } - break; - case PRI_EMHLA: /* Here is line allocation */ - case PRI_EMRBI: /* Reboot information */ - case PRI_EMAKA: /* Ack ALL */ - case PRI_EMTDO: /* Turn device On/Off */ - break; - case PRI_EMEDR: /* Enable/Disable line */ - if (cmd->dev == PRI_EMDH1) { - /* Zero means enable, no-zero means disable */ - tty_enable = !cmd->data[0]; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY enable %x\n", tty_enable); - if (tty_enable) { - sim_activate(&tty_unit[0], 1000); - sim_activate(&tty_unit[1], 1000); - } else { - sim_cancel(&tty_unit[0]); - sim_cancel(&tty_unit[1]); - } - } - break; -#endif - case PRI_EMLDR: /* Load LP RAM */ - case PRI_EMLDV: /* Load LP VFU */ - default: - break; - } - /* Mark command as finished */ - cmd->cnt = 0; - dte_in_cmd = (dte_in_cmd + 1) & 0x1F; - } -} - -/* - * Handle primary protocol, - * Send to 10 when requested. - */ -void dte_transfer(UNIT *uptr) { - uint16 cnt; - uint16 scnt; - struct _dte_queue *out; - uint16 *dp; - - /* Check if Queue empty */ - if (dte_out_res == dte_out_ptr) - return; - - out = &dte_out[dte_out_ptr]; - uptr->STATUS &= ~DTE_TO11; - clr_interrupt(DTE_DEVNUM); - - /* Compute how much 10 wants us to send */ - scnt = ((uptr->CNT ^ DTE_TO10BC) + 1) & DTE_TO10BC; - /* Check if indirect */ - if ((uptr->STATUS & DTE_SIND) != 0) { - /* Transfer indirect */ - cnt = out->dcnt; - dp = &out->data[0]; - if (cnt > scnt) /* Only send as much as we are allowed */ - cnt = scnt; - for (; cnt > 0; cnt -= 2) { - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Send Idata: %06o %03o %03o\n", - *dp, *dp >> 8, *dp & 0377); - if (Mem_write_byte(0, dp) == 0) - goto error; - dp++; - } - uptr->STATUS &= ~DTE_SIND; - } else { - sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d send CMD: %o %o %o\n", - dte_out_ptr, dte_out_res, out->cnt, out->func, out->dev); - /* Get size of packet */ - cnt = out->cnt; - if ((out->func & PRI_IND_FLG) == 0) - cnt += out->dcnt; - /* If it will not fit, request indirect */ - if (cnt > scnt) { /* If not enough space request indirect */ - out->func |= PRI_IND_FLG; - cnt = scnt; - } - /* Write out header */ - if (!Mem_write_byte(0, &cnt)) - goto error; - if (!Mem_write_byte(0, &out->func)) - goto error; - cnt -= 2; - if (!Mem_write_byte(0, &out->dev)) - goto error; - cnt -= 2; - if (!Mem_write_byte(0, &out->spare)) - goto error; - cnt -= 2; - if (out->func & PRI_IND_FLG) { -sim_debug(DEBUG_DATA, &dte_dev, "DTE: Indirect %o %o\n", cnt, out->dcnt); - if (!Mem_write_byte(0, &out->dcnt)) - goto error; - uptr->STATUS |= DTE_SIND; - goto done; - } - cnt -= 2; - dp = &out->data[0]; - for (; cnt > 0; cnt -= 2) { - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Send data: %06o %03o %03o\n", - *dp, *dp >> 8, *dp & 0377); - if (!Mem_write_byte(0, dp)) - goto error; - dp++; - } - } - out->cnt = 0; - dte_out_ptr = (dte_out_ptr + 1) & 0x1f; -done: - uptr->STATUS |= DTE_10DN; - set_interrupt(DTE_DEVNUM, uptr->STATUS); -error: - return; -} - -/* Process input from CTY and TTY's to 10. */ -void -dte_input() -{ - uint16 data1; - uint16 dataq[32]; - int n; - int ln; - int save_ptr; - char ch; - UNIT *uptr = &dte_unit[0]; - -#if KL_ITS - if (QITS && (uptr->STATUS & ITS_ON) != 0) { - uint64 word; - word = M[ITS_DTEODN]; - /* Check if ready for output done */ - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo %d\n", word, cty_done); - if ((word & SMASK) != 0) { - if (cty_done) { - word = 64LL; - cty_done--; -#if (NUM_DEVS_TTY > 0) - } else { - for (ln = 0; ln < tty_desc.lines; ln++) { - if (tty_done[ln]) { - word = (((uint64)ln + 1) << 18); - word |=(tty_connect[ln])? 64: 1; - tty_done[ln] = 0; - break; - } - } -#endif - } - if ((word & SMASK) == 0) { - M[ITS_DTEODN] = word; - /* Tell 10 something is ready */ - uptr->STATUS |= DTE_10DB; - set_interrupt(DTE_DEVNUM, uptr->STATUS); - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo\n", word); - } - } - /* Check if ready for any input */ - word = M[ITS_DTETYI]; - if ((word & SMASK) != 0) { - /* CTY first. */ - if (cty_in.in_ptr != cty_in.out_ptr) { - ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; - word = (uint64)ch; -#if (NUM_DEVS_TTY > 0) - } else { - ln = uptr->CNT; - while ((word & SMASK) != 0) { - if (tty_in[ln].in_ptr != tty_in[ln].out_ptr) { - ch = tty_in[ln].buff[tty_in[ln].out_ptr]; - tty_in[ln].out_ptr = (tty_in[ln].out_ptr + 1) & 0xff; - word = ((uint64)(ln+1) << 18) | (uint64)ch; - } - ln++; - if (ln >= tty_desc.lines) - ln = 0; - if (ln == uptr->CNT) - break; - } - uptr->CNT = ln; -#endif - } - if ((word & SMASK) == 0) { - M[ITS_DTETYI] = word; - /* Tell 10 something is ready */ - uptr->STATUS |= DTE_10DB; - set_interrupt(DTE_DEVNUM, uptr->STATUS); - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); - } - } -#if (NUM_DEVS_TTY > 0) - /* Check ready for hang up message */ - word = M[ITS_DTEHNG]; - if ((word & SMASK) != 0) { - for (ln = 0; ln < tty_desc.lines; ln++) { - if (tty_connect[ln] != tty_ldsc[ln].conn) { - if (tty_ldsc[ln].conn) - word = 015500 + ln + 1; - else - word = ln + 1; - tty_connect[ln] = tty_ldsc[ln].conn; - tty_done[ln] = tty_ldsc[ln].conn; - break; - } - } - /* Tell 10 something is ready */ - if ((word & SMASK) == 0) { - M[ITS_DTEHNG] = word; - uptr->STATUS |= DTE_10DB; - set_interrupt(DTE_DEVNUM, uptr->STATUS); - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEHNG = %012llo\n", word); - } - } -#endif - } else -#endif - if ((uptr->STATUS & DTE_SEC) == 0) { - /* Check if CTY done with input */ - if (cty_done) { - data1 = PRI_CTYDV; - if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, &data1) == 0) - return; - cty_done--; - } - /* Grab a chunck of input from CTY if any */ - n = 0; - save_ptr = cty_in.out_ptr; - while (cty_in.in_ptr != cty_in.out_ptr && n < 32) { - ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY recieve %02x\n", ch); - dataq[n++] = (PRI_CTYDV << 8) | ch; - } - if (n > 0 && dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) { - /* Restore the input pointer */ - cty_in.out_ptr = save_ptr; - return; - } -#if (NUM_DEVS_TTY > 0) - n = 0; - /* While we have room for one more packet, grab as much input as we can */ - for (ln = 0; ln < tty_desc.lines && ((dte_out_res + 1) & 0x1f) != dte_out_ptr; ln++) { - while (tty_in[ln].in_ptr != tty_in[ln].out_ptr) { - ch = tty_in[ln].buff[tty_in[ln].out_ptr]; - tty_in[ln].out_ptr = (tty_in[ln].out_ptr + 1) & 0xff; - dataq[n++] = ((ln + 2) << 8) | ch; - if (n == 32) { - if (dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) - return; - n = 0; - continue; - } - } - } - if (n > 0 && dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) - return; - n = 0; - for (ln = 0; ln < tty_desc.lines; ln++) { - if (tty_connect[ln] != tty_ldsc[ln].conn) { - data1 = ln + 2; - if (tty_ldsc[ln].conn) - n = PRI_EMDSC; - else - n = PRI_EMHUD; - if (dte_queue(n, PRI_EMDLS, 1, &data1) == 0) - return; - tty_connect[ln] = tty_ldsc[ln].conn; - } - if (tty_done[ln]) { - data1 = ln + 2; - if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, &data1) == 0) - return; - tty_done[ln] = 0; - } - } -#endif - } -} - -/* - * Queue up a packet to send to 10. - */ -int -dte_queue(int func, int dev, int dcnt, uint16 *data) -{ - uint16 *dp; - struct _dte_queue *out; - - /* Check if room in queue for this packet. */ - if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { - sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d out full\n", dte_out_res, dte_out_ptr); - return 0; - } - out = &dte_out[dte_out_res]; - out->cnt = 10; - out->func = func; - out->dev = dev; - out->dcnt = (dcnt-1)*2; - out->spare = 0; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d queue resp: %o %o %s %o\n", - dte_out_ptr, dte_out_res, out->cnt, out->func, - (out->func > PRI_EMLDV)? "***":pri_name[out->func], out->dev); - for (dp = &out->data[0]; dcnt > 0; dcnt--) { - *dp++ = *data++; - } - /* Advance pointer to next function */ - dte_out_res = (dte_out_res + 1) & 0x1f; - return 1; -} - - -/* - * If anything in queue, start a transfer, if one is not already - * pending. - */ -int -dte_start(UNIT *uptr) -{ - uint64 word; - int dcnt; - - /* Check if queue empty */ - if (dte_out_ptr == dte_out_res) - return 1; - - /* If there is interrupt pending, just return */ - if ((uptr->STATUS & (DTE_IND|DTE_10DB|DTE_11DB)) != 0) - return 1; - if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word)) { -error: - /* If we can't read it, go back to secondary */ - uptr->STATUS |= DTE_SEC|DTE_10ER; - set_interrupt(DTE_DEVNUM, uptr->STATUS); - return 0; - } - /* Bump count of messages sent */ - word = (word & ~(PRI_CMT_10IC|PRI_CMT_IP)) | ((word + 0400) & PRI_CMT_10IC); - if ((uptr->STATUS & DTE_SIND) != 0) - word |= PRI_CMT_IP; - if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) - goto error; - dcnt = dte_out[dte_out_ptr].cnt; - if ((dte_out[dte_out_ptr].func & PRI_IND_FLG) == 0) - dcnt += dte_out[dte_out_ptr].dcnt; - /* Tell 10 something is ready */ - word = (uint64)dcnt; - if ((uptr->STATUS & DTE_SIND) != 0) { - word = (uint64)(dte_out[dte_out_ptr].dcnt); - } - if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_CNT, &word)) - goto error; - uptr->STATUS |= DTE_10DB; - set_interrupt(DTE_DEVNUM, uptr->STATUS); - return 1; -} - - -/* Check for input from CTY and put on queue. */ -t_stat dtei_svc (UNIT *uptr) -{ - int32 ch; - uint32 base = 0; - UNIT *optr = &dte_unit[0]; - -#if KI_22BIT -#if KL_ITS - if (!QITS) -#endif - base = eb_ptr; -#endif - sim_clock_coschedule (uptr, tmxr_poll); - dte_input(); - if ((optr->STATUS & (DTE_SEC)) == 0) { - dte_function(uptr); /* Process queue */ - dte_start(optr); - } - - - /* If we have room see if any new lines */ - while (((cty_in.in_ptr + 1) & 0xff) != cty_in.out_ptr) { - ch = sim_poll_kbd (); - if (ch & SCPE_KFLAG) { - ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (uptr->flags)); - cty_in.buff[cty_in.in_ptr] =ch & 0377; - cty_in.in_ptr = (cty_in.in_ptr + 1) & 0xff; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %o '%c'\n", ch, - ((ch > 040 && ch < 0177)? ch: '.')); - } else - break; - } - - /* If Monitor input, place in buffer */ - if ((optr->STATUS & (DTE_SEC|DTE_MON)) == (DTE_SEC|DTE_MON) && - cty_in.in_ptr != cty_in.out_ptr && M[SEC_DTMTI + base] == 0) { - ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; - M[SEC_DTF11 + base] = ch; - M[SEC_DTMTI + base] = FMASK; - if (dte_dev.flags & TYPE_RSX20) { - uptr->STATUS |= DTE_10DB; - set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); - } - } - return SCPE_OK; -} - -/* Handle output of characters to CTY. Started whenever there is output pending */ -t_stat dteo_svc (UNIT *uptr) -{ - uint32 base = 0; - UNIT *optr = &dte_unit[0]; - -#if KI_22BIT -#if KL_ITS - if (!QITS) -#endif - base = eb_ptr; -#endif - /* Flush out any pending CTY output */ - while(cty_out.in_ptr != cty_out.out_ptr) { - char ch = cty_out.buff[cty_out.out_ptr]; - if (ch != 0) { - if (sim_putchar(ch) != SCPE_OK) { - sim_activate(uptr, 1000); - return SCPE_OK;; - } - } - cty_out.out_ptr = (cty_out.out_ptr + 1) & 0xff; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY outch %o '%c'\n", ch, - ((ch > 040 && ch < 0177)? ch: '.')); - } - cty_done++; - dte_input(); - return SCPE_OK; -} - - -/* Handle FE timer interrupts. And keepalive counts */ -t_stat -dtertc_srv(UNIT * uptr) -{ - UNIT *optr = &dte_unit[0]; - - sim_activate_after(uptr, 1000000/rtc_tps); - /* Check if clock requested */ - if (uptr->STATUS & SEC_CLK) { - rtc_tick++; - if (rtc_wait != 0) { - rtc_wait--; - } else { - UNIT *optr = &dte_unit[0]; - uint32 base = 0; -#if KI_22BIT - base = eb_ptr; -#endif - /* Set timer flag */ - M[SEC_DTCLK + base] = FMASK; - optr->STATUS |= DTE_10DB; - set_interrupt(DTE_DEVNUM, optr->STATUS); - sim_debug(DEBUG_EXP, &dte_dev, "CTY tick %x %x %06o\n", - rtc_tick, rtc_wait, optr->STATUS); - } - } -#if KL_ITS - /* Check if Timesharing is running */ - if (QITS) { - uint64 word; - - word = (M[ITS_DTECHK] + 1) & FMASK; - if (word == 0) { - optr->STATUS |= ITS_ON; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS ON\n"); - sim_activate(&tty_unit[0], 1000); - sim_activate(&tty_unit[1], 1000); - } else if (word >= (15 * 60)) { - optr->STATUS &= ~ITS_ON; - word = 15 * 60; - sim_cancel(&tty_unit[0]); - sim_cancel(&tty_unit[1]); - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS OFF\n"); - } - M[ITS_DTECHK] = word; - } else -#endif - - /* Update out keep alive timer if in secondary protocol */ - if ((optr->STATUS & DTE_SEC) == 0) { - int addr = 0144 + eb_ptr; - uint64 word; - - (void)Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word); - addr = (M[addr+1] + dte_off + PRI_CMTW_KAC) & RMASK; - word = M[addr]; - word = (word + 1) & FMASK; - M[addr] = word; - sim_debug(DEBUG_EXP, &dte_dev, "CTY keepalive %06o %012llo %06o\n", - addr, word, optr->STATUS); - } - - return SCPE_OK; -} - - -t_stat dte_reset (DEVICE *dptr) -{ - dte_unit[0].STATUS = DTE_SEC; - dte_unit[1].STATUS = 0; - dte_unit[2].STATUS = 0; - dte_unit[3].STATUS = 0; - cty_done = 0; - sim_rtcn_init_unit (&dte_unit[3], 1000, TMR_RTC); - sim_activate(&dte_unit[3], 1000); - sim_activate(&dte_unit[2], 1000); - return SCPE_OK; -} - - -t_stat -dte_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - DEVICE *dptr; - dptr = find_dev_from_unit (uptr); - if (dptr == NULL) - return SCPE_IERR; - dptr->flags &= ~DEV_M_OS; - dptr->flags |= val; - return SCPE_OK; -} - -t_stat -dte_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc) -{ - DEVICE *dptr; - - if (uptr == NULL) - return SCPE_IERR; - - dptr = find_dev_from_unit(uptr); - if (dptr == NULL) - return SCPE_IERR; - fprintf (st, "%s", (dptr->flags & TYPE_RSX20) ? "RSX20" : "RSX10"); - return SCPE_OK; -} - - -/* Stop operating system */ - -t_stat dte_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - M[CTY_SWITCH] = 1; /* tell OS to stop */ - return SCPE_OK; -} - -t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - dte_unit[0].flags = (dte_unit[0].flags & ~TT_MODE) | val; - return SCPE_OK; -} - -t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) -{ -fprintf (st, "To stop the cpu use the command:\n\n"); -fprintf (st, " sim> SET CTY STOP\n\n"); -fprintf (st, "This will write a 1 to location %03o, causing TOPS10 to stop\n\n", CTY_SWITCH); -fprintf (st, "The additional terminals can be set to one of four modes: UC, 7P, 7B, or 8B.\n\n"); -fprintf (st, " mode input characters output characters\n\n"); -fprintf (st, " UC lower case converted lower case converted to upper case,\n"); -fprintf (st, " to upper case, high-order bit cleared,\n"); -fprintf (st, " high-order bit cleared non-printing characters suppressed\n"); -fprintf (st, " 7P high-order bit cleared high-order bit cleared,\n"); -fprintf (st, " non-printing characters suppressed\n"); -fprintf (st, " 7B high-order bit cleared high-order bit cleared\n"); -fprintf (st, " 8B no changes no changes\n\n"); -fprintf (st, "The default mode is 7P. In addition, each line can be configured to\n"); -fprintf (st, "behave as though it was attached to a dataset, or hardwired to a terminal:\n\n"); -fprint_reg_help (st, &dte_dev); -return SCPE_OK; -} - -const char *dte_description (DEVICE *dptr) -{ - return "Console TTY Line"; -} - - -#if (NUM_DEVS_LP > 0) - -void -lpt_printline(UNIT *uptr, int nl) { - int trim = 0; - uint16 data1 = 1; - /* Trim off trailing blanks */ - while (uptr->COL >= 0 && lpt_buffer[uptr->POS - 1] == ' ') { - uptr->COL--; - uptr->POS--; - trim = 1; - } - lpt_buffer[uptr->POS] = '\0'; - sim_debug(DEBUG_DETAIL, &lpt_dev, "LP output %d %d [%s]\n", uptr->COL, nl, lpt_buffer); - /* Stick a carraige return and linefeed as needed */ - if (uptr->COL != 0 || trim) - lpt_buffer[uptr->POS++] = '\r'; - if (nl != 0) { - lpt_buffer[uptr->POS++] = '\n'; - uptr->LINE++; - } - if (nl > 0 && uptr->LINE >= ((int32)uptr->capac - MARGIN)) { - lpt_buffer[uptr->POS++] = '\f'; - uptr->LINE = 0; - } else if (nl < 0 && uptr->LINE >= (int32)uptr->capac) { - uptr->LINE = 0; - } - - sim_fwrite(&lpt_buffer, 1, uptr->POS, uptr->fileref); - uptr->pos += uptr->POS; - uptr->COL = 0; - uptr->POS = 0; - return; -} - - -/* Unit service */ -void -lpt_output(UNIT *uptr, char c) { - - if (c == 0) - return; - if (uptr->COL == 132) - lpt_printline(uptr, 1); - if ((uptr->flags & UNIT_UC) && (c & 0140) == 0140) - c &= 0137; - else if (c >= 040 && c < 0177) { - lpt_buffer[uptr->POS++] = c; - uptr->COL++; - } - return; -} - -t_stat lpt_svc (UNIT *uptr) -{ - char c; - uint16 data1 = 0; - - if ((uptr->flags & UNIT_ATT) == 0) - return SCPE_OK; - - while (((lpt_queue.out_ptr + 1) & 0xff) != lpt_queue.in_ptr) { - c = lpt_queue.buff[lpt_queue.out_ptr]; - lpt_queue.out_ptr = (lpt_queue.out_ptr + 1) & 0xff; - if (c < 040) { /* Control character */ - switch(c) { - case 011: /* Horizontal tab, space to 8'th column */ - lpt_output(uptr, ' '); - while ((uptr->COL & 07) != 0) - lpt_output(uptr, ' '); - break; - case 015: /* Carriage return, print line */ - lpt_printline(uptr, 0); - break; - case 012: /* Line feed, print line, space one line */ - lpt_printline(uptr, 1); - break; - case 014: /* Form feed, skip to top of page */ - lpt_printline(uptr, 0); - sim_fwrite("\014", 1, 1, uptr->fileref); - uptr->pos++; - uptr->LINE = 0; - break; - case 013: /* Vertical tab, Skip mod 20 */ - lpt_printline(uptr, 1); - while((uptr->LINE % 20) != 0) { - sim_fwrite("\r\n", 1, 2, uptr->fileref); - uptr->pos+=2; - uptr->LINE++; - } - break; - case 020: /* Skip half page */ - lpt_printline(uptr, 1); - while((uptr->LINE % 30) != 0) { - sim_fwrite("\r\n", 1, 2, uptr->fileref); - uptr->pos+=2; - uptr->LINE++; - } - break; - case 021: /* Skip even lines */ - lpt_printline(uptr, 1); - while((uptr->LINE % 2) != 0) { - sim_fwrite("\r\n", 1, 2, uptr->fileref); - uptr->pos+=2; - uptr->LINE++; - } - break; - case 022: /* Skip triple lines */ - lpt_printline(uptr, 1); - while((uptr->LINE % 3) != 0) { - sim_fwrite("\r\n", 1, 2, uptr->fileref); - uptr->pos+=2; - uptr->LINE++; - } - break; - case 023: /* Skip one line */ - lpt_printline(uptr, -1); - break; - default: /* Ignore */ - break; - } - } else { - sim_debug(DEBUG_DETAIL, &lpt_dev, "LP deque %02x '%c'\n", c, c); - lpt_output(uptr, c); - } - } - if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, &data1) == 0) - sim_activate(uptr, 1000); - return SCPE_OK; -} - -/* Reset routine */ - -t_stat lpt_reset (DEVICE *dptr) -{ - UNIT *uptr = &lpt_unit; - uptr->POS = 0; - uptr->COL = 0; - uptr->LINE = 1; - sim_cancel (&lpt_unit); /* deactivate unit */ - return SCPE_OK; -} - -/* Attach routine */ - -t_stat lpt_attach (UNIT *uptr, CONST char *cptr) -{ - return attach_unit (uptr, cptr); -} - -/* Detach routine */ - -t_stat lpt_detach (UNIT *uptr) -{ - return detach_unit (uptr); -} - -/* - * Line printer routines - */ - -t_stat -lpt_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - t_value i; - t_stat r; - if (cptr == NULL) - return SCPE_ARG; - if (uptr == NULL) - return SCPE_IERR; - i = get_uint (cptr, 10, 100, &r); - if (r != SCPE_OK) - return SCPE_ARG; - uptr->capac = (t_addr)i; - uptr->LINE = 0; - return SCPE_OK; -} - -t_stat -lpt_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc) -{ - if (uptr == NULL) - return SCPE_IERR; - fprintf(st, "linesperpage=%d", uptr->capac); - return SCPE_OK; -} - -t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) -{ -fprintf (st, "Line Printer (LPT)\n\n"); -fprintf (st, "The line printer (LPT) writes data to a disk file. The POS register specifies\n"); -fprintf (st, "the number of the next data item to be written. Thus, by changing POS, the\n"); -fprintf (st, "user can backspace or advance the printer.\n"); -fprintf (st, "The Line printer can be configured to any number of lines per page with the:\n"); -fprintf (st, " sim> SET %s0 LINESPERPAGE=n\n\n", dptr->name); -fprintf (st, "The default is 66 lines per page.\n\n"); -fprintf (st, "The device address of the Line printer can be changed\n"); -fprintf (st, " sim> SET %s0 DEV=n\n\n", dptr->name); -fprint_set_help (st, dptr); -fprint_show_help (st, dptr); -fprint_reg_help (st, dptr); -return SCPE_OK; -} - -const char *lpt_description (DEVICE *dptr) -{ - return "LPT0 line printer" ; -} - -#endif - -#if (NUM_DEVS_TTY > 0) - -/* Unit service */ -t_stat ttyi_svc (UNIT *uptr) -{ - int32 ln; - TMLN *lp; - int flg; - - if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ - return SCPE_OK; - - sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */ - - /* If we have room see if any new lines */ - ln = tmxr_poll_conn (&tty_desc); /* look for connect */ - if (ln >= 0) { - tty_ldsc[ln].rcve = 1; - sim_debug(DEBUG_DETAIL, &tty_dev, "TTY line connect %d\n", ln); - } - - tmxr_poll_tx(&tty_desc); - tmxr_poll_rx(&tty_desc); - - /* Scan each line for input */ - for (ln = 0; ln < tty_desc.lines; ln++) { - struct _buffer *iptr = &tty_in[ln]; - lp = &tty_ldsc[ln]; - if (lp->conn == 0) - continue; - flg = 1; - while (flg && ((iptr->in_ptr + 1) & 0xff) != iptr->out_ptr) { - /* Spool up as much as we have room for */ - int32 ch = tmxr_getc_ln(lp); - if ((ch & TMXR_VALID) != 0) { - ch = sim_tt_inpcvt (ch, TT_GET_MODE(tty_unit[0].flags) | TTUF_KSR); - iptr->buff[iptr->in_ptr] = ch & 0377; - iptr->in_ptr = (iptr->in_ptr + 1) & 0xff; - sim_debug(DEBUG_DETAIL, &tty_dev, "TTY recieve %d: %o\n", ln, ch); - } else - flg = 0; - } - } - - return SCPE_OK; -} - -/* Output whatever we can */ -t_stat ttyo_svc (UNIT *uptr) -{ - t_stat r; - int32 ln; - int n = 0; - TMLN *lp; - - if ((tty_unit[0].flags & UNIT_ATT) == 0) /* attached? */ - return SCPE_OK; - - sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */ - - for (ln = 0; ln < tty_desc.lines; ln++) { - struct _buffer *optr = &tty_out[ln]; - lp = &tty_ldsc[ln]; - if (lp->conn == 0) - continue; - if (optr->out_ptr == optr->in_ptr) - continue; - while (optr->out_ptr != optr->in_ptr) { - int32 ch = optr->buff[optr->out_ptr]; - ch = sim_tt_outcvt(ch, TT_GET_MODE (tty_unit[0].flags) | TTUF_KSR); - sim_debug(DEBUG_DATA, &tty_dev, "TTY: %d output %o\n", ln, ch); - r = tmxr_putc_ln (lp, ch); - if (r == SCPE_OK) - optr->out_ptr = (optr->out_ptr + 1) & 0xff; - else if (r == SCPE_LOST) { - optr->out_ptr = optr->in_ptr = 0; - continue; - } else - continue; - } - tty_done[ln] = 1; - } - return SCPE_OK; -} - -/* Reset routine */ - -t_stat tty_reset (DEVICE *dptr) -{ - return SCPE_OK; -} - - -/* SET LINES processor */ - -t_stat tty_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - int32 newln, i, t; - t_stat r; - - if (cptr == NULL) - return SCPE_ARG; - newln = (int32) get_uint (cptr, 10, NUM_LINES_TTY, &r); - if ((r != SCPE_OK) || (newln == tty_desc.lines)) - return r; - if ((newln == 0) || (newln >= NUM_LINES_TTY) || (newln % 16) != 0) - return SCPE_ARG; - if (newln < tty_desc.lines) { - for (i = newln, t = 0; i < tty_desc.lines; i++) - t = t | tty_ldsc[i].conn; - if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) - return SCPE_OK; - for (i = newln; i < tty_desc.lines; i++) { - if (tty_ldsc[i].conn) { - tmxr_linemsg (&tty_ldsc[i], "\r\nOperator disconnected line\r\n"); - tmxr_send_buffered_data (&tty_ldsc[i]); - } - tmxr_detach_ln (&tty_ldsc[i]); /* completely reset line */ - } - } - if (tty_desc.lines < newln) - memset (tty_ldsc + tty_desc.lines, 0, sizeof(*tty_ldsc)*(newln-tty_desc.lines)); - tty_desc.lines = newln; - return tty_reset (&tty_dev); /* setup lines and auto config */ -} - -/* SET LOG processor */ - -t_stat tty_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - t_stat r; - char gbuf[CBUFSIZE]; - int32 ln; - - if (cptr == NULL) - return SCPE_ARG; - cptr = get_glyph (cptr, gbuf, '='); - if ((cptr == NULL) || (*cptr == 0) || (gbuf[0] == 0)) - return SCPE_ARG; - ln = (int32) get_uint (gbuf, 10, tty_desc.lines, &r); - if ((r != SCPE_OK) || (ln >= tty_desc.lines)) - return SCPE_ARG; - return tmxr_set_log (NULL, ln, cptr, desc); -} - -/* SET NOLOG processor */ - -t_stat tty_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - t_stat r; - int32 ln; - - if (cptr == NULL) - return SCPE_ARG; - ln = (int32) get_uint (cptr, 10, tty_desc.lines, &r); - if ((r != SCPE_OK) || (ln >= tty_desc.lines)) - return SCPE_ARG; - return tmxr_set_nolog (NULL, ln, NULL, desc); -} - -/* SHOW LOG processor */ - -t_stat tty_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc) -{ - int32 i; - - for (i = 0; i < tty_desc.lines; i++) { - fprintf (st, "line %d: ", i); - tmxr_show_log (st, NULL, i, desc); - fprintf (st, "\n"); - } - return SCPE_OK; -} - - -/* Attach routine */ - -t_stat tty_attach (UNIT *uptr, CONST char *cptr) -{ -t_stat reason; - -reason = tmxr_attach (&tty_desc, uptr, cptr); -if (reason != SCPE_OK) - return reason; -sim_activate (uptr, tmxr_poll); -return SCPE_OK; -} - -/* Detach routine */ - -t_stat tty_detach (UNIT *uptr) -{ - int32 i; - t_stat reason; -reason = tmxr_detach (&tty_desc, uptr); -for (i = 0; i < tty_desc.lines; i++) - tty_ldsc[i].rcve = 0; -sim_cancel (uptr); -return reason; -} - -t_stat tty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) -{ -fprintf (st, "DC10E Terminal Interfaces\n\n"); -fprintf (st, "The DC10 supported up to 8 blocks of 8 lines. Modem control was on a seperate\n"); -fprintf (st, "line. The simulator supports this by setting modem control to a fixed offset\n"); -fprintf (st, "from the given line. The number of lines is specified with a SET command:\n\n"); -fprintf (st, " sim> SET DC LINES=n set number of additional lines to n [8-32]\n\n"); -fprintf (st, "Lines must be set in multiples of 8.\n"); -fprintf (st, "The default offset for modem lines is 32. This can be changed with\n\n"); -fprintf (st, " sim> SET DC MODEM=n set offset for modem control to n [8-32]\n\n"); -fprintf (st, "Modem control must be set larger then the number of lines\n"); -fprintf (st, "The ATTACH command specifies the port to be used:\n\n"); -tmxr_attach_help (st, dptr, uptr, flag, cptr); -fprintf (st, "The additional terminals can be set to one of four modes: UC, 7P, 7B, or 8B.\n\n"); -fprintf (st, " mode input characters output characters\n\n"); -fprintf (st, " UC lower case converted lower case converted to upper case,\n"); -fprintf (st, " to upper case, high-order bit cleared,\n"); -fprintf (st, " high-order bit cleared non-printing characters suppressed\n"); -fprintf (st, " 7P high-order bit cleared high-order bit cleared,\n"); -fprintf (st, " non-printing characters suppressed\n"); -fprintf (st, " 7B high-order bit cleared high-order bit cleared\n"); -fprintf (st, " 8B no changes no changes\n\n"); -fprintf (st, "The default mode is 7P.\n"); -fprintf (st, "Finally, each line supports output logging. The SET DCn LOG command enables\n"); -fprintf (st, "logging on a line:\n\n"); -fprintf (st, " sim> SET DCn LOG=filename log output of line n to filename\n\n"); -fprintf (st, "The SET DCn NOLOG command disables logging and closes the open log file,\n"); -fprintf (st, "if any.\n\n"); -fprintf (st, "Once DC is attached and the simulator is running, the terminals listen for\n"); -fprintf (st, "connections on the specified port. They assume that the incoming connections\n"); -fprintf (st, "are Telnet connections. The connections remain open until disconnected either\n"); -fprintf (st, "by the Telnet client, a SET DC DISCONNECT command, or a DETACH DC command.\n\n"); -fprintf (st, "Other special commands:\n\n"); -fprintf (st, " sim> SHOW DC CONNECTIONS show current connections\n"); -fprintf (st, " sim> SHOW DC STATISTICS show statistics for active connections\n"); -fprintf (st, " sim> SET DCn DISCONNECT disconnects the specified line.\n"); -fprint_reg_help (st, &tty_dev); -fprintf (st, "\nThe additional terminals do not support save and restore. All open connections\n"); -fprintf (st, "are lost when the simulator shuts down or DC is detached.\n"); -return SCPE_OK; -} - -const char *tty_description (DEVICE *dptr) -{ -return "DC10E asynchronous line interface"; -} - -#endif -#endif +/* kl10_fe.c: KL-10 front end (console terminal) simulator + + Copyright (c) 2013-2019, Richard Cornwell + + 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 + RICHARD CORNWELL 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 Richard Cornwell shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Richard Cornwell + +*/ + +#include "kx10_defs.h" +#include "sim_sock.h" +#include "sim_tmxr.h" +#include + +#if KL +#define UNIT_DUMMY (1 << UNIT_V_UF) + +#define DTE_DEVNUM 0200 +#define DEV_V_OS (DEV_V_UF + 1) /* Type RSX10/RSX20 */ +#define DEV_M_OS (1 << DEV_V_OS) +#define TYPE_RSX10 (0 << DEV_V_OS) +#define TYPE_RSX20 (1 << DEV_V_OS) + + + +/* DTE10 CONI bits */ + +#define DTE_RM 00100000 /* Restricted mode */ +#define DTE_D11 00040000 /* Dead-11 */ +#define DTE_11DB 00020000 /* TO11 Door bell request */ +#define DTE_10DB 00001000 /* TO10 Door bell request */ +#define DTE_11ER 00000400 /* Error during TO11 transfer */ +#define DTE_11DN 00000100 /* TO 11 transfer done */ +#define DTE_10DN 00000040 /* TO 10 transfer done */ +#define DTE_10ER 00000020 /* Error during TO10 transfer */ +#define DTE_PIE 00000010 /* PIO enabled */ +#define DTE_PIA 00000007 /* PI channel assigment */ + +/* internal flags */ +#define DTE_11RELD 01000000 /* Reload 11. */ +#define DTE_TO11 02000000 /* Transfer to 11 */ +#define DTE_SEC 04000000 /* In secondary protocol */ +#define DTE_IND 010000000 /* Next transfer will be indirect */ +#define DTE_SIND 020000000 /* Send indirect data next */ + +/* DTE CONO bits */ +#define DTE_CO11DB 0020000 /* Set TO11 Door bell */ +#define DTE_CO11CR 0010000 /* Clear reload 11 button */ +#define DTE_CO11SR 0004000 /* Set reload 11 button */ +#define DTE_CO10DB 0001000 /* Clear TO10 Door bell */ +#define DTE_CO11CL 0000100 /* Clear TO11 done and error */ +#define DTE_CO10CL 0000040 /* Clear TO10 done and error */ +#define DTE_PIENB 0000020 /* Load PI and enable bit */ + +/* DTE DATAO */ +#define DTE_TO10IB 010000 /* Interrupt after transfer */ +#define DTE_TO10BC 007777 /* Byte count for transfer */ + +/* Secondary protocol addresses */ +#define SEC_DTFLG 0444 /* Operation complete flag */ +#define SEC_DTCLK 0445 /* Clock interrupt flag */ +#define SEC_DTCI 0446 /* Clock interrupt instruction */ +#define SEC_DTT11 0447 /* 10 to 11 argument */ +#define SEC_DTF11 0450 /* 10 from 11 argument */ +#define SEC_DTCMD 0451 /* To 11 command word */ +#define SEC_DTSEQ 0452 /* Operation sequence number */ +#define SEC_DTOPR 0453 /* Operational DTE # */ +#define SEC_DTCHR 0454 /* Last typed character */ +#define SEC_DTMTD 0455 /* Monitor tty output complete flag */ +#define SEC_DTMTI 0456 /* Monitor tty input flag */ +#define SEC_DTSWR 0457 /* 10 switch register */ + +#define SEC_PGMCTL 00400 +#define SEC_ENDPASS 00404 +#define SEC_LOOKUP 00406 +#define SEC_RDWRD 00407 +#define SEC_RDBYT 00414 +#define SEC_ESEC 00440 +#define SEC_EPRI 00500 +#define SEC_ERTM 00540 +#define SEC_CLKCTL 01000 +#define SEC_CLKOFF 01000 +#define SEC_CLKON 01001 +#define SEC_CLKWT 01002 +#define SEC_CLKRD 01003 +#define SEC_RDSW 01400 +#define SEC_CLRDDT 03000 +#define SEC_SETDDT 03400 +#define SEC_MONO 04000 +#define SEC_MONON 04400 +#define SEC_SETPRI 05000 +#define SEC_RTM 05400 +#define SEC_CMDMSK 07400 +#define DTE_MON 00000001 /* Save in unit1 STATUS */ +#define SEC_CLK 00000002 /* Clock enabled */ +#define ITS_ON 00000004 /* ITS Is alive */ + +/* Primary or Queued protocol addresses */ +#define PRI_CMTW_0 0 +#define PRI_CMTW_PPT 1 /* Pointer to com region */ +#define PRI_CMTW_STS 2 /* Status word */ +#define PRI_CMT_PWF SMASK /* Power failure */ +#define PRI_CMT_L11 BIT1 /* Load 11 */ +#define PRI_CMT_INI BIT2 /* Init */ +#define PRI_CMT_TST BIT3 /* Valid examine bit */ +#define PRI_CMT_QP 020000000LL /* Do Queued protocol */ +#define PRI_CMT_FWD 001000000LL /* Do full word transfers */ +#define PRI_CMT_IP RSIGN /* Indirect transfer */ +#define PRI_CMT_TOT 0200000LL /* TOIT bit */ +#define PRI_CMT_10IC 0177400LL /* TO10 IC for queued transfers */ +#define PRI_CMT_11IC 0000377LL /* TO11 IC for queued transfers */ +#define PRI_CMTW_CNT 3 /* Queue Count */ +#define PRI_CMTW_KAC 5 /* Keep alive count */ +#define PRI_IND_FLG 0100000 /* Flag function as indirect */ + +#define PRI_EM2EI 001 /* Initial message to 11 */ +#define PRI_EM2TI 002 /* Replay to initial message. */ +#define PRI_EMSTR 003 /* String data */ +#define PRI_EMLNC 004 /* Line-Char */ +#define PRI_EMRDS 005 /* Request device status */ +#define PRI_EMHDS 007 /* Here is device status */ +#define PRI_EMRDT 011 /* Request Date/Time */ +#define PRI_EMHDR 012 /* Here is date and time */ +#define PRI_EMFLO 013 /* Flush output */ +#define PRI_EMSNA 014 /* Send all (ttys) */ +#define PRI_EMDSC 015 /* Dataset connect */ +#define PRI_EMHUD 016 /* Hang up dataset */ +#define PRI_EMACK 017 /* Acknowledge line */ +#define PRI_EMXOF 020 /* XOFF line */ +#define PRI_EMXON 021 /* XON line */ +#define PRI_EMHLS 022 /* Here is line speeds */ +#define PRI_EMHLA 023 /* Here is line allocation */ +#define PRI_EMRBI 024 /* Reboot information */ +#define PRI_EMAKA 025 /* Ack ALL */ +#define PRI_EMTDO 026 /* Turn device On/Off */ +#define PRI_EMEDR 027 /* Enable/Disable line */ +#define PRI_EMLDR 030 /* Load LP RAM */ +#define PRI_EMLDV 031 /* Load LP VFU */ + +#define PRI_EMCTY 001 /* Device code for CTY */ +#define PRI_EMDL1 002 /* DL11 */ +#define PRI_EMDH1 003 /* DH11 #1 */ +#define PRI_EMDLS 004 /* DLS (all ttys combined) */ +#define PRI_EMLPT 005 /* Front end LPT */ +#define PRI_EMCDR 006 /* CDR */ +#define PRI_EMCLK 007 /* Clock */ +#define PRI_EMFED 010 /* Front end device */ +#define PRI_CTYDV 000 /* Line number for CTY */ + +#if KL_ITS +/* ITS Timesharing protocol locations */ +#define ITS_DTEVER 0400 /* Protocol version and number of devices */ +#define ITS_DTECHK 0401 /* Increment at 60Hz. Ten setom 2 times per second */ +#define ITS_DTEINP 0402 /* Input from 10 to 11. Line #, Count */ +#define ITS_DTEOUT 0403 /* Output from 10 to 11 Line #, Count */ +#define ITS_DTELSP 0404 /* Line # to set speed of */ +#define ITS_DTELPR 0405 /* Parameter */ +#define ITS_DTEOST 0406 /* Line # to start output on */ +#define ITS_DTETYI 0410 /* Received char (Line #, char) */ +#define ITS_DTEODN 0411 /* Output done (Line #, buffer size) */ +#define ITS_DTEHNG 0412 /* Hangup/dialup */ +#endif + +#define TMR_RTC 2 + +extern int32 tmxr_poll; +t_stat dte_devio(uint32 dev, uint64 *data); +t_addr dte_devirq(uint32 dev, t_addr addr); +void dte_second(UNIT *uptr); +void dte_primary(UNIT *uptr); +#if KL_ITS +void dte_its(UNIT *uptr); +#endif +void dte_transfer(UNIT *uptr); +void dte_function(UNIT *uptr); +void dte_input(); +int dte_start(UNIT *uptr); +int dte_queue(int func, int dev, int dcnt, uint16 *data); +t_stat dtei_svc (UNIT *uptr); +t_stat dte_svc (UNIT *uptr); +t_stat dteo_svc (UNIT *uptr); +t_stat dtertc_srv(UNIT * uptr); +t_stat dte_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat dte_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat dte_reset (DEVICE *dptr); +t_stat dte_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *dte_description (DEVICE *dptr); +extern uint64 SW; /* Switch register */ + +char *pri_name[] = { "(0)", "EM2EI", "EM2TI", "EMSTR", "EMLNC", "EMRDS", "(6)", + "EMHDS", "(10)", "EMRDT", "EMHDR", "EMFLO", "EMSNA", "EMDSC", "EMHUD", + "EMACK", "EMXOF", "EMXON", "EMHLS", "EMHLA", "EMRBI", "EMAKA", "EMTDO", + "EMEDR", "EMLDR", "EMLDV" }; + +#if KL_ITS +#define QITS (cpu_unit[0].flags & UNIT_ITSPAGE) +#else +#define QITS 0 +#endif + +#define STATUS u3 +#define CNT u4 + +extern uint32 eb_ptr; +static int32 rtc_tps = 60; +uint16 rtc_tick; +uint16 rtc_wait = 0; + +struct _dte_queue { + int dptr; /* Pointer to working item */ + uint16 cnt; /* Number of bytes in packet */ + uint16 func; /* Function code */ + uint16 dev; /* Dev code */ + uint16 spare; /* Dev code */ + uint16 dcnt; /* Data count */ + uint16 data[256]; /* Data packet */ + uint16 sdev; /* Secondary device code */ + uint16 sz; /* Byte size */ +} dte_in[32], dte_out[32]; + +int dte_in_ptr; +int dte_in_cmd; +int dte_out_ptr; +int dte_out_res; +int dte_base; /* Base */ +int dte_off; /* Our offset */ +int dte_dt10_off; /* Offset to 10 deposit region */ +int dte_et10_off; /* Offset to 10 examine region */ +int dte_et11_off; /* Offset to 11 examine region */ +int dte_proc_num; /* Our processor number */ + +struct _buffer { + int in_ptr; /* Insert pointer */ + int out_ptr; /* Remove pointer */ + char buff[256]; /* Buffer */ +} cty_in, cty_out; +int cty_done; + +DIB dte_dib[] = { + { DTE_DEVNUM|000, 1, dte_devio, dte_devirq}, +}; + +MTAB dte_mod[] = { + { UNIT_DUMMY, 0, NULL, "STOP", &dte_stop_os }, + { TT_MODE, TT_MODE_UC, "UC", "UC", &tty_set_mode }, + { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode }, + { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode }, + { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode }, + {MTAB_XTD|MTAB_VDV, TYPE_RSX10, NULL, "RSX10", &dte_set_type, NULL, + NULL, "Sets DTE to RSX10 mode"}, + {MTAB_XTD|MTAB_VDV, TYPE_RSX20, "RSX20", "RSX20", &dte_set_type, &dte_show_type, + NULL, "Sets DTE to RSX20 mode"}, + { 0 } + }; + +UNIT dte_unit[] = { + { UDATA (&dte_svc, TT_MODE_7B, 0), 100}, + { UDATA (&dteo_svc, TT_MODE_7B, 0), 100}, + { UDATA (&dtei_svc, TT_MODE_7B|UNIT_DIS, 0), 1000 }, + { UDATA (&dtertc_srv, UNIT_IDLE|UNIT_DIS, 0), 1000 } + }; + + +DEVICE dte_dev = { + "CTY", dte_unit, NULL, dte_mod, + 4, 10, 31, 1, 8, 8, + NULL, NULL, &dte_reset, + NULL, NULL, NULL, &dte_dib, DEV_DEBUG, 0, dev_debug, + NULL, NULL, &dte_help, NULL, NULL, &dte_description + }; + + + +#ifndef NUM_DEVS_LP +#define NUM_DEVS_LP 0 +#endif + +#if (NUM_DEVS_LP > 0) + +#define COL u4 +#define POS u5 +#define LINE u6 + +#define MARGIN 6 + +#define UNIT_V_CT (UNIT_V_UF + 0) +#define UNIT_UC (1 << UNIT_V_CT) +#define UNIT_CT (3 << UNIT_V_CT) + + + +t_stat lpt_svc (UNIT *uptr); +t_stat lpt_reset (DEVICE *dptr); +t_stat lpt_attach (UNIT *uptr, CONST char *cptr); +t_stat lpt_detach (UNIT *uptr); +t_stat lpt_setlpp(UNIT *, int32, CONST char *, void *); +t_stat lpt_getlpp(FILE *, UNIT *, int32, CONST void *); +t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, + const char *cptr); +const char *lpt_description (DEVICE *dptr); + +char lpt_buffer[134 * 3]; + +struct _buffer lpt_queue; + +/* LPT data structures + + lpt_dev LPT device descriptor + lpt_unit LPT unit descriptor + lpt_reg LPT register list +*/ + +UNIT lpt_unit = { + UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 66), 100 + }; + +REG lpt_reg[] = { + { BRDATA(BUFF, lpt_buffer, 16, 8, sizeof(lpt_buffer)), REG_HRO}, + { NULL } +}; + +MTAB lpt_mod[] = { + {UNIT_CT, 0, "Lower case", "LC", NULL}, + {UNIT_CT, UNIT_UC, "Upper case", "UC", NULL}, + {MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LINESPERPAGE", "LINESPERPAGE", + &lpt_setlpp, &lpt_getlpp, NULL, "Number of lines per page"}, + { 0 } +}; + +DEVICE lpt_dev = { + "LPT", &lpt_unit, lpt_reg, lpt_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, &lpt_reset, + NULL, &lpt_attach, &lpt_detach, + NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug, + NULL, NULL, &lpt_help, NULL, NULL, &lpt_description +}; +#endif + +#ifndef NUM_DEVS_TTY +#define NUM_DEVS_TTY 0 +#endif + +#if (NUM_DEVS_TTY > 0) + +struct _buffer tty_out[NUM_LINES_TTY], tty_in[NUM_LINES_TTY]; +TMLN tty_ldsc[NUM_LINES_TTY] = { 0 }; /* Line descriptors */ +TMXR tty_desc = { NUM_LINES_TTY, 0, 0, tty_ldsc }; +int tty_connect[NUM_LINES_TTY]; +int tty_done[NUM_LINES_TTY]; +int tty_enable = 0; +extern int32 tmxr_poll; + +t_stat ttyi_svc (UNIT *uptr); +t_stat ttyo_svc (UNIT *uptr); +t_stat tty_reset (DEVICE *dptr); +t_stat tty_set_modem (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat tty_show_modem (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat tty_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat tty_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat tty_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat tty_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat tty_attach (UNIT *uptr, CONST char *cptr); +t_stat tty_detach (UNIT *uptr); +t_stat tty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, + const char *cptr); +const char *tty_description (DEVICE *dptr); + +/* TTY data structures + + tty_dev TTY device descriptor + tty_unit TTY unit descriptor + tty_reg TTY register list +*/ + +UNIT tty_unit[] = { + { UDATA (&ttyi_svc, TT_MODE_7B+UNIT_IDLE+UNIT_DISABLE+UNIT_ATTABLE, 0), KBD_POLL_WAIT}, + { UDATA (&ttyo_svc, TT_MODE_7B+UNIT_IDLE+UNIT_DIS, 0), KBD_POLL_WAIT}, + }; + +REG tty_reg[] = { + { DRDATA (TIME, tty_unit[0].wait, 24), REG_NZ + PV_LEFT }, + { NULL } + }; + +MTAB tty_mod[] = { + { TT_MODE, TT_MODE_KSR, "KSR", "KSR", NULL }, + { TT_MODE, TT_MODE_7B, "7b", "7B", NULL }, + { TT_MODE, TT_MODE_8B, "8b", "8B", NULL }, + { TT_MODE, TT_MODE_7P, "7p", "7P", NULL }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 1, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &tty_desc, "Disconnect a specific line" }, + { UNIT_ATT, UNIT_ATT, "SUMMARY", NULL, + NULL, &tmxr_show_summ, (void *) &tty_desc, "Display a summary of line states" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 1, "CONNECTIONS", NULL, + NULL, &tmxr_show_cstat, (void *) &tty_desc, "Display current connections" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "STATISTICS", NULL, + NULL, &tmxr_show_cstat, (void *) &tty_desc, "Display multiplexer statistics" }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "LINES", "LINES=n", + &tty_setnl, &tmxr_show_lines, (void *) &tty_desc, "Set number of lines" }, + { MTAB_XTD|MTAB_VDV|MTAB_NC, 0, NULL, "LOG=n=file", + &tty_set_log, NULL, (void *)&tty_desc }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, NULL, "NOLOG", + &tty_set_nolog, NULL, (void *)&tty_desc, "Disable logging on designated line" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "LOG", NULL, + NULL, &tty_show_log, (void *)&tty_desc, "Display logging for all lines" }, + { 0 } + }; + +DEVICE tty_dev = { + "TTY", tty_unit, tty_reg, tty_mod, + 2, 10, 31, 1, 8, 8, + &tmxr_ex, &tmxr_dep, &tty_reset, + NULL, &tty_attach, &tty_detach, + NULL, DEV_NET | DEV_DISABLE | DEV_DEBUG, 0, dev_debug, + NULL, NULL, &tty_help, NULL, NULL, &tty_description + }; +#endif + + +t_stat dte_devio(uint32 dev, uint64 *data) { + uint32 res; + switch(dev & 3) { + case CONI: + *data = (uint64)(dte_unit[0].STATUS) & RMASK; + sim_debug(DEBUG_CONI, &dte_dev, "CTY %03o CONI %06o\n", dev, (uint32)*data); + break; + case CONO: + res = (uint32)(*data & RMASK); + clr_interrupt(dev); + if (res & DTE_PIENB) { + dte_unit[0].STATUS &= ~(DTE_PIA|DTE_PIE); + dte_unit[0].STATUS |= res & (DTE_PIA|DTE_PIE); + } + if (res & DTE_CO11CL) + dte_unit[0].STATUS &= ~(DTE_11DN|DTE_11ER); + if (res & DTE_CO10CL) { + dte_unit[0].STATUS &= ~(DTE_10DN|DTE_10ER); + dte_start(&dte_unit[0]); + } + if (res & DTE_CO10DB) + dte_unit[0].STATUS &= ~(DTE_10DB); + if (res & DTE_CO11CR) + dte_unit[0].STATUS &= ~(DTE_11RELD); + if (res & DTE_CO11SR) + dte_unit[0].STATUS |= (DTE_11RELD); + if (res & DTE_CO11DB) { +sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n"); + dte_unit[0].STATUS |= DTE_11DB; + sim_activate(&dte_unit[0], 200); + } + if (dte_unit[0].STATUS & (DTE_10DB|DTE_11DN|DTE_10DN|DTE_11ER|DTE_10ER)) + set_interrupt(dev, dte_unit[0].STATUS); + sim_debug(DEBUG_CONO, &dte_dev, "CTY %03o CONO %06o %06o\n", dev, (uint32)*data, PC); + break; + case DATAI: + sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAI %06o\n", dev, (uint32)*data); + break; + case DATAO: + sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAO %06o\n", dev, (uint32)*data); + if (*data == 01365) { + dte_unit[0].STATUS |= DTE_SEC|DTE_10ER; + dte_unit[0].STATUS &= ~(DTE_10DB); + break; + } + dte_unit[0].CNT = (*data & (DTE_TO10IB|DTE_TO10BC)); + dte_unit[0].STATUS |= DTE_TO11; + sim_activate(&dte_unit[0], 10); + break; + } + return SCPE_OK; +} + +/* Handle KL style interrupt vectors */ +t_addr +dte_devirq(uint32 dev, t_addr addr) { + return 0142; +} + +/* Handle TO11 interrupts */ +t_stat dte_svc (UNIT *uptr) +{ + /* Did the 10 knock? */ + if (uptr->STATUS & DTE_11DB) { + /* If in secondary mode, do that protocol */ + if (uptr->STATUS & DTE_SEC) + dte_second(uptr); + else + dte_primary(uptr); /* Retrieve data */ + } else if (uptr->STATUS & DTE_TO11) { + /* Does 10 want us to send it what we have? */ + dte_transfer(uptr); + } + return SCPE_OK; +} + +/* Handle secondary protocol */ +void dte_second(UNIT *uptr) { + uint64 word; + int32 ch; + uint32 base = 0; + +#if KI_22BIT +#if KL_ITS + if (!QITS) +#endif + base = eb_ptr; +#endif + /* read command */ + word = M[SEC_DTCMD + base]; +#if KL_ITS + if (word == 0 && QITS && (uptr->STATUS & ITS_ON) != 0) { + dte_its(uptr); + uptr->STATUS &= ~DTE_11DB; + return; + } +#endif + /* Do it */ + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY secondary %012llo\n", word); + switch(word & SEC_CMDMSK) { + default: + case SEC_MONO: /* Ouput character in monitor mode */ + ch = (int32)(word & 0177); + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) { + sim_activate(uptr, 200); + return; + } + if (ch != 0) { + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + cty_out.buff[cty_out.in_ptr] = (char)(word & 0x7f); + cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + sim_activate(&dte_unit[1], 200); + } + M[SEC_DTCHR + base] = ch; + M[SEC_DTMTD + base] = FMASK; + break; + case SEC_SETPRI: +enter_pri: + if (Mem_examine_word(0, 0, &word)) + break; + dte_proc_num = (word >> 24) & 037; + dte_base = dte_proc_num + 1; + dte_off = dte_base + (word & 0177777); + dte_dt10_off = 16; + dte_et10_off = dte_dt10_off + 16; + dte_et11_off = dte_base + 16; + uptr->STATUS &= ~DTE_SEC; + dte_in_ptr = dte_out_ptr = 0; + dte_in_cmd = dte_out_res = 0; + cty_done = 0; + /* Start input process */ + M[SEC_DTCMD + base] = 0; + M[SEC_DTFLG + base] = FMASK; + uptr->STATUS &= ~DTE_11DB; +return; + break; + case SEC_SETDDT: /* Read character from console */ + if (cty_in.in_ptr == cty_in.out_ptr) { + M[SEC_DTF11 + base] = 0; + M[SEC_DTMTI + base] = FMASK; + break; + } + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + M[SEC_DTF11 + base] = 0177 & ch; + M[SEC_DTMTI + base] = FMASK; + break; + case SEC_CLRDDT: /* Clear DDT input mode */ + uptr->STATUS &= ~DTE_MON; + break; + case SEC_MONON: + uptr->STATUS |= DTE_MON; + break; + case SEC_RDSW: /* Read switch register */ + M[SEC_DTSWR + base] = SW; + M[SEC_DTF11 + base] = SW; + break; + + case SEC_PGMCTL: /* Program control: Used by KLDCP */ + switch(word) { + case SEC_ENDPASS: + case SEC_LOOKUP: + case SEC_RDWRD: + case SEC_RDBYT: + break; + case SEC_ESEC: + goto enter_pri; + case SEC_EPRI: + case SEC_ERTM: + break; + } + break; + case SEC_CLKCTL: /* Clock control: Used by KLDCP */ + switch(word) { + case SEC_CLKOFF: + dte_unit[3].STATUS &= ~SEC_CLK; + break; + case SEC_CLKWT: + rtc_wait = (uint16)(M[SEC_DTT11 + base] & 0177777); + /* Fall Through */ + + case SEC_CLKON: + dte_unit[3].STATUS |= SEC_CLK; + rtc_tick = 0; + break; + case SEC_CLKRD: + M[SEC_DTF11+base] = rtc_tick; + break; + } + break; + } + /* Acknowledge command */ + M[SEC_DTCMD + base] = 0; + M[SEC_DTFLG + base] = FMASK; + uptr->STATUS &= ~DTE_11DB; + if (dte_dev.flags & TYPE_RSX20) { + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); + } +} + +#if KL_ITS +/* Process ITS Ioeleven locations */ +void dte_its(UNIT *uptr) { + uint64 word; + char ch; + uint16 data; + int cnt; + int ln; + + /* Check for input Start */ + word = M[ITS_DTEINP]; + if ((word & SMASK) == 0) { + M[ITS_DTEINP] = FMASK; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEINP = %012llo\n", word); + } + /* Check for output Start */ + word = M[ITS_DTEOUT]; + if ((word & SMASK) == 0) { + cnt = word & 017777; + ln = ((word >> 18) & 077) - 1; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word); + while (cnt > 0) { + if (ln < 0) { + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) + return; + if (!Mem_read_byte(0, &data, 1)) + return; + ch = data & 0177; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %x\n", ch); + cty_out.buff[cty_out.in_ptr] = ch; + cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + cnt--; + if (! sim_is_active(&dte_unit[1])) + sim_activate(&dte_unit[1], 50); +#if (NUM_DEVS_TTY > 0) + } else { + struct _buffer *otty = &tty_out[ln]; + if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) + return; + if (!Mem_read_byte(0, &data, 1)) + return; + ch = data & 0177; + sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln); + otty->buff[otty->in_ptr] = ch; + otty->in_ptr = (otty->in_ptr + 1) & 0xff; + cnt--; +#endif + } + } + M[ITS_DTEOUT] = FMASK; + uptr->STATUS |= DTE_11DN; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word); + } + /* Check for line speed */ + word = M[ITS_DTELSP]; + if ((word & SMASK) == 0) { /* Ready? */ + M[ITS_DTELSP] = FMASK; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTELSP = %012llo %012llo\n", word, M[ITS_DTELPR]); + } + dte_input(); + /* Check for output Start */ + word = M[ITS_DTEOST]; + if ((word & SMASK) == 0) { + if (word == 0) + cty_done++; +#if (NUM_DEVS_TTY > 0) + else if (word > 0 && word < tty_desc.lines) { + tty_done[word-1] = 1; + } +#endif + M[ITS_DTEOST] = FMASK; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOST = %012llo\n", word); + } +} +#endif + +/* Handle primary protocol */ +void dte_primary(UNIT *uptr) { + uint64 word, iword; + int s; + int cnt; + struct _dte_queue *in; + uint16 data1, *dp; + + if ((uptr->STATUS & DTE_11DB) == 0) + return; + + /* Check if there is room for another packet */ + if (((dte_in_ptr + 1) & 0x1f) == dte_in_cmd) { + /* If not reschedule ourselves */ + sim_activate(uptr, 100); + return; + } + uptr->STATUS &= ~(DTE_11DB); + clr_interrupt(DTE_DEVNUM); + /* Check status word to see if valid */ + if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word)) { + uint32 base; +error: + base = 0; +#if KI_22BIT +#if KL_ITS + if (!QITS) +#endif + base = eb_ptr; +#endif + /* If we can't read it, go back to secondary */ + M[SEC_DTFLG + base] = FMASK; + uptr->STATUS |= DTE_SEC; + uptr->STATUS &= ~DTE_11DB; + if (dte_dev.flags & TYPE_RSX20) { + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); + } + return; + } + + if ((word & PRI_CMT_QP) == 0) { + goto error; + } + in = &dte_in[dte_in_ptr]; + /* Check if indirect */ + if ((word & PRI_CMT_IP) != 0) { + /* Transfer from 10 */ + if ((uptr->STATUS & DTE_IND) == 0) { + fprintf(stderr, "DTE out of sync\n\r"); + return; + } + /* Get size of transfer */ + if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_CNT, &iword)) + goto error; + sim_debug(DEBUG_EXP, &dte_dev, "DTE: count: %012llo\n", iword); + in->dcnt = (uint16)(iword & 0177777); + /* Read in data */ + dp = &in->data[0]; + for (cnt = in->dcnt; cnt >= 0; cnt --) { + /* Read in data */ + s = Mem_read_byte(0, dp, 0); + if (s == 0) + goto error; + in->sz = s; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o %06o\n", + *dp, *dp >> 8, *dp & 0377, ((*dp & 0377) << 8) | ((*dp >> 8) & 0377)); + dp++; + if (s <= 8) + cnt--; + } + uptr->STATUS &= ~DTE_IND; + dte_in_ptr = (dte_in_ptr + 1) & 0x1f; + } else { + /* Transfer from 10 */ + in->dptr = 0; + in->dcnt = 0; + /* Read in count */ + if (!Mem_read_byte(0, &data1, 0)) + goto error; + in->cnt = data1; + cnt = in->cnt-2; + if (!Mem_read_byte(0, &data1, 0)) + goto error; + in->func = data1; + cnt -= 2; + if (!Mem_read_byte(0, &data1, 0)) + goto error; + in->dev = data1; + cnt -= 2; + if (!Mem_read_byte(0, &data1, 0)) + goto error; + in->spare = data1; + cnt -= 2; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read CMD: %o c=%o f=%o %s d=%o\n", + dte_in_ptr, in->cnt, in->func, + ((in->func & 0377) > PRI_EMLDV)?"***":pri_name[in->func & 0377], in->dev); + dp = &in->data[0]; + for (; cnt > 0; cnt -=2) { + /* Read in data */ + if (!Mem_read_byte(0, dp, 0)) + goto error; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read data: %06o %03o %03o\n", + *dp, *dp >> 8, *dp & 0377); + dp++; + in->dcnt += 2; + } + if (in->func & PRI_IND_FLG) { + uptr->STATUS |= DTE_IND; + in->sdev = in->dcnt = in->data[0]; + word |= PRI_CMT_TOT; + if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) + goto error; + } else { + dte_in_ptr = (dte_in_ptr + 1) & 0x1f; + } + } + word &= ~PRI_CMT_TOT; + if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) + goto error; + uptr->STATUS |= DTE_11DN; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + dte_function(uptr); +} + +/* Process primary protocol packets */ +void +dte_function(UNIT *uptr) +{ + uint16 data1[32]; + int32 ch; + struct _dte_queue *cmd; + int func; + + /* Check if queue is empty */ + while (dte_in_cmd != dte_in_ptr) { + if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n", + dte_out_res, dte_out_ptr); + return; + } + cmd = &dte_in[dte_in_cmd]; + func = cmd->func & 0377; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: func %o %02o %s dev %o cnt %d dcnt %d\n", + dte_in_cmd, func, (func > PRI_EMLDV) ? "***" : pri_name[func], + cmd->dev, cmd->dcnt, cmd->dptr ); + switch (func) { + case PRI_EM2EI: /* Initial message to 11 */ + data1[0] = PRI_CTYDV; + if (dte_queue(PRI_EM2TI, PRI_EMCTY, 1, data1) == 0) + return; +#if (NUM_DEVS_LP > 0) + data1[0] = 140; + if (dte_queue(PRI_EMHLA, PRI_EMLPT, 1, data1) == 0) + return; +#endif + data1[0] = 0; + if (dte_queue(PRI_EMAKA, PRI_EMCLK, 1, data1) == 0) + return; + break; + + case PRI_EM2TI: /* Replay to initial message. */ + case PRI_EMACK: /* Acknowledge line */ + /* Should never get these */ + break; + case PRI_EMHDR: /* Here is date and time */ + /* Ignore this function */ + break; + case PRI_EMRDT: /* Request Date/Time */ + { + time_t t = time(NULL); + struct tm *tm = localtime(&t); + int yr = tm->tm_year + 1900; + int tim = (((tm->tm_hour * 60) + tm->tm_min) * 60) + + tm->tm_sec; + data1[0] = 0177777; + data1[1] = ((yr & 0377) << 8) | ((yr >> 8) & 0377); + data1[2] = (tm->tm_mon) + ((tm->tm_mday - 1) << 8); + data1[3] = (((tm->tm_wday + 6) % 7)) + + (tm->tm_isdst ? 0200 << 8 : 0); + tim >>= 1; + data1[4] = ((tim & 0377) << 8) | ((tim >> 8) & 0377); + if (dte_queue(PRI_EMHDR | PRI_IND_FLG, PRI_EMCLK, 6, data1) == 0) + return; + } + break; + + case PRI_EMSTR: /* String data */ + +#if (NUM_DEVS_LP > 0) + /* Handle printer data */ + if (cmd->dev == PRI_EMLPT) { + if (!sim_is_active(&lpt_unit)) + sim_activate(&lpt_unit, 1000); + while (cmd->dptr < cmd->dcnt) { + if (((lpt_queue.in_ptr + 1) & 0xff) == lpt_queue.out_ptr) + return; + ch = (int32)(cmd->data[cmd->dptr >> 1]); + if ((cmd->dptr & 1) == 0) + ch >>= 8; + ch &= 0177; + lpt_queue.buff[lpt_queue.in_ptr] = ch; + lpt_queue.in_ptr = (lpt_queue.in_ptr + 1) & 0xff; + cmd->dptr++; + } + if (cmd->dptr != cmd->dcnt) + return; + break; + } +#endif + +#if (NUM_DEVS_TTY > 0) + /* Handle terminal data */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377); + struct _buffer *otty; + if (ln == PRI_CTYDV) + goto cty; + ln -= 2; + if (ln > 0 && ln >= tty_desc.lines) + break; + otty = &tty_out[ln]; + if (cmd->sz > 8) + cmd->dcnt += cmd->dcnt; + while (cmd->dptr < cmd->dcnt) { + if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) + return; + ch = (int32)(cmd->data[cmd->dptr >> 1]); + if ((cmd->dptr & 1) == 0) + ch >>= 8; + ch &= 0177; + if (ch != 0) { + sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %o %d\n", ch, ln); + otty->buff[otty->in_ptr] = ch; + otty->in_ptr = (otty->in_ptr + 1) & 0xff; + } + cmd->dptr++; + } + if (cmd->dptr != cmd->dcnt) + return; + break; + } +#endif + /* Fall through */ + case PRI_EMSNA: /* Send all (ttys) */ + if (cmd->dev != PRI_EMCTY) + break; +cty: + sim_activate(&dte_unit[1], 100); + data1[0] = 0; + if (cmd->sz > 8) + cmd->dcnt += cmd->dcnt; + while (cmd->dptr < cmd->dcnt) { + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) + return; + ch = (int32)(cmd->data[cmd->dptr >> 1]); + if ((cmd->dptr & 1) == 0) + ch >>= 8; + ch &= 0177; + if (ch != 0) { + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); + cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + } + cmd->dptr++; + } + if (cmd->dptr != cmd->dcnt) + return; + break; + + case PRI_EMLNC: /* Line-Char */ + if (cmd->dev == PRI_EMDLS) { + sim_activate(&dte_unit[1], 100); + while (cmd->dptr < cmd->dcnt) { + int ln; + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) + return; + ch = (int32)(cmd->data[cmd->dptr >> 1]); + ln = (ch >> 8); + ch &= 0177; + if (ch != 0 && ln == 0) { + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); + cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + } + cmd->dptr+=2; + } + if (cmd->dptr != cmd->dcnt) + return; + } + break; + + case PRI_EMRDS: /* Request device status */ +#if (NUM_DEVS_LP > 0) + if (cmd->dev == PRI_EMLPT) { + data1[0] = 0; + if (dte_queue(PRI_EMHDS, PRI_EMLPT, 1, data1) == 0) + return; + } +#endif + if (cmd->dev == PRI_EMCTY) { + data1[0] = 0; + if (dte_queue(PRI_EMHDS, PRI_EMCTY, 1, data1) == 0) + return; + } + if (cmd->dev == PRI_EMDH1) { + data1[0] = 0; + if (dte_queue(PRI_EMHDS, PRI_EMDH1, 1, data1) == 0) + return; + } + break; + + case PRI_EMHDS: /* Here is device status */ + break; + +#if (NUM_DEVS_TTY > 0) + case PRI_EMFLO: /* Flush output */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 2;; + tty_out[ln].in_ptr = tty_out[ln].out_ptr = 0; + } + break; + case PRI_EMDSC: /* Dataset connect */ + break; + case PRI_EMHUD: /* Hang up dataset */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 2; + TMLN *lp = &tty_ldsc[ln]; + tmxr_linemsg (lp, "\r\nLine Hangup\r\n"); + tmxr_reset_ln(lp); + tty_connect[ln] = 0; + } + break; + case PRI_EMXOF: /* XOFF line */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 2; + tty_ldsc[ln].rcve = 0; + } + break; + case PRI_EMXON: /* XON line */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 2; + tty_ldsc[ln].rcve = 1; + } + break; + case PRI_EMHLS: /* Here is line speeds */ + if ((cmd->dev & 0377) == PRI_EMDLS) { + int ln = ((cmd->sdev >> 8) & 0377) - 2; + } + break; + case PRI_EMHLA: /* Here is line allocation */ + case PRI_EMRBI: /* Reboot information */ + case PRI_EMAKA: /* Ack ALL */ + case PRI_EMTDO: /* Turn device On/Off */ + break; + case PRI_EMEDR: /* Enable/Disable line */ + if (cmd->dev == PRI_EMDH1) { + /* Zero means enable, no-zero means disable */ + tty_enable = !cmd->data[0]; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY enable %x\n", tty_enable); + if (tty_enable) { + sim_activate(&tty_unit[0], 1000); + sim_activate(&tty_unit[1], 1000); + } else { + sim_cancel(&tty_unit[0]); + sim_cancel(&tty_unit[1]); + } + } + break; +#endif + case PRI_EMLDR: /* Load LP RAM */ + case PRI_EMLDV: /* Load LP VFU */ + default: + break; + } + /* Mark command as finished */ + cmd->cnt = 0; + dte_in_cmd = (dte_in_cmd + 1) & 0x1F; + } +} + +/* + * Handle primary protocol, + * Send to 10 when requested. + */ +void dte_transfer(UNIT *uptr) { + uint16 cnt; + uint16 scnt; + struct _dte_queue *out; + uint16 *dp; + + /* Check if Queue empty */ + if (dte_out_res == dte_out_ptr) + return; + + out = &dte_out[dte_out_ptr]; + uptr->STATUS &= ~DTE_TO11; + clr_interrupt(DTE_DEVNUM); + + /* Compute how much 10 wants us to send */ + scnt = ((uptr->CNT ^ DTE_TO10BC) + 1) & DTE_TO10BC; + /* Check if indirect */ + if ((uptr->STATUS & DTE_SIND) != 0) { + /* Transfer indirect */ + cnt = out->dcnt; + dp = &out->data[0]; + if (cnt > scnt) /* Only send as much as we are allowed */ + cnt = scnt; + for (; cnt > 0; cnt -= 2) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Send Idata: %06o %03o %03o\n", + *dp, *dp >> 8, *dp & 0377); + if (Mem_write_byte(0, dp) == 0) + goto error; + dp++; + } + uptr->STATUS &= ~DTE_SIND; + } else { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d send CMD: %o %o %o\n", + dte_out_ptr, dte_out_res, out->cnt, out->func, out->dev); + /* Get size of packet */ + cnt = out->cnt; + if ((out->func & PRI_IND_FLG) == 0) + cnt += out->dcnt; + /* If it will not fit, request indirect */ + if (cnt > scnt) { /* If not enough space request indirect */ + out->func |= PRI_IND_FLG; + cnt = scnt; + } + /* Write out header */ + if (!Mem_write_byte(0, &cnt)) + goto error; + if (!Mem_write_byte(0, &out->func)) + goto error; + cnt -= 2; + if (!Mem_write_byte(0, &out->dev)) + goto error; + cnt -= 2; + if (!Mem_write_byte(0, &out->spare)) + goto error; + cnt -= 2; + if (out->func & PRI_IND_FLG) { +sim_debug(DEBUG_DATA, &dte_dev, "DTE: Indirect %o %o\n", cnt, out->dcnt); + if (!Mem_write_byte(0, &out->dcnt)) + goto error; + uptr->STATUS |= DTE_SIND; + goto done; + } + cnt -= 2; + dp = &out->data[0]; + for (; cnt > 0; cnt -= 2) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Send data: %06o %03o %03o\n", + *dp, *dp >> 8, *dp & 0377); + if (!Mem_write_byte(0, dp)) + goto error; + dp++; + } + } + out->cnt = 0; + dte_out_ptr = (dte_out_ptr + 1) & 0x1f; +done: + uptr->STATUS |= DTE_10DN; + set_interrupt(DTE_DEVNUM, uptr->STATUS); +error: + return; +} + +/* Process input from CTY and TTY's to 10. */ +void +dte_input() +{ + uint16 data1; + uint16 dataq[32]; + int n; + int ln; + int save_ptr; + char ch; + UNIT *uptr = &dte_unit[0]; + +#if KL_ITS + if (QITS && (uptr->STATUS & ITS_ON) != 0) { + uint64 word; + word = M[ITS_DTEODN]; + /* Check if ready for output done */ + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo %d\n", word, cty_done); + if ((word & SMASK) != 0) { + if (cty_done) { + word = 64LL; + cty_done--; +#if (NUM_DEVS_TTY > 0) + } else { + for (ln = 0; ln < tty_desc.lines; ln++) { + if (tty_done[ln]) { + word = (((uint64)ln + 1) << 18); + word |=(tty_connect[ln])? 64: 1; + tty_done[ln] = 0; + break; + } + } +#endif + } + if ((word & SMASK) == 0) { + M[ITS_DTEODN] = word; + /* Tell 10 something is ready */ + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo\n", word); + } + } + /* Check if ready for any input */ + word = M[ITS_DTETYI]; + if ((word & SMASK) != 0) { + /* CTY first. */ + if (cty_in.in_ptr != cty_in.out_ptr) { + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + word = (uint64)ch; +#if (NUM_DEVS_TTY > 0) + } else { + ln = uptr->CNT; + while ((word & SMASK) != 0) { + if (tty_in[ln].in_ptr != tty_in[ln].out_ptr) { + ch = tty_in[ln].buff[tty_in[ln].out_ptr]; + tty_in[ln].out_ptr = (tty_in[ln].out_ptr + 1) & 0xff; + word = ((uint64)(ln+1) << 18) | (uint64)ch; + } + ln++; + if (ln >= tty_desc.lines) + ln = 0; + if (ln == uptr->CNT) + break; + } + uptr->CNT = ln; +#endif + } + if ((word & SMASK) == 0) { + M[ITS_DTETYI] = word; + /* Tell 10 something is ready */ + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); + } + } +#if (NUM_DEVS_TTY > 0) + /* Check ready for hang up message */ + word = M[ITS_DTEHNG]; + if ((word & SMASK) != 0) { + for (ln = 0; ln < tty_desc.lines; ln++) { + if (tty_connect[ln] != tty_ldsc[ln].conn) { + if (tty_ldsc[ln].conn) + word = 015500 + ln + 1; + else + word = ln + 1; + tty_connect[ln] = tty_ldsc[ln].conn; + tty_done[ln] = tty_ldsc[ln].conn; + break; + } + } + /* Tell 10 something is ready */ + if ((word & SMASK) == 0) { + M[ITS_DTEHNG] = word; + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEHNG = %012llo\n", word); + } + } +#endif + } else +#endif + if ((uptr->STATUS & DTE_SEC) == 0) { + /* Check if CTY done with input */ + if (cty_done) { + data1 = PRI_CTYDV; + if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, &data1) == 0) + return; + cty_done--; + } + /* Grab a chunck of input from CTY if any */ + n = 0; + save_ptr = cty_in.out_ptr; + while (cty_in.in_ptr != cty_in.out_ptr && n < 32) { + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY recieve %02x\n", ch); + dataq[n++] = (PRI_CTYDV << 8) | ch; + } + if (n > 0 && dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) { + /* Restore the input pointer */ + cty_in.out_ptr = save_ptr; + return; + } +#if (NUM_DEVS_TTY > 0) + n = 0; + /* While we have room for one more packet, grab as much input as we can */ + for (ln = 0; ln < tty_desc.lines && ((dte_out_res + 1) & 0x1f) != dte_out_ptr; ln++) { + while (tty_in[ln].in_ptr != tty_in[ln].out_ptr) { + ch = tty_in[ln].buff[tty_in[ln].out_ptr]; + tty_in[ln].out_ptr = (tty_in[ln].out_ptr + 1) & 0xff; + dataq[n++] = ((ln + 2) << 8) | ch; + if (n == 32) { + if (dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) + return; + n = 0; + continue; + } + } + } + if (n > 0 && dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) + return; + n = 0; + for (ln = 0; ln < tty_desc.lines; ln++) { + if (tty_connect[ln] != tty_ldsc[ln].conn) { + data1 = ln + 2; + if (tty_ldsc[ln].conn) + n = PRI_EMDSC; + else + n = PRI_EMHUD; + if (dte_queue(n, PRI_EMDLS, 1, &data1) == 0) + return; + tty_connect[ln] = tty_ldsc[ln].conn; + } + if (tty_done[ln]) { + data1 = ln + 2; + if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, &data1) == 0) + return; + tty_done[ln] = 0; + } + } +#endif + } +} + +/* + * Queue up a packet to send to 10. + */ +int +dte_queue(int func, int dev, int dcnt, uint16 *data) +{ + uint16 *dp; + struct _dte_queue *out; + + /* Check if room in queue for this packet. */ + if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) { + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d out full\n", dte_out_res, dte_out_ptr); + return 0; + } + out = &dte_out[dte_out_res]; + out->cnt = 10; + out->func = func; + out->dev = dev; + out->dcnt = (dcnt-1)*2; + out->spare = 0; + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d queue resp: %o %o %s %o\n", + dte_out_ptr, dte_out_res, out->cnt, out->func, + (out->func > PRI_EMLDV)? "***":pri_name[out->func], out->dev); + for (dp = &out->data[0]; dcnt > 0; dcnt--) { + *dp++ = *data++; + } + /* Advance pointer to next function */ + dte_out_res = (dte_out_res + 1) & 0x1f; + return 1; +} + + +/* + * If anything in queue, start a transfer, if one is not already + * pending. + */ +int +dte_start(UNIT *uptr) +{ + uint64 word; + int dcnt; + + /* Check if queue empty */ + if (dte_out_ptr == dte_out_res) + return 1; + + /* If there is interrupt pending, just return */ + if ((uptr->STATUS & (DTE_IND|DTE_10DB|DTE_11DB)) != 0) + return 1; + if (Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word)) { +error: + /* If we can't read it, go back to secondary */ + uptr->STATUS |= DTE_SEC|DTE_10ER; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + return 0; + } + /* Bump count of messages sent */ + word = (word & ~(PRI_CMT_10IC|PRI_CMT_IP)) | ((word + 0400) & PRI_CMT_10IC); + if ((uptr->STATUS & DTE_SIND) != 0) + word |= PRI_CMT_IP; + if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) + goto error; + dcnt = dte_out[dte_out_ptr].cnt; + if ((dte_out[dte_out_ptr].func & PRI_IND_FLG) == 0) + dcnt += dte_out[dte_out_ptr].dcnt; + /* Tell 10 something is ready */ + word = (uint64)dcnt; + if ((uptr->STATUS & DTE_SIND) != 0) { + word = (uint64)(dte_out[dte_out_ptr].dcnt); + } + if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_CNT, &word)) + goto error; + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + return 1; +} + + +/* Check for input from CTY and put on queue. */ +t_stat dtei_svc (UNIT *uptr) +{ + int32 ch; + uint32 base = 0; + UNIT *optr = &dte_unit[0]; + +#if KI_22BIT +#if KL_ITS + if (!QITS) +#endif + base = eb_ptr; +#endif + sim_clock_coschedule (uptr, tmxr_poll); + dte_input(); + if ((optr->STATUS & (DTE_SEC)) == 0) { + dte_function(uptr); /* Process queue */ + dte_start(optr); + } + + + /* If we have room see if any new lines */ + while (((cty_in.in_ptr + 1) & 0xff) != cty_in.out_ptr) { + ch = sim_poll_kbd (); + if (ch & SCPE_KFLAG) { + ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (uptr->flags)); + cty_in.buff[cty_in.in_ptr] =ch & 0377; + cty_in.in_ptr = (cty_in.in_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %o '%c'\n", ch, + ((ch > 040 && ch < 0177)? ch: '.')); + } else + break; + } + + /* If Monitor input, place in buffer */ + if ((optr->STATUS & (DTE_SEC|DTE_MON)) == (DTE_SEC|DTE_MON) && + cty_in.in_ptr != cty_in.out_ptr && M[SEC_DTMTI + base] == 0) { + ch = cty_in.buff[cty_in.out_ptr]; + cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + M[SEC_DTF11 + base] = ch; + M[SEC_DTMTI + base] = FMASK; + if (dte_dev.flags & TYPE_RSX20) { + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); + } + } + return SCPE_OK; +} + +/* Handle output of characters to CTY. Started whenever there is output pending */ +t_stat dteo_svc (UNIT *uptr) +{ + uint32 base = 0; + UNIT *optr = &dte_unit[0]; + +#if KI_22BIT +#if KL_ITS + if (!QITS) +#endif + base = eb_ptr; +#endif + /* Flush out any pending CTY output */ + while(cty_out.in_ptr != cty_out.out_ptr) { + char ch = cty_out.buff[cty_out.out_ptr]; + if (ch != 0) { + if (sim_putchar(ch) != SCPE_OK) { + sim_activate(uptr, 1000); + return SCPE_OK;; + } + } + cty_out.out_ptr = (cty_out.out_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY outch %o '%c'\n", ch, + ((ch > 040 && ch < 0177)? ch: '.')); + } + cty_done++; + dte_input(); + return SCPE_OK; +} + + +/* Handle FE timer interrupts. And keepalive counts */ +t_stat +dtertc_srv(UNIT * uptr) +{ + UNIT *optr = &dte_unit[0]; + + sim_activate_after(uptr, 1000000/rtc_tps); + /* Check if clock requested */ + if (uptr->STATUS & SEC_CLK) { + rtc_tick++; + if (rtc_wait != 0) { + rtc_wait--; + } else { + UNIT *optr = &dte_unit[0]; + uint32 base = 0; +#if KI_22BIT + base = eb_ptr; +#endif + /* Set timer flag */ + M[SEC_DTCLK + base] = FMASK; + optr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, optr->STATUS); + sim_debug(DEBUG_EXP, &dte_dev, "CTY tick %x %x %06o\n", + rtc_tick, rtc_wait, optr->STATUS); + } + } +#if KL_ITS + /* Check if Timesharing is running */ + if (QITS) { + uint64 word; + + word = (M[ITS_DTECHK] + 1) & FMASK; + if (word == 0) { + optr->STATUS |= ITS_ON; + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS ON\n"); + sim_activate(&tty_unit[0], 1000); + sim_activate(&tty_unit[1], 1000); + } else if (word >= (15 * 60)) { + optr->STATUS &= ~ITS_ON; + word = 15 * 60; + sim_cancel(&tty_unit[0]); + sim_cancel(&tty_unit[1]); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS OFF\n"); + } + M[ITS_DTECHK] = word; + } else +#endif + + /* Update out keep alive timer if in secondary protocol */ + if ((optr->STATUS & DTE_SEC) == 0) { + int addr = 0144 + eb_ptr; + uint64 word; + + (void)Mem_examine_word(0, dte_et11_off + PRI_CMTW_STS, &word); + addr = (M[addr+1] + dte_off + PRI_CMTW_KAC) & RMASK; + word = M[addr]; + word = (word + 1) & FMASK; + M[addr] = word; + sim_debug(DEBUG_EXP, &dte_dev, "CTY keepalive %06o %012llo %06o\n", + addr, word, optr->STATUS); + } + + return SCPE_OK; +} + + +t_stat dte_reset (DEVICE *dptr) +{ + dte_unit[0].STATUS = DTE_SEC; + dte_unit[1].STATUS = 0; + dte_unit[2].STATUS = 0; + dte_unit[3].STATUS = 0; + cty_done = 0; + sim_rtcn_init_unit (&dte_unit[3], 1000, TMR_RTC); + sim_activate(&dte_unit[3], 1000); + sim_activate(&dte_unit[2], 1000); + return SCPE_OK; +} + + +t_stat +dte_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + DEVICE *dptr; + dptr = find_dev_from_unit (uptr); + if (dptr == NULL) + return SCPE_IERR; + dptr->flags &= ~DEV_M_OS; + dptr->flags |= val; + return SCPE_OK; +} + +t_stat +dte_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + DEVICE *dptr; + + if (uptr == NULL) + return SCPE_IERR; + + dptr = find_dev_from_unit(uptr); + if (dptr == NULL) + return SCPE_IERR; + fprintf (st, "%s", (dptr->flags & TYPE_RSX20) ? "RSX20" : "RSX10"); + return SCPE_OK; +} + + +/* Stop operating system */ + +t_stat dte_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + M[CTY_SWITCH] = 1; /* tell OS to stop */ + return SCPE_OK; +} + +t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + dte_unit[0].flags = (dte_unit[0].flags & ~TT_MODE) | val; + return SCPE_OK; +} + +t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "To stop the cpu use the command:\n\n"); +fprintf (st, " sim> SET CTY STOP\n\n"); +fprintf (st, "This will write a 1 to location %03o, causing TOPS10 to stop\n\n", CTY_SWITCH); +fprintf (st, "The additional terminals can be set to one of four modes: UC, 7P, 7B, or 8B.\n\n"); +fprintf (st, " mode input characters output characters\n\n"); +fprintf (st, " UC lower case converted lower case converted to upper case,\n"); +fprintf (st, " to upper case, high-order bit cleared,\n"); +fprintf (st, " high-order bit cleared non-printing characters suppressed\n"); +fprintf (st, " 7P high-order bit cleared high-order bit cleared,\n"); +fprintf (st, " non-printing characters suppressed\n"); +fprintf (st, " 7B high-order bit cleared high-order bit cleared\n"); +fprintf (st, " 8B no changes no changes\n\n"); +fprintf (st, "The default mode is 7P. In addition, each line can be configured to\n"); +fprintf (st, "behave as though it was attached to a dataset, or hardwired to a terminal:\n\n"); +fprint_reg_help (st, &dte_dev); +return SCPE_OK; +} + +const char *dte_description (DEVICE *dptr) +{ + return "Console TTY Line"; +} + + +#if (NUM_DEVS_LP > 0) + +void +lpt_printline(UNIT *uptr, int nl) { + int trim = 0; + uint16 data1 = 1; + /* Trim off trailing blanks */ + while (uptr->COL >= 0 && lpt_buffer[uptr->POS - 1] == ' ') { + uptr->COL--; + uptr->POS--; + trim = 1; + } + lpt_buffer[uptr->POS] = '\0'; + sim_debug(DEBUG_DETAIL, &lpt_dev, "LP output %d %d [%s]\n", uptr->COL, nl, lpt_buffer); + /* Stick a carraige return and linefeed as needed */ + if (uptr->COL != 0 || trim) + lpt_buffer[uptr->POS++] = '\r'; + if (nl != 0) { + lpt_buffer[uptr->POS++] = '\n'; + uptr->LINE++; + } + if (nl > 0 && uptr->LINE >= ((int32)uptr->capac - MARGIN)) { + lpt_buffer[uptr->POS++] = '\f'; + uptr->LINE = 0; + } else if (nl < 0 && uptr->LINE >= (int32)uptr->capac) { + uptr->LINE = 0; + } + + sim_fwrite(&lpt_buffer, 1, uptr->POS, uptr->fileref); + uptr->pos += uptr->POS; + uptr->COL = 0; + uptr->POS = 0; + return; +} + + +/* Unit service */ +void +lpt_output(UNIT *uptr, char c) { + + if (c == 0) + return; + if (uptr->COL == 132) + lpt_printline(uptr, 1); + if ((uptr->flags & UNIT_UC) && (c & 0140) == 0140) + c &= 0137; + else if (c >= 040 && c < 0177) { + lpt_buffer[uptr->POS++] = c; + uptr->COL++; + } + return; +} + +t_stat lpt_svc (UNIT *uptr) +{ + char c; + uint16 data1 = 0; + + if ((uptr->flags & UNIT_ATT) == 0) + return SCPE_OK; + + while (((lpt_queue.out_ptr + 1) & 0xff) != lpt_queue.in_ptr) { + c = lpt_queue.buff[lpt_queue.out_ptr]; + lpt_queue.out_ptr = (lpt_queue.out_ptr + 1) & 0xff; + if (c < 040) { /* Control character */ + switch(c) { + case 011: /* Horizontal tab, space to 8'th column */ + lpt_output(uptr, ' '); + while ((uptr->COL & 07) != 0) + lpt_output(uptr, ' '); + break; + case 015: /* Carriage return, print line */ + lpt_printline(uptr, 0); + break; + case 012: /* Line feed, print line, space one line */ + lpt_printline(uptr, 1); + break; + case 014: /* Form feed, skip to top of page */ + lpt_printline(uptr, 0); + sim_fwrite("\014", 1, 1, uptr->fileref); + uptr->pos++; + uptr->LINE = 0; + break; + case 013: /* Vertical tab, Skip mod 20 */ + lpt_printline(uptr, 1); + while((uptr->LINE % 20) != 0) { + sim_fwrite("\r\n", 1, 2, uptr->fileref); + uptr->pos+=2; + uptr->LINE++; + } + break; + case 020: /* Skip half page */ + lpt_printline(uptr, 1); + while((uptr->LINE % 30) != 0) { + sim_fwrite("\r\n", 1, 2, uptr->fileref); + uptr->pos+=2; + uptr->LINE++; + } + break; + case 021: /* Skip even lines */ + lpt_printline(uptr, 1); + while((uptr->LINE % 2) != 0) { + sim_fwrite("\r\n", 1, 2, uptr->fileref); + uptr->pos+=2; + uptr->LINE++; + } + break; + case 022: /* Skip triple lines */ + lpt_printline(uptr, 1); + while((uptr->LINE % 3) != 0) { + sim_fwrite("\r\n", 1, 2, uptr->fileref); + uptr->pos+=2; + uptr->LINE++; + } + break; + case 023: /* Skip one line */ + lpt_printline(uptr, -1); + break; + default: /* Ignore */ + break; + } + } else { + sim_debug(DEBUG_DETAIL, &lpt_dev, "LP deque %02x '%c'\n", c, c); + lpt_output(uptr, c); + } + } + if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, &data1) == 0) + sim_activate(uptr, 1000); + return SCPE_OK; +} + +/* Reset routine */ + +t_stat lpt_reset (DEVICE *dptr) +{ + UNIT *uptr = &lpt_unit; + uptr->POS = 0; + uptr->COL = 0; + uptr->LINE = 1; + sim_cancel (&lpt_unit); /* deactivate unit */ + return SCPE_OK; +} + +/* Attach routine */ + +t_stat lpt_attach (UNIT *uptr, CONST char *cptr) +{ + return attach_unit (uptr, cptr); +} + +/* Detach routine */ + +t_stat lpt_detach (UNIT *uptr) +{ + return detach_unit (uptr); +} + +/* + * Line printer routines + */ + +t_stat +lpt_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + t_value i; + t_stat r; + if (cptr == NULL) + return SCPE_ARG; + if (uptr == NULL) + return SCPE_IERR; + i = get_uint (cptr, 10, 100, &r); + if (r != SCPE_OK) + return SCPE_ARG; + uptr->capac = (t_addr)i; + uptr->LINE = 0; + return SCPE_OK; +} + +t_stat +lpt_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc) +{ + if (uptr == NULL) + return SCPE_IERR; + fprintf(st, "linesperpage=%d", uptr->capac); + return SCPE_OK; +} + +t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "Line Printer (LPT)\n\n"); +fprintf (st, "The line printer (LPT) writes data to a disk file. The POS register specifies\n"); +fprintf (st, "the number of the next data item to be written. Thus, by changing POS, the\n"); +fprintf (st, "user can backspace or advance the printer.\n"); +fprintf (st, "The Line printer can be configured to any number of lines per page with the:\n"); +fprintf (st, " sim> SET %s0 LINESPERPAGE=n\n\n", dptr->name); +fprintf (st, "The default is 66 lines per page.\n\n"); +fprintf (st, "The device address of the Line printer can be changed\n"); +fprintf (st, " sim> SET %s0 DEV=n\n\n", dptr->name); +fprint_set_help (st, dptr); +fprint_show_help (st, dptr); +fprint_reg_help (st, dptr); +return SCPE_OK; +} + +const char *lpt_description (DEVICE *dptr) +{ + return "LPT0 line printer" ; +} + +#endif + +#if (NUM_DEVS_TTY > 0) + +/* Unit service */ +t_stat ttyi_svc (UNIT *uptr) +{ + int32 ln; + TMLN *lp; + int flg; + + if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; + + sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */ + + /* If we have room see if any new lines */ + ln = tmxr_poll_conn (&tty_desc); /* look for connect */ + if (ln >= 0) { + tty_ldsc[ln].rcve = 1; + sim_debug(DEBUG_DETAIL, &tty_dev, "TTY line connect %d\n", ln); + } + + tmxr_poll_tx(&tty_desc); + tmxr_poll_rx(&tty_desc); + + /* Scan each line for input */ + for (ln = 0; ln < tty_desc.lines; ln++) { + struct _buffer *iptr = &tty_in[ln]; + lp = &tty_ldsc[ln]; + if (lp->conn == 0) + continue; + flg = 1; + while (flg && ((iptr->in_ptr + 1) & 0xff) != iptr->out_ptr) { + /* Spool up as much as we have room for */ + int32 ch = tmxr_getc_ln(lp); + if ((ch & TMXR_VALID) != 0) { + ch = sim_tt_inpcvt (ch, TT_GET_MODE(tty_unit[0].flags) | TTUF_KSR); + iptr->buff[iptr->in_ptr] = ch & 0377; + iptr->in_ptr = (iptr->in_ptr + 1) & 0xff; + sim_debug(DEBUG_DETAIL, &tty_dev, "TTY recieve %d: %o\n", ln, ch); + } else + flg = 0; + } + } + + return SCPE_OK; +} + +/* Output whatever we can */ +t_stat ttyo_svc (UNIT *uptr) +{ + t_stat r; + int32 ln; + int n = 0; + TMLN *lp; + + if ((tty_unit[0].flags & UNIT_ATT) == 0) /* attached? */ + return SCPE_OK; + + sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */ + + for (ln = 0; ln < tty_desc.lines; ln++) { + struct _buffer *optr = &tty_out[ln]; + lp = &tty_ldsc[ln]; + if (lp->conn == 0) + continue; + if (optr->out_ptr == optr->in_ptr) + continue; + while (optr->out_ptr != optr->in_ptr) { + int32 ch = optr->buff[optr->out_ptr]; + ch = sim_tt_outcvt(ch, TT_GET_MODE (tty_unit[0].flags) | TTUF_KSR); + sim_debug(DEBUG_DATA, &tty_dev, "TTY: %d output %o\n", ln, ch); + r = tmxr_putc_ln (lp, ch); + if (r == SCPE_OK) + optr->out_ptr = (optr->out_ptr + 1) & 0xff; + else if (r == SCPE_LOST) { + optr->out_ptr = optr->in_ptr = 0; + continue; + } else + continue; + } + tty_done[ln] = 1; + } + return SCPE_OK; +} + +/* Reset routine */ + +t_stat tty_reset (DEVICE *dptr) +{ + return SCPE_OK; +} + + +/* SET LINES processor */ + +t_stat tty_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + int32 newln, i, t; + t_stat r; + + if (cptr == NULL) + return SCPE_ARG; + newln = (int32) get_uint (cptr, 10, NUM_LINES_TTY, &r); + if ((r != SCPE_OK) || (newln == tty_desc.lines)) + return r; + if ((newln == 0) || (newln >= NUM_LINES_TTY) || (newln % 16) != 0) + return SCPE_ARG; + if (newln < tty_desc.lines) { + for (i = newln, t = 0; i < tty_desc.lines; i++) + t = t | tty_ldsc[i].conn; + if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) + return SCPE_OK; + for (i = newln; i < tty_desc.lines; i++) { + if (tty_ldsc[i].conn) { + tmxr_linemsg (&tty_ldsc[i], "\r\nOperator disconnected line\r\n"); + tmxr_send_buffered_data (&tty_ldsc[i]); + } + tmxr_detach_ln (&tty_ldsc[i]); /* completely reset line */ + } + } + if (tty_desc.lines < newln) + memset (tty_ldsc + tty_desc.lines, 0, sizeof(*tty_ldsc)*(newln-tty_desc.lines)); + tty_desc.lines = newln; + return tty_reset (&tty_dev); /* setup lines and auto config */ +} + +/* SET LOG processor */ + +t_stat tty_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + t_stat r; + char gbuf[CBUFSIZE]; + int32 ln; + + if (cptr == NULL) + return SCPE_ARG; + cptr = get_glyph (cptr, gbuf, '='); + if ((cptr == NULL) || (*cptr == 0) || (gbuf[0] == 0)) + return SCPE_ARG; + ln = (int32) get_uint (gbuf, 10, tty_desc.lines, &r); + if ((r != SCPE_OK) || (ln >= tty_desc.lines)) + return SCPE_ARG; + return tmxr_set_log (NULL, ln, cptr, desc); +} + +/* SET NOLOG processor */ + +t_stat tty_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + t_stat r; + int32 ln; + + if (cptr == NULL) + return SCPE_ARG; + ln = (int32) get_uint (cptr, 10, tty_desc.lines, &r); + if ((r != SCPE_OK) || (ln >= tty_desc.lines)) + return SCPE_ARG; + return tmxr_set_nolog (NULL, ln, NULL, desc); +} + +/* SHOW LOG processor */ + +t_stat tty_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + int32 i; + + for (i = 0; i < tty_desc.lines; i++) { + fprintf (st, "line %d: ", i); + tmxr_show_log (st, NULL, i, desc); + fprintf (st, "\n"); + } + return SCPE_OK; +} + + +/* Attach routine */ + +t_stat tty_attach (UNIT *uptr, CONST char *cptr) +{ +t_stat reason; + +reason = tmxr_attach (&tty_desc, uptr, cptr); +if (reason != SCPE_OK) + return reason; +sim_activate (uptr, tmxr_poll); +return SCPE_OK; +} + +/* Detach routine */ + +t_stat tty_detach (UNIT *uptr) +{ + int32 i; + t_stat reason; +reason = tmxr_detach (&tty_desc, uptr); +for (i = 0; i < tty_desc.lines; i++) + tty_ldsc[i].rcve = 0; +sim_cancel (uptr); +return reason; +} + +t_stat tty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "DC10E Terminal Interfaces\n\n"); +fprintf (st, "The DC10 supported up to 8 blocks of 8 lines. Modem control was on a seperate\n"); +fprintf (st, "line. The simulator supports this by setting modem control to a fixed offset\n"); +fprintf (st, "from the given line. The number of lines is specified with a SET command:\n\n"); +fprintf (st, " sim> SET DC LINES=n set number of additional lines to n [8-32]\n\n"); +fprintf (st, "Lines must be set in multiples of 8.\n"); +fprintf (st, "The default offset for modem lines is 32. This can be changed with\n\n"); +fprintf (st, " sim> SET DC MODEM=n set offset for modem control to n [8-32]\n\n"); +fprintf (st, "Modem control must be set larger then the number of lines\n"); +fprintf (st, "The ATTACH command specifies the port to be used:\n\n"); +tmxr_attach_help (st, dptr, uptr, flag, cptr); +fprintf (st, "The additional terminals can be set to one of four modes: UC, 7P, 7B, or 8B.\n\n"); +fprintf (st, " mode input characters output characters\n\n"); +fprintf (st, " UC lower case converted lower case converted to upper case,\n"); +fprintf (st, " to upper case, high-order bit cleared,\n"); +fprintf (st, " high-order bit cleared non-printing characters suppressed\n"); +fprintf (st, " 7P high-order bit cleared high-order bit cleared,\n"); +fprintf (st, " non-printing characters suppressed\n"); +fprintf (st, " 7B high-order bit cleared high-order bit cleared\n"); +fprintf (st, " 8B no changes no changes\n\n"); +fprintf (st, "The default mode is 7P.\n"); +fprintf (st, "Finally, each line supports output logging. The SET DCn LOG command enables\n"); +fprintf (st, "logging on a line:\n\n"); +fprintf (st, " sim> SET DCn LOG=filename log output of line n to filename\n\n"); +fprintf (st, "The SET DCn NOLOG command disables logging and closes the open log file,\n"); +fprintf (st, "if any.\n\n"); +fprintf (st, "Once DC is attached and the simulator is running, the terminals listen for\n"); +fprintf (st, "connections on the specified port. They assume that the incoming connections\n"); +fprintf (st, "are Telnet connections. The connections remain open until disconnected either\n"); +fprintf (st, "by the Telnet client, a SET DC DISCONNECT command, or a DETACH DC command.\n\n"); +fprintf (st, "Other special commands:\n\n"); +fprintf (st, " sim> SHOW DC CONNECTIONS show current connections\n"); +fprintf (st, " sim> SHOW DC STATISTICS show statistics for active connections\n"); +fprintf (st, " sim> SET DCn DISCONNECT disconnects the specified line.\n"); +fprint_reg_help (st, &tty_dev); +fprintf (st, "\nThe additional terminals do not support save and restore. All open connections\n"); +fprintf (st, "are lost when the simulator shuts down or DC is detached.\n"); +return SCPE_OK; +} + +const char *tty_description (DEVICE *dptr) +{ +return "DC10E asynchronous line interface"; +} + +#endif +#endif diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index 414acf4..de2bc8b 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -1,776 +1,776 @@ -/* kx10_rh.c: RH10/RH20 interace routines. - - Copyright (c) 2015-2019, Richard Cornwell - - 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 - RICHARD CORNWELL 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. - -*/ - -#include "kx10_defs.h" - - -/* CONI Flags */ -#define IADR_ATTN 0000000000040LL /* Interrupt on attention */ -#define IARD_RAE 0000000000100LL /* Interrupt on register access error */ -#define DIB_CBOV 0000000000200LL /* Control bus overrun */ -#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */ -#define CXR_ILC 0000000004000LL /* Illegal function code */ -#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */ -#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */ -#define CCW_COMP_1 0000000040000LL /* Control word written. */ -#define CXR_CHAN_ER 0000000100000LL /* Channel Error */ -#define CXR_EXC 0000000200000LL /* Error in drive transfer */ -#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */ -#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */ -#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */ -#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */ -#define CXR_SD_RAE 0000200000000LL /* Register access error */ -#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */ -#define B22_FLAG 0004000000000LL /* 22 bit channel */ -#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */ -#define CC_CHAN_ACT 0020000000000LL /* Channel in use */ -#define CC_INH 0040000000000LL /* Disconnect channel */ -#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */ -#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */ - -/* RH20 CONI Flags */ -#define RH20_PCR_FULL 0000000000020LL /* Primary command file full */ -#define RH20_ATTN_ENA 0000000000040LL /* Attention enable */ -#define RH20_SCR_FULL 0000000000100LL /* Secondary command full */ -#define RH20_ATTN 0000000000200LL /* Attention */ -#define RH20_MASS_ENA 0000000000400LL /* Mass bus enable */ -#define RH20_DATA_OVR 0000000001000LL /* Data overrun */ -#define RH20_CHAN_RDY 0000000002000LL /* Channel ready to start */ -#define RH20_RAE 0000000004000LL /* Register access error */ -#define RH20_DR_RESP 0000000010000LL /* Drive no response */ -#define RH20_CHAN_ERR 0000000020000LL /* Channel error */ -#define RH20_SHRT_WC 0000000040000LL /* Short word count */ -#define RH20_LONG_WC 0000000100000LL /* Long word count */ -#define RH20_DR_EXC 0000000200000LL /* Exception */ -#define RH20_DATA_PRI 0000000400000LL /* Data parity error */ -#define RH20_SBAR 0000001000000LL /* SBAR set */ -#define RH20_XEND 0000002000000LL /* Transfer ended */ - -/* CONO Flags */ -#define ATTN_EN 0000000000040LL /* enable attention interrupt. */ -#define REA_EN 0000000000100LL /* enable register error interrupt */ -#define CBOV_CLR 0000000000200LL /* Clear CBOV */ -#define CONT_RESET 0000000002000LL /* Clear All error bits */ -#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */ -#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */ -#define OVER_CLR 0000000020000LL /* Clear DTC overrun */ -#define WRT_CW 0000000040000LL /* Write control word */ -#define CHN_CLR 0000000100000LL /* Clear Channel Error */ -#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */ -#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */ - -/* RH20 CONO Flags */ -#define RH20_DELETE_SCR 0000000000100LL /* Clear SCR */ -#define RH20_RCLP 0000000000200LL /* Reset command list */ -#define RH20_MASS_EN 0000000000400LL /* Mass bus enable */ -#define RH20_XFER_CLR 0000000001000LL /* Clear XFER error */ -#define RH20_CLR_MBC 0000000002000LL /* Clear MBC */ -#define RH20_CLR_RAE 0000000004000LL /* Clear RAE error */ - -/* DATAO/DATAI */ -#define CR_REG 0770000000000LL /* Register number */ -#define LOAD_REG 0004000000000LL /* Load register */ -#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */ -#define CR_DRIVE 0000007000000LL -#define CR_GEN_EVD 0000000400000LL /* Enable Parity */ -#define CR_DXES 0000000200000LL /* Disable DXES errors */ -#define CR_INAD 0000000077600LL -#define CR_WTEVM 0000000000100LL /* Verify Parity */ -#define CR_FUNC 0000000000076LL -#define CR_GO 0000000000001LL - -#define IRQ_VECT 0000000000777LL /* Interupt vector */ -#define IRQ_KI10 0000002000000LL -#define IRQ_KA10 0000001000000LL -#define FNC_XFER 024 /* >=? data xfr */ - -/* Status register settings */ -#define DS_OFF 0000001 /* offset mode */ -#define DS_VV 0000100 /* volume valid */ -#define DS_DRY 0000200 /* drive ready */ -#define DS_DPR 0000400 /* drive present */ -#define DS_PGM 0001000 /* programable NI */ -#define DS_LST 0002000 /* last sector */ -#define DS_WRL 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 */ - -/* RH20 channel status flags */ -#define RH20_MEM_PAR 00200000000000LL /* Memory parity error */ -#define RH20_NADR_PAR 00100000000000LL /* Address parity error */ -#define RH20_NOT_WC0 00040000000000LL /* Word count not zero */ -#define RH20_NXM_ERR 00020000000000LL /* Non existent memory */ -#define RH20_LAST_ERR 00000400000000LL /* Last transfer error */ -#define RH20_ERROR 00000200000000LL /* RH20 error */ -#define RH20_LONG_STS 00000100000000LL /* Did not reach wc */ -#define RH20_SHRT_STS 00000040000000LL /* WC reached zero */ -#define RH20_OVER 00000020000000LL /* Overrun error */ - -/* 0-37 mass bus register. - 70 SBAR, block address. - 71 STCR, neg block count, func - 72 PBAR - 73 PTCR - 74 IVIR Interrupt vector address. - 75 Diags read. - 76 Diags write. - 77 Status (tra,cb test, bar test, ev par, r/w, exc,ebl, 0, attn, sclk -*/ - -/* - * CCW 000..... New channel comand list pointer HALT. - 010..... Next CCW Address JUMP - 1xycount-address. x=halt last xfer, y=reverse -*/ - -extern uint32 eb_ptr; -void rh20_setup(struct rh_if *rhc); -void rh_setup(struct rh_if *rh, uint32 addr); -void rh_writecw(struct rh_if *rh, int nxm); - - -t_stat -rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) -{ - DEVICE *dptr; - DIB *dibp; - dptr = find_dev_from_unit (uptr); - if (dptr == NULL) - return SCPE_IERR; - dibp = (DIB *) dptr->ctxt; - dptr->flags &= ~DEV_M_RH; - dptr->flags |= val; - dibp->dev_num &= ~(RH10_DEV|RH20_DEV); - dibp->dev_num |= (val) ? RH20_DEV: RH10_DEV; - return SCPE_OK; -} - -t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc) -{ - DEVICE *dptr; - - if (uptr == NULL) - return SCPE_IERR; - - dptr = find_dev_from_unit(uptr); - if (dptr == NULL) - return SCPE_IERR; - fprintf (st, "%s", (dptr->flags & TYPE_RH20) ? "RH20" : "RH10"); - return SCPE_OK; -} - - -t_stat rh_devio(uint32 dev, uint64 *data) { - DEVICE *dptr = NULL; - struct rh_if *rhc = NULL; - int drive; - - for (drive = 0; rh[drive].dev_num != 0; drive++) { - if (rh[drive].dev_num == (dev & 0774)) { - rhc = rh[drive].rh; - dptr = rh[drive].dev; - break; - } - } - if (rhc == NULL) - return SCPE_OK; - rhc->devnum = dev & 0774; -#if KL - if (dptr->flags & TYPE_RH20) { - switch(dev & 3) { - case CONI: - *data = rhc->status & RMASK; - if (rhc->attn != 0) - *data |= RH20_ATTN; - if (rhc->rae != 0) - *data |= RH20_RAE; - sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n", - dptr->name, dev, (uint32)*data, PC, rhc->attn); - return SCPE_OK; - - case CONO: - clr_interrupt(dev); - /* Clear flags */ - if (*data & RH20_CLR_MBC) { - if (rhc->dev_reset != NULL) - rhc->dev_reset(dptr); - rhc->imode = 2; - rhc->status = 0; - } - rhc->status &= ~(07LL|IADR_ATTN|RH20_MASS_EN); - rhc->status |= *data & (07LL|IADR_ATTN|RH20_MASS_EN); - if (*data & RH20_DELETE_SCR) - rhc->status &= ~(RH20_SBAR|RH20_SCR_FULL); - if (*data & (RH20_RCLP|RH20_CLR_MBC)) - rhc->cia = eb_ptr | (rhc->devnum - 0540); - if (*data & (RH20_CLR_RAE|RH20_CLR_MBC)) - rhc->rae = 0; - if (*data & PI_ENABLE) - rhc->status &= ~PI_ENABLE; - if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) - || (rhc->status & PI_ENABLE)) - set_interrupt(rhc->devnum, rhc->status); - sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n", - dptr->name, dev, (uint32)*data, PC, rhc->status); - return SCPE_OK; - - case DATAI: - *data = 0; - if (rhc->status & BUSY && rhc->reg != 04) { - rhc->status |= CC_CHAN_ACT; - return SCPE_OK; - } - if (rhc->reg < 040) { - int parity; - *data = (uint64)(rhc->dev_read(dptr, rhc, rhc->reg) & 0177777); - parity = (int)((*data >> 8) ^ *data); - parity = (parity >> 4) ^ parity; - parity = (parity >> 2) ^ parity; - parity = ((parity >> 1) ^ parity) & 1; - *data |= ((uint64)(!parity)) << 16; - *data |= ((uint64)(rhc->drive)) << 18; - *data |= BIT10; - } else if ((rhc->reg & 070) != 070) { - rhc->rae = 1; - break; - } else { - switch(rhc->reg & 07) { - case 0: *data = rhc->sbar; break; - case 1: *data = rhc->stcr; break; - case 2: *data = rhc->pbar; break; - case 3: *data = rhc->ptcr; break; - case 4: *data = rhc->ivect; break; - case 5: - case 6: break; - case 7: *data = 0; break; - } - } - *data |= ((uint64)(rhc->reg)) << 30; - sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n", - dptr->name, dev, *data, rhc->drive, PC); - return SCPE_OK; - - case DATAO: - sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n", - dptr->name, dev, *data, PC, rhc->status); - rhc->reg = ((int)(*data >> 30)) & 077; - rhc->imode |= 2; - if (rhc->reg < 040) - rhc->drive = (int)(*data >> 18) & 07; - if (*data & LOAD_REG) { - if (rhc->reg < 040) { - clr_interrupt(dev); - /* Check if access error */ - if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0) { - set_interrupt(rhc->devnum, rhc->status); - return SCPE_OK; - } - rhc->dev_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); - if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) - || (rhc->status & PI_ENABLE)) - set_interrupt(rhc->devnum, rhc->status); - /* Check if access error */ - if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0) - set_interrupt(rhc->devnum, rhc->status); - else - rhc->rae &= ~(1 << rhc->drive); - } else if ((rhc->reg & 070) != 070) { - if ((*data & BIT9) == 0) { - rhc->rae = (1 << rhc->drive); - set_interrupt(rhc->devnum, rhc->status); - } - } else { - switch(rhc->reg & 07) { - case 0: - rhc->sbar = (*data) & (CR_DRIVE|RMASK); - rhc->status |= RH20_SBAR; - break; - case 1: - rhc->stcr = (*data) & (BIT10|BIT7|CR_DRIVE|RMASK); - rhc->status |= RH20_SCR_FULL; - break; - case 4: - rhc->ivect = (*data & IRQ_VECT); - break; - case 2: - case 3: - case 5: - case 6: - case 7: - break; - } - } - } - } - if ((rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL)) - rh20_setup(rhc); - return SCPE_OK; - } -#endif - switch(dev & 3) { - case CONI: - *data = rhc->status & ~(IADR_ATTN|IARD_RAE); - if (rhc->attn != 0 && (rhc->status & IADR_ATTN)) - *data |= IADR_ATTN; - if (rhc->rae != 0 && (rhc->status & IARD_RAE)) - *data |= IARD_RAE; -#if KI_22BIT - *data |= B22_FLAG; -#endif - sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n", - dptr->name, dev, (uint32)*data, PC, rhc->attn); - return SCPE_OK; - - case CONO: - clr_interrupt(dev); - rhc->status &= ~(07LL|IADR_ATTN|IARD_RAE); - rhc->status |= *data & (07LL|IADR_ATTN|IARD_RAE); - /* Clear flags */ - if (*data & CONT_RESET && rhc->dev_reset != NULL) - rhc->dev_reset(dptr); - if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)) - rhc->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)); - if (*data & OVER_CLR) - rhc->status &= ~(DTC_OVER); - if (*data & CBOV_CLR) - rhc->status &= ~(DIB_CBOV); - if (*data & CXR_ILC) - rhc->status &= ~(CXR_ILFC|CXR_SD_RAE); - if (*data & WRT_CW) - rh_writecw(rhc, 0); - if (*data & PI_ENABLE) - rhc->status &= ~PI_ENABLE; - if (rhc->status & PI_ENABLE) - set_interrupt(dev, rhc->status); - if ((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) - set_interrupt(dev, rhc->status); - sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n", - dptr->name, dev, (uint32)*data, PC, rhc->status); - return SCPE_OK; - - case DATAI: - *data = 0; - if (rhc->status & BUSY && rhc->reg != 04) { - rhc->status |= CC_CHAN_ACT; - return SCPE_OK; - } - if (rhc->reg == 040) { - *data = (uint64)(rhc->dev_read(dptr, rhc, 0) & 077); - *data |= ((uint64)(rhc->cia)) << 6; - *data |= ((uint64)(rhc->xfer_drive)) << 18; - } else if (rhc->reg == 044) { - *data = (uint64)rhc->ivect; - if (rhc->imode) - *data |= IRQ_KI10; - else - *data |= IRQ_KA10; - } else if (rhc->reg == 054) { - *data = (uint64)(rhc->rae); - } else if ((rhc->reg & 040) == 0) { - int parity; - *data = (uint64)(rhc->dev_read(dptr, rhc, rhc->reg) & 0177777); - parity = (int)((*data >> 8) ^ *data); - parity = (parity >> 4) ^ parity; - parity = (parity >> 2) ^ parity; - parity = ((parity >> 1) ^ parity) & 1; - *data |= ((uint64)(parity ^ 1)) << 17; - *data |= ((uint64)(rhc->drive)) << 18; - } - *data |= ((uint64)(rhc->reg)) << 30; - sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n", - dptr->name, dev, *data, rhc->drive, PC); - return SCPE_OK; - - case DATAO: - sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n", - dptr->name, dev, *data, PC, rhc->status); - rhc->reg = ((int)(*data >> 30)) & 077; - rhc->imode &= ~2; - if (rhc->reg < 040 && rhc->reg != 04) { - rhc->drive = (int)(*data >> 18) & 07; - } - if (*data & LOAD_REG) { - if (rhc->reg == 040) { - if ((*data & 1) == 0) { - return SCPE_OK; - } - - if (rhc->status & BUSY) { - rhc->status |= CC_CHAN_ACT; - return SCPE_OK; - } - - rhc->status &= ~(CCW_COMP_1|PI_ENABLE); - if (((*data >> 1) & 037) < FNC_XFER) { - rhc->status |= CXR_ILC; - rh_setirq(rhc); - sim_debug(DEBUG_DATAIO, dptr, - "%s %03o command abort %012llo, %d PC=%06o %06o\n", - dptr->name, dev, *data, rhc->drive, PC, rhc->status); - return SCPE_OK; - } - /* Check if access error */ - if (rhc->rae & (1 << rhc->drive)) - return SCPE_OK; - /* Start command */ - rh_setup(rhc, (uint32)(*data >> 6)); - rhc->xfer_drive = (int)(*data >> 18) & 07; - rhc->dev_write(dptr, rhc, 0, (uint32)(*data & 077)); - sim_debug(DEBUG_DATAIO, dptr, - "%s %03o command %012llo, %d PC=%06o %06o\n", - dptr->name, dev, *data, rhc->drive, PC, rhc->status); - } else if (rhc->reg == 044) { - /* Set KI10 Irq vector */ - rhc->ivect = (int)(*data & IRQ_VECT); - rhc->imode = (*data & IRQ_KI10) != 0; - } else if (rhc->reg == 050) { - ; /* Diagnostic access to mass bus. */ - } else if (rhc->reg == 054) { - /* clear flags */ - rhc->rae &= ~(*data & 0377); - if (rhc->rae == 0) - clr_interrupt(dev); - } else if ((rhc->reg & 040) == 0) { - rhc->drive = (int)(*data >> 18) & 07; - /* Check if access error */ - if (rhc->rae & (1 << rhc->drive)) { - return SCPE_OK; - } - rhc->dev_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); - } - } - clr_interrupt(dev); - if (((rhc->status & (IADR_ATTN|BUSY)) == IADR_ATTN && rhc->attn != 0) - || (rhc->status & PI_ENABLE)) - set_interrupt(rhc->devnum, rhc->status); - return SCPE_OK; - } - return SCPE_OK; /* Unreached */ -} - -/* Handle KI and KL style interrupt vectors */ -t_addr -rh_devirq(uint32 dev, t_addr addr) { - DEVICE *dptr = NULL; - struct rh_if *rhc = NULL; - int drive; - - for (drive = 0; rh[drive].dev_num != 0; drive++) { - if (rh[drive].dev_num == (dev & 0774)) { - rhc = rh[drive].rh; - break; - } - } - if (rhc != NULL) { - if (rhc->imode == 1) /* KI10 Style */ - addr = RSIGN | rhc->ivect; - else if (rhc->imode == 2) /* RH20 style */ - addr = rhc->ivect; - } - return addr; -} - -/* Set the attention flag for a unit */ -void rh_setattn(struct rh_if *rhc, int unit) -{ - rhc->attn |= 1<status & BUSY) == 0 && (rhc->status & IADR_ATTN) != 0) - set_interrupt(rhc->devnum, rhc->status); -} - -void rh_error(struct rh_if *rhc) -{ - if (rhc->imode == 2) - rhc->status |= RH20_DR_EXC; -} - -/* Decrement block count for RH20, nop for RH10 */ -int rh_blkend(struct rh_if *rhc) -{ -#if KL - if (rhc->imode == 2) { -//fprintf(stderr, "RH blkend %o\n\r", rhc->cia); - rhc->cia = (rhc->cia + 1) & 01777; - if (rhc->cia == 0) { - rhc->status |= RH20_XEND; - return 1; - } - } -#endif - return 0; -} - -/* Set an IRQ for a DF10 device */ -void rh_setirq(struct rh_if *rhc) { - rhc->status |= PI_ENABLE; - set_interrupt(rhc->devnum, rhc->status); -} - -/* Generate the DF10 complete word */ -void rh_writecw(struct rh_if *rhc, int nxm) { -#if KL - if (rhc->imode == 2) { - uint32 chan = (rhc->devnum - 0540); - int wc = ((rhc->wcr ^ RH20_WMASK) + 1) & RH20_WMASK; - rhc->status |= RH20_CHAN_RDY; - rhc->status &= ~(RH20_PCR_FULL); - if (wc != 0 || (rhc->status & RH20_XEND) == 0 || - (rhc->ptcr & BIT10) != 0 || nxm) { - uint64 wrd1 = SMASK|(uint64)(rhc->ccw); - if ((rhc->ptcr & BIT10) == 0 && (rhc->status & RH20_DR_EXC) != 0) - return; - if (nxm) { - wrd1 |= RH20_NXM_ERR; - rhc->status |= RH20_CHAN_ERR; - } - if (wc != 0) { - wrd1 |= RH20_NOT_WC0; - if (rhc->status & RH20_XEND) { - wrd1 |= RH20_LONG_STS; - rhc->status |= RH20_CHAN_ERR; - if ((rhc->ptcr & 010) == 0) /* Write command */ - rhc->status |= RH20_LONG_WC; - } - } else if ((rhc->status & RH20_XEND) == 0) { - wrd1 |= RH20_SHRT_STS; - rhc->status |= RH20_CHAN_ERR; - if ((rhc->ptcr & 010) == 0) /* Write command */ - rhc->status |= RH20_SHRT_WC; - } - wrd1 |= RH20_NADR_PAR; - M[eb_ptr|chan|1] = wrd1; - M[eb_ptr|chan|2] = ((uint64)rhc->cop << 33) | - (((uint64)wc) << CSHIFT) | - ((uint64)(rhc->cda) & AMASK); -//fprintf(stderr, "RH20 final %012llo %012llo %06o\n\r", M[eb_ptr|chan|1], M[eb_ptr|chan|2], wc); - } - return; - } -#endif - if (nxm) - rhc->status |= CXR_NXM; - rhc->status |= CCW_COMP_1; - if (rhc->wcr != 0) - rhc->cda++; - M[rhc->cia|1] = ((uint64)(rhc->ccw & WMASK) << CSHIFT) | ((uint64)(rhc->cda) & AMASK); -} - -/* Finish off a DF10 transfer */ -void rh_finish_op(struct rh_if *rhc, int nxm) { -#if KL - if (rhc->imode != 2) -#endif - rhc->status &= ~BUSY; - rh_writecw(rhc, nxm); - rh_setirq(rhc); -#if KL - if (rhc->imode == 2 && - (rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL)) - rh20_setup(rhc); -#endif -} - -#if KL -/* Set up for a RH20 transfer */ -void rh20_setup(struct rh_if *rhc) -{ - int reg; - DEVICE *dptr; - - for (reg = 0; rh[reg].dev_num != 0; reg++) { - if (rh[reg].rh == rhc) { - dptr = rh[reg].dev; - break; - } - } - if (dptr == 0) - return; - rhc->pbar = rhc->sbar; - rhc->ptcr = rhc->stcr; - /* Read drive status */ - rhc->drive = (rhc->ptcr >> 18) & 07; - rhc->status &= ~(RH20_DATA_OVR|RH20_CHAN_RDY|RH20_DR_RESP|RH20_CHAN_ERR|RH20_SHRT_WC|\ - RH20_LONG_WC|RH20_DR_EXC|RH20_SCR_FULL|PI_ENABLE|RH20_XEND); - rhc->status |= RH20_PCR_FULL; -// reg = rhc->dev_read(dptr, rhc, 1); - // if ((reg & (DS_DRY|DS_DPR|DS_ERR)) != (DS_DRY|DS_DPR)) - // return; - if (rhc->status & RH20_SBAR) { - rhc->drive = (rhc->pbar >> 18) & 07; - rhc->dev_write(dptr, rhc, 5, (rhc->pbar & 0177777)); - rhc->status &= ~RH20_SBAR; - } - if (rhc->ptcr & BIT7) { /* If RCPL reset I/O pointers */ - rhc->ccw = eb_ptr + (rhc->devnum - 0540); - rhc->wcr = 0; - } - /* Hold block count in cia */ - rhc->drive = (rhc->ptcr >> 18) & 07; - rhc->cia = (rhc->ptcr >> 6) & 01777; - rhc->dev_write(dptr, rhc, 0, (rhc->ptcr & 077)); - rhc->cop = 0; - rhc->wcr = 0; - rhc->status &= ~RH20_CHAN_RDY; -//fprintf(stderr, "RH setup %06o %06o %o\n\r", rhc->ptcr, rhc->ccw, rhc->cia); -} -#endif - -/* Setup for a DF10 transfer */ -void rh_setup(struct rh_if *rhc, uint32 addr) -{ - rhc->cia = addr & ICWA; - rhc->ccw = rhc->cia; - rhc->wcr = 0; - rhc->status |= BUSY; -} - - -/* Fetch the next IO control word */ -int rh_fetch(struct rh_if *rhc) { - uint64 data; -#if KL - if (rhc->imode == 2 && (rhc->cop & 2) != 0) { -// rh_finish_op(rhc, 0); - return 0; - } -#endif - if (rhc->ccw > MEMSIZE) { - rh_finish_op(rhc, 1); - return 0; - } - data = M[rhc->ccw]; -#if KL - if (rhc->imode == 2) { -//fprintf(stderr, "RH20 fetch %06o %012llo\n\r", rhc->ccw, data); - while((data & RH20_XFER) == 0) { - rhc->ccw = (uint32)(data & AMASK); - if ((data & (BIT1|BIT2)) == 0) { -// rh_finish_op(rhc, 0); - return 0; - } - if (rhc->ccw > MEMSIZE) { - rh_finish_op(rhc, 1); - return 0; - } - data = M[rhc->ccw]; -//fprintf(stderr, "RH20 fetch2 %06o %012llo\n\r", rhc->ccw, data); - } - rhc->wcr = (((data >> CSHIFT) & RH20_WMASK) ^ WMASK) + 1; - rhc->cda = (data & AMASK); - rhc->cop = (data >> 33) & 07; - rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK); - return 1; - } -#endif - while((data & (WMASK << CSHIFT)) == 0) { - if ((data & AMASK) == 0 || (uint32)(data & AMASK) == rhc->ccw) { - rh_finish_op(rhc, 0); - return 0; - } - rhc->ccw = (uint32)(data & AMASK); - if (rhc->ccw > MEMSIZE) { - rh_finish_op(rhc, 1); - return 0; - } - data = M[rhc->ccw]; - } - rhc->wcr = (uint32)((data >> CSHIFT) & WMASK); - rhc->cda = (uint32)(data & AMASK); - rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK); - return 1; -} - -/* Read next word */ -int rh_read(struct rh_if *rhc) { - uint64 data; - if (rhc->wcr == 0) { - if (!rh_fetch(rhc)) - return 0; - } - rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK); - if (rhc->cda != 0) { - if (rhc->cda > MEMSIZE) { - rh_finish_op(rhc, 1); - return 0; - } -#if KL - if (rhc->imode == 2) { - data = M[rhc->cda]; - if (rhc->cop & 01) - rhc->cda = (uint32)((rhc->cda - 1) & AMASK); - else - rhc->cda = (uint32)((rhc->cda + 1) & AMASK); - } else { - rhc->cda = (uint32)((rhc->cda + 1) & AMASK); - data = M[rhc->cda]; - } -#else - rhc->cda = (uint32)((rhc->cda + 1) & AMASK); - data = M[rhc->cda]; -#endif - } else { - data = 0; - } - rhc->buf = data; - if (rhc->wcr == 0) { - return rh_fetch(rhc); - } - return 1; -} - -/* Write next word */ -int rh_write(struct rh_if *rhc) { - if (rhc->wcr == 0) { - if (!rh_fetch(rhc)) - return 0; - } - rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK); - if (rhc->cda != 0) { - if (rhc->cda > MEMSIZE) { - rh_finish_op(rhc, 1); - return 0; - } -#if KL - if (rhc->imode == 2) { - M[rhc->cda] = rhc->buf; - if (rhc->cop & 01) - rhc->cda = (uint32)((rhc->cda - 1) & AMASK); - else - rhc->cda = (uint32)((rhc->cda + 1) & AMASK); - } else { - rhc->cda = (uint32)((rhc->cda + 1) & AMASK); - M[rhc->cda] = rhc->buf; - } -#else - rhc->cda = (uint32)((rhc->cda + 1) & AMASK); - M[rhc->cda] = rhc->buf; -#endif - } - if (rhc->wcr == 0) { - return rh_fetch(rhc); - } - return 1; -} - +/* kx10_rh.c: RH10/RH20 interace routines. + + Copyright (c) 2015-2019, Richard Cornwell + + 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 + RICHARD CORNWELL 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. + +*/ + +#include "kx10_defs.h" + + +/* CONI Flags */ +#define IADR_ATTN 0000000000040LL /* Interrupt on attention */ +#define IARD_RAE 0000000000100LL /* Interrupt on register access error */ +#define DIB_CBOV 0000000000200LL /* Control bus overrun */ +#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */ +#define CXR_ILC 0000000004000LL /* Illegal function code */ +#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */ +#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */ +#define CCW_COMP_1 0000000040000LL /* Control word written. */ +#define CXR_CHAN_ER 0000000100000LL /* Channel Error */ +#define CXR_EXC 0000000200000LL /* Error in drive transfer */ +#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */ +#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */ +#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */ +#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */ +#define CXR_SD_RAE 0000200000000LL /* Register access error */ +#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */ +#define B22_FLAG 0004000000000LL /* 22 bit channel */ +#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */ +#define CC_CHAN_ACT 0020000000000LL /* Channel in use */ +#define CC_INH 0040000000000LL /* Disconnect channel */ +#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */ +#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */ + +/* RH20 CONI Flags */ +#define RH20_PCR_FULL 0000000000020LL /* Primary command file full */ +#define RH20_ATTN_ENA 0000000000040LL /* Attention enable */ +#define RH20_SCR_FULL 0000000000100LL /* Secondary command full */ +#define RH20_ATTN 0000000000200LL /* Attention */ +#define RH20_MASS_ENA 0000000000400LL /* Mass bus enable */ +#define RH20_DATA_OVR 0000000001000LL /* Data overrun */ +#define RH20_CHAN_RDY 0000000002000LL /* Channel ready to start */ +#define RH20_RAE 0000000004000LL /* Register access error */ +#define RH20_DR_RESP 0000000010000LL /* Drive no response */ +#define RH20_CHAN_ERR 0000000020000LL /* Channel error */ +#define RH20_SHRT_WC 0000000040000LL /* Short word count */ +#define RH20_LONG_WC 0000000100000LL /* Long word count */ +#define RH20_DR_EXC 0000000200000LL /* Exception */ +#define RH20_DATA_PRI 0000000400000LL /* Data parity error */ +#define RH20_SBAR 0000001000000LL /* SBAR set */ +#define RH20_XEND 0000002000000LL /* Transfer ended */ + +/* CONO Flags */ +#define ATTN_EN 0000000000040LL /* enable attention interrupt. */ +#define REA_EN 0000000000100LL /* enable register error interrupt */ +#define CBOV_CLR 0000000000200LL /* Clear CBOV */ +#define CONT_RESET 0000000002000LL /* Clear All error bits */ +#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */ +#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */ +#define OVER_CLR 0000000020000LL /* Clear DTC overrun */ +#define WRT_CW 0000000040000LL /* Write control word */ +#define CHN_CLR 0000000100000LL /* Clear Channel Error */ +#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */ +#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */ + +/* RH20 CONO Flags */ +#define RH20_DELETE_SCR 0000000000100LL /* Clear SCR */ +#define RH20_RCLP 0000000000200LL /* Reset command list */ +#define RH20_MASS_EN 0000000000400LL /* Mass bus enable */ +#define RH20_XFER_CLR 0000000001000LL /* Clear XFER error */ +#define RH20_CLR_MBC 0000000002000LL /* Clear MBC */ +#define RH20_CLR_RAE 0000000004000LL /* Clear RAE error */ + +/* DATAO/DATAI */ +#define CR_REG 0770000000000LL /* Register number */ +#define LOAD_REG 0004000000000LL /* Load register */ +#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */ +#define CR_DRIVE 0000007000000LL +#define CR_GEN_EVD 0000000400000LL /* Enable Parity */ +#define CR_DXES 0000000200000LL /* Disable DXES errors */ +#define CR_INAD 0000000077600LL +#define CR_WTEVM 0000000000100LL /* Verify Parity */ +#define CR_FUNC 0000000000076LL +#define CR_GO 0000000000001LL + +#define IRQ_VECT 0000000000777LL /* Interupt vector */ +#define IRQ_KI10 0000002000000LL +#define IRQ_KA10 0000001000000LL +#define FNC_XFER 024 /* >=? data xfr */ + +/* Status register settings */ +#define DS_OFF 0000001 /* offset mode */ +#define DS_VV 0000100 /* volume valid */ +#define DS_DRY 0000200 /* drive ready */ +#define DS_DPR 0000400 /* drive present */ +#define DS_PGM 0001000 /* programable NI */ +#define DS_LST 0002000 /* last sector */ +#define DS_WRL 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 */ + +/* RH20 channel status flags */ +#define RH20_MEM_PAR 00200000000000LL /* Memory parity error */ +#define RH20_NADR_PAR 00100000000000LL /* Address parity error */ +#define RH20_NOT_WC0 00040000000000LL /* Word count not zero */ +#define RH20_NXM_ERR 00020000000000LL /* Non existent memory */ +#define RH20_LAST_ERR 00000400000000LL /* Last transfer error */ +#define RH20_ERROR 00000200000000LL /* RH20 error */ +#define RH20_LONG_STS 00000100000000LL /* Did not reach wc */ +#define RH20_SHRT_STS 00000040000000LL /* WC reached zero */ +#define RH20_OVER 00000020000000LL /* Overrun error */ + +/* 0-37 mass bus register. + 70 SBAR, block address. + 71 STCR, neg block count, func + 72 PBAR + 73 PTCR + 74 IVIR Interrupt vector address. + 75 Diags read. + 76 Diags write. + 77 Status (tra,cb test, bar test, ev par, r/w, exc,ebl, 0, attn, sclk +*/ + +/* + * CCW 000..... New channel comand list pointer HALT. + 010..... Next CCW Address JUMP + 1xycount-address. x=halt last xfer, y=reverse +*/ + +extern uint32 eb_ptr; +void rh20_setup(struct rh_if *rhc); +void rh_setup(struct rh_if *rh, uint32 addr); +void rh_writecw(struct rh_if *rh, int nxm); + + +t_stat +rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + DEVICE *dptr; + DIB *dibp; + dptr = find_dev_from_unit (uptr); + if (dptr == NULL) + return SCPE_IERR; + dibp = (DIB *) dptr->ctxt; + dptr->flags &= ~DEV_M_RH; + dptr->flags |= val; + dibp->dev_num &= ~(RH10_DEV|RH20_DEV); + dibp->dev_num |= (val) ? RH20_DEV: RH10_DEV; + return SCPE_OK; +} + +t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + DEVICE *dptr; + + if (uptr == NULL) + return SCPE_IERR; + + dptr = find_dev_from_unit(uptr); + if (dptr == NULL) + return SCPE_IERR; + fprintf (st, "%s", (dptr->flags & TYPE_RH20) ? "RH20" : "RH10"); + return SCPE_OK; +} + + +t_stat rh_devio(uint32 dev, uint64 *data) { + DEVICE *dptr = NULL; + struct rh_if *rhc = NULL; + int drive; + + for (drive = 0; rh[drive].dev_num != 0; drive++) { + if (rh[drive].dev_num == (dev & 0774)) { + rhc = rh[drive].rh; + dptr = rh[drive].dev; + break; + } + } + if (rhc == NULL) + return SCPE_OK; + rhc->devnum = dev & 0774; +#if KL + if (dptr->flags & TYPE_RH20) { + switch(dev & 3) { + case CONI: + *data = rhc->status & RMASK; + if (rhc->attn != 0) + *data |= RH20_ATTN; + if (rhc->rae != 0) + *data |= RH20_RAE; + sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n", + dptr->name, dev, (uint32)*data, PC, rhc->attn); + return SCPE_OK; + + case CONO: + clr_interrupt(dev); + /* Clear flags */ + if (*data & RH20_CLR_MBC) { + if (rhc->dev_reset != NULL) + rhc->dev_reset(dptr); + rhc->imode = 2; + rhc->status = 0; + } + rhc->status &= ~(07LL|IADR_ATTN|RH20_MASS_EN); + rhc->status |= *data & (07LL|IADR_ATTN|RH20_MASS_EN); + if (*data & RH20_DELETE_SCR) + rhc->status &= ~(RH20_SBAR|RH20_SCR_FULL); + if (*data & (RH20_RCLP|RH20_CLR_MBC)) + rhc->cia = eb_ptr | (rhc->devnum - 0540); + if (*data & (RH20_CLR_RAE|RH20_CLR_MBC)) + rhc->rae = 0; + if (*data & PI_ENABLE) + rhc->status &= ~PI_ENABLE; + if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) + || (rhc->status & PI_ENABLE)) + set_interrupt(rhc->devnum, rhc->status); + sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n", + dptr->name, dev, (uint32)*data, PC, rhc->status); + return SCPE_OK; + + case DATAI: + *data = 0; + if (rhc->status & BUSY && rhc->reg != 04) { + rhc->status |= CC_CHAN_ACT; + return SCPE_OK; + } + if (rhc->reg < 040) { + int parity; + *data = (uint64)(rhc->dev_read(dptr, rhc, rhc->reg) & 0177777); + parity = (int)((*data >> 8) ^ *data); + parity = (parity >> 4) ^ parity; + parity = (parity >> 2) ^ parity; + parity = ((parity >> 1) ^ parity) & 1; + *data |= ((uint64)(!parity)) << 16; + *data |= ((uint64)(rhc->drive)) << 18; + *data |= BIT10; + } else if ((rhc->reg & 070) != 070) { + rhc->rae = 1; + break; + } else { + switch(rhc->reg & 07) { + case 0: *data = rhc->sbar; break; + case 1: *data = rhc->stcr; break; + case 2: *data = rhc->pbar; break; + case 3: *data = rhc->ptcr; break; + case 4: *data = rhc->ivect; break; + case 5: + case 6: break; + case 7: *data = 0; break; + } + } + *data |= ((uint64)(rhc->reg)) << 30; + sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n", + dptr->name, dev, *data, rhc->drive, PC); + return SCPE_OK; + + case DATAO: + sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n", + dptr->name, dev, *data, PC, rhc->status); + rhc->reg = ((int)(*data >> 30)) & 077; + rhc->imode |= 2; + if (rhc->reg < 040) + rhc->drive = (int)(*data >> 18) & 07; + if (*data & LOAD_REG) { + if (rhc->reg < 040) { + clr_interrupt(dev); + /* Check if access error */ + if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0) { + set_interrupt(rhc->devnum, rhc->status); + return SCPE_OK; + } + rhc->dev_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); + if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) + || (rhc->status & PI_ENABLE)) + set_interrupt(rhc->devnum, rhc->status); + /* Check if access error */ + if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0) + set_interrupt(rhc->devnum, rhc->status); + else + rhc->rae &= ~(1 << rhc->drive); + } else if ((rhc->reg & 070) != 070) { + if ((*data & BIT9) == 0) { + rhc->rae = (1 << rhc->drive); + set_interrupt(rhc->devnum, rhc->status); + } + } else { + switch(rhc->reg & 07) { + case 0: + rhc->sbar = (*data) & (CR_DRIVE|RMASK); + rhc->status |= RH20_SBAR; + break; + case 1: + rhc->stcr = (*data) & (BIT10|BIT7|CR_DRIVE|RMASK); + rhc->status |= RH20_SCR_FULL; + break; + case 4: + rhc->ivect = (*data & IRQ_VECT); + break; + case 2: + case 3: + case 5: + case 6: + case 7: + break; + } + } + } + } + if ((rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL)) + rh20_setup(rhc); + return SCPE_OK; + } +#endif + switch(dev & 3) { + case CONI: + *data = rhc->status & ~(IADR_ATTN|IARD_RAE); + if (rhc->attn != 0 && (rhc->status & IADR_ATTN)) + *data |= IADR_ATTN; + if (rhc->rae != 0 && (rhc->status & IARD_RAE)) + *data |= IARD_RAE; +#if KI_22BIT + *data |= B22_FLAG; +#endif + sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n", + dptr->name, dev, (uint32)*data, PC, rhc->attn); + return SCPE_OK; + + case CONO: + clr_interrupt(dev); + rhc->status &= ~(07LL|IADR_ATTN|IARD_RAE); + rhc->status |= *data & (07LL|IADR_ATTN|IARD_RAE); + /* Clear flags */ + if (*data & CONT_RESET && rhc->dev_reset != NULL) + rhc->dev_reset(dptr); + if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)) + rhc->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR)); + if (*data & OVER_CLR) + rhc->status &= ~(DTC_OVER); + if (*data & CBOV_CLR) + rhc->status &= ~(DIB_CBOV); + if (*data & CXR_ILC) + rhc->status &= ~(CXR_ILFC|CXR_SD_RAE); + if (*data & WRT_CW) + rh_writecw(rhc, 0); + if (*data & PI_ENABLE) + rhc->status &= ~PI_ENABLE; + if (rhc->status & PI_ENABLE) + set_interrupt(dev, rhc->status); + if ((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0) + set_interrupt(dev, rhc->status); + sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n", + dptr->name, dev, (uint32)*data, PC, rhc->status); + return SCPE_OK; + + case DATAI: + *data = 0; + if (rhc->status & BUSY && rhc->reg != 04) { + rhc->status |= CC_CHAN_ACT; + return SCPE_OK; + } + if (rhc->reg == 040) { + *data = (uint64)(rhc->dev_read(dptr, rhc, 0) & 077); + *data |= ((uint64)(rhc->cia)) << 6; + *data |= ((uint64)(rhc->xfer_drive)) << 18; + } else if (rhc->reg == 044) { + *data = (uint64)rhc->ivect; + if (rhc->imode) + *data |= IRQ_KI10; + else + *data |= IRQ_KA10; + } else if (rhc->reg == 054) { + *data = (uint64)(rhc->rae); + } else if ((rhc->reg & 040) == 0) { + int parity; + *data = (uint64)(rhc->dev_read(dptr, rhc, rhc->reg) & 0177777); + parity = (int)((*data >> 8) ^ *data); + parity = (parity >> 4) ^ parity; + parity = (parity >> 2) ^ parity; + parity = ((parity >> 1) ^ parity) & 1; + *data |= ((uint64)(parity ^ 1)) << 17; + *data |= ((uint64)(rhc->drive)) << 18; + } + *data |= ((uint64)(rhc->reg)) << 30; + sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n", + dptr->name, dev, *data, rhc->drive, PC); + return SCPE_OK; + + case DATAO: + sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n", + dptr->name, dev, *data, PC, rhc->status); + rhc->reg = ((int)(*data >> 30)) & 077; + rhc->imode &= ~2; + if (rhc->reg < 040 && rhc->reg != 04) { + rhc->drive = (int)(*data >> 18) & 07; + } + if (*data & LOAD_REG) { + if (rhc->reg == 040) { + if ((*data & 1) == 0) { + return SCPE_OK; + } + + if (rhc->status & BUSY) { + rhc->status |= CC_CHAN_ACT; + return SCPE_OK; + } + + rhc->status &= ~(CCW_COMP_1|PI_ENABLE); + if (((*data >> 1) & 037) < FNC_XFER) { + rhc->status |= CXR_ILC; + rh_setirq(rhc); + sim_debug(DEBUG_DATAIO, dptr, + "%s %03o command abort %012llo, %d PC=%06o %06o\n", + dptr->name, dev, *data, rhc->drive, PC, rhc->status); + return SCPE_OK; + } + /* Check if access error */ + if (rhc->rae & (1 << rhc->drive)) + return SCPE_OK; + /* Start command */ + rh_setup(rhc, (uint32)(*data >> 6)); + rhc->xfer_drive = (int)(*data >> 18) & 07; + rhc->dev_write(dptr, rhc, 0, (uint32)(*data & 077)); + sim_debug(DEBUG_DATAIO, dptr, + "%s %03o command %012llo, %d PC=%06o %06o\n", + dptr->name, dev, *data, rhc->drive, PC, rhc->status); + } else if (rhc->reg == 044) { + /* Set KI10 Irq vector */ + rhc->ivect = (int)(*data & IRQ_VECT); + rhc->imode = (*data & IRQ_KI10) != 0; + } else if (rhc->reg == 050) { + ; /* Diagnostic access to mass bus. */ + } else if (rhc->reg == 054) { + /* clear flags */ + rhc->rae &= ~(*data & 0377); + if (rhc->rae == 0) + clr_interrupt(dev); + } else if ((rhc->reg & 040) == 0) { + rhc->drive = (int)(*data >> 18) & 07; + /* Check if access error */ + if (rhc->rae & (1 << rhc->drive)) { + return SCPE_OK; + } + rhc->dev_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777)); + } + } + clr_interrupt(dev); + if (((rhc->status & (IADR_ATTN|BUSY)) == IADR_ATTN && rhc->attn != 0) + || (rhc->status & PI_ENABLE)) + set_interrupt(rhc->devnum, rhc->status); + return SCPE_OK; + } + return SCPE_OK; /* Unreached */ +} + +/* Handle KI and KL style interrupt vectors */ +t_addr +rh_devirq(uint32 dev, t_addr addr) { + DEVICE *dptr = NULL; + struct rh_if *rhc = NULL; + int drive; + + for (drive = 0; rh[drive].dev_num != 0; drive++) { + if (rh[drive].dev_num == (dev & 0774)) { + rhc = rh[drive].rh; + break; + } + } + if (rhc != NULL) { + if (rhc->imode == 1) /* KI10 Style */ + addr = RSIGN | rhc->ivect; + else if (rhc->imode == 2) /* RH20 style */ + addr = rhc->ivect; + } + return addr; +} + +/* Set the attention flag for a unit */ +void rh_setattn(struct rh_if *rhc, int unit) +{ + rhc->attn |= 1<status & BUSY) == 0 && (rhc->status & IADR_ATTN) != 0) + set_interrupt(rhc->devnum, rhc->status); +} + +void rh_error(struct rh_if *rhc) +{ + if (rhc->imode == 2) + rhc->status |= RH20_DR_EXC; +} + +/* Decrement block count for RH20, nop for RH10 */ +int rh_blkend(struct rh_if *rhc) +{ +#if KL + if (rhc->imode == 2) { +//fprintf(stderr, "RH blkend %o\n\r", rhc->cia); + rhc->cia = (rhc->cia + 1) & 01777; + if (rhc->cia == 0) { + rhc->status |= RH20_XEND; + return 1; + } + } +#endif + return 0; +} + +/* Set an IRQ for a DF10 device */ +void rh_setirq(struct rh_if *rhc) { + rhc->status |= PI_ENABLE; + set_interrupt(rhc->devnum, rhc->status); +} + +/* Generate the DF10 complete word */ +void rh_writecw(struct rh_if *rhc, int nxm) { +#if KL + if (rhc->imode == 2) { + uint32 chan = (rhc->devnum - 0540); + int wc = ((rhc->wcr ^ RH20_WMASK) + 1) & RH20_WMASK; + rhc->status |= RH20_CHAN_RDY; + rhc->status &= ~(RH20_PCR_FULL); + if (wc != 0 || (rhc->status & RH20_XEND) == 0 || + (rhc->ptcr & BIT10) != 0 || nxm) { + uint64 wrd1 = SMASK|(uint64)(rhc->ccw); + if ((rhc->ptcr & BIT10) == 0 && (rhc->status & RH20_DR_EXC) != 0) + return; + if (nxm) { + wrd1 |= RH20_NXM_ERR; + rhc->status |= RH20_CHAN_ERR; + } + if (wc != 0) { + wrd1 |= RH20_NOT_WC0; + if (rhc->status & RH20_XEND) { + wrd1 |= RH20_LONG_STS; + rhc->status |= RH20_CHAN_ERR; + if ((rhc->ptcr & 010) == 0) /* Write command */ + rhc->status |= RH20_LONG_WC; + } + } else if ((rhc->status & RH20_XEND) == 0) { + wrd1 |= RH20_SHRT_STS; + rhc->status |= RH20_CHAN_ERR; + if ((rhc->ptcr & 010) == 0) /* Write command */ + rhc->status |= RH20_SHRT_WC; + } + wrd1 |= RH20_NADR_PAR; + M[eb_ptr|chan|1] = wrd1; + M[eb_ptr|chan|2] = ((uint64)rhc->cop << 33) | + (((uint64)wc) << CSHIFT) | + ((uint64)(rhc->cda) & AMASK); +//fprintf(stderr, "RH20 final %012llo %012llo %06o\n\r", M[eb_ptr|chan|1], M[eb_ptr|chan|2], wc); + } + return; + } +#endif + if (nxm) + rhc->status |= CXR_NXM; + rhc->status |= CCW_COMP_1; + if (rhc->wcr != 0) + rhc->cda++; + M[rhc->cia|1] = ((uint64)(rhc->ccw & WMASK) << CSHIFT) | ((uint64)(rhc->cda) & AMASK); +} + +/* Finish off a DF10 transfer */ +void rh_finish_op(struct rh_if *rhc, int nxm) { +#if KL + if (rhc->imode != 2) +#endif + rhc->status &= ~BUSY; + rh_writecw(rhc, nxm); + rh_setirq(rhc); +#if KL + if (rhc->imode == 2 && + (rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL)) + rh20_setup(rhc); +#endif +} + +#if KL +/* Set up for a RH20 transfer */ +void rh20_setup(struct rh_if *rhc) +{ + int reg; + DEVICE *dptr; + + for (reg = 0; rh[reg].dev_num != 0; reg++) { + if (rh[reg].rh == rhc) { + dptr = rh[reg].dev; + break; + } + } + if (dptr == 0) + return; + rhc->pbar = rhc->sbar; + rhc->ptcr = rhc->stcr; + /* Read drive status */ + rhc->drive = (rhc->ptcr >> 18) & 07; + rhc->status &= ~(RH20_DATA_OVR|RH20_CHAN_RDY|RH20_DR_RESP|RH20_CHAN_ERR|RH20_SHRT_WC|\ + RH20_LONG_WC|RH20_DR_EXC|RH20_SCR_FULL|PI_ENABLE|RH20_XEND); + rhc->status |= RH20_PCR_FULL; +// reg = rhc->dev_read(dptr, rhc, 1); + // if ((reg & (DS_DRY|DS_DPR|DS_ERR)) != (DS_DRY|DS_DPR)) + // return; + if (rhc->status & RH20_SBAR) { + rhc->drive = (rhc->pbar >> 18) & 07; + rhc->dev_write(dptr, rhc, 5, (rhc->pbar & 0177777)); + rhc->status &= ~RH20_SBAR; + } + if (rhc->ptcr & BIT7) { /* If RCPL reset I/O pointers */ + rhc->ccw = eb_ptr + (rhc->devnum - 0540); + rhc->wcr = 0; + } + /* Hold block count in cia */ + rhc->drive = (rhc->ptcr >> 18) & 07; + rhc->cia = (rhc->ptcr >> 6) & 01777; + rhc->dev_write(dptr, rhc, 0, (rhc->ptcr & 077)); + rhc->cop = 0; + rhc->wcr = 0; + rhc->status &= ~RH20_CHAN_RDY; +//fprintf(stderr, "RH setup %06o %06o %o\n\r", rhc->ptcr, rhc->ccw, rhc->cia); +} +#endif + +/* Setup for a DF10 transfer */ +void rh_setup(struct rh_if *rhc, uint32 addr) +{ + rhc->cia = addr & ICWA; + rhc->ccw = rhc->cia; + rhc->wcr = 0; + rhc->status |= BUSY; +} + + +/* Fetch the next IO control word */ +int rh_fetch(struct rh_if *rhc) { + uint64 data; +#if KL + if (rhc->imode == 2 && (rhc->cop & 2) != 0) { +// rh_finish_op(rhc, 0); + return 0; + } +#endif + if (rhc->ccw > MEMSIZE) { + rh_finish_op(rhc, 1); + return 0; + } + data = M[rhc->ccw]; +#if KL + if (rhc->imode == 2) { +//fprintf(stderr, "RH20 fetch %06o %012llo\n\r", rhc->ccw, data); + while((data & RH20_XFER) == 0) { + rhc->ccw = (uint32)(data & AMASK); + if ((data & (BIT1|BIT2)) == 0) { +// rh_finish_op(rhc, 0); + return 0; + } + if (rhc->ccw > MEMSIZE) { + rh_finish_op(rhc, 1); + return 0; + } + data = M[rhc->ccw]; +//fprintf(stderr, "RH20 fetch2 %06o %012llo\n\r", rhc->ccw, data); + } + rhc->wcr = (((data >> CSHIFT) & RH20_WMASK) ^ WMASK) + 1; + rhc->cda = (data & AMASK); + rhc->cop = (data >> 33) & 07; + rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK); + return 1; + } +#endif + while((data & (WMASK << CSHIFT)) == 0) { + if ((data & AMASK) == 0 || (uint32)(data & AMASK) == rhc->ccw) { + rh_finish_op(rhc, 0); + return 0; + } + rhc->ccw = (uint32)(data & AMASK); + if (rhc->ccw > MEMSIZE) { + rh_finish_op(rhc, 1); + return 0; + } + data = M[rhc->ccw]; + } + rhc->wcr = (uint32)((data >> CSHIFT) & WMASK); + rhc->cda = (uint32)(data & AMASK); + rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK); + return 1; +} + +/* Read next word */ +int rh_read(struct rh_if *rhc) { + uint64 data; + if (rhc->wcr == 0) { + if (!rh_fetch(rhc)) + return 0; + } + rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK); + if (rhc->cda != 0) { + if (rhc->cda > MEMSIZE) { + rh_finish_op(rhc, 1); + return 0; + } +#if KL + if (rhc->imode == 2) { + data = M[rhc->cda]; + if (rhc->cop & 01) + rhc->cda = (uint32)((rhc->cda - 1) & AMASK); + else + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + } else { + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + data = M[rhc->cda]; + } +#else + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + data = M[rhc->cda]; +#endif + } else { + data = 0; + } + rhc->buf = data; + if (rhc->wcr == 0) { + return rh_fetch(rhc); + } + return 1; +} + +/* Write next word */ +int rh_write(struct rh_if *rhc) { + if (rhc->wcr == 0) { + if (!rh_fetch(rhc)) + return 0; + } + rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK); + if (rhc->cda != 0) { + if (rhc->cda > MEMSIZE) { + rh_finish_op(rhc, 1); + return 0; + } +#if KL + if (rhc->imode == 2) { + M[rhc->cda] = rhc->buf; + if (rhc->cop & 01) + rhc->cda = (uint32)((rhc->cda - 1) & AMASK); + else + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + } else { + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + M[rhc->cda] = rhc->buf; + } +#else + rhc->cda = (uint32)((rhc->cda + 1) & AMASK); + M[rhc->cda] = rhc->buf; +#endif + } + if (rhc->wcr == 0) { + return rh_fetch(rhc); + } + return 1; +} + From ba13f67289f3aadc9635918f894a8caff3b1b929 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 10 Nov 2019 21:36:59 -0500 Subject: [PATCH 52/98] KA10: Misc fixes. Tops 20 starting to work. --- PDP10/kl10_fe.c | 2 +- PDP10/kx10_cpu.c | 132 +++++++++++++++++++++++++++-------------------- PDP10/kx10_rh.c | 1 + PDP10/kx10_rp.c | 3 ++ PDP10/kx10_rs.c | 4 +- PDP10/kx10_tu.c | 4 +- 6 files changed, 86 insertions(+), 60 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 3031978..a47d52c 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -480,7 +480,7 @@ sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n"); sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAO %06o\n", dev, (uint32)*data); if (*data == 01365) { dte_unit[0].STATUS |= DTE_SEC|DTE_10ER; - dte_unit[0].STATUS &= ~(DTE_10DB); + dte_unit[0].STATUS &= ~(DTE_10DB|DTE_IND|DTE_11DB); break; } dte_unit[0].CNT = (*data & (DTE_TO10IB|DTE_TO10BC)); diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 172040e..362a1a3 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -892,32 +892,36 @@ struct { int n; int l; } _byte_adj[] = { - { /* 37 */ 36, 6, 38, 0 }, - { /* 38 */ 30, 6, 39, 0 }, - { /* 39 */ 24, 6, 40, 0 }, - { /* 40 */ 18, 6, 41, 0 }, - { /* 41 */ 12, 6, 42, 0 }, - { /* 42 */ 6, 6, 43, 0 }, - { /* 43 */ 0, 6, 37, 1 }, - { /* 44 */ 36, 8, 45, 0 }, - { /* 45 */ 28, 8, 46, 0 }, - { /* 46 */ 20, 8, 47, 0 }, - { /* 47 */ 12, 8, 48, 0 }, - { /* 48 */ 4, 8, 44, 1 }, - { /* 49 */ 36, 7, 50, 0 }, - { /* 50 */ 29, 7, 51, 0 }, - { /* 51 */ 22, 7, 52, 0 }, - { /* 52 */ 15, 7, 53, 0 }, - { /* 53 */ 8, 7, 54, 0 }, - { /* 54 */ 1, 7, 49, 1 }, - { /* 55 */ 36, 9, 56, 0 }, - { /* 56 */ 27, 9, 57, 0 }, - { /* 57 */ 18, 9, 58, 0 }, - { /* 58 */ 9, 9, 59, 0 }, - { /* 59 */ 0, 9, 55, 1 }, - { /* 60 */ 36,18, 61, 0 }, - { /* 61 */ 18,18, 62, 0 }, - { /* 62 */ 0,18, 60, 1 } + { /* 37 */ 36, 6, 38, 0 }, /* 45 */ + { /* 38 */ 30, 6, 39, 0 }, /* 46 */ + { /* 39 */ 24, 6, 40, 0 }, /* 47 */ + { /* 40 */ 18, 6, 41, 0 }, /* 50 */ + { /* 41 */ 12, 6, 42, 0 }, /* 51 */ + { /* 42 */ 6, 6, 43, 0 }, /* 52 */ + { /* 43 */ 0, 6, 37, 1 }, /* 53 */ + + { /* 44 */ 36, 8, 45, 0 }, /* 54 */ + { /* 45 */ 28, 8, 46, 0 }, /* 55 */ + { /* 46 */ 20, 8, 47, 0 }, /* 56 */ + { /* 47 */ 12, 8, 48, 0 }, /* 57 */ + { /* 48 */ 4, 8, 44, 1 }, /* 60 */ + + { /* 49 */ 36, 7, 50, 0 }, /* 61 */ + { /* 50 */ 29, 7, 51, 0 }, /* 62 */ + { /* 51 */ 22, 7, 52, 0 }, /* 63 */ + { /* 52 */ 15, 7, 53, 0 }, /* 64 */ + { /* 53 */ 8, 7, 54, 0 }, /* 65 */ + { /* 54 */ 1, 7, 49, 1 }, /* 66 */ + + { /* 55 */ 36, 9, 56, 0 }, /* 67 */ + { /* 56 */ 27, 9, 57, 0 }, /* 70 */ + { /* 57 */ 18, 9, 58, 0 }, /* 71 */ + { /* 58 */ 9, 9, 59, 0 }, /* 72 */ + { /* 59 */ 0, 9, 55, 1 }, /* 73 */ + + { /* 60 */ 36,18, 61, 0 }, /* 74 */ + { /* 61 */ 18,18, 62, 0 }, /* 75 */ + { /* 62 */ 0,18, 60, 1 } /* 76 */ }; #endif @@ -1284,7 +1288,7 @@ t_stat dev_pag(uint32 dev, uint64 *data) { e_tlb[page+i] = 0; } /* If not user do exec mappping */ - if (/*!uf && !t20_page &&*/ (page & 0740) == 0340) { + if (!t20_page && (page & 0740) == 0340) { /* Pages 340-377 via UBT */ page += 01000 - 0340; upmp = 1; @@ -2066,7 +2070,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) int base = 0540; #endif -//fprintf(stderr, "Lookup Page %o %03o %0o %o %o\r\n", sect, page, t20_page, upmp, uf); +//fprintf(stderr, "Lookup Page %o %03o %0o upmp=%o u=%o w=%o %06o\r\n", sect, page, t20_page, upmp, uf, AB); /* Get segment pointer */ /* And save it */ #if KLB @@ -2117,7 +2121,7 @@ sect_loop: sim_interval--; cst_val = M[cst + pg]; if ((cst_val & PG_AGE) == 0) { -//fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, c); +//fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, cst_val); if (trap) { fault_data = 0; page_fault = 1; @@ -2221,7 +2225,7 @@ pg_loop: if (cst) { sim_interval--; cst_val = M[cst + pg]; -//fprintf(stderr, "ZMap %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); +//fprintf(stderr, "CMap %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); if ((cst_val & PG_AGE) == 0) { if (trap) { fault_data = 0; @@ -2233,7 +2237,7 @@ pg_loop: if (wr) cst_val |= 1; } else if (wr) { /* Trying to write and not writable */ -//fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, cst_val); +//fprintf(stderr, "WMap %012llo %012llo age\n\r", data, cst_val); if (trap) { fault_data = 0 /* Write fault */; page_fault = 1; @@ -2360,6 +2364,18 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int //fprintf(stderr, " %o %o\n\r", uf, pub); } +#if KLB + /* Check if invalid section */ + if (QKLB && t20_page && !flag && (sect & 07740) != 0) { + fault_data = (027LL << 30) | (((uint64)sect) << 18) | (uint64)addr; + if (uf) /* U */ + fault_data |= SMASK; /* BIT0 */ +//fprintf(stderr, "Invalid section %012llo\n\r", fault_data); + page_fault = 1; + return 0; + } +#endif + /* Handle KI paging odditiy */ if (!uf && !t20_page && (page & 0740) == 0340) { /* Pages 340-377 via UBT */ @@ -2373,8 +2389,9 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int else data = e_tlb[page]; +//fprintf(stderr, "Map page %06o -> %06o %06o %o\n\r", page, data, sect, flag); #if KLB - if (QKLB && t20_page && ((data >> 18) & 077) != ((flag) ? 0 : sect)) + if (QKLB && t20_page && ((data >> 18) & 037) != ((flag) ? 0 : sect)) data = 0; #endif /* If not valid, go refill it */ @@ -2409,8 +2426,21 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int /* Check if we need to modify TLB entry for TOPS 20 */ if (t20_page && (data & KL_PAG_A) && (wr & ((data & KL_PAG_W) == 0)) && (data & KL_PAG_S)) { - /* Try and reload TLB and modify the CST */ - data = load_tlb(uf, page, upmp, wr, 0, flag); + uint64 cst = FM[(06<<4)|2] & PG_MASK; + /* Update CST entry if needed */ + if (cst) { + uint64 cst_val; + int pg = data & 017777; + sim_interval--; + cst_val = M[cst + pg]; + M[cst + pg] = cst_val | 1; + } + data |= KL_PAG_W; + /* Map the page */ + if (uf || upmp) + u_tlb[page] = data; + else + e_tlb[page] = data; } /* create location. */ @@ -2501,16 +2531,6 @@ int Mem_read(int flag, int cur_context, int fetch) { t_addr addr; #if KLB - /* Check if invalid section */ - if (QKLB && t20_page && !flag && (sect & 07740) != 0) { - fault_data = (027LL << 30) | (uint64)AB | (((uint64)sect) << 18); - if (USER==0) /* U */ - fault_data |= SMASK; /* BIT0 */ -//fprintf(stderr, "Invalid section %012llo\n\r", fault_data); - page_fault = 1; - return 0; - } - if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { #else if (AB < 020) { @@ -2547,16 +2567,6 @@ int Mem_write(int flag, int cur_context) { t_addr addr; #if KLB - /* Check if invalid section */ - if (QKLB && t20_page && !flag && (sect & 07740) != 0) { - fault_data = (027LL << 30) | (uint64)AB | (((uint64)sect) << 18); - if (USER==0) /* U */ - fault_data |= SMASK; /* BIT0 */ -//fprintf(stderr, "Invalid section %012llo\n\r", fault_data); - page_fault = 1; - return 0; - } - if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { #else if (AB < 020) { @@ -5802,6 +5812,8 @@ unasign: FE = (AR >> 30) & 077; /* P */ #if KLB if (QKLB && FE > 36) { + if (FE == 077) + goto muuo; f = 1; SC = _byte_adj[(FE - 37)].s; FE = _byte_adj[(FE - 37)].p; @@ -5886,6 +5898,8 @@ fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); if (QKLB && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; //fprintf(stderr, "ILDB %012llo %d %d -> %d %d %d\n\r", AR, SCAD, i, _byte_adj[i].p, _byte_adj[i].s,_byte_adj[i].n); + if (SCAD == 077) + goto muuo; SC = _byte_adj[i].s; SCAD = (_byte_adj[i].p + (0777 ^ SC) + 1) & 0777; i++; @@ -5968,6 +5982,8 @@ fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); #if KL & KLB if (QKLB && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; + if (SCAD == 077) + goto muuo; SC = _byte_adj[i].s; SCAD = _byte_adj[i].p; ld_ptr: @@ -8252,8 +8268,14 @@ skip_op: BR = SWAP_AR; /* Fall Through */ - case 0500: /* HLL */ case 0501: /* HLLI */ +#if KL && KLB + if (IR == 0501 && QKLB && t20_page && pc_sect != 0) + AR = ((AB > 020) ? ((uint64)pc_sect) : 1) << 18; + /* Fall Through */ +#endif + + case 0500: /* HLL */ case 0502: /* HLLM */ case 0504: /* HRL */ case 0505: /* HRLI */ diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index de2bc8b..53f6cf5 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -216,6 +216,7 @@ t_stat rh_devio(uint32 dev, uint64 *data) { if (*data & RH20_CLR_MBC) { if (rhc->dev_reset != NULL) rhc->dev_reset(dptr); + rhc->attn = 0; rhc->imode = 2; rhc->status = 0; } diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index 7506b87..5d25626 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -745,6 +745,8 @@ t_stat rp_svc (UNIT *uptr) uptr->CMD |= (ER1_UNS << 16) | DS_ATA|DS_ERR; /* set drive error */ if (GET_FNC(uptr->CMD) >= FNC_XFER) { /* xfr? set done */ rh_setirq(rhc); + } else { + rh_setattn(rhc, unit); } return (SCPE_OK); } @@ -755,6 +757,7 @@ t_stat rp_svc (UNIT *uptr) if (cyl >= rp_drv_tab[dtype].cyl) { uptr->CMD &= ~DS_PIP; uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA; + rh_setattn(rhc, unit); } diff = cyl - (uptr->CCYL & 01777); if (diff < 0) { diff --git a/PDP10/kx10_rs.c b/PDP10/kx10_rs.c index e8b58e8..67fca80 100644 --- a/PDP10/kx10_rs.c +++ b/PDP10/kx10_rs.c @@ -513,7 +513,7 @@ t_stat rs_svc (UNIT *uptr) if (rh_blkend(rhc)) goto rd_end; } - sim_activate(uptr, 20); + sim_activate(uptr, 10); } else { rd_end: sim_debug(DEBUG_DETAIL, dptr, "%s%o read done\n", dptr->name, unit); @@ -569,7 +569,7 @@ rd_end: goto wr_end; } if (sts) { - sim_activate(uptr, 20); + sim_activate(uptr, 10); } else { wr_end: sim_debug(DEBUG_DETAIL, dptr, "%s%o write done\n", dptr->name, unit); diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index ac238e2..4da4b8f 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -760,10 +760,10 @@ t_stat tu_srv(UNIT * uptr) tu_error(uptr, MTSE_OK); return SCPE_OK; } else - sim_activate(uptr, reclen * 100); + sim_activate(uptr, reclen * 50); return SCPE_OK; } - sim_activate(uptr, 100); + sim_activate(uptr, 50); return SCPE_OK; } From 297150d24ca6e0d964300b58f82b52d08146ee62 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 13 Nov 2019 20:38:16 -0500 Subject: [PATCH 53/98] KA10: Changes to KL10B, Tops 20 printer support started. --- PDP10/kl10_fe.c | 64 +++++++++++++++++++++++++-------- PDP10/kx10_cpu.c | 94 +++++++++++++++++++++++++++++------------------- PDP10/kx10_rh.c | 14 ++++++-- PDP10/kx10_rp.c | 4 +-- 4 files changed, 121 insertions(+), 55 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index a47d52c..006374b 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -320,6 +320,7 @@ t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *lpt_description (DEVICE *dptr); char lpt_buffer[134 * 3]; +uint16 lpt_vfu[256]; struct _buffer lpt_queue; @@ -992,16 +993,26 @@ cty: sim_activate(&dte_unit[1], 100); while (cmd->dptr < cmd->dcnt) { int ln; - if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) - return; ch = (int32)(cmd->data[cmd->dptr >> 1]); ln = (ch >> 8); ch &= 0177; if (ch != 0 && ln == 0) { + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) + return; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + } else + if (ch != 0 && ln >= 2 && ln <= tty_desc.lines) { + struct _buffer *otty; + ln -= 2; + otty = &tty_out[ln]; + if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) + return; + sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %o %d\n", ch, ln); + otty->buff[otty->in_ptr] = ch; + otty->in_ptr = (otty->in_ptr + 1) & 0xff; } cmd->dptr+=2; } @@ -1014,18 +1025,24 @@ cty: #if (NUM_DEVS_LP > 0) if (cmd->dev == PRI_EMLPT) { data1[0] = 0; - if (dte_queue(PRI_EMHDS, PRI_EMLPT, 1, data1) == 0) +// if (cmd->data[0] != 0) + // data1[0] = 2; + data1[1] = (lpt_unit.LINE == 0) ? 0x1: 0; + data1[2] = 0100220; + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 5, data1) == 0) return; } #endif if (cmd->dev == PRI_EMCTY) { data1[0] = 0; - if (dte_queue(PRI_EMHDS, PRI_EMCTY, 1, data1) == 0) + data1[1] = 0; + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMCTY, 2, data1) == 0) return; } if (cmd->dev == PRI_EMDH1) { data1[0] = 0; - if (dte_queue(PRI_EMHDS, PRI_EMDH1, 1, data1) == 0) + data1[1] = 0; + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMDH1, 2, data1) == 0) return; } break; @@ -1033,6 +1050,15 @@ cty: case PRI_EMHDS: /* Here is device status */ break; + case PRI_EMLDV: /* Load LP VFU */ + if (cmd->dev == PRI_EMLPT) { + int ln = 0; + while (cmd->dptr < cmd->dcnt) { + lpt_vfu[ln++] = cmd->data[cmd->dptr++]; + } + } + break; + #if (NUM_DEVS_TTY > 0) case PRI_EMFLO: /* Flush output */ if ((cmd->dev & 0377) == PRI_EMDLS) { @@ -1089,7 +1115,6 @@ cty: break; #endif case PRI_EMLDR: /* Load LP RAM */ - case PRI_EMLDV: /* Load LP VFU */ default: break; } @@ -1135,8 +1160,8 @@ void dte_transfer(UNIT *uptr) { } uptr->STATUS &= ~DTE_SIND; } else { - sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d send CMD: %o %o %o\n", - dte_out_ptr, dte_out_res, out->cnt, out->func, out->dev); + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d send CMD: [%o] %o %o %o\n", + dte_out_ptr, dte_out_res, scnt, out->cnt, out->func, out->dev); /* Get size of packet */ cnt = out->cnt; if ((out->func & PRI_IND_FLG) == 0) @@ -1368,9 +1393,10 @@ dte_queue(int func, int dev, int dcnt, uint16 *data) out->func = func; out->dev = dev; out->dcnt = (dcnt-1)*2; +// out->dcnt = dcnt*2; out->spare = 0; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d queue resp: %o %o %s %o\n", - dte_out_ptr, dte_out_res, out->cnt, out->func, + sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d queue resp: %o (%o) f=%o %s d=%o\n", + dte_out_ptr, dte_out_res, out->cnt, out->dcnt, out->func, (out->func > PRI_EMLDV)? "***":pri_name[out->func], out->dev); for (dp = &out->data[0]; dcnt > 0; dcnt--) { *dp++ = *data++; @@ -1407,6 +1433,7 @@ error: } /* Bump count of messages sent */ word = (word & ~(PRI_CMT_10IC|PRI_CMT_IP)) | ((word + 0400) & PRI_CMT_10IC); + word &= ~PRI_CMT_FWD; if ((uptr->STATUS & DTE_SIND) != 0) word |= PRI_CMT_IP; if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) @@ -1415,10 +1442,11 @@ error: if ((dte_out[dte_out_ptr].func & PRI_IND_FLG) == 0) dcnt += dte_out[dte_out_ptr].dcnt; /* Tell 10 something is ready */ - word = (uint64)dcnt; if ((uptr->STATUS & DTE_SIND) != 0) { - word = (uint64)(dte_out[dte_out_ptr].dcnt); + dcnt = dte_out[dte_out_ptr].dcnt; } + sim_debug(DEBUG_DATA, &dte_dev, "DTE: start: %012llo %o\n", word, dcnt); + word = (uint64)dcnt; if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_CNT, &word)) goto error; uptr->STATUS |= DTE_10DB; @@ -1711,7 +1739,7 @@ lpt_output(UNIT *uptr, char c) { t_stat lpt_svc (UNIT *uptr) { char c; - uint16 data1 = 0; + uint16 data1[5]; if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; @@ -1781,7 +1809,15 @@ t_stat lpt_svc (UNIT *uptr) lpt_output(uptr, c); } } - if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, &data1) == 0) +// data1[0] = 0; + if (uptr->LINE == 0) { + data1[0] = 0; + data1[1] = (lpt_unit.LINE == 0) ? 0x1: 0; + data1[2] = 0100220; + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 5, data1) == 0) + sim_activate(uptr, 1000); + } + if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) sim_activate(uptr, 1000); return SCPE_OK; } diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 362a1a3..e959817 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1276,9 +1276,7 @@ t_stat dev_pag(uint32 dev, uint64 *data) { case DATAO: if (dev & 040) { /* CLRPT */ - int upmp = 0; int page = (RMASK & AB) >> 9; - int uf = (FLAGS & USER) != 0; int i; page &= ~7; @@ -1291,7 +1289,6 @@ t_stat dev_pag(uint32 dev, uint64 *data) { if (!t20_page && (page & 0740) == 0340) { /* Pages 340-377 via UBT */ page += 01000 - 0340; - upmp = 1; for(i = 0; i < 8; i++) u_tlb[page+i] = 0; } @@ -2070,7 +2067,7 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) int base = 0540; #endif -//fprintf(stderr, "Lookup Page %o %03o %0o upmp=%o u=%o w=%o %06o\r\n", sect, page, t20_page, upmp, uf, AB); +//fprintf(stderr, "Lookup Page %o %03o upmp=%o u=%o w=%o %06o\r\n", sect, page, upmp, uf, wr, AB); /* Get segment pointer */ /* And save it */ #if KLB @@ -2111,6 +2108,7 @@ sect_loop: index = (data >> 18) & PG_IDX; sim_interval--; data = M[(data & RMASK) + spt]; +//fprintf(stderr, "IMap1 %012llo %o %o %o\n\r", data, pg << 9, index, page); if (((data >> 18) & PG_STG) != 0) { fault_data = 0; page_fault = 1; @@ -2121,7 +2119,7 @@ sect_loop: sim_interval--; cst_val = M[cst + pg]; if ((cst_val & PG_AGE) == 0) { -//fprintf(stderr, "ZMap %012llo %012llo age\n\r", data, cst_val); +//fprintf(stderr, "ZMap1 %012llo %012llo age\n\r", data, cst_val); if (trap) { fault_data = 0; page_fault = 1; @@ -2132,6 +2130,7 @@ sect_loop: } sim_interval--; data = M[(pg << 9) | index]; +//fprintf(stderr, "JMap1 %012llo %o %o %o\n\r", data, pg << 9, index, page); goto sect_loop; } if (((data >> 18) & PG_STG) != 0) { @@ -2187,7 +2186,7 @@ pg_loop: index = (data >> 18) & PG_IDX; sim_interval--; data = M[(data & RMASK) + spt]; -//fprintf(stderr, "IMap %012llo %o %o %o\n\r", data, pg << 9, index, page); +//fprintf(stderr, "IMap2 %012llo %o %o %o\n\r", data, pg << 9, index, page); if (((data >> 18) & PG_STG) != 0) { fault_data = 0; page_fault = 1; @@ -2197,7 +2196,7 @@ pg_loop: if (cst) { sim_interval--; cst_val = M[cst + pg]; -//fprintf(stderr, "ZMap %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); +//fprintf(stderr, "ZMap2 %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); if ((cst_val & PG_AGE) == 0) { if (trap) { fault_data = 0; @@ -2215,7 +2214,13 @@ pg_loop: /* Now have final page */ if ((data >> 18) & PG_STG) { - fault_data = 0; + fault_data = BIT2; /* BIT2 */ + if (acc_bits & PG_CAC) + fault_data |= BIT7; /* BIT7 */ + if (acc_bits & PG_PUB) + fault_data |= BIT6; /* BIT6 */ + if (acc_bits & PG_WRT) + fault_data |= BIT4; /* BIT4 */ page_fault = 1; return 0; } @@ -2236,7 +2241,7 @@ pg_loop: if (acc_bits & PG_WRT) { if (wr) cst_val |= 1; - } else if (wr) { /* Trying to write and not writable */ + } else if (wr) { /* Trying to write and not writable */ //fprintf(stderr, "WMap %012llo %012llo age\n\r", data, cst_val); if (trap) { fault_data = 0 /* Write fault */; @@ -2455,7 +2460,11 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int (!fetch || !OP_PORTAL(M[*loc]))) { /* Handle public violation */ fault_data = ((uint64)addr) | 021LL << 30 | BIT8 |((uf)?SMASK:0); -//fprintf(stderr, "Public fault %012llo %06o %06o\n\r", fault_data, FLAGS << 5, PC); +#if KLB + if (QKLB && t20_page) + fault_data |= (((uint64)sect) << 18); +#endif +//fprintf(stderr, "Public fault %012llo %06o %06o %012llo\n\r", fault_data, FLAGS << 5, PC, data); page_fault = 1; return 0; } @@ -7305,6 +7314,10 @@ jrstf: | (prev_sect & 037) #endif ) & FMASK; + if ((FLAGS & USER) == 0) { + MB &= ~SMASK; + MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + } if (uuo_cycle | pi_cycle) { FLAGS &= ~(USER|PUBLIC); /* Clear USER */ } @@ -7335,38 +7348,38 @@ jrstf: case 014: /* SFM */ #if KLB -// if (QKLB) { - MB = ((((uint64)FLAGS) << 23) | (uint64)(prev_sect & 037)) & FMASK; -//fprintf(stderr, "SFM %012llo\n\r", MB); - (void)Mem_write(0, 0); - goto last; - // } + MB = ((((uint64)FLAGS) << 23) | (uint64)(prev_sect & 037)) & FMASK; + if ((FLAGS & USER) == 0) { + MB &= ~SMASK; + MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + } + (void)Mem_write(0, 0); + goto last; #endif - // goto muuo; case 003: /* Invalid */ case 011: /* Invalid */ case 013: /* Invalid */ case 016: /* Invalid */ - goto muuo; + goto muuo; case 004: /* HALT */ - if ((FLAGS & (USER|USERIO)) == USER || - (FLAGS & (USER|PUBLIC)) == PUBLIC) { - goto muuo; - } else { - reason = STOP_HALT; - } - break; + if ((FLAGS & (USER|USERIO)) == USER || + (FLAGS & (USER|PUBLIC)) == PUBLIC) { + goto muuo; + } else { + reason = STOP_HALT; + } + break; case 010: /* JEN */ - /* Restore interrupt level. */ - if ((FLAGS & (USER|USERIO)) == USER || - (FLAGS & (USER|PUBLIC)) == PUBLIC) { - goto muuo; - } else { - pi_restore = 1; - } - break; + /* Restore interrupt level. */ + if ((FLAGS & (USER|USERIO)) == USER || + (FLAGS & (USER|PUBLIC)) == PUBLIC) { + goto muuo; + } else { + pi_restore = 1; + } + break; } #if KL_ITS if (QITS && (FLAGS & USER)) { @@ -7530,7 +7543,17 @@ jrstf: } /* Check if Paging Enabled */ - if (!page_enable || AB < 020) { + if (!page_enable) { + AR = AB; /* direct map */ + if (flag1) /* U */ + AR |= SMASK; /* BIT0 */ + AR |= BIT2|BIT3|BIT4|BIT8; + set_reg(AC, AR); + break; + } + + /* Check if access to register */ + if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { AR = AB; /* direct map */ if (flag1) /* U */ AR |= SMASK; /* BIT0 */ @@ -8790,9 +8813,6 @@ last: #endif return SCPE_STEP; } -//#if KL -// FLAGS &= ~ADRFLT; -//#endif } /* Should never get here */ #if ITS diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index 53f6cf5..06c52be 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -218,7 +218,6 @@ t_stat rh_devio(uint32 dev, uint64 *data) { rhc->dev_reset(dptr); rhc->attn = 0; rhc->imode = 2; - rhc->status = 0; } rhc->status &= ~(07LL|IADR_ATTN|RH20_MASS_EN); rhc->status |= *data & (07LL|IADR_ATTN|RH20_MASS_EN); @@ -651,6 +650,15 @@ void rh_setup(struct rh_if *rhc, uint32 addr) /* Fetch the next IO control word */ int rh_fetch(struct rh_if *rhc) { uint64 data; + int reg; + DEVICE *dptr; + + for (reg = 0; rh[reg].dev_num != 0; reg++) { + if (rh[reg].rh == rhc) { + dptr = rh[reg].dev; + break; + } + } #if KL if (rhc->imode == 2 && (rhc->cop & 2) != 0) { // rh_finish_op(rhc, 0); @@ -662,9 +670,9 @@ int rh_fetch(struct rh_if *rhc) { return 0; } data = M[rhc->ccw]; + sim_debug(DEBUG_EXP, dptr, "%s fetch %06o %012llo\n\r", dptr->name, rhc->ccw, data); #if KL if (rhc->imode == 2) { -//fprintf(stderr, "RH20 fetch %06o %012llo\n\r", rhc->ccw, data); while((data & RH20_XFER) == 0) { rhc->ccw = (uint32)(data & AMASK); if ((data & (BIT1|BIT2)) == 0) { @@ -676,6 +684,7 @@ int rh_fetch(struct rh_if *rhc) { return 0; } data = M[rhc->ccw]; + sim_debug(DEBUG_EXP, dptr, "%s fetch2 %06o %012llo\n\r", dptr->name, rhc->ccw, data); //fprintf(stderr, "RH20 fetch2 %06o %012llo\n\r", rhc->ccw, data); } rhc->wcr = (((data >> CSHIFT) & RH20_WMASK) ^ WMASK) + 1; @@ -696,6 +705,7 @@ int rh_fetch(struct rh_if *rhc) { return 0; } data = M[rhc->ccw]; + sim_debug(DEBUG_EXP, dptr, "%s fetch2 %06o %012llo\n\r", dptr->name, rhc->ccw, data); } rhc->wcr = (uint32)((data >> CSHIFT) & WMASK); rhc->cda = (uint32)(data & AMASK); diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index 5d25626..4dd7927 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -935,8 +935,8 @@ rd_end: uptr->hwmark = 0; } sts = rh_read(rhc); - sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %06o\n", - dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->wcr); + sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %06o %06o\n", + dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr); rp_buf[ctlr][uptr->DATAPTR++] = rhc->buf; if (sts == 0) { while (uptr->DATAPTR < RP_NUMWD) From f2115249f257ed44c9e941a3bfc325c91a2e7591 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 14 Nov 2019 23:23:01 -0500 Subject: [PATCH 54/98] SCP: Updated to current. --- scp.c | 11 +++++++++++ sim_fio.c | 2 +- sim_sock.c | 55 ++++++++++++++++++++++++------------------------------ sim_tmxr.c | 6 ++++-- 4 files changed, 40 insertions(+), 34 deletions(-) diff --git a/scp.c b/scp.c index ba15f05..3a7c098 100644 --- a/scp.c +++ b/scp.c @@ -3383,6 +3383,9 @@ if (*cptr) { sim_printf ("No help available for the %s command\n", cmdp->name); } } + else { + sim_printf ("No such command or device %s\n", gbuf); + } } else { if (dptr->flags & DEV_DIS) @@ -12886,6 +12889,14 @@ if (sim_deb && dptr && ((dptr->dctrl | (uptr ? uptr->dctrl : 0)) & dbits)) { } j = i + 1; } + else { + if (buf[i] == 0) { /* Imbedded \0 character in formatted result? */ + fprintf (stderr, "sim_debug() formatted result: '%s'\r\n" + " has an imbedded \\0 character.\r\n" + "DON'T DO THAT!\r\n", buf); + abort(); + } + } } if (i > j) { if (!debug_unterm) /* print prefix when required */ diff --git a/sim_fio.c b/sim_fio.c index 97c1c0c..9bfecde 100644 --- a/sim_fio.c +++ b/sim_fio.c @@ -821,7 +821,7 @@ if (strchr (parts, 't') || strchr (parts, 'z')) { memset (&filestat, 0, sizeof (filestat)); (void)stat (fullpath, &filestat); if (sizeof (filestat.st_size) == 4) - sprintf (filesizebuf, "%ld ", filestat.st_size); + sprintf (filesizebuf, "%ld ", (long)filestat.st_size); else sprintf (filesizebuf, "%" LL_FMT "d ", (LL_TYPE)filestat.st_size); tm = localtime (&filestat.st_mtime); diff --git a/sim_sock.c b/sim_sock.c index 4235cea..01b2529 100644 --- a/sim_sock.c +++ b/sim_sock.c @@ -284,41 +284,34 @@ if (hostname) { (0 == strcmp("255.255.255.255", hostname))) { fixed[0] = &ipaddr; fixed[1] = NULL; + if ((hints->ai_flags & AI_CANONNAME) && !(hints->ai_flags & AI_NUMERICHOST)) { + he = gethostbyaddr((char *)&ipaddr, 4, AF_INET); + if (NULL != he) + cname = he->h_name; + else + cname = hostname; + } + ips = fixed; } else { - if ((0xffffffff != (ipaddr.s_addr = inet_addr(hostname))) || - (0 == strcmp("255.255.255.255", hostname))) { - fixed[0] = &ipaddr; - fixed[1] = NULL; - if ((hints->ai_flags & AI_CANONNAME) && !(hints->ai_flags & AI_NUMERICHOST)) { - he = gethostbyaddr((char *)&ipaddr, 4, AF_INET); - if (NULL != he) - cname = he->h_name; - else - cname = hostname; - } - ips = fixed; + if (hints->ai_flags & AI_NUMERICHOST) + return EAI_NONAME; + he = gethostbyname(hostname); + if (he) { + ips = (struct in_addr **)he->h_addr_list; + if (hints->ai_flags & AI_CANONNAME) + cname = he->h_name; } else { - if (hints->ai_flags & AI_NUMERICHOST) - return EAI_NONAME; - he = gethostbyname(hostname); - if (he) { - ips = (struct in_addr **)he->h_addr_list; - if (hints->ai_flags & AI_CANONNAME) - cname = he->h_name; - } - else { - switch (h_errno) - { - case HOST_NOT_FOUND: - case NO_DATA: - return EAI_NONAME; - case TRY_AGAIN: - return EAI_AGAIN; - default: - return EAI_FAIL; - } + switch (h_errno) + { + case HOST_NOT_FOUND: + case NO_DATA: + return EAI_NONAME; + case TRY_AGAIN: + return EAI_AGAIN; + default: + return EAI_FAIL; } } } diff --git a/sim_tmxr.c b/sim_tmxr.c index d81e366..efb7906 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -2745,8 +2745,10 @@ while (*tptr) { else if (0 == MATCH_CMD (cptr, "TELNET")) listennotelnet = FALSE; - else - return sim_messagef (SCPE_ARG, "Invalid Specifier: %s\n", tptr); + else { + if (*tptr) + return sim_messagef (SCPE_ARG, "Invalid Specifier: %s\n", tptr); + } } cptr = init_cptr; } From 9704d847cfcbccc1c6c8376060e33f27310e925a Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 14 Nov 2019 23:23:19 -0500 Subject: [PATCH 55/98] KA10: Cleanup of KL10B MUUO and LUUO handling. --- PDP10/kl10_fe.c | 10 ++- PDP10/kx10_cpu.c | 182 +++++++++++++++++++++++++++-------------------- 2 files changed, 111 insertions(+), 81 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 006374b..b27c853 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -1062,8 +1062,14 @@ cty: #if (NUM_DEVS_TTY > 0) case PRI_EMFLO: /* Flush output */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2;; - tty_out[ln].in_ptr = tty_out[ln].out_ptr = 0; + int ln = ((cmd->sdev >> 8) & 0377) - 2; + if (ln == -2) + cty_out.in_ptr = cty_out.out_ptr = 0; + else + tty_out[ln].in_ptr = tty_out[ln].out_ptr = 0; + data1[0] = cmd->sdev; + if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, data1) == 0) + return; } break; case PRI_EMDSC: /* Dataset connect */ diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index e959817..6bb522c 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1988,7 +1988,7 @@ sim_debug(DEBUG_DATAIO, &cpu_dev, "Rl=%06o Pl=%06o, Rh=%06o, Ph=%06o\n", Rl, Pl, #if KL int -load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) +load_tlb(int uf, int page, int upmp, int wr) { uint64 data; @@ -2071,11 +2071,8 @@ load_tlb(int uf, int page, int upmp, int wr, int trap, int flag) /* Get segment pointer */ /* And save it */ #if KLB - if (QKLB) { - base = 0540; - if (!flag) - base += (sect & 037); - } + if (QKLB) + base = 0540 + (sect & 037); #endif sim_interval--; if (uf) @@ -2120,10 +2117,8 @@ sect_loop: cst_val = M[cst + pg]; if ((cst_val & PG_AGE) == 0) { //fprintf(stderr, "ZMap1 %012llo %012llo age\n\r", data, cst_val); - if (trap) { - fault_data = 0; - page_fault = 1; - } + fault_data = 0; + page_fault = 1; return 0; } M[cst + pg] = (cst_val & cst_msk) | cst_dat; @@ -2147,10 +2142,8 @@ sect_loop: cst_val = M[cst + pg]; //fprintf(stderr, "ZMap %08o %012llo %012llo age\n\r", cst+pg, data, cst_val); if ((cst_val & PG_AGE) == 0) { - if (trap) { - fault_data = 0; - page_fault = 1; - } + fault_data = 0; + page_fault = 1; return 0; } M[cst + pg] = (cst_val & cst_msk) | cst_dat; @@ -2198,10 +2191,8 @@ pg_loop: cst_val = M[cst + pg]; //fprintf(stderr, "ZMap2 %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); if ((cst_val & PG_AGE) == 0) { - if (trap) { - fault_data = 0; - page_fault = 1; - } + fault_data = 0; + page_fault = 1; return 0; } M[cst + pg] = (cst_val & cst_msk) | cst_dat; @@ -2232,10 +2223,8 @@ pg_loop: cst_val = M[cst + pg]; //fprintf(stderr, "CMap %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); if ((cst_val & PG_AGE) == 0) { - if (trap) { - fault_data = 0; - page_fault = 1; - } + fault_data = 0; + page_fault = 1; return 0; } if (acc_bits & PG_WRT) { @@ -2243,10 +2232,8 @@ pg_loop: cst_val |= 1; } else if (wr) { /* Trying to write and not writable */ //fprintf(stderr, "WMap %012llo %012llo age\n\r", data, cst_val); - if (trap) { - fault_data = 0 /* Write fault */; - page_fault = 1; - } + fault_data = 0 /* Write fault */; + page_fault = 1; return 0; } M[cst + pg] = (cst_val & cst_msk) | cst_dat; @@ -2273,7 +2260,7 @@ pg_loop: data |= KL_PAG_C; #if KLB if (QKLB) - data |= (((flag) ? 0: sect) & 037) << 18; + data |= (sect & 037) << 18; #endif /* And save it */ if (uf) @@ -2348,7 +2335,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int /* AC = 4 all general access */ /* AC = 8 only in cur_context EA calculations */ if (flag) - uf = 0; + sect = uf = 0; else if (xct_flag != 0 && !uf && !fetch) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); #if KLB @@ -2371,7 +2358,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int #if KLB /* Check if invalid section */ - if (QKLB && t20_page && !flag && (sect & 07740) != 0) { + if (QKLB && t20_page && (sect & 07740) != 0) { fault_data = (027LL << 30) | (((uint64)sect) << 18) | (uint64)addr; if (uf) /* U */ fault_data |= SMASK; /* BIT0 */ @@ -2396,12 +2383,12 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int //fprintf(stderr, "Map page %06o -> %06o %06o %o\n\r", page, data, sect, flag); #if KLB - if (QKLB && t20_page && ((data >> 18) & 037) != ((flag) ? 0 : sect)) + if (QKLB && t20_page && ((data >> 18) & 037) != sect) data = 0; #endif /* If not valid, go refill it */ if (data == 0) { - data = load_tlb(uf, page, upmp, wr, 1, flag); + data = load_tlb(uf, page, upmp, wr); if (data == 0 && page_fault) { fault_data |= ((uint64)addr); /* Ignore faults if flag set */ @@ -2491,7 +2478,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int #endif fault_data = BIT8 | (uint64)addr; #if KLB - if (QKLB) + if (QKLB && t20_page) fault_data |= (((uint64)sect) << 18); #endif /* Remap the flag bits */ @@ -2614,6 +2601,7 @@ int exec_page_lookup(t_addr addr, int wr, int *loc) int data; int page = (RMASK & addr) >> 9; int upmp = 0; + int sav_sect = sect; /* If paging is not enabled, address is direct */ if (!page_enable) { @@ -2636,9 +2624,13 @@ int exec_page_lookup(t_addr addr, int wr, int *loc) /* If not valid, go refill it */ if (data == 0 || (data & LMASK) != 0) { - data = load_tlb(0, page, upmp, wr, 0, 1); - if (data == 0) + sect = 0; + data = load_tlb(0, page, upmp, wr); + if (data == 0) { + page_fault = 0; return 1; + } + sect = sav_sect; } *loc = ((data & 017777) << 9) + (addr & 0777); return 0; @@ -4147,7 +4139,7 @@ no_fetch: /* Handle indirection repeat until no longer indirect */ #if KL && KLB /* If we are doing a PXCT with E1 or E2 set, change section */ - if (QKLB) { + if (QKLB && t20_page) { if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) sect = cur_sect = prev_sect; @@ -4179,7 +4171,7 @@ no_fetch: AR = get_reg(ix); #if KLB /* Check if extended indexing */ - if (QKLB && cur_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + if (QKLB && t20_page && cur_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { AR = (AR + ((AB & RSIGN) ? SECTM|((uint64)AB): (uint64)AB)) & (SECTM|RMASK); sect = cur_sect = (AR >> 18) & 07777; glb_sect = 1; @@ -4203,7 +4195,7 @@ in_loop: goto last; #if KL & KLB /* Check if extended indexing */ - if (QKLB && (cur_sect != 0 || glb_sect)) { + if (QKLB && t20_page && (cur_sect != 0 || glb_sect)) { if (MB & SMASK || cur_sect == 0) { /* Instruction format IFIW */ if (MB & BIT1 && cur_sect != 0) { /* Illegal index word */ //fprintf(stderr, "Illegal fault %06o %012llo\n\r", PC, MB); @@ -4279,14 +4271,6 @@ in_loop: } while (ind & !pi_rq); if (IR != 0254) { AR &= RMASK; -#if KL & KLB - if (QKLB && IR == 0415 && pc_sect != 0) { - if (glb_sect == 0 && AR < 020) - AR |= BIT17; - else - AR |= ((uint64)cur_sect) << 18; - } -#endif } @@ -4439,9 +4423,9 @@ st_pi: /* Process the instruction */ switch (IR) { #if KL & KLB - case 0052: - case 0053: - if (QKLB && t20_page) { + case 0052: /* PMOVE */ + case 0053: /* PMOVEM */ + if (QKLB && t20_page && (FLAGS & USER) == 0) { if (Mem_read(0, 0, 0)) goto last; AB = MB & (SECTM|RMASK); @@ -4495,6 +4479,7 @@ unasign: MB = ((uint64)(IR) << 27) | ((uint64)(AC) << 23) | (uint64)(AB); AB = ub_ptr | 0424; #if KL & KLB + /* If single sections KL10 UUO starts at 425 */ if (!QKLB && !QITS && t20_page) AB = AB + 1; #endif @@ -4504,18 +4489,29 @@ unasign: #if KL & KLB if (QKLB && t20_page) MB = ((uint64)(pc_sect) << 18) | ((PC + (trap_flag == 0)) & RMASK); - else -#endif + else { + MB = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + (trap_flag == 0)) & RMASK); + if ((FLAGS & USER) == 0) { + MB &= ~SMASK; + MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + } + } +#else MB = (((uint64)(FLAGS) << 23) & LMASK) | ((PC + (trap_flag == 0)) & RMASK); if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; } +#endif Mem_write_nopage(); #if KL extend = 0; #if KLB if (QKLB && t20_page) { /* Save address */ + if (pc_sect != 0 && glb_sect == 0 && AR < 020) + AR |= BIT17; + else + AR |= ((uint64)cur_sect) << 18; MB = AR; AB ++; Mem_write_nopage(); @@ -4579,13 +4575,17 @@ unasign: #if KL & KLB /* LUUO's in non-zero section are different */ if (QKLB && t20_page && pc_sect != 0) { - AR = (((uint64)cur_sect) << 18) | AB; /* Save address */ + /* Save Effective address */ + if (pc_sect != 0 && glb_sect == 0 && AR < 020) + AR = BIT17; + else + AR = ((uint64)cur_sect) << 18; + AR |= AB; /* Save address */ /* Grab address of LUUO block from user base 420 */ AB = ((FLAGS & USER) ? ub_ptr : eb_ptr) + 0420; Mem_read_nopage(); /* Now save like MUUO */ - AB = MB & RMASK; - sect = (MB >> 18) & 07777; + AB = MB & (SECTM|RMASK); MB = (((uint64)((IR << 9) | (AC << 5))) | ((uint64)(FLAGS) << 23)) & FMASK; if ((FLAGS & USER) == 0) { MB &= ~SMASK; @@ -4596,8 +4596,6 @@ unasign: AB++; MB = ((uint64)(pc_sect) << 18) | ((PC + (trap_flag == 0)) & RMASK); Mem_write_nopage(); - extend = 0; - /* Save Effective address */ MB = AR; AB ++; Mem_write_nopage(); @@ -4707,7 +4705,7 @@ unasign: case 0105: /* ADJSP */ BR = get_reg(AC); #if KLB - if (QKLB && pc_sect != 0 && (BR & SMASK) == 0 && (BR & SECTM) != 0) { + if (QKLB && t20_page && pc_sect != 0 && (BR & SMASK) == 0 && (BR & SECTM) != 0) { AD = (((AR & RSIGN)?(LMASK|AR):AR) + BR) & (SECTM|RMASK); AD |= BR & ~(SECTM|RMASK); } else { @@ -5817,9 +5815,9 @@ unasign: if (SC) { int bpw, left, newb, adjw, adjb; - f = 0; FE = (AR >> 30) & 077; /* P */ #if KLB + f = 0; if (QKLB && FE > 36) { if (FE == 077) goto muuo; @@ -5850,14 +5848,19 @@ fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); } FE = 36 - (adjb * SC) - ((36 - FE) % SC); /* New P */ #if KLB - if (QKLB && f) { + if (f) { /* Short pointer */ - f = (AR >> 30) & 077; /* P */ - AR = (((uint64)((f + adjb) & 077)) << 30) | /* Make new BP */ + for (f = 0; f < 28; f++) { + if (_byte_adj[f].s == SC && _byte_adj[f].p == FE) { + FE = f + 37; + break; + } + } + AR = (((uint64)(FE & 077)) << 30) | /* Make new BP */ ((AR + adjw) & (SECTM|RMASK)); set_reg(AC, AR); break; - } else if (QKLB && pc_sect != 0 && (AR & BIT12) != 0) { + } else if (QKLB && t20_page && pc_sect != 0 && (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; if (Mem_read(0, 0, 0)) @@ -5904,7 +5907,7 @@ fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); AR = MB; SCAD = (AR >> 30) & 077; #if KL & KLB - if (QKLB && SCAD > 36) { /* Extended pointer */ + if (QKLB && t20_page && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; //fprintf(stderr, "ILDB %012llo %d %d -> %d %d %d\n\r", AR, SCAD, i, _byte_adj[i].p, _byte_adj[i].s,_byte_adj[i].n); if (SCAD == 077) @@ -5934,7 +5937,7 @@ fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); SCAD = ((0777 ^ SC) + 044 + 1) & 0777; #if KL #if KLB - if (QKLB && pc_sect != 0 && (AR & BIT12) != 0) { /* Full pointer */ + if (QKLB && t20_page && pc_sect != 0 && (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; if (Mem_read(0, 0, 0)) goto last; @@ -5989,7 +5992,7 @@ fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); SC = (AR >> 24) & 077; SCAD = (AR >> 30) & 077; #if KL & KLB - if (QKLB && SCAD > 36) { /* Extended pointer */ + if (QKLB && t20_page && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; if (SCAD == 077) goto muuo; @@ -6017,7 +6020,7 @@ ldb_ptr: #if KL ptr_flg = 1; #if KLB - if (QKLB && (SC < 36) && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { + if (QKLB && t20_page && (SC < 36) && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; //fprintf(stderr, "LBP %o %o %06o %012llo\n\r", SC, SCAD, AB, MB); @@ -7314,12 +7317,14 @@ jrstf: | (prev_sect & 037) #endif ) & FMASK; + /* Save Previous Public context */ if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; } if (uuo_cycle | pi_cycle) { FLAGS &= ~(USER|PUBLIC); /* Clear USER */ + sect = 0; /* Force section zero on IRQ */ } if (Mem_write(0, 0)) goto last; @@ -7347,7 +7352,6 @@ jrstf: break; case 014: /* SFM */ -#if KLB MB = ((((uint64)FLAGS) << 23) | (uint64)(prev_sect & 037)) & FMASK; if ((FLAGS & USER) == 0) { MB &= ~SMASK; @@ -7355,7 +7359,6 @@ jrstf: } (void)Mem_write(0, 0); goto last; -#endif case 003: /* Invalid */ case 011: /* Invalid */ @@ -7388,7 +7391,7 @@ jrstf: #endif PC = AR & RMASK; #if KLB - if (QKLB && glb_sect) + if (QKLB && t20_page && glb_sect) pc_sect = (AR >> 18) & 07777; #endif #else @@ -7569,8 +7572,15 @@ jrstf: flag3 = 1; } - AR = load_tlb(flag1, f, flag3, 0, 0, 0); - page_fault = 0; /* Incase error during lookup */ + AR = load_tlb(flag1, f, flag3, 0); + if (page_fault) { + page_fault = 0; + AR |= BIT8 | fault_data; + if (flag1) /* U */ + AR |= SMASK; + set_reg(AC, AR); + break; + } BR = AR; /* Remap the flag bits */ if (BR & KL_PAG_A) { /* A */ @@ -7623,7 +7633,7 @@ jrstf: /* Stack, JUMP */ case 0260: /* PUSHJ */ /* AR Frm PC */ #if KL & KLB - if (QKLB && pc_sect != 0) + if (QKLB && t20_page && pc_sect != 0) MB = ((uint64)pc_sect << 18) + (PC + !pi_cycle); else { #endif @@ -7843,7 +7853,7 @@ jrstf: case 0264: /* JSR */ /* AR Frm PC */ #if KL & KLB - if (QKLB && pc_sect != 0) + if (QKLB && t20_page && pc_sect != 0) MB = ((uint64)pc_sect << 18) + (PC + !pi_cycle); else { #endif @@ -7876,7 +7886,7 @@ jrstf: #endif PC_CHANGE #if KL & KLB - if (QKLB) { + if (QKLB && t20_page) { AR = AR + 1; if (AR & BIT17) cur_sect++; @@ -7891,7 +7901,7 @@ jrstf: case 0265: /* JSP */ /* AR Frm PC */ #if KL & KLB - if (QKLB && pc_sect != 0) + if (QKLB && t20_page && pc_sect != 0) AD = ((uint64)pc_sect << 18) + (PC + !pi_cycle); else { #endif @@ -7919,7 +7929,7 @@ jrstf: #endif PC_CHANGE #if KL & KLB - if (QKLB && glb_sect) + if (QKLB && t20_page && glb_sect) pc_sect = cur_sect; #endif PC = AR & RMASK; @@ -7941,7 +7951,7 @@ jrstf: #endif PC_CHANGE #if KL & KLB - if (QKLB && glb_sect) + if (QKLB && t20_page && glb_sect) pc_sect = cur_sect; #endif PC = AR & RMASK; @@ -8195,8 +8205,17 @@ skip_op: AR = AR & CM(BR); /* ANDCA */ break; - case 0414: /* SETM */ case 0415: /* SETMI */ +#if KL & KLB + /* XMOVEI for extended addressing */ + if (QKLB && t20_page && pc_sect != 0) { + if (glb_sect == 0 && AR < 020) + AR |= BIT17; + else + AR |= ((uint64)cur_sect) << 18; + } +#endif + case 0414: /* SETM */ case 0416: /* SETMM */ case 0417: /* SETMB */ /* SETM */ @@ -8293,8 +8312,13 @@ skip_op: case 0501: /* HLLI */ #if KL && KLB - if (IR == 0501 && QKLB && t20_page && pc_sect != 0) - AR = ((AB > 020) ? ((uint64)pc_sect) : 1) << 18; + /* XHLLI for extended addressing */ + if (QKLB && t20_page && IR == 0501 && pc_sect != 0) { + if (glb_sect == 0 && AR < 020) + AR = BIT17; + else + AR = ((uint64)cur_sect) << 18; + } /* Fall Through */ #endif From 6427b2c9b5d5d60008ffae7f9bd1c060a7ab7afe Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 17 Nov 2019 12:42:39 -0500 Subject: [PATCH 56/98] KA10: Fixed issue with OWBP and TWBP in zero section. --- PDP10/kx10_cpu.c | 101 +++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 60 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 6bb522c..bb9a5f0 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1988,7 +1988,7 @@ sim_debug(DEBUG_DATAIO, &cpu_dev, "Rl=%06o Pl=%06o, Rh=%06o, Ph=%06o\n", Rl, Pl, #if KL int -load_tlb(int uf, int page, int upmp, int wr) +load_tlb(int uf, int page, int wr) { uint64 data; @@ -2046,7 +2046,7 @@ load_tlb(int uf, int page, int upmp, int wr) #define PG_WRT 0020000 #define PG_KEP 0010000 #define PG_CAC 0004000 -#define PG_STG 0000077 +#define PG_STG (0000077LL << 18) #define PG_IDX 0000777 #define PG_MASK 0000003777777LL @@ -2067,7 +2067,7 @@ load_tlb(int uf, int page, int upmp, int wr) int base = 0540; #endif -//fprintf(stderr, "Lookup Page %o %03o upmp=%o u=%o w=%o %06o\r\n", sect, page, upmp, uf, wr, AB); +//fprintf(stderr, "Lookup Page %o %03o u=%o w=%o %06o\r\n", sect, page, uf, wr, AB); /* Get segment pointer */ /* And save it */ #if KLB @@ -2097,7 +2097,9 @@ sect_loop: case 2: /* Shared page */ acc_bits &= (data >> 18) & RMASK; sim_interval--; - data = M[(data & RMASK) + spt]; + index = data & RMASK; + data = M[index + spt]; +//fprintf(stderr, "SMap1 %012llo %o %o\n\r", data, index, index + spt); break; case 3: /* Indirect page */ @@ -2106,29 +2108,18 @@ sect_loop: sim_interval--; data = M[(data & RMASK) + spt]; //fprintf(stderr, "IMap1 %012llo %o %o %o\n\r", data, pg << 9, index, page); - if (((data >> 18) & PG_STG) != 0) { + if ((data & PG_STG) != 0) { fault_data = 0; page_fault = 1; return 0; } pg = data & PG_PAG; - if (cst) { - sim_interval--; - cst_val = M[cst + pg]; - if ((cst_val & PG_AGE) == 0) { -//fprintf(stderr, "ZMap1 %012llo %012llo age\n\r", data, cst_val); - fault_data = 0; - page_fault = 1; - return 0; - } - M[cst + pg] = (cst_val & cst_msk) | cst_dat; - } sim_interval--; data = M[(pg << 9) | index]; //fprintf(stderr, "JMap1 %012llo %o %o %o\n\r", data, pg << 9, index, page); goto sect_loop; } - if (((data >> 18) & PG_STG) != 0) { + if ((data & PG_STG) != 0) { fault_data = 0; page_fault = 1; return 0; @@ -2171,7 +2162,9 @@ pg_loop: case 2: /* Shared page */ acc_bits &= (data >> 18) & RMASK; sim_interval--; - data = M[(data & RMASK) + spt]; + index = data & RMASK; + data = M[index + spt]; +//fprintf(stderr, "SMap2 %012llo %o %o\n\r", data, index, index + spt); break; case 3: /* Indirect page */ @@ -2180,23 +2173,12 @@ pg_loop: sim_interval--; data = M[(data & RMASK) + spt]; //fprintf(stderr, "IMap2 %012llo %o %o %o\n\r", data, pg << 9, index, page); - if (((data >> 18) & PG_STG) != 0) { + if ((data & PG_STG) != 0) { fault_data = 0; page_fault = 1; return 0; } pg = data & RMASK; - if (cst) { - sim_interval--; - cst_val = M[cst + pg]; -//fprintf(stderr, "ZMap2 %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); - if ((cst_val & PG_AGE) == 0) { - fault_data = 0; - page_fault = 1; - return 0; - } - M[cst + pg] = (cst_val & cst_msk) | cst_dat; - } sim_interval--; data = M[(pg << 9) | index]; //fprintf(stderr, "JMap %012llo %o %o %o\n\r", data, pg << 9, index, page); @@ -2204,14 +2186,8 @@ pg_loop: } /* Now have final page */ - if ((data >> 18) & PG_STG) { - fault_data = BIT2; /* BIT2 */ - if (acc_bits & PG_CAC) - fault_data |= BIT7; /* BIT7 */ - if (acc_bits & PG_PUB) - fault_data |= BIT6; /* BIT6 */ - if (acc_bits & PG_WRT) - fault_data |= BIT4; /* BIT4 */ + if ((data & PG_STG) != 0) { + fault_data = 0; page_fault = 1; return 0; } @@ -2243,11 +2219,11 @@ pg_loop: } } /* Now construct a TBL entry */ -/* A = accessable */ -/* P = public */ -/* W = writable */ -/* S = user */ -/* C = cache */ + /* A = accessable */ + /* P = public */ + /* W = writable */ + /* S = user */ + /* C = cache */ data = pg | KL_PAG_A; if (acc_bits & PG_PUB) data |= KL_PAG_P; /* P */ @@ -2272,7 +2248,7 @@ pg_loop: /* Map the page */ sim_interval--; - if (uf | upmp) { + if (uf) { data = M[ub_ptr + (page >> 1)]; u_tlb[page & 01776] = (uint32)(RMASK & (data >> 18)); u_tlb[page | 1] = (uint32)(RMASK & data); @@ -2388,7 +2364,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int #endif /* If not valid, go refill it */ if (data == 0) { - data = load_tlb(uf, page, upmp, wr); + data = load_tlb(uf | upmp, page, wr); if (data == 0 && page_fault) { fault_data |= ((uint64)addr); /* Ignore faults if flag set */ @@ -2419,13 +2395,15 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int /* Check if we need to modify TLB entry for TOPS 20 */ if (t20_page && (data & KL_PAG_A) && (wr & ((data & KL_PAG_W) == 0)) && (data & KL_PAG_S)) { uint64 cst = FM[(06<<4)|2] & PG_MASK; + uint64 cst_msk = FM[(06<<4)|0]; + uint64 cst_dat = FM[(06<<4)|1]; /* Update CST entry if needed */ if (cst) { uint64 cst_val; int pg = data & 017777; sim_interval--; cst_val = M[cst + pg]; - M[cst + pg] = cst_val | 1; + M[cst + pg] = (cst_msk & cst_val) | cst_dat | 1; } data |= KL_PAG_W; /* Map the page */ @@ -2625,7 +2603,7 @@ int exec_page_lookup(t_addr addr, int wr, int *loc) /* If not valid, go refill it */ if (data == 0 || (data & LMASK) != 0) { sect = 0; - data = load_tlb(0, page, upmp, wr); + data = load_tlb(upmp, page, wr); if (data == 0) { page_fault = 0; return 1; @@ -5818,7 +5796,7 @@ unasign: FE = (AR >> 30) & 077; /* P */ #if KLB f = 0; - if (QKLB && FE > 36) { + if (QKLB && t20_page && pc_sect != 0 && FE > 36) { if (FE == 077) goto muuo; f = 1; @@ -5907,7 +5885,7 @@ fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); AR = MB; SCAD = (AR >> 30) & 077; #if KL & KLB - if (QKLB && t20_page && SCAD > 36) { /* Extended pointer */ + if (QKLB && t20_page && pc_sect != 0 && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; //fprintf(stderr, "ILDB %012llo %d %d -> %d %d %d\n\r", AR, SCAD, i, _byte_adj[i].p, _byte_adj[i].s,_byte_adj[i].n); if (SCAD == 077) @@ -5992,7 +5970,7 @@ fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); SC = (AR >> 24) & 077; SCAD = (AR >> 30) & 077; #if KL & KLB - if (QKLB && t20_page && SCAD > 36) { /* Extended pointer */ + if (QKLB && t20_page && pc_sect != 0 && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; if (SCAD == 077) goto muuo; @@ -6020,7 +5998,7 @@ ldb_ptr: #if KL ptr_flg = 1; #if KLB - if (QKLB && t20_page && (SC < 36) && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { + if (QKLB && t20_page && (SC < 36) && pc_sect != 0 && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; //fprintf(stderr, "LBP %o %o %06o %012llo\n\r", SC, SCAD, AB, MB); @@ -7561,6 +7539,7 @@ jrstf: if (flag1) /* U */ AR |= SMASK; /* BIT0 */ AR |= BIT2|BIT3|BIT4|BIT8; +fprintf(stderr, "Map reg %012llo %06o\r\n", AR, AB); set_reg(AC, AR); break; } @@ -7572,12 +7551,13 @@ jrstf: flag3 = 1; } - AR = load_tlb(flag1, f, flag3, 0); + AR = load_tlb(flag1 | flag3, f, 0); if (page_fault) { page_fault = 0; - AR |= BIT8 | fault_data; + AR |= fault_data; if (flag1) /* U */ AR |= SMASK; +fprintf(stderr, "Map fault %012llo %06o\r\n", AR, AB); set_reg(AC, AR); break; } @@ -7599,6 +7579,7 @@ jrstf: } else AR = (f & 01740) ? 0 : 0377777LL; AR |= BIT8; +fprintf(stderr, "Map ok %012llo %06o\r\n", AR, AB); #else /* Figure out if this is a user space access */ if (xct_flag != 0 && !flag1) { @@ -8708,7 +8689,7 @@ last: Mem_read_nopage(); FLAGS = (MB >> 23) & 017777; /* If transistioning from user to executive adjust flags */ - if ((FLAGS & USER) != 0 && flag1) + if ((FLAGS & USER) == 0 && flag1) FLAGS |= USERIO; if ((FLAGS & USER) == 0 && (flag3 || (FLAGS & OVR) != 0)) FLAGS |= PRV_PUB|OVR; @@ -8872,7 +8853,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) /* Advance pointer */ //fprintf(stderr, "%s %012llo %012llo %2o %2o %03o\n\r", (wr)?"store":"load", val1, val2, s, p, np); #if KLB - if (QKLB && t20_page) { + if (QKLB && t20_page && pc_sect != 0) { if (p > 36) { /* Extended pointer */ int i = p - 37; *sz = s = _byte_adj[i].s; @@ -8890,7 +8871,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) sect = (MB >> 18) & 07777; glb_sect = 1; //fprintf(stderr, "Load_bytex %012llo %012llo %06 %2o %2o\n\r", val1, val2, sect, s, p); - } else if (pc_sect != 0 && (val1 & BIT12) != 0) { /* Full pointer */ + } else if ((val1 & BIT12) != 0) { /* Full pointer */ if (np & 0400) { np = p = ((0777 ^ s) + 044 + 1) & 0777; if (val2 & SMASK) @@ -9198,7 +9179,7 @@ adj_byte(int n) /* Advance pointer */ np = (p + (0777 ^ s) + 1) & 0777; #if KLB - if (QKLB && t20_page) { + if (QKLB && t20_page && pc_sect != 0) { if (p > 36) { /* Extended pointer */ int i = p - 37; s = _byte_adj[i].s; @@ -9209,7 +9190,7 @@ adj_byte(int n) set_reg(n+1, val1); set_reg(n+2, val2); return; - } else if (pc_sect != 0 && (val1 & BIT12) != 0) { /* Full pointer */ + } else if ((val1 & BIT12) != 0) { /* Full pointer */ if (np & 0400) val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); } else { @@ -9258,7 +9239,7 @@ adv_byte(int n) /* Advance pointer */ np = (p + (0777 ^ s) + 1) & 0777; #if KLB - if (QKLB && t20_page) { + if (QKLB && t20_page && pc_sect != 0) { if (p > 36) { /* Extended pointer */ int i = p - 37; s = _byte_adj[i].s; @@ -9270,7 +9251,7 @@ adv_byte(int n) np = ((0777 ^ s) + 044 + 1) & 0777; val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); } - } else if (pc_sect != 0 && (val1 & BIT12) != 0) { /* Full pointer */ + } else if ((val1 & BIT12) != 0) { /* Full pointer */ if (np & 0400) { np = ((0777 ^ s) + 044 + 1) & 0777; val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); From 5e66f1ef654c488fac4f8d3ec357f31470ef2504 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 17 Nov 2019 12:43:20 -0500 Subject: [PATCH 57/98] SCP: Updated to current. --- scp.c | 16 ++++++++++++++-- sim_card.c | 18 +++++++++--------- sim_disk.c | 28 ++++++++++++---------------- sim_serial.c | 2 +- sim_tape.c | 50 +++++++++++++++++++++++++++++++++++++++----------- 5 files changed, 75 insertions(+), 39 deletions(-) diff --git a/scp.c b/scp.c index 3a7c098..762e7eb 100644 --- a/scp.c +++ b/scp.c @@ -2865,7 +2865,8 @@ fprintf (st, " HELP dev SET\n"); fprintf (st, " HELP dev SHOW\n"); fprintf (st, " HELP dev REGISTERS\n\n"); fprintf (st, "Help is available for the following commands:\n\n "); -qsort (hlp_cmdp, cmd_cnt, sizeof(*hlp_cmdp), _cmd_name_compare); +if (hlp_cmdp) + qsort (hlp_cmdp, cmd_cnt, sizeof(*hlp_cmdp), _cmd_name_compare); line_offset = 4; for (i=0; iname, st); @@ -5713,9 +5714,10 @@ return SCPE_OK; const char *sprint_capac (DEVICE *dptr, UNIT *uptr) { -static char capac_buf[((CHAR_BIT * sizeof (t_value) * 4 + 3)/3) + 8]; +static char capac_buf[((CHAR_BIT * sizeof (t_value) * 4 + 3)/3) + 12]; t_addr kval = (uptr->flags & UNIT_BINK)? 1024: 1000; t_addr mval; +double remfrac; t_addr psize = uptr->capac; const char *scale, *width; @@ -5730,18 +5732,28 @@ else width = "B"; if ((psize < (kval * 10)) && (0 != (psize % kval))) { + remfrac = 0.0; scale = ""; } else if ((psize < (mval * 10)) && (0 != (psize % mval))){ scale = "K"; + remfrac = ((double)(psize % kval))/kval; psize = psize / kval; } else { scale = "M"; + remfrac = ((double)(psize % mval))/mval; psize = psize / mval; } sprint_val (capac_buf, (t_value) psize, 10, T_ADDR_W, PV_LEFT); +if ((remfrac != 0.0) && (sim_switches & SWMASK ('R'))) { + char *plast_char = &capac_buf[strlen (capac_buf) - 1]; + char save_char = *plast_char; + + sprintf (plast_char, "%0.3f", remfrac); + *plast_char = save_char; + } sprintf (&capac_buf[strlen (capac_buf)], "%s%s", scale, width); return capac_buf; } diff --git a/sim_card.c b/sim_card.c index f33e7dd..0923bb2 100644 --- a/sim_card.c +++ b/sim_card.c @@ -599,12 +599,12 @@ sim_card_eof(UNIT *uptr) struct _card_buffer { - char buffer[8192+500]; /* Buffer data */ + uint8 buffer[8192+500]; /* Buffer data */ int len; /* Amount of data in buffer */ int size; /* Size of last card read */ }; -static int _cmpcard(const char *p, const char *s) { +static int _cmpcard(const uint8 *p, const char *s) { int i; if (p[0] != '~') return 0; @@ -629,7 +629,7 @@ _sim_parse_card(UNIT *uptr, DEVICE *dptr, struct _card_buffer *buf, uint16 (*ima /* Check buffer to see if binary card in it. */ for (i = 0, temp = 0; i < 160 && i len; i+=2) - temp |= buf->buffer[i]; + temp |= (uint16)(buf->buffer[i] & 0xFF); /* Check if every other char < 16 & full buffer */ if ((temp & 0x0f) == 0 && i == 160) mode = MODE_BIN; /* Probably binary */ @@ -789,9 +789,9 @@ _sim_parse_card(UNIT *uptr, DEVICE *dptr, struct _card_buffer *buf, uint16 (*ima } /* Move data to buffer */ for (col = i = 0; i < 160;) { - temp |= buf->buffer[i]; + temp |= (uint16)(buf->buffer[i] & 0xff); (*image)[col] = (buf->buffer[i++] >> 4) & 0xF; - (*image)[col++] |= ((uint16)buf->buffer[i++]) << 4; + (*image)[col++] |= ((uint16)buf->buffer[i++] & 0xf) << 4; } /* Check if format error */ if (temp & 0xF) @@ -802,8 +802,8 @@ _sim_parse_card(UNIT *uptr, DEVICE *dptr, struct _card_buffer *buf, uint16 (*ima case MODE_CBN: sim_debug(DEBUG_CARD, dptr, "cbn\n"); /* Check if first character is a tape mark */ - if (((uint8)buf->buffer[0]) == 0217 && - (buf->len == 1 || (((uint8)buf->buffer[1]) & 0200) != 0)) { + if (buf->buffer[0] == 0217 && + (buf->len == 1 || (buf->buffer[1] & 0200) != 0)) { i = 1; (*image)[0] |= CARD_EOF; break; @@ -844,7 +844,7 @@ _sim_parse_card(UNIT *uptr, DEVICE *dptr, struct _card_buffer *buf, uint16 (*ima case MODE_BCD: sim_debug(DEBUG_CARD, dptr, "bcd ["); /* Check if first character is a tape mark */ - if (((uint8)buf->buffer[0]) == 0217 && (((uint8)buf->buffer[1]) & 0200) != 0) { + if (buf->buffer[0] == 0217 && (buf->buffer[1] & 0200) != 0) { i = 1; (*image)[0] |= CARD_EOF; break; @@ -885,7 +885,7 @@ _sim_parse_card(UNIT *uptr, DEVICE *dptr, struct _card_buffer *buf, uint16 (*ima (*image)[0] |= CARD_ERR; /* Move data to buffer */ for (i = 0; i < 80 && i < buf->len; i++) { - temp = buf->buffer[i] & 0xFF; + temp = (uint16)(buf->buffer[i]) & 0xFF; (*image)[i] = ebcdic_to_hol[temp]; } break; diff --git a/sim_disk.c b/sim_disk.c index df3183d..1c8a2a2 100644 --- a/sim_disk.c +++ b/sim_disk.c @@ -1110,8 +1110,7 @@ static t_offset get_ods2_filesystem_size (UNIT *uptr) DEVICE *dptr; t_addr saved_capac; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; -t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu; /* Make sure we can access the largest sector */ -uint32 capac_factor; +t_offset temp_capac = (sim_toffset_64 ? (t_addr)0xFFFFFFFFu : (t_addr)0x7FFFFFFFu); /* Make sure we can access the largest sector */ ODS2_HomeBlock Home; ODS2_FileHeader Header; ODS2_Retreval *Retr; @@ -1123,9 +1122,8 @@ t_seccnt sects_read; if ((dptr = find_dev_from_unit (uptr)) == NULL) return ret_val; -capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capacity units (word: 2, byte: 1) */ saved_capac = uptr->capac; -uptr->capac = (t_addr)(temp_capac/(capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))); +uptr->capac = temp_capac; if ((sim_disk_rdsect (uptr, 512 / ctx->sector_size, (uint8 *)&Home, §s_read, sizeof (Home) / ctx->sector_size)) || (sects_read != (sizeof (Home) / ctx->sector_size))) goto Return_Cleanup; @@ -1197,8 +1195,7 @@ static t_offset get_ods1_filesystem_size (UNIT *uptr) DEVICE *dptr; t_addr saved_capac; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; -t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu; /* Make sure we can access the largest sector */ -uint32 capac_factor; +t_addr temp_capac = (sim_toffset_64 ? (t_addr)0xFFFFFFFFu : (t_addr)0x7FFFFFFFu); /* Make sure we can access the largest sector */ ODS1_HomeBlock Home; ODS1_FileHeader Header; ODS1_Retreval *Retr; @@ -1211,9 +1208,8 @@ t_seccnt sects_read; if ((dptr = find_dev_from_unit (uptr)) == NULL) return ret_val; -capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capacity units (word: 2, byte: 1) */ saved_capac = uptr->capac; -uptr->capac = (t_addr)(temp_capac/(capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))); +uptr->capac = temp_capac; if ((sim_disk_rdsect (uptr, 512 / ctx->sector_size, (uint8 *)&Home, §s_read, sizeof (Home) / ctx->sector_size)) || (sects_read != (sizeof (Home) / ctx->sector_size))) goto Return_Cleanup; @@ -1274,8 +1270,7 @@ static t_offset get_ultrix_filesystem_size (UNIT *uptr) DEVICE *dptr; t_addr saved_capac; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; -t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu; /* Make sure we can access the largest sector */ -uint32 capac_factor; +t_addr temp_capac = (sim_toffset_64 ? (t_addr)0xFFFFFFFFu : (t_addr)0x7FFFFFFFu); /* Make sure we can access the largest sector */ uint8 sector_buf[512]; ultrix_disklabel *Label = (ultrix_disklabel *)(sector_buf + sizeof (sector_buf) - sizeof (ultrix_disklabel)); t_offset ret_val = (t_offset)-1; @@ -1285,9 +1280,8 @@ t_seccnt sects_read; if ((dptr = find_dev_from_unit (uptr)) == NULL) return ret_val; -capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; /* save capacity units (word: 2, byte: 1) */ saved_capac = uptr->capac; -uptr->capac = (t_addr)(temp_capac/(capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))); +uptr->capac = temp_capac; if ((sim_disk_rdsect (uptr, 31 * (512 / ctx->sector_size), sector_buf, §s_read, 512 / ctx->sector_size)) || (sects_read != (512 / ctx->sector_size))) goto Return_Cleanup; @@ -1393,8 +1387,7 @@ static t_offset get_rt11_filesystem_size (UNIT *uptr) DEVICE *dptr; t_addr saved_capac; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; -t_offset temp_capac = 512 * (t_offset)0xFFFFFFFFu; -uint32 capac_factor; +t_addr temp_capac = (sim_toffset_64 ? (t_addr)0xFFFFFFFFu : (t_addr)0x7FFFFFFFu); /* Make sure we can access the largest sector */ uint8 sector_buf[1024]; RT11_HomeBlock Home; t_seccnt sects_read; @@ -1409,9 +1402,8 @@ t_offset ret_val = (t_offset)-1; if ((dptr = find_dev_from_unit (uptr)) == NULL) return ret_val; -capac_factor = ((dptr->dwidth / dptr->aincr) == 16) ? 2 : 1; saved_capac = uptr->capac; -uptr->capac = (t_addr)(temp_capac / (capac_factor * ((dptr->flags & DEV_SECTORS) ? 512 : 1))); +uptr->capac = temp_capac; for (part = 0; part < RT11_MAXPARTITIONS; part++) { uint16 seg_highest; @@ -2018,10 +2010,14 @@ if (container_size && (container_size != (t_offset)-1)) { if ((container_size < current_unit_size) && ((DKUF_F_VHD == DK_GET_FMT (uptr)) || (0 != (uptr->flags & UNIT_RO)))) { if (!sim_quiet) { + int32 saved_switches = sim_switches; + + sim_switches = SWMASK ('R'); uptr->capac = (t_addr)(container_size/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))); sim_printf ("%s%d: non expandable disk container '%s' is smaller than simulated device (%s < ", sim_dname (dptr), (int)(uptr-dptr->units), cptr, sprint_capac (dptr, uptr)); uptr->capac = saved_capac; sim_printf ("%s)\n", sprint_capac (dptr, uptr)); + sim_switches = saved_switches; } sim_disk_detach (uptr); return SCPE_OPENERR; diff --git a/sim_serial.c b/sim_serial.c index dc13960..86ae870 100644 --- a/sim_serial.c +++ b/sim_serial.c @@ -448,8 +448,8 @@ return port; void sim_close_serial (SERHANDLE port) { -sim_close_os_serial (port); _serial_remove_from_open_list (port); +sim_close_os_serial (port); } t_stat sim_config_serial (SERHANDLE port, CONST char *sconfig) diff --git a/sim_tape.c b/sim_tape.c index 8729a89..89cd09e 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -598,6 +598,16 @@ if (MT_GET_FMT (uptr) < MTUF_F_ANSI) fflush (uptr->fileref); } +static const char *_sim_tape_format_name (UNIT *uptr) +{ +int32 f = MT_GET_FMT (uptr); + +if (f == MTUF_F_ANSI) + return ansi_args[MT_GET_ANSI_TYP (uptr)].name; +else + return fmts[f].name; +} + /* Attach tape unit */ t_stat sim_tape_attach (UNIT *uptr, CONST char *cptr) @@ -662,6 +672,7 @@ switch (MT_GET_FMT (uptr)) { if (1) { const char *ocptr = cptr; char label[CBUFSIZE] = "simh"; + int file_errors = 0; if ((MT_GET_ANSI_TYP (uptr) == MTAT_F_RT11) || (MT_GET_ANSI_TYP (uptr) == MTAT_F_RSX11) || @@ -678,10 +689,16 @@ switch (MT_GET_FMT (uptr)) { if (!uptr->fileref) return SCPE_MEM; while (*cptr != 0) { /* do all mods */ + uint32 initial_file_count = tape->file_count; + cptr = get_glyph_nc (cptr, gbuf, ','); /* get filename */ - sim_dir_scan (gbuf, sim_tape_add_ansi_entry, tape); + r = sim_dir_scan (gbuf, sim_tape_add_ansi_entry, tape); + if (r != SCPE_OK) + sim_messagef (SCPE_ARG, "file not found: %s\n", gbuf); + if (tape->file_count == initial_file_count) + ++file_errors; } - if (tape->file_count > 0) { + if ((tape->file_count > 0) && (file_errors == 0)) { r = SCPE_OK; memory_tape_add_block (tape, NULL, 0); /* Tape Mark */ uptr->flags |= UNIT_ATT; @@ -693,6 +710,7 @@ switch (MT_GET_FMT (uptr)) { r = SCPE_ARG; memory_free_tape (uptr->fileref); uptr->fileref = NULL; + cptr = ocptr; } } break; @@ -798,11 +816,12 @@ switch (MT_GET_FMT (uptr)) { break; } if (r != SCPE_OK) { /* error? */ + r = sim_messagef (r, "Can't open %s format tape image: %s\n", _sim_tape_format_name (uptr), cptr); if (auto_format) /* format was specified at attach time? */ sim_tape_set_fmt (uptr, 0, "SIMH", NULL); /* restore default format */ uptr->recsize = 0; uptr->tape_eom = 0; - return sim_messagef (r, "Can't open tape image: %s\n", cptr); + return r; } if ((sim_switches & SWMASK ('D')) && !had_debug) { @@ -3220,12 +3239,7 @@ return sim_messagef (SCPE_ARG, "Unknown tape format: %s\n", cptr); t_stat sim_tape_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc) { -int32 f = MT_GET_FMT (uptr); - -if (f == MTUF_F_ANSI) - fprintf (st, "%s format", ansi_args[MT_GET_ANSI_TYP (uptr)].name); -else - fprintf (st, "%s format", fmts[f].name); +fprintf (st, "%s format", _sim_tape_format_name (uptr)); return SCPE_OK; } @@ -4232,7 +4246,7 @@ static void ansi_fill_text_buffer (FILE *f, char *buf, size_t buf_size, size_t r if (rec_size >= record_skip_ending) rec_size -= record_skip_ending; if ((rec_size + 4) > (int)(buf_size - offset)) { /* room for record? */ - fseek (f, start, SEEK_SET); + (void)fseek (f, start, SEEK_SET); break; } sprintf (rec_size_str, "%04u", (int)(rec_size + 4)); @@ -4387,6 +4401,7 @@ return tape; static int ansi_add_file_to_tape (MEMORY_TAPE *tape, const char *filename) { FILE *f; +struct stat statb; struct ansi_tape_parameters *ansi = &ansi_args[tape->ansi_type]; uint8 *block = NULL; size_t max_record_size; @@ -4401,9 +4416,22 @@ HDR2 hdr2; HDR3 hdr3; HDR4 hdr4; +memset (&statb, 0, sizeof (statb)); +if (stat (filename, &statb)) { + sim_printf ("Can't stat: %s\n", filename); + return -1; + } +if (S_IFDIR & statb.st_mode) { + sim_printf ("Can't put a directory on tape: %s\n", filename); + return -1; + } +if (!(S_IFREG & statb.st_mode)) { + sim_printf ("Can't put a non regular file on tape: %s\n", filename); + return -1; + } f = fopen (filename, "rb"); if (f == NULL) { - fprintf (stderr, "Can't open: %s - %s\n", filename, strerror(errno)); + sim_printf ("Can't open: %s - %s\n", filename, strerror(errno)); return errno; } tape_classify_file_contents (f, &max_record_size, &lf_line_endings, &crlf_line_endings); From 39f721faf9cb77e75ac9b5a7d446ffeb36f48de3 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 17 Nov 2019 23:34:13 -0500 Subject: [PATCH 58/98] KA10: More KL10B bug fixes. --- PDP10/kx10_cpu.c | 77 ++++++++++++++++++++++++------------------------ PDP10/kx10_rh.c | 2 +- 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index bb9a5f0..ef3a7c6 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -889,39 +889,37 @@ int opflags[] = { struct { int p; int s; - int n; - int l; } _byte_adj[] = { - { /* 37 */ 36, 6, 38, 0 }, /* 45 */ - { /* 38 */ 30, 6, 39, 0 }, /* 46 */ - { /* 39 */ 24, 6, 40, 0 }, /* 47 */ - { /* 40 */ 18, 6, 41, 0 }, /* 50 */ - { /* 41 */ 12, 6, 42, 0 }, /* 51 */ - { /* 42 */ 6, 6, 43, 0 }, /* 52 */ - { /* 43 */ 0, 6, 37, 1 }, /* 53 */ + { /* 37 */ 36, 6 }, /* 45 */ + { /* 38 */ 30, 6 }, /* 46 */ + { /* 39 */ 24, 6 }, /* 47 */ + { /* 40 */ 18, 6 }, /* 50 */ + { /* 41 */ 12, 6 }, /* 51 */ + { /* 42 */ 6, 6 }, /* 52 */ + { /* 43 */ 0, 6 }, /* 53 */ - { /* 44 */ 36, 8, 45, 0 }, /* 54 */ - { /* 45 */ 28, 8, 46, 0 }, /* 55 */ - { /* 46 */ 20, 8, 47, 0 }, /* 56 */ - { /* 47 */ 12, 8, 48, 0 }, /* 57 */ - { /* 48 */ 4, 8, 44, 1 }, /* 60 */ + { /* 44 */ 36, 8 }, /* 54 */ + { /* 45 */ 28, 8 }, /* 55 */ + { /* 46 */ 20, 8 }, /* 56 */ + { /* 47 */ 12, 8 }, /* 57 */ + { /* 48 */ 4, 8 }, /* 60 */ - { /* 49 */ 36, 7, 50, 0 }, /* 61 */ - { /* 50 */ 29, 7, 51, 0 }, /* 62 */ - { /* 51 */ 22, 7, 52, 0 }, /* 63 */ - { /* 52 */ 15, 7, 53, 0 }, /* 64 */ - { /* 53 */ 8, 7, 54, 0 }, /* 65 */ - { /* 54 */ 1, 7, 49, 1 }, /* 66 */ + { /* 49 */ 36, 7 }, /* 61 */ + { /* 50 */ 29, 7 }, /* 62 */ + { /* 51 */ 22, 7 }, /* 63 */ + { /* 52 */ 15, 7 }, /* 64 */ + { /* 53 */ 8, 7 }, /* 65 */ + { /* 54 */ 1, 7 }, /* 66 */ - { /* 55 */ 36, 9, 56, 0 }, /* 67 */ - { /* 56 */ 27, 9, 57, 0 }, /* 70 */ - { /* 57 */ 18, 9, 58, 0 }, /* 71 */ - { /* 58 */ 9, 9, 59, 0 }, /* 72 */ - { /* 59 */ 0, 9, 55, 1 }, /* 73 */ + { /* 55 */ 36, 9 }, /* 67 */ + { /* 56 */ 27, 9 }, /* 70 */ + { /* 57 */ 18, 9 }, /* 71 */ + { /* 58 */ 9, 9 }, /* 72 */ + { /* 59 */ 0, 9 }, /* 73 */ - { /* 60 */ 36,18, 61, 0 }, /* 74 */ - { /* 61 */ 18,18, 62, 0 }, /* 75 */ - { /* 62 */ 0,18, 60, 1 } /* 76 */ + { /* 60 */ 36,18 }, /* 74 */ + { /* 61 */ 18,18 }, /* 75 */ + { /* 62 */ 0,18 } /* 76 */ }; #endif @@ -2315,7 +2313,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int else if (xct_flag != 0 && !uf && !fetch) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); #if KLB -//fprintf(stderr, " s%o", sect); +//fprintf(stderr, " s%o %o", sect, glb_sect); #endif if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || @@ -2326,7 +2324,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int #if KLB if (QKLB && !glb_sect && !extend) sect = prev_sect; -//fprintf(stderr, " os%o", sect); +//fprintf(stderr, " ps=%o os%o", prev_sect, sect); #endif } //fprintf(stderr, " %o %o\n\r", uf, pub); @@ -4421,6 +4419,7 @@ st_pi: /* Fall through */ #else case 0052: case 0053: + /* Fall through */ #endif muuo: case 0000: /* UUO */ @@ -5802,7 +5801,7 @@ unasign: f = 1; SC = _byte_adj[(FE - 37)].s; FE = _byte_adj[(FE - 37)].p; -fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); +//fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); } #endif left = (36 - FE) / SC; /* Number bytes left (36 - P)/S */ @@ -5887,7 +5886,7 @@ fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); #if KL & KLB if (QKLB && t20_page && pc_sect != 0 && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; -//fprintf(stderr, "ILDB %012llo %d %d -> %d %d %d\n\r", AR, SCAD, i, _byte_adj[i].p, _byte_adj[i].s,_byte_adj[i].n); +//fprintf(stderr, "ILDB %012llo %d %d -> %d %d\n\r", AR, SCAD, i, _byte_adj[i].p, _byte_adj[i].s); if (SCAD == 077) goto muuo; SC = _byte_adj[i].s; @@ -7539,7 +7538,7 @@ jrstf: if (flag1) /* U */ AR |= SMASK; /* BIT0 */ AR |= BIT2|BIT3|BIT4|BIT8; -fprintf(stderr, "Map reg %012llo %06o\r\n", AR, AB); +//fprintf(stderr, "Map reg %012llo %06o\r\n", AR, AB); set_reg(AC, AR); break; } @@ -7557,7 +7556,7 @@ fprintf(stderr, "Map reg %012llo %06o\r\n", AR, AB); AR |= fault_data; if (flag1) /* U */ AR |= SMASK; -fprintf(stderr, "Map fault %012llo %06o\r\n", AR, AB); +//fprintf(stderr, "Map fault %012llo %06o\r\n", AR, AB); set_reg(AC, AR); break; } @@ -7579,7 +7578,7 @@ fprintf(stderr, "Map fault %012llo %06o\r\n", AR, AB); } else AR = (f & 01740) ? 0 : 0377777LL; AR |= BIT8; -fprintf(stderr, "Map ok %012llo %06o\r\n", AR, AB); +//fprintf(stderr, "Map ok %012llo %06o\r\n", AR, AB); #else /* Figure out if this is a user space access */ if (xct_flag != 0 && !flag1) { @@ -8663,9 +8662,11 @@ last: FLAGS |= trap_flag & (TRP1|TRP2); trap_flag = (TRP1|TRP2); #if KLB - if (QKLB && t20_page) - MB = (((uint64)(FLAGS) << 23) & LMASK) | (uint64)(pc_sect & 037); - else + if (QKLB && t20_page) { + MB = (((uint64)(FLAGS) << 23) & LMASK); + if ((FLAGS & USER) == 0) + MB |= (uint64)(prev_sect & 037); + } else #endif MB = (((uint64)(FLAGS) << 23) & LMASK) | (PC & RMASK); if ((FLAGS & USER) == 0) { diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index 06c52be..e20e186 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -651,7 +651,7 @@ void rh_setup(struct rh_if *rhc, uint32 addr) int rh_fetch(struct rh_if *rhc) { uint64 data; int reg; - DEVICE *dptr; + DEVICE *dptr = NULL; for (reg = 0; rh[reg].dev_num != 0; reg++) { if (rh[reg].rh == rhc) { From f8c6b52192549afcef42b5c5b73ee53bc1db9421 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 20 Nov 2019 22:39:25 -0500 Subject: [PATCH 59/98] SCP: Updated to current. --- sim_fio.c | 4 +++- sim_tape.c | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/sim_fio.c b/sim_fio.c index 9bfecde..6fef8ea 100644 --- a/sim_fio.c +++ b/sim_fio.c @@ -782,7 +782,9 @@ else { return NULL; } strlcpy (fullpath, dir, tot_len); - strlcat (fullpath, "/", tot_len); + if ((dir[strlen (dir) - 1] != '/') && /* if missing a trailing directory separator? */ + (dir[strlen (dir) - 1] != '\\')) + strlcat (fullpath, "/", tot_len); /* then add one */ strlcat (fullpath, filepath, tot_len); } while ((c = strchr (fullpath, '\\'))) /* standardize on / directory separator */ diff --git a/sim_tape.c b/sim_tape.c index 89cd09e..4a24d1b 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -816,7 +816,16 @@ switch (MT_GET_FMT (uptr)) { break; } if (r != SCPE_OK) { /* error? */ - r = sim_messagef (r, "Can't open %s format tape image: %s\n", _sim_tape_format_name (uptr), cptr); + switch (MT_GET_FMT (uptr)) { + case MTUF_F_ANSI: + case MTUF_F_TAR: + case MTUF_F_FIXED: + r = sim_messagef (r, "Error opening %s format internal tape image generated from: %s\n", _sim_tape_format_name (uptr), cptr); + break; + default: + r = sim_messagef (r, "Error opening %s format tape image: %s - %s\n", _sim_tape_format_name (uptr), cptr, strerror(errno)); + break; + } if (auto_format) /* format was specified at attach time? */ sim_tape_set_fmt (uptr, 0, "SIMH", NULL); /* restore default format */ uptr->recsize = 0; @@ -4416,24 +4425,27 @@ HDR2 hdr2; HDR3 hdr3; HDR4 hdr4; -memset (&statb, 0, sizeof (statb)); -if (stat (filename, &statb)) { - sim_printf ("Can't stat: %s\n", filename); - return -1; - } -if (S_IFDIR & statb.st_mode) { - sim_printf ("Can't put a directory on tape: %s\n", filename); - return -1; - } -if (!(S_IFREG & statb.st_mode)) { - sim_printf ("Can't put a non regular file on tape: %s\n", filename); - return -1; - } f = fopen (filename, "rb"); if (f == NULL) { sim_printf ("Can't open: %s - %s\n", filename, strerror(errno)); return errno; } +memset (&statb, 0, sizeof (statb)); +if (fstat (fileno (f), &statb)) { + sim_printf ("Can't stat: %s\n", filename); + fclose (f); + return -1; + } +if (S_IFDIR & statb.st_mode) { + sim_printf ("Can't put a directory on tape: %s\n", filename); + fclose (f); + return -1; + } +if (!(S_IFREG & statb.st_mode)) { + sim_printf ("Can't put a non regular file on tape: %s\n", filename); + fclose (f); + return -1; + } tape_classify_file_contents (f, &max_record_size, &lf_line_endings, &crlf_line_endings); ansi_make_HDR1 (&hdr1, &tape->vol1, &hdr4, filename, tape->ansi_type); sprintf (file_sequence, "%04d", 1 + tape->file_count); From 5e5c6af5eb369883257cc9e75404b61bd9f83774 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 20 Nov 2019 22:40:03 -0500 Subject: [PATCH 60/98] KA10: Fixes to allow KL10B to boot Tops20 V3 through V5 --- PDP10/kl10_fe.c | 1 - PDP10/kx10_cpu.c | 66 ++++++++++++++++++++++++++++++++---------------- PDP10/kx10_rh.c | 13 +++++----- 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index b27c853..efdf739 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -1536,7 +1536,6 @@ t_stat dteo_svc (UNIT *uptr) ((ch > 040 && ch < 0177)? ch: '.')); } cty_done++; - dte_input(); return SCPE_OK; } diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index ef3a7c6..9768435 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2322,7 +2322,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; #if KLB - if (QKLB && !glb_sect && !extend) + if (QKLB && (!glb_sect || ((xct_flag & 4) != 0 && prev_sect == 0)) && !extend) sect = prev_sect; //fprintf(stderr, " ps=%o os%o", prev_sect, sect); #endif @@ -4085,7 +4085,7 @@ no_fetch: AD = MB; /* Save for historical sake */ IA = AB; #if KL & KLB - glb_sect = 0; +// glb_sect = 0; #endif i_flags = opflags[IR]; BYF5 = 0; @@ -4112,20 +4112,28 @@ no_fetch: } #endif - /* Handle indirection repeat until no longer indirect */ #if KL && KLB - /* If we are doing a PXCT with E1 or E2 set, change section */ - if (QKLB && t20_page) { - if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || - ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) - sect = cur_sect = prev_sect; - /* Short cut for extended pointer address */ - if (ptr_flg && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { /* Full pointer */ - ind = 1; /* Allow us to read word, xDB has already bumped AB */ - goto in_loop; - } - } + /* If we are doing a PXCT with E1 or E2 set, change section */ + if (QKLB && t20_page) { + if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || + ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) + sect = cur_sect = prev_sect; + /* Short cut for extended pointer address */ + if (ptr_flg && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { /* Full pointer */ + ind = 1; /* Allow us to read word, xDB has already bumped AB */ + goto in_loop; + } + /* If we are evaluating a address from non-zero section to reference zero sections. + Then we need to force the current section to zero before starting. + + This fixes the case of a XCT 4,[instr n,addr] that should really be in section + zero. */ +// if ((xct_flag & 4) != 0 && (FLAGS & USER) == 0 && prev_sect == 0) + // cur_sect = prev_sect; + } + #endif + /* Handle indirection repeat until no longer indirect */ do { if ((!pi_cycle) & pi_pending #if KI | KL @@ -4451,6 +4459,10 @@ unasign: if (QKLB && t20_page) { AR = (((uint64)cur_sect) << 18) | (uint64)AB; /* Save address */ MB = (((uint64)((IR << 9) | (AC << 5))) | ((uint64)(FLAGS) << 23)) & FMASK; + if ((FLAGS & USER) == 0) { + MB &= ~SMASK; + MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + } } else #endif MB = ((uint64)(IR) << 27) | ((uint64)(AC) << 23) | (uint64)(AB); @@ -4496,14 +4508,14 @@ unasign: #endif /* Save context */ AB ++; - MB = SMASK|BIT1 | + MB = SMASK|BIT2| ((uint64)(fm_sel & 0160) << 23) | ((uint64)(prev_ctx & 0160) << 20) | (ub_ptr >> 9); #if KLB - if (QKLB && t20_page) { - MB |= ((uint64)(prev_sect & 037) << 18); - prev_sect = pc_sect; + if (QKLB && t20_page && (FLAGS & USER) == 0) { + MB |= BIT1|((uint64)(prev_sect & 037) << 18); +// prev_sect = pc_sect; } #endif Mem_write_nopage(); @@ -4530,8 +4542,13 @@ unasign: if ((FLAGS & USER) == 0) { if ((AB & 4) != 0) FLAGS |= USERIO; +#if KL + if ((AB & 2)) + FLAGS |= PRV_PUB; +#else if ((AB & 2 || (FLAGS & OVR) != 0)) FLAGS |= PRV_PUB|OVR; +#endif } PC = MB & RMASK; f_pc_inh = 1; @@ -8661,14 +8678,14 @@ last: AB++; FLAGS |= trap_flag & (TRP1|TRP2); trap_flag = (TRP1|TRP2); + MB = (((uint64)(FLAGS) << 23) & LMASK); #if KLB if (QKLB && t20_page) { - MB = (((uint64)(FLAGS) << 23) & LMASK); if ((FLAGS & USER) == 0) MB |= (uint64)(prev_sect & 037); } else #endif - MB = (((uint64)(FLAGS) << 23) & LMASK) | (PC & RMASK); + MB |= (PC & RMASK); if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; @@ -8688,12 +8705,17 @@ last: if (FLAGS & USER) flag1 = 1; Mem_read_nopage(); +#if KLB + if (QKLB && t20_page) + FLAGS = 0; + else +#endif FLAGS = (MB >> 23) & 017777; /* If transistioning from user to executive adjust flags */ if ((FLAGS & USER) == 0 && flag1) FLAGS |= USERIO; - if ((FLAGS & USER) == 0 && (flag3 || (FLAGS & OVR) != 0)) - FLAGS |= PRV_PUB|OVR; + if ((FLAGS & USER) == 0 && flag3) + FLAGS |= PRV_PUB; PC = MB & RMASK; #if KLB if (QKLB && t20_page) diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index e20e186..36235b0 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -549,16 +549,17 @@ void rh_writecw(struct rh_if *rhc, int nxm) { wrd1 |= RH20_NOT_WC0; if (rhc->status & RH20_XEND) { wrd1 |= RH20_LONG_STS; - rhc->status |= RH20_CHAN_ERR; - if ((rhc->ptcr & 010) == 0) /* Write command */ - rhc->status |= RH20_LONG_WC; + if ((rhc->ptcr & 070) == 060) /* Write command */ + rhc->status |= RH20_CHAN_ERR|RH20_LONG_WC; } } else if ((rhc->status & RH20_XEND) == 0) { wrd1 |= RH20_SHRT_STS; - rhc->status |= RH20_CHAN_ERR; - if ((rhc->ptcr & 010) == 0) /* Write command */ - rhc->status |= RH20_SHRT_WC; + if ((rhc->ptcr & 070) == 060) /* Write command */ + rhc->status |= RH20_SHRT_WC|RH20_CHAN_ERR; } + /* No error and not storing */ + if ((rhc->status & RH20_CHAN_ERR) == 0 && (rhc->ptcr & BIT10) == 0) + return; wrd1 |= RH20_NADR_PAR; M[eb_ptr|chan|1] = wrd1; M[eb_ptr|chan|2] = ((uint64)rhc->cop << 33) | From 9cef8d12c25eacf2d2d57c0685ed591f9bc916a8 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 24 Nov 2019 13:56:15 -0500 Subject: [PATCH 61/98] SCP: Updated display to current. --- display/type340.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- display/type340.h | 6 ++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/display/type340.c b/display/type340.c index 2e65617..32fc8cf 100644 --- a/display/type340.c +++ b/display/type340.c @@ -115,9 +115,7 @@ enum jump_type { DJP=2, DJS=3, DDS=1 }; /* type 347 */ /* put all the state in a struct "just in case" */ static struct type340 { -#ifdef NOTYET ty340word DAC; /* Display Address Counter */ -#endif ty340word status; /* see ST340_XXX in type340.h */ signed short xpos, ypos; /* 10 bits, signed (for OOB checks) */ char initialized; /* 0 before display_init */ @@ -143,7 +141,6 @@ static struct type340 { #define UNIT(N) (u340+(N)) #endif -#if 0 /* NOT USED WITH PDP-6 Type 344 Interface!! */ void ty340_set_dac(ty340word addr) @@ -157,7 +154,50 @@ ty340_set_dac(ty340word addr) u->status = 0; /* XXX just clear stopped? */ ty340_rfd(); /* ready for data */ } + +void +ty340_cycle(void) +{ + struct type340 *u = UNIT(0); + + if (u->status == 0) { + ty340word insn = ty340_fetch(u->DAC); + u->status = ty340_instruction (insn); + u->DAC = (u->DAC + 1) & 07777; + } +} + +ty340word +ty340_get_dac(void) +{ + struct type340 *u = UNIT(0); + return u->DAC; +} + +ty340word +ty340_get_asr(void) +{ +#if TYPE347 + struct type340 *u = UNIT(0); + return u->ASR; +#else + return 0; #endif +} + +ty340word +ty340_sense(ty340word flags) +{ + struct type340 *u = UNIT(0); + return u->status & flags; +} + +void +ty340_clear(ty340word flags) +{ + struct type340 *u = UNIT(0); + u->status &= ~flags; +} ty340word ty340_reset(void *dptr) diff --git a/display/type340.h b/display/type340.h index 1c39dc1..5caf06d 100644 --- a/display/type340.h +++ b/display/type340.h @@ -49,7 +49,13 @@ typedef unsigned int ty340word; ty340word ty340_reset(void *); ty340word ty340_status(void); ty340word ty340_instruction(ty340word inst); +ty340word ty340_get_dac(void); +ty340word ty340_get_asr(void); +ty340word ty340_sense(ty340word); void ty340_set_dac(ty340word addr); +void ty340_clear(ty340word addr); +void ty340_cycle(void); +void ty340_set_status(ty340word); void ty342_set_grid(int, int); /* From 5432b2d2fe6182c7f8d7ba06cbe4e9a8b47daf58 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 24 Nov 2019 13:57:00 -0500 Subject: [PATCH 62/98] KA10: Updates to allow Tops 20 V3-5 to run on KL10B. --- PDP10/kl10_fe.c | 83 +++++++++---- PDP10/kx10_cpu.c | 307 +++++++++++++++++++++++++--------------------- PDP10/kx10_defs.h | 5 - PDP10/kx10_dp.c | 2 +- 4 files changed, 226 insertions(+), 171 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index efdf739..2da9550 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -233,7 +233,7 @@ struct _dte_queue { uint16 dev; /* Dev code */ uint16 spare; /* Dev code */ uint16 dcnt; /* Data count */ - uint16 data[256]; /* Data packet */ + uint16 data[258]; /* Data packet */ uint16 sdev; /* Secondary device code */ uint16 sz; /* Byte size */ } dte_in[32], dte_out[32]; @@ -300,6 +300,11 @@ DEVICE dte_dev = { #define COL u4 #define POS u5 #define LINE u6 +#define LPST us9 + +#define PTRMSK 00777 /* Current data load pointer */ +#define EOFFLG 01000 /* Tops 20 wants EOF */ +#define VFUFLG 02000 /* Tell Tops 20 that VFU loaded */ #define MARGIN 6 @@ -826,7 +831,9 @@ error: } if (in->func & PRI_IND_FLG) { uptr->STATUS |= DTE_IND; - in->sdev = in->dcnt = in->data[0]; + in->dcnt = in->data[0]; + in->sdev = (in->dcnt >> 8) & 0377; + in->dcnt &= 0377; word |= PRI_CMT_TOT; if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word)) goto error; @@ -911,6 +918,7 @@ dte_function(UNIT *uptr) if (cmd->dev == PRI_EMLPT) { if (!sim_is_active(&lpt_unit)) sim_activate(&lpt_unit, 1000); + lpt_unit.LPST &= ~EOFFLG; while (cmd->dptr < cmd->dcnt) { if (((lpt_queue.in_ptr + 1) & 0xff) == lpt_queue.out_ptr) return; @@ -931,7 +939,7 @@ dte_function(UNIT *uptr) #if (NUM_DEVS_TTY > 0) /* Handle terminal data */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377); + int ln = cmd->sdev; struct _buffer *otty; if (ln == PRI_CTYDV) goto cty; @@ -1024,30 +1032,55 @@ cty: case PRI_EMRDS: /* Request device status */ #if (NUM_DEVS_LP > 0) if (cmd->dev == PRI_EMLPT) { - data1[0] = 0; -// if (cmd->data[0] != 0) - // data1[0] = 2; - data1[1] = (lpt_unit.LINE == 0) ? 0x1: 0; + if (cmd->data[0] != 0) { + data1[0] = 2; + data1[1] = 0; + data1[2] = 0; + } else { + data1[0] = (lpt_unit.LINE == 0) ? 0x1: 0; + data1[1] = 0; + if (lpt_unit.LPST & EOFFLG) + data1[0] |= 040; + if (lpt_unit.LPST & VFUFLG) + data1[1] |= 04; data1[2] = 0100220; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 5, data1) == 0) + } + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) return; } #endif if (cmd->dev == PRI_EMCTY) { data1[0] = 0; data1[1] = 0; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMCTY, 2, data1) == 0) + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMCTY, 3, data1) == 0) return; } if (cmd->dev == PRI_EMDH1) { data1[0] = 0; data1[1] = 0; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMDH1, 2, data1) == 0) + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMDH1, 3, data1) == 0) return; } break; case PRI_EMHDS: /* Here is device status */ + if (cmd->dev == PRI_EMLPT) { + sim_debug(DEBUG_DETAIL, &dte_dev, "TTY HDS %06o %06o %06o\n", cmd->data[0], cmd->data[1], cmd->data[2]); + data1[0] = (lpt_unit.LINE == 0) ? 0x1: 0; + data1[1] = 0; + if (cmd->data[0] & 040) { + data1[0] |= 040; + lpt_unit.LPST |= EOFFLG; + } + if (lpt_unit.LPST & VFUFLG) + data1[1] |= 04; + data1[2] = 0100220; + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) + return; +// if (cmd->data[1] & 040) { + // lpt_unit.LPST |= EOFFLG; +// } + } break; case PRI_EMLDV: /* Load LP VFU */ @@ -1056,18 +1089,19 @@ cty: while (cmd->dptr < cmd->dcnt) { lpt_vfu[ln++] = cmd->data[cmd->dptr++]; } + lpt_unit.LPST |= VFUFLG; } break; #if (NUM_DEVS_TTY > 0) case PRI_EMFLO: /* Flush output */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2; + int ln = cmd->sdev - 2; if (ln == -2) cty_out.in_ptr = cty_out.out_ptr = 0; else tty_out[ln].in_ptr = tty_out[ln].out_ptr = 0; - data1[0] = cmd->sdev; + data1[0] = cmd->sdev << 8; if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, data1) == 0) return; } @@ -1076,7 +1110,7 @@ cty: break; case PRI_EMHUD: /* Hang up dataset */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2; + int ln = cmd->sdev - 2; TMLN *lp = &tty_ldsc[ln]; tmxr_linemsg (lp, "\r\nLine Hangup\r\n"); tmxr_reset_ln(lp); @@ -1085,19 +1119,19 @@ cty: break; case PRI_EMXOF: /* XOFF line */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2; + int ln = cmd->sdev - 2; tty_ldsc[ln].rcve = 0; } break; case PRI_EMXON: /* XON line */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2; + int ln = cmd->sdev - 2; tty_ldsc[ln].rcve = 1; } break; case PRI_EMHLS: /* Here is line speeds */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = ((cmd->sdev >> 8) & 0377) - 2; + int ln = cmd->sdev - 2; } break; case PRI_EMHLA: /* Here is line allocation */ @@ -1191,7 +1225,9 @@ void dte_transfer(UNIT *uptr) { cnt -= 2; if (out->func & PRI_IND_FLG) { sim_debug(DEBUG_DATA, &dte_dev, "DTE: Indirect %o %o\n", cnt, out->dcnt); - if (!Mem_write_byte(0, &out->dcnt)) + uint16 dwrd = out->dcnt; + dwrd |= (out->sdev << 8); + if (!Mem_write_byte(0, &dwrd)) goto error; uptr->STATUS |= DTE_SIND; goto done; @@ -1745,6 +1781,7 @@ t_stat lpt_svc (UNIT *uptr) { char c; uint16 data1[5]; + int l = uptr->LINE; if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; @@ -1814,14 +1851,16 @@ t_stat lpt_svc (UNIT *uptr) lpt_output(uptr, c); } } -// data1[0] = 0; - if (uptr->LINE == 0) { - data1[0] = 0; - data1[1] = (lpt_unit.LINE == 0) ? 0x1: 0; + if ((l != 0 && uptr->LINE == 0) || (l == 0 && uptr->LINE != 0)) { + data1[0] = (lpt_unit.LINE == 0) ? 0x1: 0; + data1[1] = 0; + if (lpt_unit.LPST & VFUFLG) + data1[1] |= 04; data1[2] = 0100220; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 5, data1) == 0) + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) sim_activate(uptr, 1000); } + data1[0] = 0; if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) sim_activate(uptr, 1000); return SCPE_OK; diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 9768435..b5a09d0 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1497,9 +1497,9 @@ t_stat dev_mtr(uint32 dev, uint64 *data) { /* Read memory accounting */ if (page_enable) { sim_interval--; - res = M[ub_ptr + 0506]; + res = M[ub_ptr + 0507]; sim_interval--; - BR = (M[ub_ptr + 0507] & CMASK); + BR = (M[ub_ptr + 0506] & CMASK); } else { res = 0 << 12; BR = 0; @@ -1515,9 +1515,9 @@ t_stat dev_mtr(uint32 dev, uint64 *data) { rtc_tim = ((int)us); if (page_enable) { sim_interval--; - res = M[ub_ptr + 0504]; + res = M[ub_ptr + 0505]; sim_interval--; - BR = (M[ub_ptr + 0505] & CMASK); + BR = (M[ub_ptr + 0504] & CMASK); } else { res = 0; BR = t << 12; @@ -1593,9 +1593,9 @@ t_stat dev_tim(uint32 dev, uint64 *data) { rtc_tim = ((int)us); if (page_enable) { sim_interval--; - res = (M[ub_ptr + 0504]); + res = (M[ub_ptr + 0505]); sim_interval--; - BR = M[ub_ptr + 0505]; + BR = M[ub_ptr + 0504]; } else { res = 0 << 12; BR = t; @@ -2308,9 +2308,12 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int /* AC = 2 use ptr_flg */ /* AC = 4 all general access */ /* AC = 8 only in cur_context EA calculations */ - if (flag) - sect = uf = 0; - else if (xct_flag != 0 && !uf && !fetch) { + if (flag) { + uf = 0; +#if KLB + sect = 0; +#endif + } else if (xct_flag != 0 && !uf && !fetch) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); #if KLB //fprintf(stderr, " s%o %o", sect, glb_sect); @@ -2322,7 +2325,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; #if KLB - if (QKLB && (!glb_sect || ((xct_flag & 4) != 0 && prev_sect == 0)) && !extend) + if (QKLB && (!glb_sect/* || ((xct_flag & 4) != 0 && prev_sect == 0)*/) && !extend) sect = prev_sect; //fprintf(stderr, " ps=%o os%o", prev_sect, sect); #endif @@ -2519,6 +2522,17 @@ int Mem_read(int flag, int cur_context, int fetch) { } //fprintf(stderr, "\n\r"); } +#if KLB + /* Check if invalid section */ + if (QKLB && t20_page && !flag && (sect & 07740) != 0) { + fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); + if (USER==0) /* U */ + fault_data |= SMASK; /* BIT0 */ +//fprintf(stderr, "Invalid section %012llo\n\r", fault_data); + page_fault = 1; + return 0; + } +#endif MB = get_reg(AB); } else { if (!page_lookup(AB, flag, &addr, 0, cur_context, fetch)) @@ -2555,6 +2569,17 @@ int Mem_write(int flag, int cur_context) { } //fprintf(stderr, "\n\r"); } +#if KLB + /* Check if invalid section */ + if (QKLB && t20_page && !flag && (sect & 07740) != 0) { + fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); + if (USER==0) /* U */ + fault_data |= SMASK; /* BIT0 */ +//fprintf(stderr, "Invalid section %012llo\n\r", fault_data); + page_fault = 1; + return 0; + } +#endif set_reg(AB, MB); } else { if (!page_lookup(AB, flag, &addr, 1, cur_context, 0)) @@ -2577,7 +2602,9 @@ int exec_page_lookup(t_addr addr, int wr, int *loc) int data; int page = (RMASK & addr) >> 9; int upmp = 0; +#if KLB int sav_sect = sect; +#endif /* If paging is not enabled, address is direct */ if (!page_enable) { @@ -2600,13 +2627,17 @@ int exec_page_lookup(t_addr addr, int wr, int *loc) /* If not valid, go refill it */ if (data == 0 || (data & LMASK) != 0) { +#if KLB sect = 0; +#endif data = load_tlb(upmp, page, wr); if (data == 0) { page_fault = 0; return 1; } +#if KLB sect = sav_sect; +#endif } *loc = ((data & 017777) << 9) + (addr & 0777); return 0; @@ -4085,7 +4116,7 @@ no_fetch: AD = MB; /* Save for historical sake */ IA = AB; #if KL & KLB -// glb_sect = 0; + glb_sect = 0; #endif i_flags = opflags[IR]; BYF5 = 0; @@ -4123,15 +4154,8 @@ no_fetch: ind = 1; /* Allow us to read word, xDB has already bumped AB */ goto in_loop; } - /* If we are evaluating a address from non-zero section to reference zero sections. - Then we need to force the current section to zero before starting. - - This fixes the case of a XCT 4,[instr n,addr] that should really be in section - zero. */ -// if ((xct_flag & 4) != 0 && (FLAGS & USER) == 0 && prev_sect == 0) - // cur_sect = prev_sect; } - + #endif /* Handle indirection repeat until no longer indirect */ do { @@ -4508,15 +4532,15 @@ unasign: #endif /* Save context */ AB ++; - MB = SMASK|BIT2| + MB = SMASK| ((uint64)(fm_sel & 0160) << 23) | ((uint64)(prev_ctx & 0160) << 20) | (ub_ptr >> 9); #if KLB - if (QKLB && t20_page && (FLAGS & USER) == 0) { + if (QKLB && t20_page /*&& (FLAGS & USER) == 0*/) MB |= BIT1|((uint64)(prev_sect & 037) << 18); -// prev_sect = pc_sect; - } + if (QKLB && t20_page && (FLAGS & USER) != 0) + prev_sect = pc_sect; #endif Mem_write_nopage(); #endif @@ -7284,8 +7308,9 @@ jrstf: FLAGS |= BR & (OVR|NODIV|FLTUND|BYTI|FLTOVR|CRY1|CRY0|\ TRP1|TRP2|PUBLIC|PCHNG|ADRFLT); FLAGS &= ~PRV_PUB; - if ((FLAGS & USER) == 0) + if ((FLAGS & USER) == 0) { FLAGS |= (BR & OVR) ? PRV_PUB : 0; + } #if KL_ITS if (QITS) FLAGS |= f; @@ -7306,77 +7331,83 @@ jrstf: case 007: /* XPCW */ //fprintf(stderr, "XPCW %06o %06o %06o %06o\r\n", pc_sect, AB, PC, FLAGS << 5); - MB = ((((uint64)FLAGS) << 23) + MB = ((((uint64)FLAGS) << 23) #if KLB - | (prev_sect & 037) + | (prev_sect & 037) #endif - ) & FMASK; - /* Save Previous Public context */ - if ((FLAGS & USER) == 0) { - MB &= ~SMASK; - MB |= (FLAGS & PRV_PUB) ? SMASK : 0; - } - if (uuo_cycle | pi_cycle) { - FLAGS &= ~(USER|PUBLIC); /* Clear USER */ - sect = 0; /* Force section zero on IRQ */ - } - if (Mem_write(0, 0)) - goto last; - AB = (AB + 1) & RMASK; + ) & FMASK; + /* Save Previous Public context */ + if ((FLAGS & USER) == 0) { + MB &= ~SMASK; + MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + } + if (uuo_cycle | pi_cycle) { + FLAGS &= ~(USER|PUBLIC); /* Clear USER */ #if KLB - if (QKLB && t20_page) - MB = (((((uint64)pc_sect) << 18) | PC) + !pi_cycle) & (SECTM|RMASK); - else + sect = 0; /* Force section zero on IRQ */ #endif - MB = (PC + !pi_cycle) & (RMASK); - if (Mem_write(0, 0)) - goto last; - AB = (AB + 1) & RMASK; - goto xjrstf; + } + if (Mem_write(0, 0)) + goto last; + AB = (AB + 1) & RMASK; +#if KLB + if (QKLB && t20_page) + MB = (((((uint64)pc_sect) << 18) | PC) + !pi_cycle) & (SECTM|RMASK); + else +#endif + MB = (PC + !pi_cycle) & (RMASK); + if (Mem_write(0, 0)) + goto last; + AB = (AB + 1) & RMASK; + goto xjrstf; case 015: /* XJRST */ - if (Mem_read(0, 0, 0)) - goto last; - AR = MB; /* Get PC. */ + if (Mem_read(0, 0, 0)) + goto last; + AR = MB; /* Get PC. */ #if KLB - if (QKLB && t20_page) { - pc_sect = (AR >> 18) & 07777; - } + if (QKLB && t20_page) { + pc_sect = (AR >> 18) & 07777; + } #endif - break; + break; case 014: /* SFM */ - MB = ((((uint64)FLAGS) << 23) | (uint64)(prev_sect & 037)) & FMASK; - if ((FLAGS & USER) == 0) { - MB &= ~SMASK; - MB |= (FLAGS & PRV_PUB) ? SMASK : 0; - } - (void)Mem_write(0, 0); - goto last; +#if KLB + MB = ((((uint64)FLAGS) << 23) | (uint64)(prev_sect & 037)) & FMASK; +#else + MB = (((uint64)FLAGS) << 23) & FMASK; +#endif + if ((FLAGS & USER) == 0) { + MB &= ~SMASK; + MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + } + (void)Mem_write(0, 0); + goto last; case 003: /* Invalid */ case 011: /* Invalid */ case 013: /* Invalid */ case 016: /* Invalid */ - goto muuo; + goto muuo; case 004: /* HALT */ - if ((FLAGS & (USER|USERIO)) == USER || - (FLAGS & (USER|PUBLIC)) == PUBLIC) { - goto muuo; - } else { - reason = STOP_HALT; - } - break; + if ((FLAGS & (USER|USERIO)) == USER || + (FLAGS & (USER|PUBLIC)) == PUBLIC) { + goto muuo; + } else { + reason = STOP_HALT; + } + break; case 010: /* JEN */ - /* Restore interrupt level. */ - if ((FLAGS & (USER|USERIO)) == USER || - (FLAGS & (USER|PUBLIC)) == PUBLIC) { - goto muuo; - } else { - pi_restore = 1; - } - break; + /* Restore interrupt level. */ + if ((FLAGS & (USER|USERIO)) == USER || + (FLAGS & (USER|PUBLIC)) == PUBLIC) { + goto muuo; + } else { + pi_restore = 1; + } + break; } #if KL_ITS if (QITS && (FLAGS & USER)) { @@ -7549,6 +7580,7 @@ jrstf: break; } +#if KLB /* Check if access to register */ if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { AR = AB; /* direct map */ @@ -7559,6 +7591,7 @@ jrstf: set_reg(AC, AR); break; } +#endif /* Handle KI paging odditiy */ if (!flag1 && !t20_page && (f & 0740) == 0340) { @@ -7569,7 +7602,7 @@ jrstf: AR = load_tlb(flag1 | flag3, f, 0); if (page_fault) { - page_fault = 0; + page_fault = 0; AR |= fault_data; if (flag1) /* U */ AR |= SMASK; @@ -7639,6 +7672,7 @@ jrstf: if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + MB &= FMASK; } #if KL & KLB } @@ -7647,23 +7681,17 @@ jrstf: #if KL BYF5 = 1; #if KLB - if (QKLB && t20_page) { - if (pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - AR = (AR + 1) & FMASK; - sect = (AR >> 18) & 07777; - } else { - sect = pc_sect; - AR = AOB(AR); - if (pc_sect != 0 && (AR & RMASK) < 020) - sect = 1; - } - } else + f = glb_sect; + if (QKLB && t20_page && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR = (AR + 1) & FMASK; + sect = (AR >> 18) & 07777; + glb_sect = 1; + } else { + sect = pc_sect; + glb_sect = 0; #endif #endif AR = AOB(AR); - AB = AR & RMASK; - if (Mem_write(uuo_cycle | pi_cycle, 0)) - goto last; FLAGS &= ~ (BYTI|ADRFLT|TRP1|TRP2); if (AR & C1) { #if KI | KL @@ -7674,6 +7702,12 @@ jrstf: check_apr_irq(); #endif } +#if KL && KLB + } +#endif + AB = AR & RMASK; + if (Mem_write(uuo_cycle | pi_cycle, 0)) + goto last; #if !PDP6 if (uuo_cycle | pi_cycle) { FLAGS &= ~(USER|PUBLIC); /* Clear USER */ @@ -7691,27 +7725,24 @@ jrstf: } #endif #if KL & KLB - if (QKLB && glb_sect) + if (QKLB && t20_page && f) pc_sect = cur_sect; #endif PC = BR & RMASK; PC_CHANGE f_pc_inh = 1; +//fprintf(stderr, "Pushj %06o %06o %012llo %012llo %06o\n\r", pc_sect, cur_sect, AR, MB, PC); break; case 0261: /* PUSH */ #if KL BYF5 = 1; #if KLB - if (QKLB && t20_page) { - if (pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - AR = (AR + 1) & FMASK; - sect = (AR >> 18) & 07777; - } else { - sect = pc_sect; - AR = AOB(AR); - } - } else + if (QKLB && t20_page &&pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR = (AR + 1) & FMASK; + sect = (AR >> 18) & 07777; + } else { + sect = pc_sect; #endif #endif AR = AOB(AR); @@ -7727,13 +7758,6 @@ jrstf: #endif } #if KLB - if (QKLB && t20_page) { - if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) - sect = prev_sect; - if (sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - sect = (AR >> 18) & 07777; - glb_sect = 1; - } } #endif if (Mem_write(0, 0)) @@ -7745,19 +7769,16 @@ jrstf: BYF5 = 1; /* Tell PXCT that this is stack */ #if KLB flag1 = glb_sect; + glb_sect = 0; + sect = pc_sect; if (QKLB && t20_page) { - f = (pc_sect != 0); - sect = pc_sect; - if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) { - sect = prev_sect; - f = (prev_sect != 0); + if ((xct_flag & 1) != 0 && (FLAGS & USER) == 0) + sect = prev_sect; + if (sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + sect = (AR >> 18) & 07777; + glb_sect = 1; } - if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - sect = (AR >> 18) & 07777; - glb_sect = 1; - } - } else - f = 0; + } //fprintf(stderr, "Pop %o %o %06o %06o %06o %012llo %012llo\n\r", f, xct_flag, prev_sect, sect, cur_sect, AR, BR); #endif #endif @@ -7777,9 +7798,13 @@ jrstf: if (Mem_write(0, 0)) goto last; #if KL & KLB - if (QKLB && f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - AR = (AR - 1) & FMASK; - break; + if (QKLB && t20_page) { + if ((xct_flag & 1) != 0 && (FLAGS & USER) == 0) + sect = prev_sect; + if (sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + AR = (AR - 1) & FMASK; + break; + } } #endif AR = SOB(AR); @@ -7799,21 +7824,19 @@ jrstf: #if KL BYF5 = 1; /* Tell PXCT that this is stack */ #if KLB - if (QKLB && t20_page) { - f = (pc_sect != 0); - sect = pc_sect; - if ((FLAGS & USER) == 0 && (xct_flag & 1) != 0) { - f = (prev_sect != 0); - sect = prev_sect; - } - if (f && (AR & SMASK) == 0 && (AR & SECTM) != 0) { - sect = (AR >> 18) & 07777; - glb_sect = 1; - } + glb_sect = 0; + sect = pc_sect; + if (QKLB && t20_page && (xct_flag & 1) != 0 && (FLAGS & USER) == 0) + sect = prev_sect; + if (QKLB && t20_page && sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { + sect = (AR >> 18) & 07777; + glb_sect = 1; + AR = (AR - 1) & FMASK; } else - f = 0; #endif #endif + AR = SOB(AR); + if (Mem_read(0, 0, 0)) goto last; #if ITS | KL_ITS @@ -7827,16 +7850,13 @@ jrstf: #if KL BYF5 = 0; /* Tell PXCT that this is stack */ #if KLB - if (QKLB && f) { + if (QKLB && t20_page && pc_sect != 0) { pc_sect = (MB >> 18) & 07777; - if ((AR & SMASK) == 0 && (AR & SECTM) != 0) { - AR = (AR - 1) & FMASK; + if ((AR & SMASK) == 0 && (AR & SECTM) != 0) break; - } } #endif #endif - AR = SOB(AR); if ((AR & C1) == 0) { #if KI | KL if (!pi_cycle) @@ -7846,6 +7866,7 @@ jrstf: check_apr_irq(); #endif } +//fprintf(stderr, "Popj %06o %06o %012llo %012llo %06o\n\r", pc_sect, cur_sect, AR, MB, PC); break; case 0264: /* JSR */ /* AR Frm PC */ @@ -8318,7 +8339,7 @@ skip_op: } /* Fall Through */ #endif - + case 0500: /* HLL */ case 0502: /* HLLM */ case 0504: /* HRL */ @@ -8678,7 +8699,7 @@ last: AB++; FLAGS |= trap_flag & (TRP1|TRP2); trap_flag = (TRP1|TRP2); - MB = (((uint64)(FLAGS) << 23) & LMASK); + MB = (((uint64)(FLAGS) << 23) & LMASK); #if KLB if (QKLB && t20_page) { if ((FLAGS & USER) == 0) @@ -10150,7 +10171,7 @@ tim_srv(UNIT * uptr) /* * This sequence of instructions is a mix that hopefully - * represents a resonable instruction set that is a close + * represents a resonable instruction set that is a close * estimate to the normal calibrated result. */ diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index f76979f..f5d555d 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -51,15 +51,10 @@ #endif #if KL -#define KLA 1 #define KLB 1 #define EPT440 0 /* Force KL10A to 440 section address */ #endif -#ifndef KLA -#define KLA 0 -#endif - #ifndef KLB #define KLB 0 #endif diff --git a/PDP10/kx10_dp.c b/PDP10/kx10_dp.c index 15f8d62..75496e4 100644 --- a/PDP10/kx10_dp.c +++ b/PDP10/kx10_dp.c @@ -721,7 +721,7 @@ t_stat dp_svc (UNIT *uptr) CLR_BUF(uptr); } if (r) - sim_activate(uptr, 10); + sim_activate(uptr, 40); else { uptr->STATUS &= ~(SRC_DONE|END_CYL|BUSY); uptr->UFLAGS |= DONE; From b2cfeaa3ced8a22e47bb660fb16bd86ba86d8da7 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 24 Nov 2019 23:35:29 -0500 Subject: [PATCH 63/98] KA10: Fixed extended Byte instructions for Tops 20 pointers. --- PDP10/kx10_cpu.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index b5a09d0..2d66e7c 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2325,7 +2325,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; #if KLB - if (QKLB && (!glb_sect/* || ((xct_flag & 4) != 0 && prev_sect == 0)*/) && !extend) + if (QKLB && (!glb_sect || ((xct_flag & 4) != 0 && prev_sect == 0)) && !extend) sect = prev_sect; //fprintf(stderr, " ps=%o os%o", prev_sect, sect); #endif @@ -6017,13 +6017,14 @@ unasign: SC = _byte_adj[i].s; SCAD = _byte_adj[i].p; ld_ptr: + glb_sect = 1; sect = (AR >> 18) & 07777; - AB = AR & RMASK; + FLAGS |= BYTI; + BYF5 = 1; + goto ld_exe; } #endif ldb_ptr: - MQ = (uint64)(1) << SC; - MQ -= 1; f_load_pc = 0; f_inst_fetch = 0; f_pc_inh = 1; @@ -6051,13 +6052,18 @@ ldb_ptr: } #endif } else { - AB = AR & RMASK; #if KL ptr_flg = 0; +#if KLB +ld_exe: +#endif #else if ((IR & 06) == 6) modify = 1; #endif + AB = AR & RMASK; + MQ = (uint64)(1) << SC; + MQ -= 1; if (Mem_read(0, 0, 0)) goto last; AR = MB; From 24226358b08da500548e7ce9d688ae453a669df6 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 1 Dec 2019 23:33:06 -0500 Subject: [PATCH 64/98] SCP: Updated to current. --- sim_disk.c | 2 +- sim_tape.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sim_disk.c b/sim_disk.c index 1c8a2a2..a66dc1c 100644 --- a/sim_disk.c +++ b/sim_disk.c @@ -1123,7 +1123,7 @@ t_seccnt sects_read; if ((dptr = find_dev_from_unit (uptr)) == NULL) return ret_val; saved_capac = uptr->capac; -uptr->capac = temp_capac; +uptr->capac = (t_addr)temp_capac; if ((sim_disk_rdsect (uptr, 512 / ctx->sector_size, (uint8 *)&Home, §s_read, sizeof (Home) / ctx->sector_size)) || (sects_read != (sizeof (Home) / ctx->sector_size))) goto Return_Cleanup; diff --git a/sim_tape.c b/sim_tape.c index 4a24d1b..21ec102 100644 --- a/sim_tape.c +++ b/sim_tape.c @@ -3274,9 +3274,11 @@ tape_size = (t_addr)sim_fsize (uptr->fileref); sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: tape_size: %" T_ADDR_FMT "u\n", tape_size); for (objc = 0, sizec = 0, tpos = 0;; ) { (void)sim_tape_seek (uptr, tpos); - i = sim_fread (&bc, sizeof (t_tpclnt), 1, uptr->fileref); + i = sim_fread (&bc, sizeof (bc), 1, uptr->fileref); if (i == 0) /* past or at eof? */ break; + if (bc > 65535) /* Range check length value to satisfy Coverity */ + break; if (countmap[bc] == 0) sizec++; ++countmap[bc]; From 4d6871bc0d7d22a29ec935122af10f02ce8165f1 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 1 Dec 2019 23:34:43 -0500 Subject: [PATCH 65/98] KA10: Renamed LPT to LP20. --- PDP10/kl10_fe.c | 217 +++++++++++++++++++++++++--------------------- PDP10/kx10_cpu.c | 9 +- PDP10/kx10_defs.h | 3 + PDP10/kx10_sys.c | 3 + makefile | 2 +- 5 files changed, 131 insertions(+), 103 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 2da9550..9f98962 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -291,16 +291,17 @@ DEVICE dte_dev = { -#ifndef NUM_DEVS_LP -#define NUM_DEVS_LP 0 +#ifndef NUM_DEVS_LP20 +#define NUM_DEVS_LP20 0 #endif -#if (NUM_DEVS_LP > 0) +#if (NUM_DEVS_LP20 > 0) #define COL u4 #define POS u5 #define LINE u6 #define LPST us9 +#define LPCNT us10 #define PTRMSK 00777 /* Current data load pointer */ #define EOFFLG 01000 /* Tops 20 wants EOF */ @@ -314,52 +315,53 @@ DEVICE dte_dev = { -t_stat lpt_svc (UNIT *uptr); -t_stat lpt_reset (DEVICE *dptr); -t_stat lpt_attach (UNIT *uptr, CONST char *cptr); -t_stat lpt_detach (UNIT *uptr); -t_stat lpt_setlpp(UNIT *, int32, CONST char *, void *); -t_stat lpt_getlpp(FILE *, UNIT *, int32, CONST void *); -t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, +t_stat lp20_svc (UNIT *uptr); +t_stat lp20_reset (DEVICE *dptr); +t_stat lp20_attach (UNIT *uptr, CONST char *cptr); +t_stat lp20_detach (UNIT *uptr); +t_stat lp20_setlpp(UNIT *, int32, CONST char *, void *); +t_stat lp20_getlpp(FILE *, UNIT *, int32, CONST void *); +t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); -const char *lpt_description (DEVICE *dptr); +const char *lp20_description (DEVICE *dptr); -char lpt_buffer[134 * 3]; -uint16 lpt_vfu[256]; +char lp20_buffer[134 * 3]; +uint16 lp20_vfu[256]; +uint16 lp20_ram[256]; -struct _buffer lpt_queue; +struct _buffer lp20_queue; /* LPT data structures - lpt_dev LPT device descriptor - lpt_unit LPT unit descriptor - lpt_reg LPT register list + lp20_dev LPT device descriptor + lp20_unit LPT unit descriptor + lp20_reg LPT register list */ -UNIT lpt_unit = { - UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 66), 100 +UNIT lp20_unit = { + UDATA (&lp20_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 66), 100 }; -REG lpt_reg[] = { - { BRDATA(BUFF, lpt_buffer, 16, 8, sizeof(lpt_buffer)), REG_HRO}, +REG lp20_reg[] = { + { BRDATA(BUFF, lp20_buffer, 16, 8, sizeof(lp20_buffer)), REG_HRO}, { NULL } }; -MTAB lpt_mod[] = { +MTAB lp20_mod[] = { {UNIT_CT, 0, "Lower case", "LC", NULL}, {UNIT_CT, UNIT_UC, "Upper case", "UC", NULL}, {MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LINESPERPAGE", "LINESPERPAGE", - &lpt_setlpp, &lpt_getlpp, NULL, "Number of lines per page"}, + &lp20_setlpp, &lp20_getlpp, NULL, "Number of lines per page"}, { 0 } }; -DEVICE lpt_dev = { - "LPT", &lpt_unit, lpt_reg, lpt_mod, +DEVICE lp20_dev = { + "LP20", &lp20_unit, lp20_reg, lp20_mod, 1, 10, 31, 1, 8, 8, - NULL, NULL, &lpt_reset, - NULL, &lpt_attach, &lpt_detach, + NULL, NULL, &lp20_reset, + NULL, &lp20_attach, &lp20_detach, NULL, DEV_DISABLE | DEV_DEBUG, 0, dev_debug, - NULL, NULL, &lpt_help, NULL, NULL, &lpt_description + NULL, NULL, &lp20_help, NULL, NULL, &lp20_description }; #endif @@ -875,7 +877,7 @@ dte_function(UNIT *uptr) data1[0] = PRI_CTYDV; if (dte_queue(PRI_EM2TI, PRI_EMCTY, 1, data1) == 0) return; -#if (NUM_DEVS_LP > 0) +#if (NUM_DEVS_LP20 > 0) data1[0] = 140; if (dte_queue(PRI_EMHLA, PRI_EMLPT, 1, data1) == 0) return; @@ -913,21 +915,21 @@ dte_function(UNIT *uptr) case PRI_EMSTR: /* String data */ -#if (NUM_DEVS_LP > 0) +#if (NUM_DEVS_LP20 > 0) /* Handle printer data */ if (cmd->dev == PRI_EMLPT) { - if (!sim_is_active(&lpt_unit)) - sim_activate(&lpt_unit, 1000); - lpt_unit.LPST &= ~EOFFLG; + if (!sim_is_active(&lp20_unit)) + sim_activate(&lp20_unit, 1000); + lp20_unit.LPST &= ~EOFFLG; while (cmd->dptr < cmd->dcnt) { - if (((lpt_queue.in_ptr + 1) & 0xff) == lpt_queue.out_ptr) + if (((lp20_queue.in_ptr + 1) & 0xff) == lp20_queue.out_ptr) return; ch = (int32)(cmd->data[cmd->dptr >> 1]); if ((cmd->dptr & 1) == 0) ch >>= 8; ch &= 0177; - lpt_queue.buff[lpt_queue.in_ptr] = ch; - lpt_queue.in_ptr = (lpt_queue.in_ptr + 1) & 0xff; + lp20_queue.buff[lp20_queue.in_ptr] = ch; + lp20_queue.in_ptr = (lp20_queue.in_ptr + 1) & 0xff; cmd->dptr++; } if (cmd->dptr != cmd->dcnt) @@ -1030,20 +1032,21 @@ cty: break; case PRI_EMRDS: /* Request device status */ -#if (NUM_DEVS_LP > 0) +#if (NUM_DEVS_LP20 > 0) if (cmd->dev == PRI_EMLPT) { if (cmd->data[0] != 0) { data1[0] = 2; data1[1] = 0; data1[2] = 0; } else { - data1[0] = (lpt_unit.LINE == 0) ? 0x1: 0; - data1[1] = 0; - if (lpt_unit.LPST & EOFFLG) + data1[0] = 0; + data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; + if (lp20_unit.LPST & EOFFLG) data1[0] |= 040; - if (lpt_unit.LPST & VFUFLG) - data1[1] |= 04; - data1[2] = 0100220; +// if (lp20_unit.LPST & VFUFLG) + // data1[1] |= 04; + lp20_unit.LPST &= ~EOFFLG; + data1[2] = 0; //0100220; } if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) return; @@ -1066,33 +1069,49 @@ cty: case PRI_EMHDS: /* Here is device status */ if (cmd->dev == PRI_EMLPT) { sim_debug(DEBUG_DETAIL, &dte_dev, "TTY HDS %06o %06o %06o\n", cmd->data[0], cmd->data[1], cmd->data[2]); - data1[0] = (lpt_unit.LINE == 0) ? 0x1: 0; - data1[1] = 0; + data1[0] = 0; + data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; if (cmd->data[0] & 040) { data1[0] |= 040; - lpt_unit.LPST |= EOFFLG; + lp20_unit.LPST |= EOFFLG; + lp20_unit.LPCNT = 0; } - if (lpt_unit.LPST & VFUFLG) - data1[1] |= 04; +// if (lp20_unit.LPST & VFUFLG) + // data1[1] |= 04; data1[2] = 0100220; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) - return; +// if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) + // return; // if (cmd->data[1] & 040) { - // lpt_unit.LPST |= EOFFLG; + // lp20_unit.LPST |= EOFFLG; // } } break; - +#if (NUM_DEVS_LP20 > 0) case PRI_EMLDV: /* Load LP VFU */ if (cmd->dev == PRI_EMLPT) { - int ln = 0; + int ln = lp20_unit.LPCNT; while (cmd->dptr < cmd->dcnt) { - lpt_vfu[ln++] = cmd->data[cmd->dptr++]; + lp20_vfu[ln++] = cmd->data[cmd->dptr++]; } - lpt_unit.LPST |= VFUFLG; + lp20_unit.LPST |= VFUFLG; + lp20_unit.LPCNT = ln; } break; + case PRI_EMLDR: /* Load LP RAM */ + if (cmd->dev == PRI_EMLPT) { + int ln = lp20_unit.LPCNT; + for (;cmd->dptr < cmd->dcnt; cmd->dptr++, ln++) { + if (ln < 256) + lp20_ram[ln] = cmd->data[cmd->dptr]; + } + lp20_unit.LPCNT = ln; + for (ln = 0; ln < 256; ln++) + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP20 RAM %02x => %04x\n", ln, lp20_ram[ln]); + } + break; +#endif + #if (NUM_DEVS_TTY > 0) case PRI_EMFLO: /* Flush output */ if ((cmd->dev & 0377) == PRI_EMDLS) { @@ -1154,7 +1173,6 @@ cty: } break; #endif - case PRI_EMLDR: /* Load LP RAM */ default: break; } @@ -1724,35 +1742,35 @@ const char *dte_description (DEVICE *dptr) } -#if (NUM_DEVS_LP > 0) +#if (NUM_DEVS_LP20 > 0) void -lpt_printline(UNIT *uptr, int nl) { +lp20_printline(UNIT *uptr, int nl) { int trim = 0; uint16 data1 = 1; /* Trim off trailing blanks */ - while (uptr->COL >= 0 && lpt_buffer[uptr->POS - 1] == ' ') { + while (uptr->COL >= 0 && lp20_buffer[uptr->POS - 1] == ' ') { uptr->COL--; uptr->POS--; trim = 1; } - lpt_buffer[uptr->POS] = '\0'; - sim_debug(DEBUG_DETAIL, &lpt_dev, "LP output %d %d [%s]\n", uptr->COL, nl, lpt_buffer); + lp20_buffer[uptr->POS] = '\0'; + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP output %d %d [%s]\n", uptr->COL, nl, lp20_buffer); /* Stick a carraige return and linefeed as needed */ if (uptr->COL != 0 || trim) - lpt_buffer[uptr->POS++] = '\r'; + lp20_buffer[uptr->POS++] = '\r'; if (nl != 0) { - lpt_buffer[uptr->POS++] = '\n'; + lp20_buffer[uptr->POS++] = '\n'; uptr->LINE++; } if (nl > 0 && uptr->LINE >= ((int32)uptr->capac - MARGIN)) { - lpt_buffer[uptr->POS++] = '\f'; + lp20_buffer[uptr->POS++] = '\f'; uptr->LINE = 0; } else if (nl < 0 && uptr->LINE >= (int32)uptr->capac) { uptr->LINE = 0; } - sim_fwrite(&lpt_buffer, 1, uptr->POS, uptr->fileref); + sim_fwrite(&lp20_buffer, 1, uptr->POS, uptr->fileref); uptr->pos += uptr->POS; uptr->COL = 0; uptr->POS = 0; @@ -1762,22 +1780,22 @@ lpt_printline(UNIT *uptr, int nl) { /* Unit service */ void -lpt_output(UNIT *uptr, char c) { +lp20_output(UNIT *uptr, char c) { if (c == 0) return; if (uptr->COL == 132) - lpt_printline(uptr, 1); + lp20_printline(uptr, 1); if ((uptr->flags & UNIT_UC) && (c & 0140) == 0140) c &= 0137; else if (c >= 040 && c < 0177) { - lpt_buffer[uptr->POS++] = c; + lp20_buffer[uptr->POS++] = c; uptr->COL++; } return; } -t_stat lpt_svc (UNIT *uptr) +t_stat lp20_svc (UNIT *uptr) { char c; uint16 data1[5]; @@ -1786,30 +1804,31 @@ t_stat lpt_svc (UNIT *uptr) if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; - while (((lpt_queue.out_ptr + 1) & 0xff) != lpt_queue.in_ptr) { - c = lpt_queue.buff[lpt_queue.out_ptr]; - lpt_queue.out_ptr = (lpt_queue.out_ptr + 1) & 0xff; + while (((lp20_queue.out_ptr + 1) & 0xff) != lp20_queue.in_ptr) { + c = lp20_queue.buff[lp20_queue.out_ptr]; + lp20_queue.out_ptr = (lp20_queue.out_ptr + 1) & 0xff; if (c < 040) { /* Control character */ + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x %04x\n", c, lp20_ram[c] ); switch(c) { case 011: /* Horizontal tab, space to 8'th column */ - lpt_output(uptr, ' '); + lp20_output(uptr, ' '); while ((uptr->COL & 07) != 0) - lpt_output(uptr, ' '); + lp20_output(uptr, ' '); break; case 015: /* Carriage return, print line */ - lpt_printline(uptr, 0); + lp20_printline(uptr, 0); break; case 012: /* Line feed, print line, space one line */ - lpt_printline(uptr, 1); + lp20_printline(uptr, 1); break; case 014: /* Form feed, skip to top of page */ - lpt_printline(uptr, 0); + lp20_printline(uptr, 0); sim_fwrite("\014", 1, 1, uptr->fileref); uptr->pos++; uptr->LINE = 0; break; case 013: /* Vertical tab, Skip mod 20 */ - lpt_printline(uptr, 1); + lp20_printline(uptr, 1); while((uptr->LINE % 20) != 0) { sim_fwrite("\r\n", 1, 2, uptr->fileref); uptr->pos+=2; @@ -1817,7 +1836,7 @@ t_stat lpt_svc (UNIT *uptr) } break; case 020: /* Skip half page */ - lpt_printline(uptr, 1); + lp20_printline(uptr, 1); while((uptr->LINE % 30) != 0) { sim_fwrite("\r\n", 1, 2, uptr->fileref); uptr->pos+=2; @@ -1825,7 +1844,7 @@ t_stat lpt_svc (UNIT *uptr) } break; case 021: /* Skip even lines */ - lpt_printline(uptr, 1); + lp20_printline(uptr, 1); while((uptr->LINE % 2) != 0) { sim_fwrite("\r\n", 1, 2, uptr->fileref); uptr->pos+=2; @@ -1833,7 +1852,7 @@ t_stat lpt_svc (UNIT *uptr) } break; case 022: /* Skip triple lines */ - lpt_printline(uptr, 1); + lp20_printline(uptr, 1); while((uptr->LINE % 3) != 0) { sim_fwrite("\r\n", 1, 2, uptr->fileref); uptr->pos+=2; @@ -1841,22 +1860,22 @@ t_stat lpt_svc (UNIT *uptr) } break; case 023: /* Skip one line */ - lpt_printline(uptr, -1); + lp20_printline(uptr, -1); break; default: /* Ignore */ break; } } else { - sim_debug(DEBUG_DETAIL, &lpt_dev, "LP deque %02x '%c'\n", c, c); - lpt_output(uptr, c); + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x '%c' %04x\n", c, c, lp20_ram[c] ); + lp20_output(uptr, c); } } if ((l != 0 && uptr->LINE == 0) || (l == 0 && uptr->LINE != 0)) { - data1[0] = (lpt_unit.LINE == 0) ? 0x1: 0; - data1[1] = 0; - if (lpt_unit.LPST & VFUFLG) - data1[1] |= 04; - data1[2] = 0100220; + data1[0] = 0; + data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; +// if (uptr->LPST & VFUFLG) + // data1[1] |= 04; + data1[2] = 0; //0100220; if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) sim_activate(uptr, 1000); } @@ -1868,26 +1887,26 @@ t_stat lpt_svc (UNIT *uptr) /* Reset routine */ -t_stat lpt_reset (DEVICE *dptr) +t_stat lp20_reset (DEVICE *dptr) { - UNIT *uptr = &lpt_unit; + UNIT *uptr = &lp20_unit; uptr->POS = 0; uptr->COL = 0; uptr->LINE = 1; - sim_cancel (&lpt_unit); /* deactivate unit */ + sim_cancel (&lp20_unit); /* deactivate unit */ return SCPE_OK; } /* Attach routine */ -t_stat lpt_attach (UNIT *uptr, CONST char *cptr) +t_stat lp20_attach (UNIT *uptr, CONST char *cptr) { return attach_unit (uptr, cptr); } /* Detach routine */ -t_stat lpt_detach (UNIT *uptr) +t_stat lp20_detach (UNIT *uptr) { return detach_unit (uptr); } @@ -1897,7 +1916,7 @@ t_stat lpt_detach (UNIT *uptr) */ t_stat -lpt_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc) +lp20_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc) { t_value i; t_stat r; @@ -1914,7 +1933,7 @@ lpt_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc) } t_stat -lpt_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc) +lp20_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc) { if (uptr == NULL) return SCPE_IERR; @@ -1922,7 +1941,7 @@ lpt_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc) return SCPE_OK; } -t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { fprintf (st, "Line Printer (LPT)\n\n"); fprintf (st, "The line printer (LPT) writes data to a disk file. The POS register specifies\n"); @@ -1939,9 +1958,9 @@ fprint_reg_help (st, dptr); return SCPE_OK; } -const char *lpt_description (DEVICE *dptr) +const char *lp20_description (DEVICE *dptr) { - return "LPT0 line printer" ; + return "LP20 line printer" ; } #endif diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 2d66e7c..811abc5 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -102,7 +102,7 @@ #define HIST_PC2 0x80000000 #define HIST_PCE 0x20000000 #define HIST_MIN 64 -#define HIST_MAX 500000 +#define HIST_MAX 5000000 #define TMR_RTC 0 #define TMR_QUA 1 @@ -2325,7 +2325,10 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; #if KLB - if (QKLB && (!glb_sect || ((xct_flag & 4) != 0 && prev_sect == 0)) && !extend) +// if (QKLB && glb_sect && (((xct_flag & 014) == 04 && !BYF5 && !ptr_flg) || +// ((xct_flag & 03) == 01 && BYF5))) +// sect = prev_sect; + if (QKLB && (!glb_sect /*|| ((xct_flag & 4) != 0 && prev_sect == 0)*/) && !extend) sect = prev_sect; //fprintf(stderr, " ps=%o os%o", prev_sect, sect); #endif @@ -2339,7 +2342,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fault_data = (027LL << 30) | (((uint64)sect) << 18) | (uint64)addr; if (uf) /* U */ fault_data |= SMASK; /* BIT0 */ -//fprintf(stderr, "Invalid section %012llo\n\r", fault_data); +//fprintf(stderr, "Invalid section %012llo %06o\n\r", fault_data, PC); page_fault = 1; return 0; } diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index f5d555d..4df7a53 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -410,6 +410,7 @@ extern int Mem_deposit_word(int n, int wrd, uint64 *data); extern int Mem_read_byte(int n, uint16 *data, int byte); extern int Mem_write_byte(int n, uint16 *data); extern DEVICE dte_dev; +extern DEVICE lp20_dev; extern DEVICE tty_dev; #else extern DEVICE cty_dev; @@ -587,6 +588,7 @@ int auxcpu_write (t_addr addr, t_uint64); #define NUM_DEVS_DT 0 #define NUM_DEVS_DK 0 #define NUM_DEVS_DP 0 +#define NUM_DEVS_LP20 1 #define NUM_DEVS_TTY 1 #define NUM_LINES_TTY 40 #else @@ -594,6 +596,7 @@ int auxcpu_write (t_addr addr, t_uint64); #define NUM_DEVS_DT 1 #define NUM_DEVS_DK 1 #define NUM_DEVS_DP 2 +#define NUM_DEVS_LP20 0 #define NUM_DEVS_TTY 0 #endif #define NUM_DEVS_RP 4 diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index cc923c8..5fbe055 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -75,6 +75,9 @@ DEVICE *sim_devices[] = { #if (NUM_DEVS_LP > 0) &lpt_dev, #endif +#if (NUM_DEVS_LP20 > 0) + &lp20_dev, +#endif #if (NUM_DEVS_CR > 0) &cr_dev, #endif diff --git a/makefile b/makefile index e645ce4..bd21b40 100644 --- a/makefile +++ b/makefile @@ -1271,7 +1271,7 @@ KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \ ${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rh.c \ ${KL10D}/kx10_rp.c ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c \ ${KL10D}/kx10_imp.c ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c \ - ${KL10D}/ka10_ch10.c + ${KL10D}/ka10_ch10.c ${KL10D}/kx10_lp.c KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT} PDP1D = PDP1 From 5fe616ce38a582ac5e631cdad6f1f3c0929aa55a Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 1 Dec 2019 23:44:29 -0500 Subject: [PATCH 66/98] KA10: Updated documenation to current. --- doc/ka10_doc.doc | Bin 242688 -> 215552 bytes doc/ki10_doc.doc | Bin 148992 -> 149504 bytes doc/kl10_doc.doc | Bin 0 -> 146432 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/kl10_doc.doc diff --git a/doc/ka10_doc.doc b/doc/ka10_doc.doc index 58e8d19bc07a9789ca4d4db73a1f999ebf598d23..1efc75b796e54b3196b64187b333a7ae4c62bf08 100644 GIT binary patch literal 215552 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%0APZ%Exn=|RsHKUnRH#^U8tX~HMk%A#x9;ptDLx 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 Ue-8*#*BWgdY1cMmU(h7*f98?<9RL6T diff --git a/doc/ki10_doc.doc b/doc/ki10_doc.doc index 42c1f6bd94847f45ad5842c7a29afa059499a339..c6031e9dd49aaae320d615c0bead193f915295d3 100644 GIT binary patch delta 13056 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 TIqv_Rm{AhJe%| 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 literal 0 HcmV?d00001 From 4d79f225a88b47a8af3b027d6461219118449abd Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Mon, 2 Dec 2019 21:59:43 -0500 Subject: [PATCH 67/98] KA10: Fixed KL10 compile for Windows. --- PDP10/kl10_fe.c | 2 +- Visual Studio Projects/PDP10-KL.vcproj | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 9f98962..12859e9 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -1242,8 +1242,8 @@ void dte_transfer(UNIT *uptr) { goto error; cnt -= 2; if (out->func & PRI_IND_FLG) { -sim_debug(DEBUG_DATA, &dte_dev, "DTE: Indirect %o %o\n", cnt, out->dcnt); uint16 dwrd = out->dcnt; +sim_debug(DEBUG_DATA, &dte_dev, "DTE: Indirect %o %o\n", cnt, out->dcnt); dwrd |= (out->sdev << 8); if (!Mem_write_byte(0, &dwrd)) goto error; diff --git a/Visual Studio Projects/PDP10-KL.vcproj b/Visual Studio Projects/PDP10-KL.vcproj index 3e0c09f..4b9ca5f 100644 --- a/Visual Studio Projects/PDP10-KL.vcproj +++ b/Visual Studio Projects/PDP10-KL.vcproj @@ -221,6 +221,10 @@ RelativePath="..\PDP10\kx10_imp.c" > + + From 79bf7cff9d44d54f592c29828e1987696b7e6d45 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 5 Dec 2019 23:16:37 -0500 Subject: [PATCH 68/98] KA10: Fixed issues with Tops 20 V5-V7 with DLUSER. --- PDP10/kx10_cpu.c | 143 ++++++++++++++++++++++++++++++----------------- PDP10/kx10_rh.c | 25 +++++---- PDP10/kx10_tu.c | 46 +++++++++++---- 3 files changed, 139 insertions(+), 75 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 811abc5..198e1f5 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -301,6 +301,7 @@ typedef struct { uint32 flags; uint64 mb; uint64 fmb; + uint16 prev_sect; } InstHistory; int32 hst_p = 0; /* history pointer */ @@ -2325,11 +2326,11 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; #if KLB -// if (QKLB && glb_sect && (((xct_flag & 014) == 04 && !BYF5 && !ptr_flg) || -// ((xct_flag & 03) == 01 && BYF5))) -// sect = prev_sect; +// if (QKLB && (!glb_sect || (((xct_flag & 014) == 04 && !BYF5 && !ptr_flg) || + // ((xct_flag & 03) == 01 && BYF5))) && !extend) + // sect = prev_sect; if (QKLB && (!glb_sect /*|| ((xct_flag & 4) != 0 && prev_sect == 0)*/) && !extend) - sect = prev_sect; + sect = prev_sect; //fprintf(stderr, " ps=%o os%o", prev_sect, sect); #endif } @@ -2541,6 +2542,7 @@ int Mem_read(int flag, int cur_context, int fetch) { if (!page_lookup(AB, flag, &addr, 0, cur_context, fetch)) return 1; if (addr >= (int)MEMSIZE) { +//fprintf(stderr, "NXM error r %08o\n\r", addr); irq_flags |= 02000; return 1; } @@ -2588,6 +2590,7 @@ int Mem_write(int flag, int cur_context) { if (!page_lookup(AB, flag, &addr, 1, cur_context, 0)) return 1; if (addr >= (int)MEMSIZE) { +//fprintf(stderr, "NXM error w %08o\n\r", addr); irq_flags |= 02000; return 1; } @@ -3933,6 +3936,7 @@ int Mem_read_nopage() { MB = get_reg(AB); } else { if (AB >= (int)MEMSIZE) { +//fprintf(stderr, "NXM non-page error r %08o\n\r", AB); #if KL irq_flags |= 02000; #else @@ -3956,6 +3960,7 @@ int Mem_write_nopage() { set_reg(AB, MB); } else { if (AB >= (int)MEMSIZE) { +//fprintf(stderr, "NXM non-page error w %08o\n\r", AB); #if KL irq_flags |= 02000; #else @@ -4103,9 +4108,11 @@ fetch: } #endif if (Mem_read(pi_cycle | uuo_cycle, 1, 1)) { +#if !KL pi_rq = check_irq_level(); if (pi_rq) goto st_pi; +#endif #if KL if (((fault_data >> 30) & 037) == 021) PC = (PC + 1) & RMASK; @@ -4149,9 +4156,13 @@ no_fetch: #if KL && KLB /* If we are doing a PXCT with E1 or E2 set, change section */ if (QKLB && t20_page) { - if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || - ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) - sect = cur_sect = prev_sect; + if (xct_flag != 0 && (FLAGS & USER) == 0) { + if (((xct_flag & 8) != 0 && !ptr_flg) || + ((xct_flag & 2) != 0 && ptr_flg) || + ((xct_flag & 014) == 04 && !BYF5/* && !ptr_flg*/) || + ((xct_flag & 03) == 01 && BYF5)) + sect = cur_sect = prev_sect; + } /* Short cut for extended pointer address */ if (ptr_flg && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { /* Full pointer */ ind = 1; /* Allow us to read word, xDB has already bumped AB */ @@ -4377,6 +4388,9 @@ st_pi: #endif ; +#if KL && KLB + hst[hst_p].prev_sect = prev_sect; +#endif hst[hst_p].ac = get_reg(AC); } @@ -4484,11 +4498,18 @@ unasign: /* Save Opcode */ #if KL & KLB if (QKLB && t20_page) { - AR = (((uint64)cur_sect) << 18) | (uint64)AB; /* Save address */ + AR = (uint64)AB; /* Save address */ + if (pc_sect != 0) { + if (glb_sect == 0 && AB < 020) + AR |= BIT17; + else + AR |= ((uint64)cur_sect) << 18; + } MB = (((uint64)((IR << 9) | (AC << 5))) | ((uint64)(FLAGS) << 23)) & FMASK; if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + MB |= (uint64)(prev_sect); } } else #endif @@ -4535,14 +4556,14 @@ unasign: #endif /* Save context */ AB ++; - MB = SMASK| + MB = SMASK|BIT2| ((uint64)(fm_sel & 0160) << 23) | ((uint64)(prev_ctx & 0160) << 20) | (ub_ptr >> 9); #if KLB if (QKLB && t20_page /*&& (FLAGS & USER) == 0*/) MB |= BIT1|((uint64)(prev_sect & 037) << 18); - if (QKLB && t20_page && (FLAGS & USER) != 0) + if (QKLB && t20_page /* && (FLAGS & USER) != 0*/) prev_sect = pc_sect; #endif Mem_write_nopage(); @@ -4569,13 +4590,16 @@ unasign: if ((FLAGS & USER) == 0) { if ((AB & 4) != 0) FLAGS |= USERIO; -#if KL - if ((AB & 2)) - FLAGS |= PRV_PUB; -#else +//#if KL +// if ((AB & 2)) +// FLAGS |= PRV_PUB; +//#if KLB +// if ((!QKLB || !t20_page) && (FLAGS & OVR) != 0) +// FLAGS |= PRV_PUB; +//#else if ((AB & 2 || (FLAGS & OVR) != 0)) FLAGS |= PRV_PUB|OVR; -#endif +//#endif } PC = MB & RMASK; f_pc_inh = 1; @@ -7280,7 +7304,7 @@ xjrstf: #if KLB if (QKLB && t20_page) { pc_sect = (AR >> 18) & 07777; - if ((FLAGS & USER) == 0 && ((BR >> 23) & USER) == 0) + if (AC != 07 && (FLAGS & USER) == 0 && ((BR >> 23) & USER) == 0) prev_sect = BR & 037; } #endif @@ -7340,15 +7364,15 @@ jrstf: case 007: /* XPCW */ //fprintf(stderr, "XPCW %06o %06o %06o %06o\r\n", pc_sect, AB, PC, FLAGS << 5); - MB = ((((uint64)FLAGS) << 23) -#if KLB - | (prev_sect & 037) -#endif - ) & FMASK; + MB = (((uint64)FLAGS) << 23) & FMASK; /* Save Previous Public context */ if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; +#if KLB + if (QKLB && t20_page) + MB |= (uint64)(prev_sect & 037); +#endif } if (uuo_cycle | pi_cycle) { FLAGS &= ~(USER|PUBLIC); /* Clear USER */ @@ -7382,14 +7406,14 @@ jrstf: break; case 014: /* SFM */ -#if KLB - MB = ((((uint64)FLAGS) << 23) | (uint64)(prev_sect & 037)) & FMASK; -#else MB = (((uint64)FLAGS) << 23) & FMASK; -#endif if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; +#if KLB + if (QKLB && t20_page) + MB |= (uint64)(prev_sect & 037); +#endif } (void)Mem_write(0, 0); goto last; @@ -7715,6 +7739,8 @@ jrstf: } #endif AB = AR & RMASK; + if (hst_lnt) + hst[hst_p].mb = MB; if (Mem_write(uuo_cycle | pi_cycle, 0)) goto last; #if !PDP6 @@ -7769,6 +7795,8 @@ jrstf: #if KLB } #endif + if (hst_lnt) + hst[hst_p].mb = MB; if (Mem_write(0, 0)) goto last; break; @@ -7794,6 +7822,8 @@ jrstf: AB = AR & RMASK; if (Mem_read(0, 0, 0)) goto last; + if (hst_lnt) + hst[hst_p].mb = MB; AB = BR & RMASK; #if KL BYF5 = 0; /* Now back to data */ @@ -7848,6 +7878,8 @@ jrstf: if (Mem_read(0, 0, 0)) goto last; + if (hst_lnt) + hst[hst_p].mb = MB; #if ITS | KL_ITS if (QITS && (FLAGS & USER)) { jpc = PC; @@ -8686,10 +8718,6 @@ last: /* Handle page fault and traps */ if (page_enable && page_fault) { page_fault = 0; - if (pi_cycle) { - pi_cycle = 0; - set_pi_hold(); /* Hold off all lower interrupts */ - } //fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); BYF5 = 0; #if KL_ITS @@ -8706,9 +8734,16 @@ last: MB = fault_data; Mem_write_nopage(); AB++; + /* If fault on trap, kill the pi_cycle flag */ + if (trap_flag) + pi_cycle = 0; FLAGS |= trap_flag & (TRP1|TRP2); trap_flag = (TRP1|TRP2); MB = (((uint64)(FLAGS) << 23) & LMASK); + if ((FLAGS & USER) == 0) { + MB &= ~SMASK; + MB |= (FLAGS & PRV_PUB) ? SMASK : 0; + } #if KLB if (QKLB && t20_page) { if ((FLAGS & USER) == 0) @@ -8716,10 +8751,6 @@ last: } else #endif MB |= (PC & RMASK); - if ((FLAGS & USER) == 0) { - MB &= ~SMASK; - MB |= (FLAGS & PRV_PUB) ? SMASK : 0; - } Mem_write_nopage(); AB++; #if KLB @@ -8742,10 +8773,12 @@ last: #endif FLAGS = (MB >> 23) & 017777; /* If transistioning from user to executive adjust flags */ - if ((FLAGS & USER) == 0 && flag1) - FLAGS |= USERIO; - if ((FLAGS & USER) == 0 && flag3) - FLAGS |= PRV_PUB; + if ((FLAGS & USER) == 0) { + if (flag1) + FLAGS |= USERIO; + if (flag3) + FLAGS |= PRV_PUB; + } PC = MB & RMASK; #if KLB if (QKLB && t20_page) @@ -8754,11 +8787,29 @@ last: xct_flag = 0; f_load_pc = 1; f_pc_inh = 1; + if (pi_cycle) { +//fprintf(stderr, "Page fault trap %06o\n\r", PC); + pi_cycle = 0; + irq_flags |= 01000; + FM[(7 << 4) | 2] = fault_data; + pi_enable = 0; +// pi_rq = check_irq_level(); + // goto st_pi; + } +// if (pi_cycle) { + // pi_cycle = 0; + // set_pi_hold(); /* Hold off all lower interrupts */ + // pi_restore = 1; /* Release the pending IRQ */ + // } } #endif #if KI /* Handle page fault and traps */ if (page_enable && page_fault) { + if (pi_cycle) { +//fprintf(stderr, "Page fault trap %06o\n\r", PC); + inout_fail = 1; + } page_fault = 0; AB = ub_ptr + ((FLAGS & USER) ? 0427 : 0426); MB = fault_data; @@ -8793,27 +8844,12 @@ last: /* Dismiss an interrupt */ if (pi_cycle) { #if KI | KL - if (page_enable && page_fault) { - page_fault = 0; -//fprintf(stderr, "Page fault trap %06o\n\r", PC); - pi_cycle = 0; -#if KI - inout_fail = 1; -#else - irq_flags |= 01000; - FM[(7 << 4) | 2] = fault_data; -#endif - check_apr_irq(); - pi_rq = check_irq_level(); - goto st_pi; - } if (trap_flag != 0) { pi_hold = pi_ov = 0; f_pc_inh = 0; trap_flag = 0; } #endif - if ((IR & 0700) == 0700 && ((AC & 04) == 0)) { pi_hold = pi_ov; if ((!pi_hold) & f_inst_fetch) { @@ -10569,6 +10605,9 @@ for (k = 0; k < lnt; k++) { /* print specified */ fputs (" ", st); #if KI | KL fprintf (st, "%c%06o ", ((h->flags & (PRV_PUB << 5))? 'p':' '), h->flags & 0777777); +#if KLB + fprintf (st, "%02o ", h->prev_sect); +#endif #else fprintf (st, "%06o ", h->flags); #endif diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index 36235b0..209fe7d 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -539,23 +539,25 @@ void rh_writecw(struct rh_if *rhc, int nxm) { if (wc != 0 || (rhc->status & RH20_XEND) == 0 || (rhc->ptcr & BIT10) != 0 || nxm) { uint64 wrd1 = SMASK|(uint64)(rhc->ccw); - if ((rhc->ptcr & BIT10) == 0 && (rhc->status & RH20_DR_EXC) != 0) + if ((rhc->ptcr & BIT10) == 0 || (rhc->status & RH20_DR_EXC) != 0) return; if (nxm) { wrd1 |= RH20_NXM_ERR; rhc->status |= RH20_CHAN_ERR; } if (wc != 0) { - wrd1 |= RH20_NOT_WC0; - if (rhc->status & RH20_XEND) { - wrd1 |= RH20_LONG_STS; - if ((rhc->ptcr & 070) == 060) /* Write command */ - rhc->status |= RH20_CHAN_ERR|RH20_LONG_WC; - } + wrd1 |= RH20_NOT_WC0; + if (rhc->status & RH20_XEND) { + wrd1 |= RH20_LONG_STS; + if ((rhc->ptcr & 070) == 060) { /* Write command */ + rhc->status |= RH20_LONG_WC|RH20_CHAN_ERR; + } + } } else if ((rhc->status & RH20_XEND) == 0) { - wrd1 |= RH20_SHRT_STS; - if ((rhc->ptcr & 070) == 060) /* Write command */ - rhc->status |= RH20_SHRT_WC|RH20_CHAN_ERR; + wrd1 |= RH20_SHRT_STS; + if ((rhc->ptcr & 070) == 060) { /* Write command */ + rhc->status |= RH20_SHRT_WC|RH20_CHAN_ERR; + } } /* No error and not storing */ if ((rhc->status & RH20_CHAN_ERR) == 0 && (rhc->ptcr & BIT10) == 0) @@ -588,7 +590,8 @@ void rh_finish_op(struct rh_if *rhc, int nxm) { rh_setirq(rhc); #if KL if (rhc->imode == 2 && - (rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL)) + (rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL) && + (rhc->status & (RH20_DR_EXC|RH20_CHAN_ERR)) == 0) rh20_setup(rhc); #endif } diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index 4da4b8f..a390b54 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -277,19 +277,30 @@ tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { case FNC_READ: /* read */ case FNC_READREV: /* read w/ headers */ tu_frame[ctlr] = 0; + tu_tcr[ctlr] |= TC_FCS; + /* Fall through */ + + case FNC_WRITE: /* write */ + case FNC_SPACEF: /* Space forward */ + case FNC_SPACEB: /* Space backward */ + if ((tu_tcr[ctlr] & TC_FCS) == 0) { + uptr->STATUS |= ER1_NEF; + break; + } /* Fall through */ case FNC_ERASE: /* Erase gap */ - case FNC_WRITE: /* write */ case FNC_WTM: /* Write tape mark */ - case FNC_SPACEF: /* Space forward */ - case FNC_SPACEB: /* Space backward */ case FNC_WCHK: /* write check */ case FNC_REWIND: /* rewind */ case FNC_UNLOAD: /* unload */ case FNC_WCHKREV: /* write w/ headers */ uptr->CMD |= CS_PIP|CS1_GO; - uptr->CMD &= ~CS_TM; + rhc->attn = 0; + for (i = 0; i < 8; i++) { + if (dptr->units[i].CMD & CS_ATA) + rhc->attn = 1; + } CLR_BUF(uptr); uptr->DATAPTR = 0; sim_activate(uptr, 100); @@ -333,6 +344,7 @@ tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { break; case 005: /* frame count */ tu_frame[ctlr] = data & 0177777; + tu_tcr[ctlr] |= TC_FCS; break; case 006: /* drive type */ case 007: /* look ahead */ @@ -368,12 +380,12 @@ tu_read(DEVICE *dptr, struct rh_if *rhc, int reg) { break; case 001: /* status */ temp = DS_DPR; - if (rhc->attn != 0) + if (uptr->CMD & CS_ATA) temp |= DS_ATA; if (uptr->CMD & CS_CHANGE) temp |= DS_SSC; if ((uptr->STATUS & 0177777) != 0) - temp |= DS_ERR|DS_ATA; + temp |= DS_ERR; if ((uptr->flags & UNIT_ATT) != 0) { temp |= DS_MOL; if (uptr->CMD & CS_TM) @@ -471,7 +483,7 @@ void tu_error(UNIT * uptr, t_stat r) } if (uptr->CMD & CS_ATA) rh_setattn(rhc, 0); - if (uptr->CMD & (CS_ATA | CS_TM)) + if (GET_FNC(uptr->CMD) >= FNC_XFER && uptr->CMD & (CS_ATA | CS_TM)) rh_error(rhc); uptr->CMD &= ~(CS_MOTION|CS_PIP|CS1_GO); sim_debug(DEBUG_EXP, dptr, "Setting status %d\n", r); @@ -589,6 +601,8 @@ t_stat tu_srv(UNIT * uptr) if ((r = sim_tape_rdrecf(uptr, &tu_buf[ctlr][0], &reclen, TU_NUMFR)) != MTSE_OK) { sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r); + if (r == MTSE_TMK) + uptr->STATUS |= ER1_FCE; tu_error(uptr, r); rh_finish_op(rhc, 0); } else { @@ -620,16 +634,18 @@ t_stat tu_srv(UNIT * uptr) rh_finish_op(rhc, 0); return SCPE_OK; } - sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo\n", - dptr->name, unit, rhc->buf); + sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo %d\n", + dptr->name, unit, rhc->buf, uptr->DATAPTR); rhc->buf = 0; } } else { if (uptr->CPOS != 0) { - sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo\n", + sim_debug(DEBUG_DATA, dptr, "%s%o readf %012llo\n", dptr->name, unit, rhc->buf); rh_write(rhc); } + if (tu_frame[ctlr] != 0) + uptr->STATUS |= ER1_FCE; tu_error(uptr, MTSE_OK); (void)rh_blkend(rhc); rh_finish_op(rhc, 0); @@ -681,8 +697,10 @@ t_stat tu_srv(UNIT * uptr) uptr->CPOS &= 010; } tu_frame[ctlr] = 0177777 & (tu_frame[ctlr] + 1); - if (tu_frame[ctlr] == 0) + if (tu_frame[ctlr] == 0) { uptr->CPOS = 010; + tu_tcr[ctlr] &= ~(TC_FCS); + } } if (uptr->CPOS == 010) { /* Write out the block */ @@ -750,6 +768,8 @@ t_stat tu_srv(UNIT * uptr) case MTSE_EOM: /* end of medium */ if (tu_frame[ctlr] != 0) uptr->STATUS |= ER1_FCE; + else + tu_tcr[ctlr] &= ~(TC_FCS); uptr->CMD |= CS_ATA; /* Stop motion if we recieve any of these */ tu_error(uptr, r); @@ -759,8 +779,10 @@ t_stat tu_srv(UNIT * uptr) uptr->CMD |= CS_ATA; tu_error(uptr, MTSE_OK); return SCPE_OK; - } else + } else { + tu_tcr[ctlr] &= ~(TC_FCS); sim_activate(uptr, reclen * 50); + } return SCPE_OK; } sim_activate(uptr, 50); From 88f6e514410dc41e7059da533792fb80e006708f Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sat, 7 Dec 2019 23:30:51 -0500 Subject: [PATCH 69/98] KA10: Changes to try and get Tops 20 to print to FE printer. --- PDP10/kl10_fe.c | 80 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 12859e9..9a72cc1 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -136,6 +136,7 @@ #define PRI_EMSTR 003 /* String data */ #define PRI_EMLNC 004 /* Line-Char */ #define PRI_EMRDS 005 /* Request device status */ +#define PRI_EMOPS 006 #define PRI_EMHDS 007 /* Here is device status */ #define PRI_EMRDT 011 /* Request Date/Time */ #define PRI_EMHDR 012 /* Here is date and time */ @@ -305,7 +306,7 @@ DEVICE dte_dev = { #define PTRMSK 00777 /* Current data load pointer */ #define EOFFLG 01000 /* Tops 20 wants EOF */ -#define VFUFLG 02000 /* Tell Tops 20 that VFU loaded */ +#define HDSFLG 02000 /* Tell Tops 20 The current device status */ #define MARGIN 6 @@ -1031,6 +1032,11 @@ cty: } break; + case PRI_EMOPS: + if (cmd->dev == PRI_EMLPT) { + lp20_unit.LINE = 0; + } + break; case PRI_EMRDS: /* Request device status */ #if (NUM_DEVS_LP20 > 0) if (cmd->dev == PRI_EMLPT) { @@ -1038,18 +1044,21 @@ cty: data1[0] = 2; data1[1] = 0; data1[2] = 0; - } else { - data1[0] = 0; - data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; - if (lp20_unit.LPST & EOFFLG) - data1[0] |= 040; -// if (lp20_unit.LPST & VFUFLG) - // data1[1] |= 04; - lp20_unit.LPST &= ~EOFFLG; - data1[2] = 0; //0100220; - } if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) return; + } else { + lp20_unit.LPST |= HDSFLG; + if (!sim_is_active(&lp20_unit)) + sim_activate(&lp20_unit, 1000); +// data1[0] = 0; + // data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; + // if (lp20_unit.LPST & EOFFLG) + // data1[0] |= 040; + // +// if (lp20_unit.LPST & VFUFLG) + // data1[1] |= 04; + // data1[2] = 0; //0100220; + } } #endif if (cmd->dev == PRI_EMCTY) { @@ -1069,21 +1078,27 @@ cty: case PRI_EMHDS: /* Here is device status */ if (cmd->dev == PRI_EMLPT) { sim_debug(DEBUG_DETAIL, &dte_dev, "TTY HDS %06o %06o %06o\n", cmd->data[0], cmd->data[1], cmd->data[2]); - data1[0] = 0; - data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; +// data1[0] = 0; + // data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; if (cmd->data[0] & 040) { - data1[0] |= 040; + // data1[0] |= 040; lp20_unit.LPST |= EOFFLG; lp20_unit.LPCNT = 0; } + lp20_unit.LPST |= HDSFLG; + if (!sim_is_active(&lp20_unit)) + sim_activate(&lp20_unit, 1000); // if (lp20_unit.LPST & VFUFLG) // data1[1] |= 04; - data1[2] = 0100220; + // data1[2] = 0100220; // if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) // return; // if (cmd->data[1] & 040) { // lp20_unit.LPST |= EOFFLG; // } + // if ((lp20_unit.LPST & EOFFLG) != 0 && dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) + // return; + // lp20_unit.LPST &= ~EOFFLG; } break; #if (NUM_DEVS_LP20 > 0) @@ -1093,7 +1108,6 @@ cty: while (cmd->dptr < cmd->dcnt) { lp20_vfu[ln++] = cmd->data[cmd->dptr++]; } - lp20_unit.LPST |= VFUFLG; lp20_unit.LPCNT = ln; } break; @@ -1112,6 +1126,7 @@ cty: break; #endif + #if (NUM_DEVS_TTY > 0) case PRI_EMFLO: /* Flush output */ if ((cmd->dev & 0377) == PRI_EMDLS) { @@ -1151,6 +1166,8 @@ cty: case PRI_EMHLS: /* Here is line speeds */ if ((cmd->dev & 0377) == PRI_EMDLS) { int ln = cmd->sdev - 2; + sim_debug(DEBUG_DETAIL, &tty_dev, "HDL %o o=%d i=%d %o\n", + ln, cmd->data[0], cmd->data[1], cmd->data[2]); } break; case PRI_EMHLA: /* Here is line allocation */ @@ -1803,8 +1820,22 @@ t_stat lp20_svc (UNIT *uptr) if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; + if (uptr->LPST & HDSFLG) { + data1[0] = 0; + data1[1] = (uptr->LINE == 0) ? 0x1: 0; + if (uptr->LPST & EOFFLG) + data1[0] |= 040; +// if (uptr->LPST & VFUFLG) + // data1[1] |= 04; + data1[2] = 0110200; //0100220; + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) + sim_activate(uptr, 1000); + uptr->LPST &= ~(HDSFLG|EOFFLG); + } - while (((lp20_queue.out_ptr + 1) & 0xff) != lp20_queue.in_ptr) { + if (lp20_queue.out_ptr == lp20_queue.in_ptr) + return SCPE_OK; + while (lp20_queue.out_ptr != lp20_queue.in_ptr) { c = lp20_queue.buff[lp20_queue.out_ptr]; lp20_queue.out_ptr = (lp20_queue.out_ptr + 1) & 0xff; if (c < 040) { /* Control character */ @@ -1870,18 +1901,15 @@ t_stat lp20_svc (UNIT *uptr) lp20_output(uptr, c); } } - if ((l != 0 && uptr->LINE == 0) || (l == 0 && uptr->LINE != 0)) { + if (lp20_queue.out_ptr == lp20_queue.in_ptr) { data1[0] = 0; - data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; -// if (uptr->LPST & VFUFLG) - // data1[1] |= 04; - data1[2] = 0; //0100220; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) + if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) sim_activate(uptr, 1000); + if (uptr->LINE == 0) { + uptr->LPST |= HDSFLG; + sim_activate(uptr, 1000); + } } - data1[0] = 0; - if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) - sim_activate(uptr, 1000); return SCPE_OK; } From bce19570aa9770fe09bc182e7b1ef015175713c8 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 10 Dec 2019 00:03:51 -0500 Subject: [PATCH 70/98] KA10: Fixes to remove some errors in DFKE? diags. --- PDP10/kx10_cpu.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 198e1f5..7c42c6e 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -4108,7 +4108,7 @@ fetch: } #endif if (Mem_read(pi_cycle | uuo_cycle, 1, 1)) { -#if !KL +#if KA | PDP6 pi_rq = check_irq_level(); if (pi_rq) goto st_pi; @@ -4159,8 +4159,8 @@ no_fetch: if (xct_flag != 0 && (FLAGS & USER) == 0) { if (((xct_flag & 8) != 0 && !ptr_flg) || ((xct_flag & 2) != 0 && ptr_flg) || - ((xct_flag & 014) == 04 && !BYF5/* && !ptr_flg*/) || - ((xct_flag & 03) == 01 && BYF5)) + (prev_sect == 0 && (xct_flag & 014) == 04 && !BYF5/* && !ptr_flg*/) || + (prev_sect == 0 && (xct_flag & 03) == 01 && BYF5)) sect = cur_sect = prev_sect; } /* Short cut for extended pointer address */ @@ -4298,7 +4298,9 @@ in_loop: /* If there is a interrupt handle it. */ if (pi_rq) { +#if KA | PDP6 st_pi: +#endif sim_debug(DEBUG_IRQ, &cpu_dev, "trap irq %o %03o %03o \n", pi_enc, PIR, PIH); pi_cycle = 1; @@ -4556,7 +4558,7 @@ unasign: #endif /* Save context */ AB ++; - MB = SMASK|BIT2| + MB = SMASK| ((uint64)(fm_sel & 0160) << 23) | ((uint64)(prev_ctx & 0160) << 20) | (ub_ptr >> 9); From 7b590739e8e541427107bd9b95ca8fe1eed0c8b8 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 10 Dec 2019 19:50:34 -0500 Subject: [PATCH 71/98] KA10: Removed KLB compile option. --- PDP10/kx10_cpu.c | 293 ++++++++-------------------------------------- PDP10/kx10_defs.h | 7 +- 2 files changed, 53 insertions(+), 247 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 7c42c6e..149e39e 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1,6 +1,6 @@ /* ka10_cpu.c: PDP-10 CPU simulator - Copyright (c) 2011-2017, Richard Cornwell + Copyright (c) 2011-2019, Richard Cornwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -189,13 +189,11 @@ int brk_flags; /* Break flags */ int t20_page; /* Tops 20 paging selected */ int ptr_flg; /* Access to pointer value */ int extend = 0; /* Process extended instruction */ -#if KLB int sect; /* Actual resolved section */ int cur_sect; /* Current section */ int prev_sect; /* Previous section */ int pc_sect; /* Program counter section */ int glb_sect; /* Global section access */ -#endif #else int small_user; /* Small user flag */ #endif @@ -491,7 +489,7 @@ MTAB cpu_mod[] = { #if KI|KL { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SERIAL", "SERIAL", &cpu_set_serial, &cpu_show_serial, NULL, "CPU Serial Number" }, -#if KLB +#if KL { UNIT_M_PAGE, 0, "KL10A", "KL10A", NULL, NULL, NULL, "Base KL10"}, { UNIT_M_PAGE, UNIT_KL10B, "KL10B", "KL10B", NULL, NULL, NULL, @@ -880,13 +878,13 @@ int opflags[] = { #else #define QWAITS 0 #endif -#if KLB +#if KL #define QKLB (cpu_unit[0].flags & UNIT_KL10B) #else #define QKLB 0 #endif -#if KL & KLB +#if KL struct { int p; int s; @@ -1297,12 +1295,10 @@ t_stat dev_pag(uint32 dev, uint64 *data) { fm_sel = (uint8)(res >> 23) & 0160; prev_ctx = (res >> 20) & 0160; } -#if KLB if (QKLB && (res & BIT1) != 0) { /* Load previous section */ prev_sect = (res >> 18) & 037; } -#endif if ((res & RSIGN) == 0) { int t; double us = sim_activate_time_usecs (&cpu_unit[0]); @@ -1334,10 +1330,8 @@ t_stat dev_pag(uint32 dev, uint64 *data) { res |= ((uint64)(prev_ctx & 0160)) << 20; res |= ((uint64)(fm_sel & 0160)) << 23; res |= SMASK|BIT1|BIT2; -#if KLB if (QKLB) res |= ((uint64)prev_sect & 037) << 18; -#endif *data = res; sim_debug(DEBUG_DATAIO, &cpu_dev, "DATAI PAG %012llo\n", *data); break; @@ -1436,10 +1430,8 @@ t_stat dev_apr(uint32 dev, uint64 *data) { /* Bit 20 Channel? */ /* Bit 21 Extended KL10 */ /* Bit 22 Master Osc */ -#if KLB if (QKLB) AR |= BIT1|BIT4|040000; -#endif AR |= (uint64)((apr_serial == -1) ? DEF_SERIAL : apr_serial); sim_debug(DEBUG_DATAIO, &cpu_dev, "APRID BLKI %012llo\n", MB); } else { @@ -2069,10 +2061,8 @@ load_tlb(int uf, int page, int wr) //fprintf(stderr, "Lookup Page %o %03o u=%o w=%o %06o\r\n", sect, page, uf, wr, AB); /* Get segment pointer */ /* And save it */ -#if KLB if (QKLB) base = 0540 + (sect & 037); -#endif sim_interval--; if (uf) data = M[ub_ptr + base]; @@ -2233,10 +2223,8 @@ pg_loop: } if (acc_bits & PG_CAC) data |= KL_PAG_C; -#if KLB if (QKLB) data |= (sect & 037) << 18; -#endif /* And save it */ if (uf) u_tlb[page] = data & (SECTM|RMASK); @@ -2311,33 +2299,23 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int /* AC = 8 only in cur_context EA calculations */ if (flag) { uf = 0; -#if KLB sect = 0; -#endif } else if (xct_flag != 0 && !uf && !fetch) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); -#if KLB //fprintf(stderr, " s%o %o", sect, glb_sect); -#endif if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || ((xct_flag & 1) != 0 && !cur_context && BYF5 )) { uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; -#if KLB -// if (QKLB && (!glb_sect || (((xct_flag & 014) == 04 && !BYF5 && !ptr_flg) || - // ((xct_flag & 03) == 01 && BYF5))) && !extend) - // sect = prev_sect; if (QKLB && (!glb_sect /*|| ((xct_flag & 4) != 0 && prev_sect == 0)*/) && !extend) sect = prev_sect; //fprintf(stderr, " ps=%o os%o", prev_sect, sect); -#endif } //fprintf(stderr, " %o %o\n\r", uf, pub); } -#if KLB /* Check if invalid section */ if (QKLB && t20_page && (sect & 07740) != 0) { fault_data = (027LL << 30) | (((uint64)sect) << 18) | (uint64)addr; @@ -2347,7 +2325,6 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int page_fault = 1; return 0; } -#endif /* Handle KI paging odditiy */ if (!uf && !t20_page && (page & 0740) == 0340) { @@ -2363,10 +2340,8 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int data = e_tlb[page]; //fprintf(stderr, "Map page %06o -> %06o %06o %o\n\r", page, data, sect, flag); -#if KLB if (QKLB && t20_page && ((data >> 18) & 037) != sect) data = 0; -#endif /* If not valid, go refill it */ if (data == 0) { data = load_tlb(uf | upmp, page, wr); @@ -2384,10 +2359,8 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int return 0; #endif fault_data |= BIT8; -#if KLB if (QKLB && t20_page) fault_data |= (((uint64)sect) << 18); -#endif if (fault_data & BIT1) return 0; if (wr) /* T */ @@ -2430,10 +2403,8 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int (!fetch || !OP_PORTAL(M[*loc]))) { /* Handle public violation */ fault_data = ((uint64)addr) | 021LL << 30 | BIT8 |((uf)?SMASK:0); -#if KLB if (QKLB && t20_page) fault_data |= (((uint64)sect) << 18); -#endif //fprintf(stderr, "Public fault %012llo %06o %06o %012llo\n\r", fault_data, FLAGS << 5, PC, data); page_fault = 1; return 0; @@ -2460,10 +2431,8 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int } #endif fault_data = BIT8 | (uint64)addr; -#if KLB if (QKLB && t20_page) fault_data |= (((uint64)sect) << 18); -#endif /* Remap the flag bits */ if (uf) { /* U */ fault_data |= SMASK; /* BIT0 */ @@ -2509,11 +2478,7 @@ void set_reg(int reg, uint64 value) { int Mem_read(int flag, int cur_context, int fetch) { t_addr addr; -#if KLB if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { -#else - if (AB < 020) { -#endif if (xct_flag != 0 && !fetch && (FLAGS & USER) == 0) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgr ", IR, PC, AB, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || @@ -2526,7 +2491,6 @@ int Mem_read(int flag, int cur_context, int fetch) { } //fprintf(stderr, "\n\r"); } -#if KLB /* Check if invalid section */ if (QKLB && t20_page && !flag && (sect & 07740) != 0) { fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); @@ -2536,7 +2500,6 @@ int Mem_read(int flag, int cur_context, int fetch) { page_fault = 1; return 0; } -#endif MB = get_reg(AB); } else { if (!page_lookup(AB, flag, &addr, 0, cur_context, fetch)) @@ -2557,11 +2520,7 @@ int Mem_read(int flag, int cur_context, int fetch) { int Mem_write(int flag, int cur_context) { t_addr addr; -#if KLB if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { -#else - if (AB < 020) { -#endif if (xct_flag != 0 && (FLAGS & USER) == 0) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgw ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || @@ -2574,7 +2533,6 @@ int Mem_write(int flag, int cur_context) { } //fprintf(stderr, "\n\r"); } -#if KLB /* Check if invalid section */ if (QKLB && t20_page && !flag && (sect & 07740) != 0) { fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); @@ -2584,7 +2542,6 @@ int Mem_write(int flag, int cur_context) { page_fault = 1; return 0; } -#endif set_reg(AB, MB); } else { if (!page_lookup(AB, flag, &addr, 1, cur_context, 0)) @@ -2608,9 +2565,7 @@ int exec_page_lookup(t_addr addr, int wr, int *loc) int data; int page = (RMASK & addr) >> 9; int upmp = 0; -#if KLB int sav_sect = sect; -#endif /* If paging is not enabled, address is direct */ if (!page_enable) { @@ -2633,17 +2588,13 @@ int exec_page_lookup(t_addr addr, int wr, int *loc) /* If not valid, go refill it */ if (data == 0 || (data & LMASK) != 0) { -#if KLB sect = 0; -#endif data = load_tlb(upmp, page, wr); if (data == 0) { page_fault = 0; return 1; } -#if KLB sect = sav_sect; -#endif } *loc = ((data & 017777) << 9) + (addr & 0777); return 0; @@ -4081,10 +4032,8 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ #if KI | KL trap_flag = 0; #if KL -#if KLB sect = cur_sect = pc_sect; glb_sect = 0; -#endif extend = 0; ptr_flg = 0; #endif @@ -4125,7 +4074,7 @@ no_fetch: AC = (MB >> 23) & 017; AD = MB; /* Save for historical sake */ IA = AB; -#if KL & KLB +#if KL glb_sect = 0; #endif i_flags = opflags[IR]; @@ -4153,7 +4102,7 @@ no_fetch: } #endif -#if KL && KLB +#if KL /* If we are doing a PXCT with E1 or E2 set, change section */ if (QKLB && t20_page) { if (xct_flag != 0 && (FLAGS & USER) == 0) { @@ -4191,7 +4140,6 @@ no_fetch: AR = FM[prev_ctx|ix]; else AR = get_reg(ix); -#if KLB /* Check if extended indexing */ if (QKLB && t20_page && cur_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { AR = (AR + ((AB & RSIGN) ? SECTM|((uint64)AB): (uint64)AB)) & (SECTM|RMASK); @@ -4200,7 +4148,6 @@ no_fetch: AB = 0; } else glb_sect = 0; -#endif /* For KL */ AR = MB = (AB + AR) & FMASK; #else @@ -4209,13 +4156,13 @@ no_fetch: #endif AB = MB & RMASK; } -#if KL & KLB +#if KL in_loop: #endif if (ind & !pi_rq) { if (Mem_read(pi_cycle | uuo_cycle, 1, 0)) goto last; -#if KL & KLB +#if KL /* Check if extended indexing */ if (QKLB && t20_page && (cur_sect != 0 || glb_sect)) { if (MB & SMASK || cur_sect == 0) { /* Instruction format IFIW */ @@ -4311,9 +4258,7 @@ st_pi: xct_flag = 0; #if KI | KL #if KL -#if KLB sect = cur_sect = 0; -#endif extend = 0; #endif /* @@ -4369,10 +4314,8 @@ st_pi: #if KL if (extend) hst[hst_p].pc |= HIST_PCE; -#if KLB hst[hst_p].pc |= (pc_sect << 18); hst[hst_p].ea |= (sect << 18); -#endif #endif hst[hst_p].ir = AD; hst[hst_p].flags = (FLAGS << 5) @@ -4390,7 +4333,7 @@ st_pi: #endif ; -#if KL && KLB +#if KL hst[hst_p].prev_sect = prev_sect; #endif hst[hst_p].ac = get_reg(AC); @@ -4449,7 +4392,7 @@ st_pi: /* Process the instruction */ switch (IR) { -#if KL & KLB +#if KL case 0052: /* PMOVE */ case 0053: /* PMOVEM */ if (QKLB && t20_page && (FLAGS & USER) == 0) { @@ -4498,7 +4441,7 @@ muuo: #endif unasign: /* Save Opcode */ -#if KL & KLB +#if KL if (QKLB && t20_page) { AR = (uint64)AB; /* Save address */ if (pc_sect != 0) { @@ -4517,7 +4460,7 @@ unasign: #endif MB = ((uint64)(IR) << 27) | ((uint64)(AC) << 23) | (uint64)(AB); AB = ub_ptr | 0424; -#if KL & KLB +#if KL /* If single sections KL10 UUO starts at 425 */ if (!QKLB && !QITS && t20_page) AB = AB + 1; @@ -4525,7 +4468,7 @@ unasign: Mem_write_nopage(); /* Save flags */ AB++; -#if KL & KLB +#if KL if (QKLB && t20_page) MB = ((uint64)(pc_sect) << 18) | ((PC + (trap_flag == 0)) & RMASK); else { @@ -4545,7 +4488,6 @@ unasign: Mem_write_nopage(); #if KL extend = 0; -#if KLB if (QKLB && t20_page) { /* Save address */ if (pc_sect != 0 && glb_sect == 0 && AR < 020) AR |= BIT17; @@ -4555,19 +4497,16 @@ unasign: AB ++; Mem_write_nopage(); } -#endif /* Save context */ AB ++; MB = SMASK| ((uint64)(fm_sel & 0160) << 23) | ((uint64)(prev_ctx & 0160) << 20) | (ub_ptr >> 9); -#if KLB if (QKLB && t20_page /*&& (FLAGS & USER) == 0*/) MB |= BIT1|((uint64)(prev_sect & 037) << 18); if (QKLB && t20_page /* && (FLAGS & USER) != 0*/) prev_sect = pc_sect; -#endif Mem_write_nopage(); #endif /* Read in new PC and flags */ @@ -4581,7 +4520,7 @@ unasign: AB |= 4; Mem_read_nopage(); -#if KL & KLB +#if KL if (QKLB && t20_page) { pc_sect = (MB >> 18) & 00037; FLAGS = 0; @@ -4592,16 +4531,8 @@ unasign: if ((FLAGS & USER) == 0) { if ((AB & 4) != 0) FLAGS |= USERIO; -//#if KL -// if ((AB & 2)) -// FLAGS |= PRV_PUB; -//#if KLB -// if ((!QKLB || !t20_page) && (FLAGS & OVR) != 0) -// FLAGS |= PRV_PUB; -//#else if ((AB & 2 || (FLAGS & OVR) != 0)) FLAGS |= PRV_PUB|OVR; -//#endif } PC = MB & RMASK; f_pc_inh = 1; @@ -4619,7 +4550,7 @@ unasign: case 0024: case 0025: case 0026: case 0027: case 0030: case 0031: case 0032: case 0033: case 0034: case 0035: case 0036: case 0037: -#if KL & KLB +#if KL /* LUUO's in non-zero section are different */ if (QKLB && t20_page && pc_sect != 0) { /* Save Effective address */ @@ -4751,22 +4682,15 @@ unasign: #if KL case 0105: /* ADJSP */ BR = get_reg(AC); -#if KLB if (QKLB && t20_page && pc_sect != 0 && (BR & SMASK) == 0 && (BR & SECTM) != 0) { - AD = (((AR & RSIGN)?(LMASK|AR):AR) + BR) & (SECTM|RMASK); - AD |= BR & ~(SECTM|RMASK); + AD = (((AR & RSIGN)?(LMASK|AR):AR) + BR) & (SECTM|RMASK); + AD |= BR & ~(SECTM|RMASK); } else { -#endif - AD = (BR + AR) & RMASK; - AD |= (BR & LMASK) + ((AR << 18) & LMASK); -#if KLB - if (QKLB && pc_sect == 0) -#endif - if (((BR ^ AD) & SMASK) != 0) - FLAGS |= TRP2; -#if KLB + AD = (BR + AR) & RMASK; + AD |= (BR & LMASK) + ((AR << 18) & LMASK); + if (QKLB && pc_sect == 0 && ((BR ^ AD) & SMASK) != 0) + FLAGS |= TRP2; } -#endif i_flags = SAC; AR = AD & FMASK; break; @@ -5863,7 +5787,6 @@ unasign: int bpw, left, newb, adjw, adjb; FE = (AR >> 30) & 077; /* P */ -#if KLB f = 0; if (QKLB && t20_page && pc_sect != 0 && FE > 36) { if (FE == 077) @@ -5873,7 +5796,6 @@ unasign: FE = _byte_adj[(FE - 37)].p; //fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); } -#endif left = (36 - FE) / SC; /* Number bytes left (36 - P)/S */ bpw = left + (FE / SC); /* Bytes per word */ if (bpw == 0) { @@ -5894,7 +5816,6 @@ unasign: adjw--; } FE = 36 - (adjb * SC) - ((36 - FE) % SC); /* New P */ -#if KLB if (f) { /* Short pointer */ for (f = 0; f < 28; f++) { @@ -5928,7 +5849,6 @@ unasign: set_reg(AC+1, BR); break; } -#endif AR = (((uint64)(FE & 077)) << 30) | /* Make new BP */ (AR & PMASK & LMASK) | /* S,IX,I */ ((AR + adjw) & RMASK); @@ -5953,7 +5873,7 @@ unasign: } AR = MB; SCAD = (AR >> 30) & 077; -#if KL & KLB +#if KL if (QKLB && t20_page && pc_sect != 0 && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; //fprintf(stderr, "ILDB %012llo %d %d -> %d %d\n\r", AR, SCAD, i, _byte_adj[i].p, _byte_adj[i].s); @@ -5983,7 +5903,6 @@ unasign: if (SCAD & 0400) { SCAD = ((0777 ^ SC) + 044 + 1) & 0777; #if KL -#if KLB if (QKLB && t20_page && pc_sect != 0 && (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; if (Mem_read(0, 0, 0)) @@ -6003,7 +5922,6 @@ unasign: goto last; AB = (AB - 1) & RMASK; } else -#endif AR = (AR & LMASK) | ((AR + 1) & RMASK); #elif KI AR = (AR & LMASK) | ((AR + 1) & RMASK); @@ -6038,7 +5956,7 @@ unasign: AR = MB; SC = (AR >> 24) & 077; SCAD = (AR >> 30) & 077; -#if KL & KLB +#if KL if (QKLB && t20_page && pc_sect != 0 && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; if (SCAD == 077) @@ -6067,14 +5985,12 @@ ldb_ptr: BYF5 = 1; #if KL ptr_flg = 1; -#if KLB if (QKLB && t20_page && (SC < 36) && pc_sect != 0 && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; //fprintf(stderr, "LBP %o %o %06o %012llo\n\r", SC, SCAD, AB, MB); } #endif -#endif #if ITS if (QITS && pi_cycle == 0 && mem_prot == 0) { opc = PC | (FLAGS << 18); @@ -6083,9 +5999,7 @@ ldb_ptr: } else { #if KL ptr_flg = 0; -#if KLB ld_exe: -#endif #else if ((IR & 06) == 6) modify = 1; @@ -7303,13 +7217,11 @@ xjrstf: if (Mem_read(0, 0, 0)) goto last; AR = MB; /* Get PC. */ -#if KLB if (QKLB && t20_page) { pc_sect = (AR >> 18) & 07777; if (AC != 07 && (FLAGS & USER) == 0 && ((BR >> 23) & USER) == 0) prev_sect = BR & 037; } -#endif BR = BR >> 23; /* Move flags into position */ goto jrstf; @@ -7371,26 +7283,20 @@ jrstf: if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; -#if KLB if (QKLB && t20_page) MB |= (uint64)(prev_sect & 037); -#endif } if (uuo_cycle | pi_cycle) { FLAGS &= ~(USER|PUBLIC); /* Clear USER */ -#if KLB sect = 0; /* Force section zero on IRQ */ -#endif } if (Mem_write(0, 0)) goto last; AB = (AB + 1) & RMASK; -#if KLB if (QKLB && t20_page) MB = (((((uint64)pc_sect) << 18) | PC) + !pi_cycle) & (SECTM|RMASK); else -#endif - MB = (PC + !pi_cycle) & (RMASK); + MB = (PC + !pi_cycle) & (RMASK); if (Mem_write(0, 0)) goto last; AB = (AB + 1) & RMASK; @@ -7400,11 +7306,9 @@ jrstf: if (Mem_read(0, 0, 0)) goto last; AR = MB; /* Get PC. */ -#if KLB if (QKLB && t20_page) { pc_sect = (AR >> 18) & 07777; } -#endif break; case 014: /* SFM */ @@ -7412,10 +7316,8 @@ jrstf: if ((FLAGS & USER) == 0) { MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; -#if KLB if (QKLB && t20_page) MB |= (uint64)(prev_sect & 037); -#endif } (void)Mem_write(0, 0); goto last; @@ -7584,14 +7486,6 @@ jrstf: f = AB >> 9; flag1 = (FLAGS & USER) != 0; flag3 = 0; -#if KI - /* Check if Paging Enabled */ - if (!page_enable || AB < 020) { - AR = 0020000LL + f; /* direct map */ - set_reg(AC, AR); - break; - } -#endif #if KL /* Invalid in user unless USERIO set, or not in supervisor mode */ if ((FLAGS & (USER|USERIO)) == USER || (FLAGS & (USER|PUBLIC)) == PUBLIC) @@ -7600,9 +7494,7 @@ jrstf: /* Figure out if this is a user space access */ if (xct_flag & 4) { flag1 = (FLAGS & USERIO) != 0; -#if KLB sect = prev_sect; -#endif } /* Check if Paging Enabled */ @@ -7615,7 +7507,6 @@ jrstf: break; } -#if KLB /* Check if access to register */ if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { AR = AB; /* direct map */ @@ -7626,7 +7517,6 @@ jrstf: set_reg(AC, AR); break; } -#endif /* Handle KI paging odditiy */ if (!flag1 && !t20_page && (f & 0740) == 0340) { @@ -7665,6 +7555,12 @@ jrstf: AR |= BIT8; //fprintf(stderr, "Map ok %012llo %06o\r\n", AR, AB); #else + /* Check if Paging Enabled */ + if (!page_enable || AB < 020) { + AR = 0020000LL + f; /* direct map */ + set_reg(AC, AR); + break; + } /* Figure out if this is a user space access */ if (xct_flag != 0 && !flag1) { if ((xct_flag & 2) != 0) { @@ -7697,7 +7593,7 @@ jrstf: /* Stack, JUMP */ case 0260: /* PUSHJ */ /* AR Frm PC */ -#if KL & KLB +#if KL if (QKLB && t20_page && pc_sect != 0) MB = ((uint64)pc_sect << 18) + (PC + !pi_cycle); else { @@ -7709,13 +7605,12 @@ jrstf: MB |= (FLAGS & PRV_PUB) ? SMASK : 0; MB &= FMASK; } -#if KL & KLB +#if KL } #endif #endif #if KL BYF5 = 1; -#if KLB f = glb_sect; if (QKLB && t20_page && pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { AR = (AR + 1) & FMASK; @@ -7724,7 +7619,6 @@ jrstf: } else { sect = pc_sect; glb_sect = 0; -#endif #endif AR = AOB(AR); FLAGS &= ~ (BYTI|ADRFLT|TRP1|TRP2); @@ -7737,7 +7631,7 @@ jrstf: check_apr_irq(); #endif } -#if KL && KLB +#if KL } #endif AB = AR & RMASK; @@ -7761,7 +7655,7 @@ jrstf: jpc = PC; } #endif -#if KL & KLB +#if KL if (QKLB && t20_page && f) pc_sect = cur_sect; #endif @@ -7774,13 +7668,11 @@ jrstf: case 0261: /* PUSH */ #if KL BYF5 = 1; -#if KLB if (QKLB && t20_page &&pc_sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { AR = (AR + 1) & FMASK; sect = (AR >> 18) & 07777; } else { sect = pc_sect; -#endif #endif AR = AOB(AR); AB = AR & RMASK; @@ -7794,7 +7686,7 @@ jrstf: check_apr_irq(); #endif } -#if KLB +#if KL } #endif if (hst_lnt) @@ -7806,7 +7698,6 @@ jrstf: case 0262: /* POP */ #if KL BYF5 = 1; /* Tell PXCT that this is stack */ -#if KLB flag1 = glb_sect; glb_sect = 0; sect = pc_sect; @@ -7819,7 +7710,6 @@ jrstf: } } //fprintf(stderr, "Pop %o %o %06o %06o %06o %012llo %012llo\n\r", f, xct_flag, prev_sect, sect, cur_sect, AR, BR); -#endif #endif AB = AR & RMASK; if (Mem_read(0, 0, 0)) @@ -7829,16 +7719,14 @@ jrstf: AB = BR & RMASK; #if KL BYF5 = 0; /* Now back to data */ -#if KLB if (QKLB && t20_page) { sect = cur_sect; glb_sect = flag1; } -#endif #endif if (Mem_write(0, 0)) goto last; -#if KL & KLB +#if KL if (QKLB && t20_page) { if ((xct_flag & 1) != 0 && (FLAGS & USER) == 0) sect = prev_sect; @@ -7864,7 +7752,6 @@ jrstf: AB = AR & RMASK; #if KL BYF5 = 1; /* Tell PXCT that this is stack */ -#if KLB glb_sect = 0; sect = pc_sect; if (QKLB && t20_page && (xct_flag & 1) != 0 && (FLAGS & USER) == 0) @@ -7874,7 +7761,6 @@ jrstf: glb_sect = 1; AR = (AR - 1) & FMASK; } else -#endif #endif AR = SOB(AR); @@ -7892,13 +7778,11 @@ jrstf: PC = MB & RMASK; #if KL BYF5 = 0; /* Tell PXCT that this is stack */ -#if KLB if (QKLB && t20_page && pc_sect != 0) { pc_sect = (MB >> 18) & 07777; if ((AR & SMASK) == 0 && (AR & SECTM) != 0) break; } -#endif #endif if ((AR & C1) == 0) { #if KI | KL @@ -7913,7 +7797,7 @@ jrstf: break; case 0264: /* JSR */ /* AR Frm PC */ -#if KL & KLB +#if KL if (QKLB && t20_page && pc_sect != 0) MB = ((uint64)pc_sect << 18) + (PC + !pi_cycle); else { @@ -7924,7 +7808,7 @@ jrstf: MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; } -#if KL & KLB +#if KL } #endif #endif @@ -7946,7 +7830,7 @@ jrstf: } #endif PC_CHANGE -#if KL & KLB +#if KL if (QKLB && t20_page) { AR = AR + 1; if (AR & BIT17) @@ -7961,7 +7845,7 @@ jrstf: break; case 0265: /* JSP */ /* AR Frm PC */ -#if KL & KLB +#if KL if (QKLB && t20_page && pc_sect != 0) AD = ((uint64)pc_sect << 18) + (PC + !pi_cycle); else { @@ -7974,7 +7858,7 @@ jrstf: AD &= ~SMASK; AD |= (FLAGS & PRV_PUB) ? SMASK : 0; } -#if KL & KLB +#if KL } #endif #endif @@ -7989,7 +7873,7 @@ jrstf: } #endif PC_CHANGE -#if KL & KLB +#if KL if (QKLB && t20_page && glb_sect) pc_sect = cur_sect; #endif @@ -8011,7 +7895,7 @@ jrstf: } #endif PC_CHANGE -#if KL & KLB +#if KL if (QKLB && t20_page && glb_sect) pc_sect = cur_sect; #endif @@ -8267,7 +8151,7 @@ skip_op: break; case 0415: /* SETMI */ -#if KL & KLB +#if KL /* XMOVEI for extended addressing */ if (QKLB && t20_page && pc_sect != 0) { if (glb_sect == 0 && AR < 020) @@ -8372,7 +8256,7 @@ skip_op: /* Fall Through */ case 0501: /* HLLI */ -#if KL && KLB +#if KL /* XHLLI for extended addressing */ if (QKLB && t20_page && IR == 0501 && pc_sect != 0) { if (glb_sect == 0 && AR < 020) @@ -8729,10 +8613,8 @@ last: } else #endif AB = ub_ptr | 0500; -#if KLB if (!QKLB && !QITS && t20_page) AB++; -#endif MB = fault_data; Mem_write_nopage(); AB++; @@ -8746,34 +8628,28 @@ last: MB &= ~SMASK; MB |= (FLAGS & PRV_PUB) ? SMASK : 0; } -#if KLB if (QKLB && t20_page) { if ((FLAGS & USER) == 0) MB |= (uint64)(prev_sect & 037); } else -#endif MB |= (PC & RMASK); Mem_write_nopage(); AB++; -#if KLB if (QKLB && t20_page) { MB = (((uint64)pc_sect) << 18) | (PC & RMASK); Mem_write_nopage(); AB++; } -#endif flag1 = flag3 = 0; if (FLAGS & PUBLIC) flag3 = 1; if (FLAGS & USER) flag1 = 1; Mem_read_nopage(); -#if KLB if (QKLB && t20_page) FLAGS = 0; else -#endif - FLAGS = (MB >> 23) & 017777; + FLAGS = (MB >> 23) & 017777; /* If transistioning from user to executive adjust flags */ if ((FLAGS & USER) == 0) { if (flag1) @@ -8782,10 +8658,8 @@ last: FLAGS |= PRV_PUB; } PC = MB & RMASK; -#if KLB if (QKLB && t20_page) pc_sect = (MB >> 18) & 07777; -#endif xct_flag = 0; f_load_pc = 1; f_pc_inh = 1; @@ -8943,7 +8817,6 @@ do_byte_setup(int n, int wr, int *pos, int *sz) np = (p + (0777 ^ s) + 1) & 0777; /* Advance pointer */ //fprintf(stderr, "%s %012llo %012llo %2o %2o %03o\n\r", (wr)?"store":"load", val1, val2, s, p, np); -#if KLB if (QKLB && t20_page && pc_sect != 0) { if (p > 36) { /* Extended pointer */ int i = p - 37; @@ -9010,9 +8883,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) glb_sect = 0; //fprintf(stderr, "Load_byte3 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } - } else -#endif - { + } else { if (np & 0400) { np = p = ((0777 ^ s) + 044 + 1) & 0777; val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); @@ -9020,13 +8891,11 @@ do_byte_setup(int n, int wr, int *pos, int *sz) ix = GET_XR(val1); ind = TST_IND(val1) != 0; MB = (val1 & RMASK) | ((val1 & RSIGN)? LMASK:0); -#if KLB sect = cur_sect; if ((FLAGS & USER) == 0 && (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) sect = prev_sect; glb_sect = 0; -#endif //fprintf(stderr, "Load_byte4 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } *pos = np & 077; @@ -9034,7 +8903,6 @@ do_byte_setup(int n, int wr, int *pos, int *sz) AB = MB & RMASK; if (ix) { temp = get_reg(ix); -#if KLB /* Check if extended indexing */ if (QKLB && t20_page && glb_sect != 0 && (temp & SMASK) == 0 && (temp & SECTM) != 0) { //fprintf(stderr, "Index %06o %012llo %06o\n\r", AB, temp, sect); @@ -9045,18 +8913,16 @@ do_byte_setup(int n, int wr, int *pos, int *sz) //fprintf(stderr, "Index2 %06o %012llo %06o\n\r", AB, temp, sect); } else glb_sect = 0; -#endif temp = MB = (MB + temp) & FMASK; AB = MB & RMASK; } while (ind & !check_irq_level()) { - ptr_flg = 1; + ptr_flg = 1; if (Mem_read(0, 1, 0)) { - ptr_flg = 0; + ptr_flg = 0; return 1; } - ptr_flg = 0; -#if KLB + ptr_flg = 0; /* Check if extended indexing */ if (QKLB && sect != 0) { if (MB & SMASK) { /* Instruction format IFIW */ @@ -9105,13 +8971,11 @@ do_byte_setup(int n, int wr, int *pos, int *sz) //fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, sect, AB); } } else { -#endif ix = GET_XR(MB); ind = TST_IND(MB) != 0; AB = MB & RMASK; if (ix) { temp = get_reg(ix); -#if KLB /* Check if extended indexing */ if (QKLB && sect != 0 && (temp & SMASK) == 0 && (temp & SECTM) != 0) { //fprintf(stderr, "Index %06o %012llo %06o\n\r", AB, temp, sect); @@ -9123,13 +8987,10 @@ do_byte_setup(int n, int wr, int *pos, int *sz) AB = 0; } else glb_sect = 0; -#endif temp = MB = (MB + temp) & FMASK; AB = MB & RMASK; } -#if KLB } -#endif /* Handle events during a indirect loop */ if (sim_interval-- <= 0) { if (sim_process_event() != SCPE_OK) { @@ -9269,7 +9130,6 @@ adj_byte(int n) p = (val1 >> 30) & 077; /* Advance pointer */ np = (p + (0777 ^ s) + 1) & 0777; -#if KLB if (QKLB && t20_page && pc_sect != 0) { if (p > 36) { /* Extended pointer */ int i = p - 37; @@ -9288,9 +9148,7 @@ adj_byte(int n) if (np & 0400) val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); } - } else -#endif - { + } else { if (np & 0400) val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); } @@ -9329,7 +9187,6 @@ adv_byte(int n) p = (val1 >> 30) & 077; /* Advance pointer */ np = (p + (0777 ^ s) + 1) & 0777; -#if KLB if (QKLB && t20_page && pc_sect != 0) { if (p > 36) { /* Extended pointer */ int i = p - 37; @@ -9353,9 +9210,7 @@ adv_byte(int n) val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); } } - } else -#endif - { + } else { if (np & 0400) { np = ((0777 ^ s) + 044 + 1) & 0777; val1 = (val1 & LMASK) | ((val1 + 1) & RMASK); @@ -9549,12 +9404,10 @@ do_extend(uint32 ia) case 004: /* EDIT */ val2 = MB; /* Save address of translate table */ -#if KLB if (QKLB && pc_sect != 0 && glb_sect) xlat_sect = (val2 >> 18) & 07777; else xlat_sect = cur_sect; -#endif /* Fetch filler values */ AB = (ia + 1) & RMASK; if (Mem_read(0, 1, 0)) @@ -9572,7 +9425,6 @@ do_extend(uint32 ia) /* Read in pattern control */ reg = get_reg(ext_ac); AB = reg & RMASK; -#if KLB if (QKLB && pc_sect != 0) { sect = (reg >> 18) & 07777; glb_sect = 1; @@ -9580,7 +9432,6 @@ do_extend(uint32 ia) sect = cur_sect; glb_sect = 0; } -#endif if (Mem_read(0, 0, 0)) return 0; i = (reg >> 30) & 03; @@ -9588,11 +9439,9 @@ do_extend(uint32 ia) val1 = (MB >> ((3 - i) * 9)) & 0777; i++; if (i > 3) { -#if KLB if (QKLB && pc_sect != 0) reg = (reg & ~(SECTM|RMASK)) | ((reg + 1) & (SECTM|RMASK)); else -#endif reg = (reg & LMASK) | ((reg+1) & RMASK); i = 0; } @@ -9611,9 +9460,7 @@ do_extend(uint32 ia) return 0; a = 1; AB = (val2 + (val1 >> 1)) & RMASK; -#if KLB sect = xlat_sect; -#endif if (Mem_read(0, 0, 0)) return 0; if ((val1 & 1) == 0) @@ -9644,7 +9491,6 @@ do_extend(uint32 ia) adj_byte(ext_ac+3); reg |= SMASK; AR = get_reg(ext_ac+3); -#if KLB if (QKLB && pc_sect != 0) { sect = (AR >> 18) & 07777; glb_sect = 1; @@ -9652,12 +9498,10 @@ do_extend(uint32 ia) sect = cur_sect; glb_sect = 0; } -#endif AB = AR & RMASK; MB = get_reg(ext_ac+4); if (Mem_write(0, 0)) return 0; -#if KLB if (QKLB && pc_sect != 0 && (MB & BIT12) != 0) { AB = (++AR) & RMASK; sect = (AR >> 18) & 07777; @@ -9665,7 +9509,6 @@ do_extend(uint32 ia) if (Mem_write(0,0)) return 0; } -#endif if (fill2 != 0) { if (!store_byte(ext_ac+3, fill1, 0)) { return 0; @@ -9689,7 +9532,6 @@ do_extend(uint32 ia) case 2: /* Set signifigance */ if ((reg & SMASK) == 0) { AR = get_reg(ext_ac+3); -#if KLB if (QKLB && pc_sect != 0) { sect = (AR >> 18) & 07777; glb_sect = 1; @@ -9697,12 +9539,10 @@ do_extend(uint32 ia) sect = cur_sect; glb_sect = 0; } -#endif AB = AR & RMASK; MB = get_reg(ext_ac+4); if (Mem_write(0, 0)) return 0; -#if KLB if (QKLB && pc_sect != 0 && (MB & BIT12) != 0) { AB = (++AR) & RMASK; sect = (AR >> 18) & 07777; @@ -9710,7 +9550,6 @@ do_extend(uint32 ia) if (Mem_write(0,0)) return 0; } -#endif if (fill2 != 0) { val1 = fill2; i = 1; @@ -9723,7 +9562,6 @@ do_extend(uint32 ia) break; case 4: /* Exchange Mark */ AR = get_reg(ext_ac+3); -#if KLB if (QKLB && pc_sect != 0) { sect = (AR >> 18) & 07777; glb_sect = 1; @@ -9731,21 +9569,17 @@ do_extend(uint32 ia) sect = cur_sect; glb_sect = 0; } -#endif AB = AR & RMASK; if (Mem_read(0, 0, 0)) return 0; BR = MB; MB = get_reg(ext_ac+4); -#if KLB /* Make sure byte pointers are same size */ if (QKLB && (MB & BIT12) != (BR & BIT12)) return 0; -#endif if (Mem_write(0, 0)) return 0; //fprintf(stderr, "Edit exchange %06o %06o %012llo %012llo\n\r", sect, AB, BR, MB); -#if KLB if (QKLB && pc_sect != 0 && (BR & BIT12) != 0) { AB = (AR + 1) & RMASK; sect = ((AR + 1)>> 18) & 07777; @@ -9770,7 +9604,6 @@ do_extend(uint32 ia) } set_reg(ext_ac+5, AD); } -#endif set_reg(ext_ac+4, BR); break; case 5: @@ -9781,9 +9614,7 @@ do_extend(uint32 ia) case 1: /* Insert Message char */ if ((reg & SMASK) != 0) { AB = (ia + (val1 & 077) + 1) & RMASK; -#if KLB sect = cur_sect; -#endif if (Mem_read(0, 0, 0)) return 0; i = 1; @@ -9826,12 +9657,10 @@ do_extend(uint32 ia) case 010: /* CVTDBO */ case 011: /* CVTDBT */ -#if KLB if (QKLB && pc_sect != 0 && glb_sect) xlat_sect = (AR >> 18) & 07777; else xlat_sect = cur_sect; -#endif val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); /* Check if conversion started */ if ((get_reg(ext_ac) & SMASK) == 0) { @@ -9855,9 +9684,7 @@ do_extend(uint32 ia) if (IR == 010) { val1 = (val1 + val2) & FMASK; } else { -#if KLB sect = xlat_sect; -#endif f = do_xlate((uint32)(val2 & RMASK), val1, 017); if (f < 0) break; @@ -9906,12 +9733,10 @@ do_extend(uint32 ia) val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); else { val2 = AB; -#if KLB if (QKLB && pc_sect != 0 && glb_sect) xlat_sect = (AR >> 18) & 07777; else xlat_sect = cur_sect; -#endif } /* Get fill */ AB = (ia + 1) & RMASK; @@ -9966,9 +9791,7 @@ do_extend(uint32 ia) if (IR == 013) { /* Read first translation entry */ AB = (val1 + val2) & RMASK; -#if KLB sect = xlat_sect; -#endif if (Mem_read(0, 0, 0)) { set_reg(ext_ac + 3, (reg & (SMASK|EXPO)) | (f+1)); return 0; @@ -10003,7 +9826,6 @@ do_extend(uint32 ia) val2 = ((AR & RSIGN) ? LMASK : 0) | (AR & RMASK); } else if (IR == 015) { AB = ia; -#if KLB if (QKLB) { if (pc_sect != 0 && glb_sect) xlat_sect = (AR >> 18) & 07777; @@ -10011,7 +9833,6 @@ do_extend(uint32 ia) xlat_sect = cur_sect; } else xlat_sect = 0; -#endif if (Mem_read(0, 1, 0)) return 0; val2 = MB; @@ -10034,9 +9855,7 @@ do_extend(uint32 ia) if ((val1 & ~msk) != 0) return 0; } else if (IR == 015) { -#if KLB sect = xlat_sect; -#endif f = do_xlate((uint32)(val2), val1, 07777); if (f < 0) return 0; @@ -10089,7 +9908,6 @@ do_extend(uint32 ia) break; case 020: /* XBLT */ -#if KLB if (QKLB) { glb_sect = 1; reg = get_reg(ext_ac); @@ -10146,7 +9964,6 @@ xblt_done: set_reg(ext_ac + 2, val2); return 0; } -#endif case 021: /* GSNGL */ case 022: /* GDBLE */ case 023: /* GDFIX */ @@ -10583,21 +10400,17 @@ for (k = 0; k < lnt; k++) { /* print specified */ h = &hst[(++di) % hst_lnt]; /* entry pointer */ if (h->pc & HIST_PC) { /* instruction? */ #if KL -#if KLB if (QKLB) fprintf(st, "%08o ", h->pc & 0777777777); else -#endif #endif fprintf (st, "%06o ", h->pc & 0777777); fprint_val (st, h->ac, 8, 36, PV_RZRO); fputs (" ", st); #if KL -#if KLB if (QKLB) fprintf(st, "%08o ", h->ea & 0777777777); else -#endif #endif fprintf (st, "%06o ", h->ea); fputs (" ", st); @@ -10607,9 +10420,7 @@ for (k = 0; k < lnt; k++) { /* print specified */ fputs (" ", st); #if KI | KL fprintf (st, "%c%06o ", ((h->flags & (PRV_PUB << 5))? 'p':' '), h->flags & 0777777); -#if KLB fprintf (st, "%02o ", h->prev_sect); -#endif #else fprintf (st, "%06o ", h->flags); #endif diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 4df7a53..31b84e4 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -51,12 +51,7 @@ #endif #if KL -#define KLB 1 -#define EPT440 0 /* Force KL10A to 440 section address */ -#endif - -#ifndef KLB -#define KLB 0 +#define EPT440 0 /* Force KL10 to use as 440 section address */ #endif #if (PDP6 + KA + KI + KL) != 1 From a7a3888530c998977b7d67c410ef24a1a222dea6 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 10 Dec 2019 19:51:01 -0500 Subject: [PATCH 72/98] KA10: Updated copyright date. --- PDP10/kx10_rp.c | 2 +- PDP10/kx10_rs.c | 2 +- PDP10/kx10_sys.c | 2 +- PDP10/kx10_tu.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index 4dd7927..d0d93a2 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -1,6 +1,6 @@ /* ka10_rp.c: Dec RH10 RP04/5/6 - Copyright (c) 2013-2017, Richard Cornwell + Copyright (c) 2013-2019, Richard Cornwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/PDP10/kx10_rs.c b/PDP10/kx10_rs.c index 67fca80..c553791 100644 --- a/PDP10/kx10_rs.c +++ b/PDP10/kx10_rs.c @@ -1,6 +1,6 @@ /* ka10_rs.c: Dec RH10 RS04 - Copyright (c) 2017, Richard Cornwell + Copyright (c) 2017-2019, Richard Cornwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index 5fbe055..77819db 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -3,7 +3,7 @@ Copyright (c) 2005-2009, Robert M Supnik - Copyright (c) 2011-2018, Richard Cornwell + Copyright (c) 2011-2019, Richard Cornwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index a390b54..381954b 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -1,6 +1,6 @@ /* ka10_tu.c: Dec RH10 TM03/TU10 tape controller - Copyright (c) 2017, Richard Cornwell + Copyright (c) 2017-2019, Richard Cornwell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), From c876213189ed0aaf93640d831d024fa8b22678dc Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 10 Dec 2019 19:51:33 -0500 Subject: [PATCH 73/98] Updated Readme to reflect KL10 Status. --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 63798b9..cfcdd02 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ The PDP6 runs TOPS 10 4.5 off Dectape. The KA10 sim has successfully run Tops 10 4.5, 5.03 and Tops 10 6.03, ITS and WAITS. The KI10 sim has successfully run Tops 10 6.03 with VMSER. -The KL10 sim has successfully run Tops 10 6.03 with VMSER and ITS. +The KL10 sim has successfully run Tops 10 6.03 with VMSER and ITS. Tops 10 7.03, Tops 20 V2-V7. Disk * RC10 RD10/RM10 @@ -123,6 +123,9 @@ The KL10 sim has successfully run Tops 10 6.03 with VMSER and ITS. * Knight Kludge mux for ITS. * Terminals on KL10 Front End. + * LP10 Line printer. + * LP20 Line printer on KL10 Front End. + * IMP networking support for ITS and TENEX. * CH10 networking support for ITS. From 1b86b6802a888bb91bf3256f6f437576e6391311 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Tue, 10 Dec 2019 23:02:27 -0500 Subject: [PATCH 74/98] KA10: Fixed build issue with KL10B. --- PDP10/kx10_defs.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 31b84e4..3c351db 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -356,11 +356,7 @@ extern DEBTAB crd_debug[]; #define UNIT_V_PAGE (UNIT_V_MAOFF + 1) #define UNIT_MAOFF (1 << UNIT_V_MAOFF) #if KL -#if KLB #define UNIT_KL10B (1 << UNIT_V_PAGE) -#else -#define UNIT_KL10B (0) -#endif #define UNIT_TWOSEG (0) #else #define UNIT_TWOSEG (1 << UNIT_V_PAGE) From 99fc84f9fd13fa952414aa54fb95a11179d1eb08 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 12 Dec 2019 08:53:54 -0500 Subject: [PATCH 75/98] KA10: Fixed KL10B to pass diags. --- PDP10/kx10_cpu.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 149e39e..bd70b97 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2309,7 +2309,12 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int ((xct_flag & 1) != 0 && !cur_context && BYF5 )) { uf = (FLAGS & USERIO) != 0; pub = (FLAGS & PRV_PUB) != 0; - if (QKLB && (!glb_sect /*|| ((xct_flag & 4) != 0 && prev_sect == 0)*/) && !extend) + + if ((xct_flag & 014) == 04 && !ptr_flg && glb_sect == 0) +// if (QKLB && (!glb_sect /*|| ((xct_flag & 4) != 0 && prev_sect == 0)*/) && !extend) + sect = prev_sect; + if ((xct_flag & 03) == 01 && BYF5 && glb_sect == 0) +// if (QKLB && (!glb_sect /*|| ((xct_flag & 4) != 0 && prev_sect == 0)*/) && !extend) sect = prev_sect; //fprintf(stderr, " ps=%o os%o", prev_sect, sect); } @@ -4107,9 +4112,10 @@ no_fetch: if (QKLB && t20_page) { if (xct_flag != 0 && (FLAGS & USER) == 0) { if (((xct_flag & 8) != 0 && !ptr_flg) || - ((xct_flag & 2) != 0 && ptr_flg) || - (prev_sect == 0 && (xct_flag & 014) == 04 && !BYF5/* && !ptr_flg*/) || - (prev_sect == 0 && (xct_flag & 03) == 01 && BYF5)) + ((xct_flag & 2) != 0 && ptr_flg) //|| +//// (/*prev_sect == 0 && */(xct_flag & 014) == 04 && !BYF5/* && !ptr_flg*/) || +// // (/*prev_sect == 0 && */(xct_flag & 03) == 01 && BYF5) +) sect = cur_sect = prev_sect; } /* Short cut for extended pointer address */ @@ -4135,7 +4141,7 @@ no_fetch: ix = GET_XR(MB); if (ix) { #if KL - if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || + if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) AR = FM[prev_ctx|ix]; else @@ -4177,7 +4183,7 @@ in_loop: ix = GET_XR(MB); AB = MB & RMASK; if (ix) { - if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || + if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) AR = FM[prev_ctx|ix]; else @@ -4194,8 +4200,8 @@ in_loop: } MB = AR; } else { - if (((xct_flag & 014) != 014 || (FLAGS & USER) != 0)) - glb_sect = 0; +// if (((xct_flag & 014) != 014 || (FLAGS & USER) != 0)) + glb_sect = 0; if ((MB & RMASK) < 020) sect = cur_sect = 1; AR = MB; @@ -4207,7 +4213,7 @@ in_loop: ix = (MB >> 30) & 017; AB = MB & (SECTM|RMASK); if (ix) { - if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0) || + if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) AR = FM[prev_ctx|ix]; else @@ -7352,10 +7358,8 @@ jrstf: } #endif PC = AR & RMASK; -#if KLB if (QKLB && t20_page && glb_sect) pc_sect = (AR >> 18) & 07777; -#endif #else if (uuo_cycle | pi_cycle) { FLAGS &= ~USER; /* Clear USER */ @@ -7676,7 +7680,6 @@ jrstf: #endif AR = AOB(AR); AB = AR & RMASK; - MB = BR; if (AR & C1) { #if KI | KL if (!pi_cycle) @@ -7689,6 +7692,7 @@ jrstf: #if KL } #endif + MB = BR; if (hst_lnt) hst[hst_p].mb = MB; if (Mem_write(0, 0)) From 30620d1883315f37a03d0d53a29f04e2f9d5a48e Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 18 Dec 2019 23:14:22 -0500 Subject: [PATCH 76/98] KA10: Misc changes. --- PDP10/kl10_fe.c | 30 +++++++++--- PDP10/kx10_cpu.c | 119 ++++++++++++++++++++++++++--------------------- 2 files changed, 91 insertions(+), 58 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 9a72cc1..9f5914c 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -307,6 +307,7 @@ DEVICE dte_dev = { #define PTRMSK 00777 /* Current data load pointer */ #define EOFFLG 01000 /* Tops 20 wants EOF */ #define HDSFLG 02000 /* Tell Tops 20 The current device status */ +#define ACKFLG 04000 /* Post an acknowwledge message */ #define MARGIN 6 @@ -1077,7 +1078,7 @@ cty: case PRI_EMHDS: /* Here is device status */ if (cmd->dev == PRI_EMLPT) { - sim_debug(DEBUG_DETAIL, &dte_dev, "TTY HDS %06o %06o %06o\n", cmd->data[0], cmd->data[1], cmd->data[2]); + sim_debug(DEBUG_DETAIL, &dte_dev, "LPT HDS %06o %06o %06o\n", cmd->data[0], cmd->data[1], cmd->data[2]); // data1[0] = 0; // data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; if (cmd->data[0] & 040) { @@ -1093,9 +1094,9 @@ cty: // data1[2] = 0100220; // if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) // return; -// if (cmd->data[1] & 040) { +// if (cmd->data[0] & 040) { // lp20_unit.LPST |= EOFFLG; -// } + // } // if ((lp20_unit.LPST & EOFFLG) != 0 && dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) // return; // lp20_unit.LPST &= ~EOFFLG; @@ -1109,6 +1110,9 @@ cty: lp20_vfu[ln++] = cmd->data[cmd->dptr++]; } lp20_unit.LPCNT = ln; + // lp20_unit.LPST |= ACKFLG; + if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) + sim_activate(uptr, 1000); } break; @@ -1120,8 +1124,11 @@ cty: lp20_ram[ln] = cmd->data[cmd->dptr]; } lp20_unit.LPCNT = ln; + // lp20_unit.LPST |= ACKFLG; for (ln = 0; ln < 256; ln++) sim_debug(DEBUG_DETAIL, &lp20_dev, "LP20 RAM %02x => %04x\n", ln, lp20_ram[ln]); + if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) + sim_activate(uptr, 1000); } break; #endif @@ -1822,14 +1829,21 @@ t_stat lp20_svc (UNIT *uptr) return SCPE_OK; if (uptr->LPST & HDSFLG) { data1[0] = 0; + data1[1] = (uptr->LINE == 0) ? 0x1: 0; if (uptr->LPST & EOFFLG) data1[0] |= 040; // if (uptr->LPST & VFUFLG) // data1[1] |= 04; data1[2] = 0110200; //0100220; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 4, data1) == 0) sim_activate(uptr, 1000); + if ((uptr->LPST & (EOFFLG)) == (EOFFLG)) { + data1[0] = 0; + if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) + sim_activate(uptr, 1000); +// uptr->LPST &= ~ACKFLG; + } uptr->LPST &= ~(HDSFLG|EOFFLG); } @@ -1896,6 +1910,10 @@ t_stat lp20_svc (UNIT *uptr) default: /* Ignore */ break; } + if (uptr->LINE == 0) { + uptr->LPST |= HDSFLG; + sim_activate(uptr, 1000); + } } else { sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x '%c' %04x\n", c, c, lp20_ram[c] ); lp20_output(uptr, c); @@ -1904,10 +1922,10 @@ t_stat lp20_svc (UNIT *uptr) if (lp20_queue.out_ptr == lp20_queue.in_ptr) { data1[0] = 0; if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) - sim_activate(uptr, 1000); + sim_activate(uptr, 1000); if (uptr->LINE == 0) { uptr->LPST |= HDSFLG; - sim_activate(uptr, 1000); + sim_activate(uptr, 1000); } } return SCPE_OK; diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index bd70b97..c801635 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1299,14 +1299,14 @@ t_stat dev_pag(uint32 dev, uint64 *data) { /* Load previous section */ prev_sect = (res >> 18) & 037; } - if ((res & RSIGN) == 0) { - int t; - double us = sim_activate_time_usecs (&cpu_unit[0]); - t = rtc_tim - ((int)us); - update_times(t); - rtc_tim = ((int)us); - } if (res & BIT2) { + if ((res & RSIGN) == 0) { + int t; + double us = sim_activate_time_usecs (&cpu_unit[0]); + t = rtc_tim - ((int)us); + update_times(t); + rtc_tim = ((int)us); + } ub_ptr = (res & 017777) << 9; for (i = 0; i < 512; i++) { u_tlb[i] = 0; @@ -2300,7 +2300,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int if (flag) { uf = 0; sect = 0; - } else if (xct_flag != 0 && !uf && !fetch) { + } else if (xct_flag != 0 && !fetch) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); //fprintf(stderr, " s%o %o", sect, glb_sect); if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || @@ -2484,7 +2484,7 @@ int Mem_read(int flag, int cur_context, int fetch) { t_addr addr; if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { - if (xct_flag != 0 && !fetch && (FLAGS & USER) == 0) { + if (xct_flag != 0 && !fetch) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgr ", IR, PC, AB, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || @@ -2526,7 +2526,7 @@ int Mem_write(int flag, int cur_context) { t_addr addr; if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { - if (xct_flag != 0 && (FLAGS & USER) == 0) { + if (xct_flag != 0) { //fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgw ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || @@ -2826,7 +2826,7 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int /* Figure out if this is a user space access */ if (flag) uf = 0; - else if (xct_flag != 0 && !cur_context && !uf) { + else if (xct_flag != 0 && !cur_context) { if (((xct_flag & 2) != 0 && wr != 0) || ((xct_flag & 1) != 0 && (wr == 0 || modify))) { uf = (FLAGS & USERIO) != 0; @@ -3049,7 +3049,7 @@ int page_lookup_its(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, /* Figure out if this is a user space access */ if (flag) uf = 0; - else if (xct_flag != 0 && !cur_context && !uf) { + else if (xct_flag != 0 && !cur_context) { if (((xct_flag & 2) != 0 && wr != 0) || ((xct_flag & 1) != 0 && (wr == 0 || modify))) { uf = 1; @@ -3160,7 +3160,7 @@ int Mem_read_its(int flag, int cur_context, int fetch) { t_addr addr; if (AB < 020) { - if ((xct_flag & 1) != 0 && !cur_context && (FLAGS & USER) == 0) { + if ((xct_flag & 1) != 0 && !cur_context) { MB = M[(ac_stack & 01777777) + AB]; return 0; } @@ -3207,7 +3207,7 @@ int Mem_write_its(int flag, int cur_context) { t_addr addr; if (AB < 020) { - if ((xct_flag & 2) != 0 && !cur_context && (FLAGS & USER) == 0) { + if ((xct_flag & 2) != 0 && !cur_context) { M[(ac_stack & 01777777) + AB] = MB; return 0; } @@ -3309,7 +3309,7 @@ int page_lookup_bbn(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, if (flag) uf = 0; else { - if (QWAITS && xct_flag != 0 && !fetch && !uf) { + if (QWAITS && xct_flag != 0 && !fetch) { if (xct_flag & 010 && cur_context) /* Indirect */ uf = 1; if (xct_flag & 004 && wr == 0) /* XR */ @@ -3317,7 +3317,7 @@ int page_lookup_bbn(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, if (xct_flag & 001 && (wr == 1 || BYF5)) /* XW or XLB or XDB */ uf = 1; } - if (!QWAITS && (FLAGS & EXJSYS) == 0 && uf == 0 && !fetch && xct_flag != 0) { + if (!QWAITS && (FLAGS & EXJSYS) == 0 && xct_flag != 0 && !fetch) { if (xct_flag & 010 && cur_context) uf = 1; if (xct_flag & 004 && wr == 0) @@ -3574,7 +3574,7 @@ int page_lookup_waits(t_addr addr, int flag, t_addr *loc, int wr, int cur_contex /* Figure out if this is a user space access */ if (flag) uf = 0; - else if (xct_flag != 0 && !fetch && !uf) { + else if (xct_flag != 0 && !fetch) { if (xct_flag & 010 && cur_context) /* Indirect */ uf = 1; if (xct_flag & 004 && wr == 0) /* XR */ @@ -4110,12 +4110,15 @@ no_fetch: #if KL /* If we are doing a PXCT with E1 or E2 set, change section */ if (QKLB && t20_page) { - if (xct_flag != 0 && (FLAGS & USER) == 0) { + if (xct_flag != 0) { if (((xct_flag & 8) != 0 && !ptr_flg) || - ((xct_flag & 2) != 0 && ptr_flg) //|| -//// (/*prev_sect == 0 && */(xct_flag & 014) == 04 && !BYF5/* && !ptr_flg*/) || -// // (/*prev_sect == 0 && */(xct_flag & 03) == 01 && BYF5) -) + ((xct_flag & 2) != 0 && ptr_flg) +/* The following two lines are needed for Tops20 V3 */ +#if 1 + || ((xct_flag & 014) == 04 && !ptr_flg && prev_sect == 0) || + ((xct_flag & 03) == 01 && ptr_flg && prev_sect == 0) +#endif + ) sect = cur_sect = prev_sect; } /* Short cut for extended pointer address */ @@ -4141,8 +4144,8 @@ no_fetch: ix = GET_XR(MB); if (ix) { #if KL - if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || - ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) + if (((xct_flag & 8) != 0 && !ptr_flg) || + ((xct_flag & 2) != 0 && ptr_flg)) AR = FM[prev_ctx|ix]; else AR = get_reg(ix); @@ -4183,8 +4186,8 @@ in_loop: ix = GET_XR(MB); AB = MB & RMASK; if (ix) { - if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || - ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) + if (((xct_flag & 8) != 0 && !ptr_flg) || + ((xct_flag & 2) != 0 && ptr_flg)) AR = FM[prev_ctx|ix]; else AR = get_reg(ix); @@ -4213,8 +4216,8 @@ in_loop: ix = (MB >> 30) & 017; AB = MB & (SECTM|RMASK); if (ix) { - if (((xct_flag & 8) != 0 && (FLAGS & USER) == 0 && !ptr_flg) || - ((xct_flag & 2) != 0 && (FLAGS & USER) == 0 && ptr_flg)) + if (((xct_flag & 8) != 0 && !ptr_flg) || + ((xct_flag & 2) != 0 && ptr_flg)) AR = FM[prev_ctx|ix]; else AR = get_reg(ix); @@ -4509,10 +4512,10 @@ unasign: ((uint64)(fm_sel & 0160) << 23) | ((uint64)(prev_ctx & 0160) << 20) | (ub_ptr >> 9); - if (QKLB && t20_page /*&& (FLAGS & USER) == 0*/) + if (QKLB && t20_page) { MB |= BIT1|((uint64)(prev_sect & 037) << 18); - if (QKLB && t20_page /* && (FLAGS & USER) != 0*/) - prev_sect = pc_sect; + prev_sect = pc_sect & 037; + } Mem_write_nopage(); #endif /* Read in new PC and flags */ @@ -5965,6 +5968,7 @@ unasign: #if KL if (QKLB && t20_page && pc_sect != 0 && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; +//fprintf(stderr, "LDB %012llo %d %d -> %d %d\n\r", AR, SCAD, i, _byte_adj[i].p, _byte_adj[i].s); if (SCAD == 077) goto muuo; SC = _byte_adj[i].s; @@ -7098,7 +7102,13 @@ left: do { AIO_CHECK_EVENT; /* queue async events */ if (sim_interval <= 0) { - sim_process_event(); + if ((reason = sim_process_event()) != SCPE_OK) { + f_pc_inh = 1; + f_load_pc = 0; + f_inst_fetch = 0; + set_reg(AC, AR); + break; + } } /* Allow for interrupt */ if (pi_pending) { @@ -7477,7 +7487,7 @@ jrstf: one_p_arm = 0; } #endif -#if ITS +#if KL_ITS if (QITS && one_p_arm) { FLAGS |= ADRFLT; one_p_arm = 0; @@ -7706,7 +7716,7 @@ jrstf: glb_sect = 0; sect = pc_sect; if (QKLB && t20_page) { - if ((xct_flag & 1) != 0 && (FLAGS & USER) == 0) + if ((xct_flag & 1) != 0) sect = prev_sect; if (sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { sect = (AR >> 18) & 07777; @@ -7732,7 +7742,7 @@ jrstf: goto last; #if KL if (QKLB && t20_page) { - if ((xct_flag & 1) != 0 && (FLAGS & USER) == 0) + if ((xct_flag & 1) != 0) sect = prev_sect; if (sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { AR = (AR - 1) & FMASK; @@ -7758,7 +7768,7 @@ jrstf: BYF5 = 1; /* Tell PXCT that this is stack */ glb_sect = 0; sect = pc_sect; - if (QKLB && t20_page && (xct_flag & 1) != 0 && (FLAGS & USER) == 0) + if (QKLB && t20_page && (xct_flag & 1) != 0) sect = prev_sect; if (QKLB && t20_page && sect != 0 && (AR & SMASK) == 0 && (AR & SECTM) != 0) { sect = (AR >> 18) & 07777; @@ -8859,9 +8869,9 @@ do_byte_setup(int n, int wr, int *pos, int *sz) ix = GET_XR(val2); MB = (val2 & RMASK) | ((val2 & RSIGN)? LMASK:0); sect = cur_sect; - if ((FLAGS & USER) == 0 && - (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) - sect = prev_sect; +// if ((FLAGS & USER) == 0 && + // (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) + // sect = prev_sect; glb_sect = 0; //fprintf(stderr, "Load_byte1 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } else { @@ -8881,9 +8891,9 @@ do_byte_setup(int n, int wr, int *pos, int *sz) ind = TST_IND(val1) != 0; MB = (val1 & RMASK) | ((val1 & RSIGN)? LMASK:0); sect = cur_sect; - if ((FLAGS & USER) == 0 && - (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) - sect = prev_sect; +// if ((FLAGS & USER) == 0 && + // (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) + // sect = prev_sect; glb_sect = 0; //fprintf(stderr, "Load_byte3 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } @@ -8896,9 +8906,9 @@ do_byte_setup(int n, int wr, int *pos, int *sz) ind = TST_IND(val1) != 0; MB = (val1 & RMASK) | ((val1 & RSIGN)? LMASK:0); sect = cur_sect; - if ((FLAGS & USER) == 0 && - (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) - sect = prev_sect; + // if ((FLAGS & USER) == 0 && + // (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) + // sect = prev_sect; glb_sect = 0; //fprintf(stderr, "Load_byte4 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } @@ -8921,12 +8931,12 @@ do_byte_setup(int n, int wr, int *pos, int *sz) AB = MB & RMASK; } while (ind & !check_irq_level()) { - ptr_flg = 1; + // ptr_flg = 1; if (Mem_read(0, 1, 0)) { - ptr_flg = 0; + // ptr_flg = 0; return 1; } - ptr_flg = 0; + // ptr_flg = 0; /* Check if extended indexing */ if (QKLB && sect != 0) { if (MB & SMASK) { /* Instruction format IFIW */ @@ -8995,12 +9005,14 @@ do_byte_setup(int n, int wr, int *pos, int *sz) AB = MB & RMASK; } } +#if 0 /* Handle events during a indirect loop */ if (sim_interval-- <= 0) { if (sim_process_event() != SCPE_OK) { - return 1; + return -1; } } +#endif }; /* Update pointer */ val1 &= PMASK; @@ -9011,8 +9023,8 @@ do_byte_setup(int n, int wr, int *pos, int *sz) set_reg(n+2, val2); modify = wr; - ptr_flg = !wr; - BYF5 = wr; +// ptr_flg = !wr; + // BYF5 = wr; /* Read final value */ if (Mem_read(0, 0, 0)) { modify = ptr_flg = BYF5 = 0; @@ -9038,9 +9050,11 @@ load_byte(int n, uint64 *data, uint64 fill, int cnt) } /* Fetch Pointer word */ + ptr_flg = 1; if (do_byte_setup(n, 0, &p, &s)) goto back; + ptr_flg = 0; /* Generate mask for given size */ msk = (uint64)(1) << s; msk--; @@ -9073,6 +9087,7 @@ store_byte(int n, uint64 data, int cnt) int s, p; /* Fetch Pointer word */ + BYF5 = 1; if (do_byte_setup(n, 1, &p, &s)) goto back; @@ -9083,10 +9098,10 @@ store_byte(int n, uint64 data, int cnt) MB &= CM(msk); MB |= msk & ((uint64)(data) << p); //fprintf(stderr, "store_bytes %2o %2o %06o %06o %012llo\n\r", s, p, sect, AB, data); - BYF5 = 1; if (Mem_write(0, 0)) goto back; + BYF5 = 0; if (cnt) { /* Decrement count */ val1 = get_reg(n); From a4719d9faffa6fafb630a540d16008eb528ba68c Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 18 Dec 2019 23:14:56 -0500 Subject: [PATCH 77/98] SCP: Updated to current. --- Visual Studio Projects/Pre-Build-Event.cmd | 3 +- makefile | 7 ++ scp.c | 84 +++++++++++++++++++--- scp.h | 1 + sim_console.c | 8 +++ sim_console.h | 12 ++-- sim_serial.c | 2 +- sim_timer.c | 5 ++ sim_video.c | 10 ++- 9 files changed, 112 insertions(+), 20 deletions(-) diff --git a/Visual Studio Projects/Pre-Build-Event.cmd b/Visual Studio Projects/Pre-Build-Event.cmd index a5c02bb..1261014 100644 --- a/Visual Studio Projects/Pre-Build-Event.cmd +++ b/Visual Studio Projects/Pre-Build-Event.cmd @@ -29,6 +29,7 @@ rem rem Everything implicitly requires BUILD to also be set to have rem any meaning, it always gets set. set _X_BUILD=BUILD +set _X_REQUIRED_WINDOWS_BUILD=20191213 call :FindVCVersion _VC_VER set _PDB=%~dpn1.pdb @@ -127,7 +128,7 @@ if not exist ..\..\windows-build goto _notice1 if not exist ..\..\windows-build/lib goto _notice2 set _X_WINDOWS_BUILD= for /F "usebackq tokens=2" %%i in (`findstr /C:"WINDOWS-BUILD" ..\..\windows-build\Windows-Build_Versions.txt`) do SET _X_WINDOWS_BUILD=%%i -if "%_X_WINDOWS_BUILD%" LSS "20190815" goto _notice2 +if "%_X_WINDOWS_BUILD%" LSS "%_X_REQUIRED_WINDOWS_BUILD%" goto _notice2 set _X_LAST_WINDOWS_BUILD= if exist Pre-Build-Event.last-windows-build-version.txt for /F "usebackq tokens=2" %%i in (`findstr /C:"WINDOWS-BUILD" Pre-Build-Event.last-windows-build-version.txt`) do SET _X_LAST_WINDOWS_BUILD=%%i if "%_X_WINDOWS_BUILD%" EQU "%_X_LAST_WINDOWS_BUILD%" goto _new_or_same_windows_build diff --git a/makefile b/makefile index bd21b40..3a4c9c6 100644 --- a/makefile +++ b/makefile @@ -554,6 +554,13 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) OS_CCDEFS += -DHAVE_LIBPNG OS_LDFLAGS += -lpng $(info using libpng: $(call find_lib,png) $(call find_include,png)) + ifneq (,$(call find_include,zlib)) + ifneq (,$(call find_lib,z)) + OS_CCDEFS += -DHAVE_ZLIB + OS_LDFLAGS += -lz + $(info using zlib: $(call find_lib,z) $(call find_include,zlib)) + endif + endif endif endif ifneq (,$(call find_include,glob)) diff --git a/scp.c b/scp.c index 762e7eb..ac8921c 100644 --- a/scp.c +++ b/scp.c @@ -1186,6 +1186,15 @@ static const char simh_help[] = #define HLP_CP "*Commands Copying_Files CP" "3CP\n" "++CP sfile dfile copies a file\n" + "2Renaming Files\n" +#define HLP_RENAME "*Commands Renaming_Files RENAME" + "3RENAME\n" + "++RENAME origname newname renames a file\n" +#define HLP_MOVE "*Commands Renaming_Files MOVE" + "3MOVE\n" + "++MOVE origname newname renames a file\n" + "+or\n" + "++MV origname newname renames a file\n" "2Creating Directories\n" #define HLP_MKDIR "*Commands Creating_Directories MKDIR" "3MKDIR\n" @@ -1966,6 +1975,8 @@ static const char simh_help[] = " which don't specify an explicit DELAY parameter along with a string\n" " If a SEND command is processed and no DELAY value has been specified,\n" " the default value of the delay parameter is 1000.\n" + " The value n can be specified with a suffix of k or m which indicates\n" + " a multiplier of 1000 or 1000000 respectively\n" /***************** 80 character line width template *************************/ "4After\n" " Specifies an integer (>=0) representing a minimal number of instructions\n" @@ -1976,6 +1987,8 @@ static const char simh_help[] = " which don't specify an explicit AFTER parameter along with a string\n" " If a SEND command is processed and no AFTER value has been specified,\n" " the default value of the delay parameter is the DELAY parameter value.\n" + " The value n can be specified with a suffix of k or m which indicates\n" + " a multiplier of 1000 or 1000000 respectively\n" "4Escaping String Data\n" " The following character escapes are explicitly supported:\n" "++\\r Sends the ASCII Carriage Return character (Decimal value 13)\n" @@ -2025,7 +2038,9 @@ static const char simh_help[] = " Data which is output prior to the definition of an expect rule is not\n" " eligible to be matched against.\n\n" " The NOEXPECT command removes a previously defined EXPECT command for the\n" - " console or a specific multiplexer line.\n\n" + " console or a specific multiplexer line. A NOEXPECT command, without a\n" + " specific mention of a particular EXPECT match string, will remove all\n" + " currently defined EXPECT match rules.\n\n" " The SHOW EXPECT command displays all of the pending EXPECT state for\n" " the console or a specific multiplexer line.\n" /***************** 80 character line width template *************************/ @@ -2109,6 +2124,8 @@ static const char simh_help[] = " enough for more than one expect rule to match before an earlier haltafter\n" " delay has expired, only a single EXPECT rule can be defined if a non-zero\n" " HaltAfter parameter has been set.\n" + " The value n can be specified with a suffix of k or m which indicates\n" + " a multiplier of 1000 or 1000000 respectively\n" /***************** 80 character line width template *************************/ #define HLP_SLEEP "*Commands Executing_Command_Files Pausing_Command_Execution" "3Pausing Command Execution\n" @@ -2344,6 +2361,9 @@ static CTAB cmd_table[] = { { "RM", &delete_cmd, 0, HLP_RM, NULL, NULL }, { "COPY", ©_cmd, 0, HLP_COPY, NULL, NULL }, { "CP", ©_cmd, 0, HLP_CP, NULL, NULL }, + { "RENAME", &rename_cmd, 0, HLP_RENAME, NULL, NULL }, + { "MOVE", &rename_cmd, 0, HLP_MOVE, NULL, NULL }, + { "MV", &rename_cmd, 0, HLP_MOVE, NULL, NULL }, { "MKDIR", &mkdir_cmd, 0, HLP_MKDIR, NULL, NULL }, { "RMDIR", &rmdir_cmd, 0, HLP_RMDIR, NULL, NULL }, { "SET", &set_cmd, 0, HLP_SET, NULL, NULL }, @@ -3410,6 +3430,7 @@ return SCPE_OK; t_stat spawn_cmd (int32 flag, CONST char *cptr) { t_stat status; + if ((cptr == NULL) || (strlen (cptr) == 0)) cptr = getenv("SHELL"); if ((cptr == NULL) || (strlen (cptr) == 0)) @@ -4728,9 +4749,9 @@ delay = get_default_env_parameter (dev_name, "SIM_SEND_DELAY", SEND_DEFAULT_DELA after = get_default_env_parameter (dev_name, "SIM_SEND_AFTER", delay); while (*cptr) { if ((!strncmp(gbuf, "DELAY=", 6)) && (gbuf[6])) { - delay = (uint32)get_uint (&gbuf[6], 10, 10000000, &r); + delay = (uint32)get_uint (&gbuf[6], 10, 2000000000, &r); if (r != SCPE_OK) - return sim_messagef (SCPE_ARG, "Invalid Delay Value\n"); + return sim_messagef (SCPE_ARG, "Invalid Delay Value: %s\n", &gbuf[6]); cptr = tptr; tptr = get_glyph (cptr, gbuf, ','); delay_set = TRUE; @@ -4739,9 +4760,9 @@ while (*cptr) { continue; } if ((!strncmp(gbuf, "AFTER=", 6)) && (gbuf[6])) { - after = (uint32)get_uint (&gbuf[6], 10, 10000000, &r); + after = (uint32)get_uint (&gbuf[6], 10, 2000000000, &r); if (r != SCPE_OK) - return sim_messagef (SCPE_ARG, "Invalid After Value\n"); + return sim_messagef (SCPE_ARG, "Invalid After Value: %s\n", &gbuf[6]); cptr = tptr; tptr = get_glyph (cptr, gbuf, ','); after_set = TRUE; @@ -6574,17 +6595,39 @@ if ((stat == SCPE_OK) && (copy_state.count)) return copy_state.stat; } +t_stat rename_cmd (int32 flg, CONST char *cptr) +{ +char sname[CBUFSIZE], dname[CBUFSIZE]; + +if ((!cptr) || (*cptr == 0)) + return SCPE_2FARG; +cptr = get_glyph_quoted (cptr, sname, 0); +if ((!cptr) || (*cptr == 0)) + return SCPE_2FARG; +cptr = get_glyph_quoted (cptr, dname, 0); +if (0 == rename (sname, dname)) + return SCPE_OK; +return sim_messagef (SCPE_ARG, "Can't rename '%s' to '%s': %s\n\n", sname, dname, strerror (errno)); +} + t_stat mkdir_cmd (int32 flg, CONST char *cptr) { char path[CBUFSIZE]; char *c; struct stat filestat; +GET_SWITCHES (cptr); /* get switches */ if ((!cptr) || (*cptr == '\0')) return sim_messagef (SCPE_2FARG, "Must specify a directory path\n"); strlcpy (path, cptr, sizeof (path)); while ((c = strchr (path, '\\'))) *c = '/'; +if (path[strlen (path) - 1] == '/') /* trim any trailing / from the path */ + path[strlen (path) - 1] = '\0'; +while ((c = strstr (path, "//"))) + memmove (c, c + 1, strlen (c + 1) + 1); /* clean out any empty directories // */ +if ((!stat (path, &filestat)) && (filestat.st_mode & S_IFDIR)) + return sim_messagef (SCPE_OK, "directory %s already exists\n", path); c = path; while ((c = strchr (c, '/'))) { *c = '\0'; @@ -6620,6 +6663,7 @@ return SCPE_OK; t_stat rmdir_cmd (int32 flg, CONST char *cptr) { +GET_SWITCHES (cptr); /* get switches */ if ((!cptr) || (*cptr == '\0')) return sim_messagef (SCPE_2FARG, "Must specify a directory\n"); if (rmdir (cptr)) @@ -7325,8 +7369,10 @@ if (*cptr == 0) /* must be more */ gbuf[sizeof(gbuf)-1] = '\0'; strlcpy (gbuf, cptr, sizeof(gbuf)); sim_trim_endspc (gbuf); -if ((sfile = sim_fopen (gbuf, "wb")) == NULL) - return SCPE_OPENERR; +if ((sfile = sim_fopen (gbuf, "r+b")) == NULL) { /* try existing file */ + if ((sfile = sim_fopen (gbuf, "wb")) == NULL) /* create new empty file */ + return SCPE_OPENERR; + } r = sim_save (sfile); fclose (sfile); return r; @@ -7463,6 +7509,8 @@ for (i = 0; i < (device_count + sim_internal_device_count); i++) {/* loop thru d fputc ('\n', sfile); /* end registers */ } fputc ('\n', sfile); /* end devices */ +if (!ferror (sfile)) + sim_set_fsize (sfile, (t_addr)sim_ftell (sfile)); /* truncate the save file */ return (ferror (sfile))? SCPE_IOERR: SCPE_OK; /* error during save? */ } @@ -9398,7 +9446,17 @@ if ((cptr == tptr) || (val > max)) *status = SCPE_ARG; else { while (sim_isspace (*tptr)) tptr++; - if (*tptr != 0) + if (sim_toupper (*tptr) == 'K') { + val *= 1000; + ++tptr; + } + else { + if (sim_toupper (*tptr) == 'M') { + val *= 1000000; + ++tptr; + } + } + if ((*tptr != 0) || (val > max)) *status = SCPE_ARG; } return val; @@ -11779,9 +11837,9 @@ if (*cptr == '[') { } tptr = get_glyph (cptr, gbuf, ','); if ((!strncmp(gbuf, "HALTAFTER=", 10)) && (gbuf[10])) { - after = (uint32)get_uint (&gbuf[10], 10, 100000000, &r); + after = (uint32)get_uint (&gbuf[10], 10, 2000000000, &r); if (r != SCPE_OK) - return sim_messagef (SCPE_ARG, "Invalid Halt After Value\n"); + return sim_messagef (SCPE_ARG, "Invalid Halt After Value: %s\n", &gbuf[10]); cptr = tptr; after_set = TRUE; } @@ -12277,6 +12335,12 @@ memcpy(snd->buffer+snd->insoff, data, size); snd->insoff += size; snd->delay = (sim_switches & SWMASK ('T')) ? (uint32)((sim_timer_inst_per_sec()*delay)/1000000.0) : delay; snd->after = (sim_switches & SWMASK ('T')) ? (uint32)((sim_timer_inst_per_sec()*after)/1000000.0) : after; +if (sim_switches & SWMASK ('T')) + sim_debug (snd->dbit, snd->dptr, "%d bytes queued for input. Delay %d usecs = %d insts, After %d usecs = %d insts\n", + (int)size, (int)delay, (int)snd->delay, (int)after, (int)snd->after); +else + sim_debug (snd->dbit, snd->dptr, "%d bytes queued for input. Delay=%d, After=%d\n", + (int)size, (int)delay, (int)after); snd->next_time = sim_gtime() + snd->after; return SCPE_OK; } diff --git a/scp.h b/scp.h index b2966d1..8beaa05 100644 --- a/scp.h +++ b/scp.h @@ -95,6 +95,7 @@ t_stat dir_cmd (int32 flg, CONST char *cptr); t_stat type_cmd (int32 flg, CONST char *cptr); t_stat delete_cmd (int32 flg, CONST char *cptr); t_stat copy_cmd (int32 flg, CONST char *cptr); +t_stat rename_cmd (int32 flg, CONST char *cptr); t_stat mkdir_cmd (int32 flg, CONST char *cptr); t_stat rmdir_cmd (int32 flg, CONST char *cptr); t_stat brk_cmd (int32 flag, CONST char *ptr); diff --git a/sim_console.c b/sim_console.c index 41558b2..6a0674b 100644 --- a/sim_console.c +++ b/sim_console.c @@ -182,6 +182,13 @@ int32 sim_del_char = '\b'; /* delete character */ #else int32 sim_del_char = 0177; #endif +t_bool sim_signaled_int_char /* WRU character detected by signal while running */ +#if defined (_WIN32) || defined (_VMS) || defined (__CYGWIN__) + = FALSE; +#else + = TRUE; +#endif +uint32 sim_last_poll_kbd_time; /* time when sim_poll_kbd was called */ extern TMLN *sim_oline; /* global output socket */ static t_stat sim_con_poll_svc (UNIT *uptr); /* console connection poll routine */ @@ -2835,6 +2842,7 @@ t_stat sim_poll_kbd (void) { t_stat c; +sim_last_poll_kbd_time = sim_os_msec (); /* record when this poll happened */ if (sim_send_poll_data (&sim_con_send, &c)) /* injected input characters available? */ return c; if (!sim_rem_master_mode) { diff --git a/sim_console.h b/sim_console.h index 6f27d99..37a1fe0 100644 --- a/sim_console.h +++ b/sim_console.h @@ -127,12 +127,14 @@ int32 sim_tt_outcvt (int32 c, uint32 mode); t_stat sim_tt_settabs (UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat sim_tt_showtabs (FILE *st, UNIT *uptr, int32 val, CONST void *desc); -extern int32 sim_rem_cmd_active_line; /* command in progress on line # */ +extern int32 sim_rem_cmd_active_line; /* command in progress on line # */ -extern int32 sim_int_char; /* interrupt character */ -extern int32 sim_brk_char; /* break character */ -extern int32 sim_tt_pchar; /* printable character mask */ -extern int32 sim_del_char; /* delete character */ +extern int32 sim_int_char; /* interrupt character */ +extern int32 sim_brk_char; /* break character */ +extern int32 sim_tt_pchar; /* printable character mask */ +extern int32 sim_del_char; /* delete character */ +extern t_bool sim_signaled_int_char; /* WRU character detected by signal while running */ +extern uint32 sim_last_poll_kbd_time; /* time when sim_poll_kbd was called */ #ifdef __cplusplus } diff --git a/sim_serial.c b/sim_serial.c index 86ae870..74bdfb3 100644 --- a/sim_serial.c +++ b/sim_serial.c @@ -362,7 +362,7 @@ if (serial_open_device_count) { for (i=0; imp->dptr->name, (int)(serial_open_devices[i].line->mp->ldsc-serial_open_devices[i].line), - serial_open_devices[i].line->destination, d ? " {" : "", d ? d : "", d ? ")" : "", serial_open_devices[i].line->serconfig); + serial_open_devices[i].line->destination, ((d != NULL) && (*d != '\0')) ? " (" : "", ((d != NULL) && (*d != '\0')) ? d : "", ((d != NULL) && (*d != '\0')) ? ")" : "", serial_open_devices[i].line->serconfig); } } return SCPE_OK; diff --git a/sim_timer.c b/sim_timer.c index 8c77303..b120716 100644 --- a/sim_timer.c +++ b/sim_timer.c @@ -987,6 +987,11 @@ if (sim_calb_tmr != tmr) { return rtc->currd; } new_rtime = sim_os_msec (); /* wall time */ +if (!sim_signaled_int_char && + ((new_rtime - sim_last_poll_kbd_time) > 500)) { + sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(tmr=%d) gratuitious keyboard poll after %d msecs\n", tmr, (int)(new_rtime - sim_last_poll_kbd_time)); + (void)sim_poll_kbd (); + } ++rtc->calibrations; /* count calibrations */ sim_debug (DBG_TRC, &sim_timer_dev, "sim_rtcn_calb(ticksper=%d, tmr=%d)\n", ticksper, tmr); if (new_rtime < rtc->rtime) { /* time running backwards? */ diff --git a/sim_video.c b/sim_video.c index d0b0488..fe9d6cb 100644 --- a/sim_video.c +++ b/sim_video.c @@ -1871,9 +1871,13 @@ if (1) { snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1), ", PNG Version %s", PNG_LIBPNG_VER_STRING); png_destroy_read_struct(&png, NULL, NULL); -#if defined (HAVE_ZLIB) - snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1), - ", zlib: %s", zlibVersion()); +#if defined (ZLIB_VERSION) + if (strcmp (ZLIB_VERSION, zlibVersion ())) + snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1), + ", zlib: (Compiled: %s, Runtime: %s)", ZLIB_VERSION, zlibVersion ()); + else + snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1), + ", zlib: %s", ZLIB_VERSION); #endif } #endif From 031546f73339bb0f40de94270e59e9e0c4c2cb63 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 8 Jan 2020 23:50:47 -0500 Subject: [PATCH 78/98] KA10: Fixed error in IDBP and Address Fault Inhibit. Tops 20 V3-7 works. --- PDP10/kx10_cpu.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index c801635..aea011e 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2352,11 +2352,6 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int data = load_tlb(uf | upmp, page, wr); if (data == 0 && page_fault) { fault_data |= ((uint64)addr); - /* Ignore faults if flag set */ - if (FLAGS & ADRFLT) { - page_fault = 0; - return 1; - } if (uf) /* U */ fault_data |= SMASK; #if KL_ITS @@ -2399,10 +2394,6 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int /* create location. */ *loc = ((data & 017777) << 9) + (addr & 0777); - /* Ignore faults if flag set */ - if (FLAGS & ADRFLT) - return 1; - /* If PUBLIC and private page, make sure we are fetching a Portal */ if ((data & KL_PAG_A) && !flag && pub && ((data & KL_PAG_P) == 0) && (!fetch || !OP_PORTAL(M[*loc]))) { @@ -5999,7 +5990,8 @@ ldb_ptr: /* Full pointer */ AB = (AB + 1) & RMASK; //fprintf(stderr, "LBP %o %o %06o %012llo\n\r", SC, SCAD, AB, MB); - } + } else + glb_sect = 0; #endif #if ITS if (QITS && pi_cycle == 0 && mem_prot == 0) { @@ -6031,7 +6023,8 @@ ld_exe: AR &= CM(MQ); AR |= BR & MQ; MB = AR & FMASK; - Mem_write(0, 0); + if (Mem_write(0, 0)) + goto last; } FLAGS &= ~BYTI; BYF5 = 0; From 0b35b1f309af0f9a4af3d5a3a0c3067b3709b9f5 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 15 Jan 2020 08:24:30 -0500 Subject: [PATCH 79/98] SCP: Updated to current. --- Visual Studio Projects/3B2.vcproj | 4 +- Visual Studio Projects/B5500.vcproj | 4 +- Visual Studio Projects/I701.vcproj | 4 +- Visual Studio Projects/I7010.vcproj | 4 +- Visual Studio Projects/I704.vcproj | 4 +- Visual Studio Projects/I7070.vcproj | 4 +- Visual Studio Projects/I7080.vcproj | 4 +- Visual Studio Projects/I7090.vcproj | 4 +- Visual Studio Projects/I7094.vcproj | 4 +- Visual Studio Projects/IBM360.vcproj | 4 +- Visual Studio Projects/IBM360_32.vcproj | 4 +- Visual Studio Projects/ICL1900.vcproj | 4 +- Visual Studio Projects/PDP10-KA.vcproj | 4 +- Visual Studio Projects/PDP10-KI.vcproj | 4 +- Visual Studio Projects/PDP10-KL.vcproj | 8 +- Visual Studio Projects/SEL32.vcproj | 4 +- makefile | 215 ++++++++++++------------ scp.c | 9 + 18 files changed, 152 insertions(+), 140 deletions(-) diff --git a/Visual Studio Projects/3B2.vcproj b/Visual Studio Projects/3B2.vcproj index 7b5220d..239d694 100644 --- a/Visual Studio Projects/3B2.vcproj +++ b/Visual Studio Projects/3B2.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../3B2/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG" + PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG" KeepComments="false" BasicRuntimeChecks="0" RuntimeLibrary="1" @@ -125,7 +125,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="../3B2/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG" + PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/B5500.vcproj b/Visual Studio Projects/B5500.vcproj index aa52723..9f6d460 100644 --- a/Visual Studio Projects/B5500.vcproj +++ b/Visual Studio Projects/B5500.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" KeepComments="false" BasicRuntimeChecks="0" RuntimeLibrary="1" @@ -126,7 +126,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/I701.vcproj b/Visual Studio Projects/I701.vcproj index eb473ef..eee30d4 100644 --- a/Visual Studio Projects/I701.vcproj +++ b/Visual Studio Projects/I701.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I701;USE_INT64;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I701;USE_INT64;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" @@ -123,7 +123,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I701;USE_INT64;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I701;USE_INT64;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/I7010.vcproj b/Visual Studio Projects/I7010.vcproj index 8f1cd27..5215d94 100644 --- a/Visual Studio Projects/I7010.vcproj +++ b/Visual Studio Projects/I7010.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I7010;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I7010;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" @@ -123,7 +123,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I7010;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I7010;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/I704.vcproj b/Visual Studio Projects/I704.vcproj index 5083ea6..e947345 100644 --- a/Visual Studio Projects/I704.vcproj +++ b/Visual Studio Projects/I704.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I704;USE_INT64;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I704;USE_INT64;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" @@ -123,7 +123,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I704;USE_INT64;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I704;USE_INT64;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/I7070.vcproj b/Visual Studio Projects/I7070.vcproj index 4166872..2e740f4 100644 --- a/Visual Studio Projects/I7070.vcproj +++ b/Visual Studio Projects/I7070.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I7070;USE_INT64;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I7070;USE_INT64;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" @@ -123,7 +123,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I7070;USE_INT64;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I7070;USE_INT64;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/I7080.vcproj b/Visual Studio Projects/I7080.vcproj index 71ac5c0..adfa460 100644 --- a/Visual Studio Projects/I7080.vcproj +++ b/Visual Studio Projects/I7080.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I7080;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I7080;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" @@ -123,7 +123,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I7080;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I7080;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/I7090.vcproj b/Visual Studio Projects/I7090.vcproj index 384e9f5..aa2514e 100644 --- a/Visual Studio Projects/I7090.vcproj +++ b/Visual Studio Projects/I7090.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I7090;USE_INT64;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I7090;USE_INT64;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" BasicRuntimeChecks="3" RuntimeLibrary="1" UsePrecompiledHeader="0" @@ -123,7 +123,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="I7090;USE_INT64;USE_SIM_CARD;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="I7090;USE_INT64;USE_SIM_CARD;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/I7094.vcproj b/Visual Studio Projects/I7094.vcproj index ed21cb0..abcc94a 100644 --- a/Visual Studio Projects/I7094.vcproj +++ b/Visual Studio Projects/I7094.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_INT64;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_INT64;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" KeepComments="false" BasicRuntimeChecks="0" RuntimeLibrary="1" @@ -125,7 +125,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_INT64;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="WIN32;_CRT_NONSTDC_NO_WARNINGS;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_INT64;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/IBM360.vcproj b/Visual Studio Projects/IBM360.vcproj index e781ac4..1b36048 100644 --- a/Visual Studio Projects/IBM360.vcproj +++ b/Visual Studio Projects/IBM360.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../windows-build/libSDL/SDL2-2.0.5/include;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18" - PreprocessorDefinitions="IBM360;USE_64BIT;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="IBM360;USE_64BIT;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" KeepComments="false" MinimalRebuild="true" BasicRuntimeChecks="0" @@ -127,7 +127,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="../../windows-build/libSDL/SDL2-2.0.5/include;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18" - PreprocessorDefinitions="IBM360;USE_64BIT;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="IBM360;USE_64BIT;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/IBM360_32.vcproj b/Visual Studio Projects/IBM360_32.vcproj index 46ae8d5..9155cce 100644 --- a/Visual Studio Projects/IBM360_32.vcproj +++ b/Visual Studio Projects/IBM360_32.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../windows-build/libSDL/SDL2-2.0.5/include;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18" - PreprocessorDefinitions="IBM360;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="IBM360;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" KeepComments="false" MinimalRebuild="true" BasicRuntimeChecks="0" @@ -127,7 +127,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="../../windows-build/libSDL/SDL2-2.0.5/include;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18" - PreprocessorDefinitions="IBM360;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="IBM360;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/ICL1900.vcproj b/Visual Studio Projects/ICL1900.vcproj index 4d4dca5..0e3070f 100644 --- a/Visual Studio Projects/ICL1900.vcproj +++ b/Visual Studio Projects/ICL1900.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../windows-build/libSDL/SDL2-2.0.5/include;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18" - PreprocessorDefinitions="ICL1900;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="ICL1900;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" KeepComments="false" MinimalRebuild="true" BasicRuntimeChecks="0" @@ -127,7 +127,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="../../windows-build/libSDL/SDL2-2.0.5/include;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18" - PreprocessorDefinitions="ICL1900;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="ICL1900;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;USE_SIM_CARD;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/PDP10-KA.vcproj b/Visual Studio Projects/PDP10-KA.vcproj index a20c066..f97eaf2 100644 --- a/Visual Studio Projects/PDP10-KA.vcproj +++ b/Visual Studio Projects/PDP10-KA.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../PDP10/;../PDP11/;../VAX/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KA=1;USE_DISPLAY;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;PTW32_STATIC_LIB;USE_READER_THREAD;SIM_ASYNCH_IO" + PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KA=1;SIM_BUILD_TOOL=simh-Visual-Studio-Project;USE_DISPLAY;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;PTW32_STATIC_LIB;USE_READER_THREAD;SIM_ASYNCH_IO" KeepComments="false" BasicRuntimeChecks="0" RuntimeLibrary="1" @@ -126,7 +126,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="../PDP10/;../PDP11/;../VAX/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KA=1;USE_DISPLAY;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;PTW32_STATIC_LIB;USE_READER_THREAD;SIM_ASYNCH_IO" + PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KA=1;SIM_BUILD_TOOL=simh-Visual-Studio-Project;USE_DISPLAY;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;PTW32_STATIC_LIB;USE_READER_THREAD;SIM_ASYNCH_IO" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/PDP10-KI.vcproj b/Visual Studio Projects/PDP10-KI.vcproj index e59f8e6..90ad3c0 100644 --- a/Visual Studio Projects/PDP10-KI.vcproj +++ b/Visual Studio Projects/PDP10-KI.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../PDP10/;../PDP11/;../VAX/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KI=1;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;USE_DISPLAY;DISPLAY_TYPE=DIS_TYPE30;PIX_SCALE=RES_HALF;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KI=1;SIM_BUILD_TOOL=simh-Visual-Studio-Project;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;USE_DISPLAY;DISPLAY_TYPE=DIS_TYPE30;PIX_SCALE=RES_HALF;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" KeepComments="false" BasicRuntimeChecks="0" RuntimeLibrary="1" @@ -126,7 +126,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="../PDP10/;../PDP11/;../VAX/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KI=1;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;USE_DISPLAY;DISPLAY_TYPE=DIS_TYPE30;PIX_SCALE=RES_HALF;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KI=1;SIM_BUILD_TOOL=simh-Visual-Studio-Project;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;USE_DISPLAY;DISPLAY_TYPE=DIS_TYPE30;PIX_SCALE=RES_HALF;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/Visual Studio Projects/PDP10-KL.vcproj b/Visual Studio Projects/PDP10-KL.vcproj index 4b9ca5f..a1a00af 100644 --- a/Visual Studio Projects/PDP10-KL.vcproj +++ b/Visual Studio Projects/PDP10-KL.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../PDP10/;../PDP11/;../VAX/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KL=1;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KL=1;SIM_BUILD_TOOL=simh-Visual-Studio-Project;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" KeepComments="false" BasicRuntimeChecks="0" RuntimeLibrary="1" @@ -126,7 +126,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="../PDP10/;../PDP11/;../VAX/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KI=1;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;USE_DISPLAY;DISPLAY_TYPE=DIS_TYPE30;PIX_SCALE=RES_HALF;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KL=1;SIM_BUILD_TOOL=simh-Visual-Studio-Project;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;USE_DISPLAY;DISPLAY_TYPE=DIS_TYPE30;PIX_SCALE=RES_HALF;USE_SIM_VIDEO;HAVE_LIBSDL;HAVE_LIBPNG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -205,6 +205,10 @@ RelativePath="..\PDP10\kl10_fe.c" > + + diff --git a/Visual Studio Projects/SEL32.vcproj b/Visual Studio Projects/SEL32.vcproj index e5982bc..eb83569 100644 --- a/Visual Studio Projects/SEL32.vcproj +++ b/Visual Studio Projects/SEL32.vcproj @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../../windows-build/libSDL/SDL2-2.0.5/include;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18" - PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" KeepComments="false" MinimalRebuild="true" BasicRuntimeChecks="0" @@ -126,7 +126,7 @@ OmitFramePointers="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="../../windows-build/libSDL/SDL2-2.0.5/include;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18" - PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" diff --git a/makefile b/makefile index 3a4c9c6..bcd15c2 100644 --- a/makefile +++ b/makefile @@ -78,7 +78,7 @@ # # CC Command (and platform available options). (Poor man's autoconf) # -ifneq (,$(GREP_OPTIONS)) +ifneq (,${GREP_OPTIONS}) $(info GREP_OPTIONS is defined in your environment.) $(info ) $(info This variable interfers with the proper operation of this script.) @@ -96,40 +96,40 @@ ifeq (old,$(shell gmake --version /dev/null 2>&1 | grep 'GNU Make' | awk '{ if ( $(warning *** Warning *** GNU Make Version $(GMAKE_VERSION) is too old to) $(warning *** Warning *** fully process this makefile) endif -BUILD_SINGLE := $(MAKECMDGOALS) $(BLANK_SUFFIX) +BUILD_SINGLE := ${MAKECMDGOALS} $(BLANK_SUFFIX) BUILD_MULTIPLE_VERB = is # building the pdp1, pdp11, tx-0, or any microvax simulator could use video support -ifneq (,$(or $(findstring XXpdp1XX,$(addsuffix XX,$(addprefix XX,$(MAKECMDGOALS)))),$(findstring pdp11,$(MAKECMDGOALS)),$(findstring tx-0,$(MAKECMDGOALS)),$(findstring microvax1,$(MAKECMDGOALS)),$(findstring microvax2,$(MAKECMDGOALS)),$(findstring microvax3900,$(MAKECMDGOALS)),$(findstring XXvaxXX,$(addsuffix XX,$(addprefix XX,$(MAKECMDGOALS)))))) +ifneq (,$(or $(findstring XXpdp1XX,$(addsuffix XX,$(addprefix XX,${MAKECMDGOALS}))),$(findstring pdp11,${MAKECMDGOALS}),$(findstring tx-0,${MAKECMDGOALS}),$(findstring microvax1,${MAKECMDGOALS}),$(findstring microvax2,${MAKECMDGOALS}),$(findstring microvax3900,${MAKECMDGOALS}),$(findstring XXvaxXX,$(addsuffix XX,$(addprefix XX,${MAKECMDGOALS}))))) VIDEO_USEFUL = true endif # building the besm6 needs both video support and fontfile support -ifneq (,$(findstring besm6,$(MAKECMDGOALS))) +ifneq (,$(findstring besm6,${MAKECMDGOALS})) VIDEO_USEFUL = true BESM6_BUILD = true endif # building the PDP6, KA10 or KI10 needs video support -ifneq (,$(or $(findstring pdp6,$(MAKECMDGOALS)),$(findstring pdp10-ka,$(MAKECMDGOALS)),$(findstring pdp10-ki,$(MAKECMDGOALS)))) +ifneq (,$(or $(findstring pdp6,${MAKECMDGOALS}),$(findstring pdp10-ka,${MAKECMDGOALS}),$(findstring pdp10-ki,${MAKECMDGOALS}))) VIDEO_USEFUL = true endif # building the KA10, KI10 or KL10 networking can be used. -ifneq (,$(or $(findstring pdp10-ka,$(MAKECMDGOALS)),$(findstring pdp10-ki,$(MAKECMDGOALS),$(findstring pdp10-kl,$MAKECMDGOALS)))) +ifneq (,$(or $(findstring pdp10-ka,${MAKECMDGOALS}),$(findstring pdp10-ki,${MAKECMDGOALS},$(findstring pdp10-kl,${MAKECMDGOALS})))) NETWORK_USEFUL = true endif # building the pdp11, pdp10, or any vax simulator could use networking support -ifneq (,$(or $(findstring pdp11,$(MAKECMDGOALS)),$(findstring pdp10,$(MAKECMDGOALS)),$(findstring vax,$(MAKECMDGOALS)),$(findstring all,$(MAKECMDGOALS)))) +ifneq (,$(or $(findstring pdp11,${MAKECMDGOALS}),$(findstring pdp10,${MAKECMDGOALS}),$(findstring vax,${MAKECMDGOALS}),$(findstring all,${MAKECMDGOALS}))) NETWORK_USEFUL = true - ifneq (,$(findstring all,$(MAKECMDGOALS))) + ifneq (,$(findstring all,${MAKECMDGOALS})) BUILD_MULTIPLE = s BUILD_MULTIPLE_VERB = are VIDEO_USEFUL = true BESM6_BUILD = true endif - ifneq (,$(word 2,$(MAKECMDGOALS))) + ifneq (,$(word 2,${MAKECMDGOALS})) BUILD_MULTIPLE = s BUILD_MULTIPLE_VERB = are endif else - ifeq ($(MAKECMDGOALS),) + ifeq (${MAKECMDGOALS},) # default target is all NETWORK_USEFUL = true VIDEO_USEFUL = true @@ -139,28 +139,28 @@ else BESM6_BUILD = true endif endif -find_exe = $(abspath $(strip $(firstword $(foreach dir,$(strip $(subst :, ,$(PATH))),$(wildcard $(dir)/$(1)))))) -find_lib = $(abspath $(strip $(firstword $(foreach dir,$(strip $(LIBPATH)),$(wildcard $(dir)/lib$(1).$(LIBEXT)))))) -find_include = $(abspath $(strip $(firstword $(foreach dir,$(strip $(INCPATH)),$(wildcard $(dir)/$(1).h))))) +find_exe = $(abspath $(strip $(firstword $(foreach dir,$(strip $(subst :, ,${PATH})),$(wildcard $(dir)/$(1)))))) +find_lib = $(abspath $(strip $(firstword $(foreach dir,$(strip ${LIBPATH}),$(wildcard $(dir)/lib$(1).${LIBEXT}))))) +find_include = $(abspath $(strip $(firstword $(foreach dir,$(strip ${INCPATH}),$(wildcard $(dir)/$(1).h))))) ifneq (0,$(TESTS)) find_test = $(abspath $(wildcard $(1)/tests/$(2)_test.ini)) TESTING_FEATURES = - Per simulator tests will be run else TESTING_FEATURES = - Per simulator tests will be skipped endif -ifneq ($(findstring Windows,$(OS)),) - ifeq ($(findstring .exe,$(SHELL)),.exe) +ifneq ($(findstring Windows,${OS}),) + ifeq ($(findstring .exe,${SHELL}),.exe) # MinGW WIN32 := 1 else # Msys or cygwin ifeq (MINGW,$(findstring MINGW,$(shell uname))) $(info *** This makefile can not be used with the Msys bash shell) - $(error Use build_mingw.bat $(MAKECMDGOALS) from a Windows command prompt) + $(error Use build_mingw.bat ${MAKECMDGOALS} from a Windows command prompt) endif endif endif -ifeq ($(WIN32),) #*nix Environments (&& cygwin) - ifeq ($(GCC),) +ifeq (${WIN32},) #*nix Environments (&& cygwin) + ifeq (${GCC},) ifeq (,$(shell which gcc 2>/dev/null)) $(info *** Warning *** Using local cc since gcc isn't available locally.) $(info *** Warning *** You may need to install gcc to build working simulators.) @@ -181,55 +181,55 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) OSTYPE = cygwin OSNAME = windows-build endif - ifeq (,$(shell $(GCC) -v /dev/null 2>&1 | grep 'clang')) - GCC_VERSION = $(shell $(GCC) -v /dev/null 2>&1 | grep 'gcc version' | awk '{ print $$3 }') + ifeq (,$(shell ${GCC} -v /dev/null 2>&1 | grep 'clang')) + GCC_VERSION = $(shell ${GCC} -v /dev/null 2>&1 | grep 'gcc version' | awk '{ print $$3 }') COMPILER_NAME = GCC Version: $(GCC_VERSION) ifeq (,$(GCC_VERSION)) ifeq (SunOS,$(OSTYPE)) - ifneq (,$(shell $(GCC) -V 2>&1 | grep 'Sun C')) - SUNC_VERSION = $(shell $(GCC) -V 2>&1 | grep 'Sun C') + ifneq (,$(shell ${GCC} -V 2>&1 | grep 'Sun C')) + SUNC_VERSION = $(shell ${GCC} -V 2>&1 | grep 'Sun C') COMPILER_NAME = $(wordlist 2,10,$(SUNC_VERSION)) CC_STD = -std=c99 endif endif ifeq (HP-UX,$(OSTYPE)) - ifneq (,$(shell what `which $(firstword $(GCC)) 2>&1`| grep -i compiler)) - COMPILER_NAME = $(strip $(shell what `which $(firstword $(GCC)) 2>&1` | grep -i compiler)) + ifneq (,$(shell what `which $(firstword ${GCC}) 2>&1`| grep -i compiler)) + COMPILER_NAME = $(strip $(shell what `which $(firstword ${GCC}) 2>&1` | grep -i compiler)) CC_STD = -std=gnu99 endif endif else - ifeq (,$(findstring ++,$(GCC))) + ifeq (,$(findstring ++,${GCC})) CC_STD = -std=gnu99 else CPP_BUILD = 1 endif endif else - ifeq (Apple,$(shell $(GCC) -v /dev/null 2>&1 | grep 'Apple' | awk '{ print $$1 }')) - COMPILER_NAME = $(shell $(GCC) -v /dev/null 2>&1 | grep 'Apple' | awk '{ print $$1 " " $$2 " " $$3 " " $$4 }') + ifeq (Apple,$(shell ${GCC} -v /dev/null 2>&1 | grep 'Apple' | awk '{ print $$1 }')) + COMPILER_NAME = $(shell ${GCC} -v /dev/null 2>&1 | grep 'Apple' | awk '{ print $$1 " " $$2 " " $$3 " " $$4 }') CLANG_VERSION = $(word 4,$(COMPILER_NAME)) else - COMPILER_NAME = $(shell $(GCC) -v /dev/null 2>&1 | grep 'clang version' | awk '{ print $$1 " " $$2 " " $$3 }') + COMPILER_NAME = $(shell ${GCC} -v /dev/null 2>&1 | grep 'clang version' | awk '{ print $$1 " " $$2 " " $$3 }') CLANG_VERSION = $(word 3,$(COMPILER_NAME)) ifeq (,$(findstring .,$(CLANG_VERSION))) - COMPILER_NAME = $(shell $(GCC) -v /dev/null 2>&1 | grep 'clang version' | awk '{ print $$1 " " $$2 " " $$3 " " $$4 }') + COMPILER_NAME = $(shell ${GCC} -v /dev/null 2>&1 | grep 'clang version' | awk '{ print $$1 " " $$2 " " $$3 " " $$4 }') CLANG_VERSION = $(word 4,$(COMPILER_NAME)) endif endif - ifeq (,$(findstring ++,$(GCC))) + ifeq (,$(findstring ++,${GCC})) CC_STD = -std=c99 else CPP_BUILD = 1 OS_CCDEFS += -Wno-deprecated endif endif - ifeq (git-repo,$(shell if $(TEST) -d ./.git; then echo git-repo; fi)) + ifeq (git-repo,$(shell if ${TEST} -d ./.git; then echo git-repo; fi)) GIT_PATH=$(strip $(shell which git)) ifeq (,$(GIT_PATH)) $(error building using a git repository, but git is not available) endif - ifeq (commit-id-exists,$(shell if $(TEST) -e .git-commit-id; then echo commit-id-exists; fi)) + ifeq (commit-id-exists,$(shell if ${TEST} -e .git-commit-id; then echo commit-id-exists; fi)) CURRENT_GIT_COMMIT_ID=$(strip $(shell grep 'SIM_GIT_COMMIT_ID' .git-commit-id | awk '{ print $$2 }')) ACTUAL_GIT_COMMIT_ID=$(strip $(shell git log -1 --pretty="%H")) ifneq ($(CURRENT_GIT_COMMIT_ID),$(ACTUAL_GIT_COMMIT_ID)) @@ -248,7 +248,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif LTO_EXCLUDE_VERSIONS = PCAPLIB = pcap - ifeq (agcc,$(findstring agcc,$(GCC))) # Android target build? + ifeq (agcc,$(findstring agcc,${GCC})) # Android target build? OS_CCDEFS = -D_GNU_SOURCE ifeq (,$(NOASYNCH)) OS_CCDEFS += -DSIM_ASYNCH_IO @@ -256,15 +256,15 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) OS_LDFLAGS = -lm else # Non-Android (or Native Android) Builds ifeq (,$(INCLUDES)$(LIBRARIES)) - INCPATH:=$(shell LANG=C; $(GCC) -x c -v -E /dev/null 2>&1 | grep -A 10 '> search starts here' | grep '^ ' | tr -d '\n') - ifeq (,$(INCPATH)) + INCPATH:=$(shell LANG=C; ${GCC} -x c -v -E /dev/null 2>&1 | grep -A 10 '> search starts here' | grep '^ ' | tr -d '\n') + ifeq (,${INCPATH}) INCPATH:=/usr/include endif LIBPATH:=/usr/lib else $(info *** Warning ***) ifeq (,$(INCLUDES)) - INCPATH:=$(shell LANG=C; $(GCC) -x c -v -E /dev/null 2>&1 | grep -A 10 '> search starts here' | grep '^ ' | tr -d '\n') + INCPATH:=$(shell LANG=C; ${GCC} -x c -v -E /dev/null 2>&1 | grep -A 10 '> search starts here' | grep '^ ' | tr -d '\n') else $(info *** Warning *** Unsupported build with INCLUDES defined as: $(INCLUDES)) INCPATH:=$(strip $(subst :, ,$(INCLUDES))) @@ -284,28 +284,28 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) $(info *** Warning ***) endif OS_CCDEFS += -D_GNU_SOURCE - GCC_OPTIMIZERS_CMD = $(GCC) -v --help 2>&1 - GCC_WARNINGS_CMD = $(GCC) -v --help 2>&1 - LD_ELF = $(shell echo | $(GCC) -E -dM - | grep __ELF__) + GCC_OPTIMIZERS_CMD = ${GCC} -v --help 2>&1 + GCC_WARNINGS_CMD = ${GCC} -v --help 2>&1 + LD_ELF = $(shell echo | ${GCC} -E -dM - | grep __ELF__) ifeq (Darwin,$(OSTYPE)) OSNAME = OSX LIBEXT = dylib ifneq (include,$(findstring include,$(UNSUPPORTED_BUILD))) - INCPATH:=$(shell LANG=C; $(GCC) -x c -v -E /dev/null 2>&1 | grep -A 10 '> search starts here' | grep '^ ' | grep -v 'framework directory' | tr -d '\n') + INCPATH:=$(shell LANG=C; ${GCC} -x c -v -E /dev/null 2>&1 | grep -A 10 '> search starts here' | grep '^ ' | grep -v 'framework directory' | tr -d '\n') endif - ifeq (incopt,$(shell if $(TEST) -d /opt/local/include; then echo incopt; fi)) + ifeq (incopt,$(shell if ${TEST} -d /opt/local/include; then echo incopt; fi)) INCPATH += /opt/local/include OS_CCDEFS += -I/opt/local/include endif - ifeq (libopt,$(shell if $(TEST) -d /opt/local/lib; then echo libopt; fi)) + ifeq (libopt,$(shell if ${TEST} -d /opt/local/lib; then echo libopt; fi)) LIBPATH += /opt/local/lib OS_LDFLAGS += -L/opt/local/lib endif - ifeq (HomeBrew,$(shell if $(TEST) -d /usr/local/Cellar; then echo HomeBrew; fi)) + ifeq (HomeBrew,$(shell if ${TEST} -d /usr/local/Cellar; then echo HomeBrew; fi)) INCPATH += $(foreach dir,$(wildcard /usr/local/Cellar/*/*),$(dir)/include) LIBPATH += $(foreach dir,$(wildcard /usr/local/Cellar/*/*),$(dir)/lib) endif - ifeq (libXt,$(shell if $(TEST) -d /usr/X11/lib; then echo libXt; fi)) + ifeq (libXt,$(shell if ${TEST} -d /usr/X11/lib; then echo libXt; fi)) LIBPATH += /usr/X11/lib OS_LDFLAGS += -L/usr/X11/lib endif @@ -316,12 +316,15 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif ifneq (lib,$(findstring lib,$(UNSUPPORTED_BUILD))) ifeq (Android,$(shell uname -o)) - ifneq (,$(shell if $(TEST) -d /system/lib; then echo systemlib; fi)) + ifneq (,$(shell if ${TEST} -d ${PREFIX}/lib; then echo prefixlib; fi)) + LIBPATH += ${PREFIX}/lib + endif + ifneq (,$(shell if ${TEST} -d /system/lib; then echo systemlib; fi)) LIBPATH += /system/lib endif LIBPATH += $(LD_LIBRARY_PATH) endif - ifeq (ldconfig,$(shell if $(TEST) -e /sbin/ldconfig; then echo ldconfig; fi)) + ifeq (ldconfig,$(shell if ${TEST} -e /sbin/ldconfig; then echo ldconfig; fi)) LIBPATH := $(sort $(foreach lib,$(shell /sbin/ldconfig -p | grep ' => /' | sed 's/^.* => //'),$(dir $(lib)))) endif endif @@ -334,11 +337,11 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif LIBEXT = so OS_LDFLAGS += -lsocket -lnsl - ifeq (incsfw,$(shell if $(TEST) -d /opt/sfw/include; then echo incsfw; fi)) + ifeq (incsfw,$(shell if ${TEST} -d /opt/sfw/include; then echo incsfw; fi)) INCPATH += /opt/sfw/include OS_CCDEFS += -I/opt/sfw/include endif - ifeq (libsfw,$(shell if $(TEST) -d /opt/sfw/lib; then echo libsfw; fi)) + ifeq (libsfw,$(shell if ${TEST} -d /opt/sfw/lib; then echo libsfw; fi)) LIBPATH += /opt/sfw/lib OS_LDFLAGS += -L/opt/sfw/lib -R/opt/sfw/lib endif @@ -346,18 +349,18 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) else ifeq (cygwin,$(OSTYPE)) # use 0readme_ethernet.txt documented Windows pcap build components - INCPATH += ../windows-build/winpcap/WpdPack/include - LIBPATH += ../windows-build/winpcap/WpdPack/lib + INCPATH += ../windows-build/winpcap/WpdPack/Include + LIBPATH += ../windows-build/winpcap/WpdPack/Lib PCAPLIB = wpcap LIBEXT = a else ifneq (,$(findstring AIX,$(OSTYPE))) OS_LDFLAGS += -lm -lrt - ifeq (incopt,$(shell if $(TEST) -d /opt/freeware/include; then echo incopt; fi)) + ifeq (incopt,$(shell if ${TEST} -d /opt/freeware/include; then echo incopt; fi)) INCPATH += /opt/freeware/include OS_CCDEFS += -I/opt/freeware/include endif - ifeq (libopt,$(shell if $(TEST) -d /opt/freeware/lib; then echo libopt; fi)) + ifeq (libopt,$(shell if ${TEST} -d /opt/freeware/lib; then echo libopt; fi)) LIBPATH += /opt/freeware/lib OS_LDFLAGS += -L/opt/freeware/lib endif @@ -395,23 +398,23 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) LIBPATH = $(subst :, ,$(LPATH)) endif endif - OS_LDFLAGS += $(patsubst %,-L%,$(LIBPATH)) + OS_LDFLAGS += $(patsubst %,-L%,${LIBPATH}) endif endif endif - ifeq (usrpkglib,$(shell if $(TEST) -d /usr/pkg/lib; then echo usrpkglib; fi)) + ifeq (usrpkglib,$(shell if ${TEST} -d /usr/pkg/lib; then echo usrpkglib; fi)) LIBPATH += /usr/pkg/lib INCPATH += /usr/pkg/include OS_LDFLAGS += -L/usr/pkg/lib -R/usr/pkg/lib OS_CCDEFS += -I/usr/pkg/include endif - ifeq (X11R7,$(shell if $(TEST) -d /usr/X11R7/lib; then echo X11R7; fi)) + ifeq (X11R7,$(shell if ${TEST} -d /usr/X11R7/lib; then echo X11R7; fi)) LIBPATH += /usr/X11R7/lib INCPATH += /usr/X11R7/include OS_LDFLAGS += -L/usr/X11R7/lib -R/usr/X11R7/lib OS_CCDEFS += -I/usr/X11R7/include endif - ifeq (/usr/local/lib,$(findstring /usr/local/lib,$(LIBPATH))) + ifeq (/usr/local/lib,$(findstring /usr/local/lib,${LIBPATH})) INCPATH += /usr/local/include OS_CCDEFS += -I/usr/local/include endif @@ -438,14 +441,14 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) # Some gcc versions don't support LTO, so only use LTO when the compiler is known to support it ifeq (,$(NO_LTO)) ifneq (,$(GCC_VERSION)) - ifeq (,$(shell $(GCC) -v /dev/null 2>&1 | grep '\-\-enable-lto')) + ifeq (,$(shell ${GCC} -v /dev/null 2>&1 | grep '\-\-enable-lto')) LTO_EXCLUDE_VERSIONS += $(GCC_VERSION) endif endif endif endif - $(info lib paths are: $(LIBPATH)) - $(info include paths are: $(INCPATH)) + $(info lib paths are: ${LIBPATH}) + $(info include paths are: ${INCPATH}) need_search = $(strip $(shell ld -l$(1) /dev/null 2>&1 | grep $(1) | sed s/$(1)//)) LD_SEARCH_NEEDED := $(call need_search,ZzzzzzzZ) ifneq (,$(call find_lib,m)) @@ -468,7 +471,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) OS_LDFLAGS += -lpthread $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) else - LIBEXTSAVE := $(LIBEXT) + LIBEXTSAVE := ${LIBEXT} LIBEXT = a ifneq (,$(call find_lib,pthread)) OS_CCDEFS += -DUSE_READER_THREAD @@ -490,25 +493,16 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif endif endif - # Find available RegEx library. Prefer libpcreposix - except on OS X. - ifneq (,$(and $(call find_include,pcreposix),$(call find_include,pcre),$(subst Darwin,,$(OSTYPE)))) - ifneq (,$(and $(call find_lib,pcreposix),$(call find_lib,pcre))) - OS_CCDEFS += -DHAVE_PCREPOSIX_H - OS_LDFLAGS += -lpcreposix -lpcre - $(info using libpcreposix: $(call find_lib,pcreposix) $(call find_lib,pcre) $(call find_include,pcreposix) $(call find_include,pcre)) - ifeq ($(LD_SEARCH_NEEDED),$(call need_search,pcreposix)) - OS_LDFLAGS += -L$(dir $(call find_lib,pcreposix)) + # Find PCRE RegEx library. + ifneq (,$(call find_include,pcre)) + ifneq (,$(call find_lib,pcre)) + OS_CCDEFS += -DHAVE_PCRE_H + OS_LDFLAGS += -lpcre + $(info using libpcre: $(call find_lib,pcre) $(call find_include,pcre)) + ifeq ($(LD_SEARCH_NEEDED),$(call need_search,pcre)) + OS_LDFLAGS += -L$(dir $(call find_lib,pcre)) endif endif - else - # If libpcreposix isn't available, fall back to the local regex.h - # Presume that the local regex support is available in the C runtime - # without a specific reference to a library. This may not be true on - # some platforms. - ifneq (,$(call find_include,regex)) - OS_CCDEFS += -DHAVE_REGEX_H - $(info using regex: $(call find_include,regex)) - endif endif # Find available ncurses library. ifneq (,$(call find_include,ncurses)) @@ -530,7 +524,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif ifneq (,$(call find_include,dlfcn)) ifneq (,$(call find_lib,dl)) - OS_CCDEFS += -DHAVE_DLOPEN=$(LIBEXT) + OS_CCDEFS += -DHAVE_DLOPEN=${LIBEXT} OS_LDFLAGS += -ldl $(info using libdl: $(call find_lib,dl) $(call find_include,dlfcn)) else @@ -539,7 +533,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) $(info using libdl: $(call find_include,dlfcn)) else ifneq (,$(call find_lib,dld)) - OS_CCDEFS += -DHAVE_DLOPEN=$(LIBEXT) + OS_CCDEFS += -DHAVE_DLOPEN=${LIBEXT} OS_LDFLAGS += -ldld $(info using libdld: $(call find_lib,dld) $(call find_include,dlfcn)) endif @@ -572,13 +566,18 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif ifneq (,$(call find_include,sys/mman)) ifneq (,$(shell grep shm_open $(call find_include,sys/mman))) - OS_CCDEFS += -DHAVE_SHM_OPEN - $(info using mman: $(call find_include,sys/mman)) + # some Linux installs have been known to have the include, but are + # missing librt (where the shm_ APIs are implemented on Linux) + # other OSes seem have these APIs implemented elsewhere + ifneq (,$(if $(findstring Linux,$(OSTYPE)),$(call find_lib,rt),OK)) + OS_CCDEFS += -DHAVE_SHM_OPEN + $(info using mman: $(call find_include,sys/mman)) + endif endif endif ifneq (,$(VIDEO_USEFUL)) ifeq (cygwin,$(OSTYPE)) - LIBEXTSAVE := $(LIBEXT) + LIBEXTSAVE := ${LIBEXT} LIBEXT = dll.a endif ifneq (,$(call find_include,SDL2/SDL)) @@ -713,7 +712,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) NETWORK_FEATURES = - dynamic networking support using $(OSNAME) provided libpcap components endif else - LIBEXTSAVE := $(LIBEXT) + LIBEXTSAVE := ${LIBEXT} LIBEXT = a ifneq (,$(call find_lib,$(PCAPLIB))) NETWORK_CCDEFS += -DUSE_NETWORK @@ -725,7 +724,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif else # On non-Linux platforms, we'll still try to provide deprecated support for libpcap in /usr/local - INCPATHSAVE := $(INCPATH) + INCPATHSAVE := ${INCPATH} ifeq (,$(findstring Linux,$(OSTYPE))) # Look for package built from tcpdump.org sources with default install target (or cygwin winpcap) INCPATH += /usr/local/include @@ -740,11 +739,11 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) ifneq (,$(shell grep pcap_compile $(PCAP_H_PATH) | grep const)) BPF_CONST_STRING = -DBPF_CONST_STRING endif - LIBEXTSAVE := $(LIBEXT) + LIBEXTSAVE := ${LIBEXT} # first check if binary - shared objects are available/installed in the linker known search paths ifneq (,$(call find_lib,$(PCAPLIB))) NETWORK_CCDEFS = -DUSE_SHARED -I$(dir $(call find_include,pcap)) $(BPF_CONST_STRING) - NETWORK_FEATURES = - dynamic networking support using libpcap components from www.tcpdump.org and locally installed libpcap.$(LIBEXT) + NETWORK_FEATURES = - dynamic networking support using libpcap components from www.tcpdump.org and locally installed libpcap.${LIBEXT} $(info using libpcap: $(call find_include,pcap)) else LIBPATH += /usr/local/lib @@ -771,7 +770,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) $(info *** Warning ***) endif else - $(error using libpcap: $(call find_include,pcap) missing $(PCAPLIB).$(LIBEXT)) + $(error using libpcap: $(call find_include,pcap) missing $(PCAPLIB).${LIBEXT}) endif NETWORK_LAN_FEATURES += PCAP endif @@ -867,7 +866,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) NETWORK_CCDEFS += -DUSE_NETWORK endif endif - ifeq (bsdtuntap,$(shell if $(TEST) -e /usr/include/net/if_tun.h -o -e /Library/Extensions/tap.kext; then echo bsdtuntap; fi)) + ifeq (bsdtuntap,$(shell if ${TEST} -e /usr/include/net/if_tun.h -o -e /Library/Extensions/tap.kext; then echo bsdtuntap; fi)) # Provide support for Tap networking on BSD platforms (including OS X) NETWORK_CCDEFS += -DHAVE_TAP_NETWORK -DHAVE_BSDTUNTAP NETWORK_LAN_FEATURES += TAP @@ -875,7 +874,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) NETWORK_CCDEFS += -DUSE_NETWORK endif endif - ifeq (slirp,$(shell if $(TEST) -e slirp_glue/sim_slirp.c; then echo slirp; fi)) + ifeq (slirp,$(shell if ${TEST} -e slirp_glue/sim_slirp.c; then echo slirp; fi)) NETWORK_CCDEFS += -Islirp -Islirp_glue -Islirp_glue/qemu -DHAVE_SLIRP_NETWORK -DUSE_SIMH_SLIRP_DEBUG slirp/*.c slirp_glue/*.c NETWORK_LAN_FEATURES += NAT(SLiRP) endif @@ -892,10 +891,10 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) endif NETWORK_OPT = $(NETWORK_CCDEFS) endif - ifneq (binexists,$(shell if $(TEST) -e BIN; then echo binexists; fi)) - MKDIRBIN = mkdir -p BIN + ifneq (binexists,$(shell if ${TEST} -e BIN/buildtools; then echo binexists; fi)) + MKDIRBIN = mkdir -p BIN/buildtools endif - ifeq (commit-id-exists,$(shell if $(TEST) -e .git-commit-id; then echo commit-id-exists; fi)) + ifeq (commit-id-exists,$(shell if ${TEST} -e .git-commit-id; then echo commit-id-exists; fi)) GIT_COMMIT_ID=$(shell grep 'SIM_GIT_COMMIT_ID' .git-commit-id | awk '{ print $$2 }') GIT_COMMIT_TIME=$(shell grep 'SIM_GIT_COMMIT_TIME' .git-commit-id | awk '{ print $$2 }') else @@ -930,14 +929,14 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) else #Win32 Environments (via MinGW32) GCC := gcc - GCC_Path := $(abspath $(dir $(word 1,$(wildcard $(addsuffix /$(GCC).exe,$(subst ;, ,$(PATH))))))) + GCC_Path := $(abspath $(dir $(word 1,$(wildcard $(addsuffix /${GCC}.exe,$(subst ;, ,${PATH})))))) ifeq (rename-build-support,$(shell if exist ..\windows-build-windows-build echo rename-build-support)) REMOVE_OLD_BUILD := $(shell if exist ..\windows-build rmdir/s/q ..\windows-build) FIXED_BUILD := $(shell move ..\windows-build-windows-build ..\windows-build >NUL) endif - GCC_VERSION = $(word 3,$(shell $(GCC) --version)) + GCC_VERSION = $(word 3,$(shell ${GCC} --version)) COMPILER_NAME = GCC Version: $(GCC_VERSION) - ifeq (,$(findstring ++,$(GCC))) + ifeq (,$(findstring ++,${GCC})) CC_STD = -std=gnu99 else CPP_BUILD = 1 @@ -948,8 +947,8 @@ else endif INCPATH = $(abspath $(wildcard $(GCC_Path)\..\include $(subst $(PATH_SEPARATOR), ,$(CPATH)) $(subst $(PATH_SEPARATOR), ,$(C_INCLUDE_PATH)))) LIBPATH = $(abspath $(wildcard $(GCC_Path)\..\lib $(subst :, ,$(LIBRARY_PATH)))) - $(info lib paths are: $(LIBPATH)) - $(info include paths are: $(INCPATH)) + $(info lib paths are: ${LIBPATH}) + $(info include paths are: ${INCPATH}) # Give preference to any MinGW provided threading (if available) ifneq (,$(call find_include,pthread)) PTHREADS_CCDEFS = -DUSE_READER_THREAD @@ -1082,7 +1081,7 @@ ifneq ($(DEBUG),) else ifneq (,$(findstring clang,$(COMPILER_NAME))$(findstring LLVM,$(COMPILER_NAME))) CFLAGS_O = -O2 -fno-strict-overflow - GCC_OPTIMIZERS_CMD = $(GCC) --help + GCC_OPTIMIZERS_CMD = ${GCC} --help NO_LTO = 1 else NO_LTO = 1 @@ -1096,7 +1095,7 @@ else GCC_MAJOR_VERSION = $(firstword $(subst ., ,$(GCC_VERSION))) ifneq (3,$(GCC_MAJOR_VERSION)) ifeq (,$(GCC_OPTIMIZERS_CMD)) - GCC_OPTIMIZERS_CMD = $(GCC) --help=optimizers + GCC_OPTIMIZERS_CMD = ${GCC} --help=optimizers endif endif ifneq (,$(GCC_OPTIMIZERS_CMD)) @@ -1133,13 +1132,13 @@ else endif ifneq (3,$(GCC_MAJOR_VERSION)) ifeq (,$(GCC_WARNINGS_CMD)) - GCC_WARNINGS_CMD = $(GCC) --help=warnings + GCC_WARNINGS_CMD = ${GCC} --help=warnings endif ifneq (,$(findstring -Wunused-result,$(shell $(GCC_WARNINGS_CMD)))) CFLAGS_O += -Wno-unused-result endif endif -ifneq (clean,$(MAKECMDGOALS)) +ifneq (clean,${MAKECMDGOALS}) BUILD_FEATURES := $(BUILD_FEATURES). $(COMPILER_NAME) $(info ***) $(info *** $(BUILD_SINGLE)Simulator$(BUILD_MULTIPLE) being built with:) @@ -1173,7 +1172,7 @@ ifneq ($(DONT_USE_READER_THREAD),) endif CC_OUTSPEC = -o $@ -CC := $(GCC) $(CC_STD) -U__STRICT_ANSI__ $(CFLAGS_G) $(CFLAGS_O) $(CFLAGS_GIT) $(CFLAGS_I) -DSIM_COMPILER="$(COMPILER_NAME)" -I . $(OS_CCDEFS) $(ROMS_OPT) +CC := ${GCC} $(CC_STD) -U__STRICT_ANSI__ $(CFLAGS_G) $(CFLAGS_O) $(CFLAGS_GIT) $(CFLAGS_I) -DSIM_COMPILER="$(COMPILER_NAME)" -DSIM_BUILD_TOOL=simh-makefile -I . $(OS_CCDEFS) $(ROMS_OPT) LDFLAGS := $(OS_LDFLAGS) $(NETWORK_LDFLAGS) $(LDFLAGS_O) # @@ -1278,7 +1277,7 @@ KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \ ${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rh.c \ ${KL10D}/kx10_rp.c ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c \ ${KL10D}/kx10_imp.c ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c \ - ${KL10D}/ka10_ch10.c ${KL10D}/kx10_lp.c + ${KL10D}/ka10_ch10.c ${KL10D}/kx10_lp.c ${KL10D}/kl10_nia.c KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT} PDP1D = PDP1 @@ -1585,7 +1584,7 @@ IBM1130 = ${IBM1130D}/ibm1130_cpu.c ${IBM1130D}/ibm1130_cr.c \ ${IBM1130D}/ibm1130_plot.c ${IBM1130D}/ibm1130_sca.c \ ${IBM1130D}/ibm1130_t2741.c IBM1130_OPT = -I ${IBM1130D} -ifneq ($(WIN32),) +ifneq (${WIN32},) IBM1130_OPT += -DGUI_SUPPORT -lgdi32 endif @@ -1910,7 +1909,7 @@ EXPERIMENTAL = cdc1700 experimental : $(EXPERIMENTAL) clean : -ifeq ($(WIN32),) +ifeq (${WIN32},) ${RM} -r ${BIN} else if exist BIN\*.exe del /q BIN\*.exe @@ -1924,7 +1923,7 @@ ifeq (agcc,$(findstring agcc,$(firstword $(CC)))) else ${CC} sim_BuildROMs.c $(CC_OUTSPEC) endif -ifeq ($(WIN32),) +ifeq (${WIN32},) $@ ${RM} $@ ifeq (Darwin,$(OSTYPE)) # remove Xcode's debugging symbols folder too @@ -2062,7 +2061,7 @@ microvax3900 : ${BIN}BuildROMs${EXE} ${BIN}microvax3900${EXE} ${BIN}microvax3900${EXE} : ${VAX} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} ${CC} ${VAX} ${SIM} ${VAX_OPT} $(CC_OUTSPEC) ${LDFLAGS} -ifeq ($(WIN32),) +ifeq (${WIN32},) cp ${BIN}microvax3900${EXE} ${BIN}vax${EXE} else copy $(@D)\microvax3900${EXE} $(@D)\vax${EXE} @@ -2219,7 +2218,7 @@ ibm1130 : ${BIN}ibm1130${EXE} ${BIN}ibm1130${EXE} : ${IBM1130} ifneq (1,$(CPP_BUILD)$(CPP_FORCE)) ${MKDIRBIN} -ifneq ($(WIN32),) +ifneq (${WIN32},) windres ${IBM1130D}/ibm1130.rc $(BIN)ibm1130.o ${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} $(BIN)ibm1130.o $(CC_OUTSPEC) ${LDFLAGS} del BIN\ibm1130.o diff --git a/scp.c b/scp.c index ac8921c..d0ea586 100644 --- a/scp.c +++ b/scp.c @@ -5893,6 +5893,15 @@ if (flag) { #undef S_str #undef S_xstr #endif +#endif +#if defined (SIM_BUILD_TOOL) +#define S_xstr(a) S_str(a) +#define S_str(a) #a + fprintf (st, "\n Build Tool: %s", S_xstr(SIM_BUILD_TOOL)); +#undef S_str +#undef S_xstr +#else + fprintf (st, "\n Build Tool: undefined (probably cmake)"); #endif fprintf (st, "\n Memory Access: %s Endian", sim_end ? "Little" : "Big"); fprintf (st, "\n Memory Pointer Size: %d bits", (int)sizeof(dptr)*8); From 34838dc38b6ae435b864bb90d5edbaedc380d26a Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 15 Jan 2020 08:25:25 -0500 Subject: [PATCH 80/98] KA10: Fixes to allow FE tty to work on Tops20 --- PDP10/kl10_fe.c | 97 +++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 40 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 9f5914c..e9e744f 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -144,7 +144,7 @@ #define PRI_EMSNA 014 /* Send all (ttys) */ #define PRI_EMDSC 015 /* Dataset connect */ #define PRI_EMHUD 016 /* Hang up dataset */ -#define PRI_EMACK 017 /* Acknowledge line */ +#define PRI_EMLBE 017 /* Acknowledge line */ #define PRI_EMXOF 020 /* XOFF line */ #define PRI_EMXON 021 /* XON line */ #define PRI_EMHLS 022 /* Here is line speeds */ @@ -165,6 +165,7 @@ #define PRI_EMCLK 007 /* Clock */ #define PRI_EMFED 010 /* Front end device */ #define PRI_CTYDV 000 /* Line number for CTY */ +#define NUM_DLS 5 /* Number of first DH Line */ #if KL_ITS /* ITS Timesharing protocol locations */ @@ -210,7 +211,7 @@ extern uint64 SW; /* Switch register */ char *pri_name[] = { "(0)", "EM2EI", "EM2TI", "EMSTR", "EMLNC", "EMRDS", "(6)", "EMHDS", "(10)", "EMRDT", "EMHDR", "EMFLO", "EMSNA", "EMDSC", "EMHUD", - "EMACK", "EMXOF", "EMXON", "EMHLS", "EMHLA", "EMRBI", "EMAKA", "EMTDO", + "EMLBE", "EMXOF", "EMXON", "EMHLS", "EMHLA", "EMRBI", "EMAKA", "EMTDO", "EMEDR", "EMLDR", "EMLDV" }; #if KL_ITS @@ -890,7 +891,7 @@ dte_function(UNIT *uptr) break; case PRI_EM2TI: /* Replay to initial message. */ - case PRI_EMACK: /* Acknowledge line */ + case PRI_EMLBE: /* Acknowledge line */ /* Should never get these */ break; case PRI_EMHDR: /* Here is date and time */ @@ -922,7 +923,7 @@ dte_function(UNIT *uptr) if (cmd->dev == PRI_EMLPT) { if (!sim_is_active(&lp20_unit)) sim_activate(&lp20_unit, 1000); - lp20_unit.LPST &= ~EOFFLG; +// lp20_unit.LPST &= ~EOFFLG; while (cmd->dptr < cmd->dcnt) { if (((lp20_queue.in_ptr + 1) & 0xff) == lp20_queue.out_ptr) return; @@ -947,7 +948,7 @@ dte_function(UNIT *uptr) struct _buffer *otty; if (ln == PRI_CTYDV) goto cty; - ln -= 2; + ln -= NUM_DLS; if (ln > 0 && ln >= tty_desc.lines) break; otty = &tty_out[ln]; @@ -1008,7 +1009,7 @@ cty: ch = (int32)(cmd->data[cmd->dptr >> 1]); ln = (ch >> 8); ch &= 0177; - if (ch != 0 && ln == 0) { + if (ch != 0 && ln == PRI_CTYDV) { if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) return; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); @@ -1016,9 +1017,9 @@ cty: cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; } else - if (ch != 0 && ln >= 2 && ln <= tty_desc.lines) { + if (ch != 0 && ln >= NUM_DLS && ln <= tty_desc.lines) { struct _buffer *otty; - ln -= 2; + ln -= NUM_DLS; otty = &tty_out[ln]; if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) return; @@ -1111,7 +1112,8 @@ cty: } lp20_unit.LPCNT = ln; // lp20_unit.LPST |= ACKFLG; - if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) + data1[0] = 0; + if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) sim_activate(uptr, 1000); } break; @@ -1127,7 +1129,8 @@ cty: // lp20_unit.LPST |= ACKFLG; for (ln = 0; ln < 256; ln++) sim_debug(DEBUG_DETAIL, &lp20_dev, "LP20 RAM %02x => %04x\n", ln, lp20_ram[ln]); - if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) + data1[0] = 0; + if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) sim_activate(uptr, 1000); } break; @@ -1137,13 +1140,20 @@ cty: #if (NUM_DEVS_TTY > 0) case PRI_EMFLO: /* Flush output */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = cmd->sdev - 2; - if (ln == -2) + int ln = cmd->data[0] - NUM_DLS; + + sim_debug(DEBUG_DETAIL, &dte_dev, "Flush out %d %o\n", ln, cmd->data[0]); + if (ln == (NUM_DLS - PRI_CTYDV)) cty_out.in_ptr = cty_out.out_ptr = 0; else tty_out[ln].in_ptr = tty_out[ln].out_ptr = 0; - data1[0] = cmd->sdev << 8; - if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, data1) == 0) + data1[0] = (ln + NUM_DLS) | (PRI_EMDLS << 8); + if (dte_queue(PRI_EMLBE, PRI_EMDLS, 1, data1) == 0) + return; + } + if ((cmd->dev & 0377) == PRI_EMLPT) { + data1[0] = cmd->data[0]; + if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) return; } break; @@ -1151,28 +1161,34 @@ cty: break; case PRI_EMHUD: /* Hang up dataset */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = cmd->sdev - 2; - TMLN *lp = &tty_ldsc[ln]; - tmxr_linemsg (lp, "\r\nLine Hangup\r\n"); - tmxr_reset_ln(lp); - tty_connect[ln] = 0; + int ln = cmd->sdev - NUM_DLS; + if (ln >= 0) { + TMLN *lp = &tty_ldsc[ln]; + tmxr_linemsg (lp, "\r\nLine Hangup\r\n"); + tmxr_reset_ln(lp); + tty_connect[ln] = 0; + } } break; case PRI_EMXOF: /* XOFF line */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = cmd->sdev - 2; - tty_ldsc[ln].rcve = 0; + int ln = cmd->sdev - NUM_DLS; + if (ln >= 0) { + tty_ldsc[ln].rcve = 0; + } } break; case PRI_EMXON: /* XON line */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = cmd->sdev - 2; - tty_ldsc[ln].rcve = 1; + int ln = cmd->sdev - NUM_DLS; + if (ln >= 0) { + tty_ldsc[ln].rcve = 1; + } } break; case PRI_EMHLS: /* Here is line speeds */ if ((cmd->dev & 0377) == PRI_EMDLS) { - int ln = cmd->sdev - 2; + int ln = cmd->sdev - NUM_DLS; sim_debug(DEBUG_DETAIL, &tty_dev, "HDL %o o=%d i=%d %o\n", ln, cmd->data[0], cmd->data[1], cmd->data[2]); } @@ -1185,7 +1201,7 @@ cty: case PRI_EMEDR: /* Enable/Disable line */ if (cmd->dev == PRI_EMDH1) { /* Zero means enable, no-zero means disable */ - tty_enable = !cmd->data[0]; + tty_enable = !((cmd->data[0] >> 8) & 0xff); sim_debug(DEBUG_DETAIL, &dte_dev, "CTY enable %x\n", tty_enable); if (tty_enable) { sim_activate(&tty_unit[0], 1000); @@ -1399,7 +1415,7 @@ dte_input() /* Check if CTY done with input */ if (cty_done) { data1 = PRI_CTYDV; - if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, &data1) == 0) + if (dte_queue(PRI_EMLBE, PRI_EMDLS, 1, &data1) == 0) return; cty_done--; } @@ -1424,7 +1440,7 @@ dte_input() while (tty_in[ln].in_ptr != tty_in[ln].out_ptr) { ch = tty_in[ln].buff[tty_in[ln].out_ptr]; tty_in[ln].out_ptr = (tty_in[ln].out_ptr + 1) & 0xff; - dataq[n++] = ((ln + 2) << 8) | ch; + dataq[n++] = ((ln + NUM_DLS) << 8) | ch; if (n == 32) { if (dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) return; @@ -1437,8 +1453,8 @@ dte_input() return; n = 0; for (ln = 0; ln < tty_desc.lines; ln++) { + data1 = (ln + NUM_DLS) | (PRI_EMDLS << 8); if (tty_connect[ln] != tty_ldsc[ln].conn) { - data1 = ln + 2; if (tty_ldsc[ln].conn) n = PRI_EMDSC; else @@ -1448,8 +1464,7 @@ dte_input() tty_connect[ln] = tty_ldsc[ln].conn; } if (tty_done[ln]) { - data1 = ln + 2; - if (dte_queue(PRI_EMACK, PRI_EMDLS, 1, &data1) == 0) + if (dte_queue(PRI_EMLBE, PRI_EMDLS, 1, &data1) == 0) return; tty_done[ln] = 0; } @@ -1827,7 +1842,7 @@ t_stat lp20_svc (UNIT *uptr) if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; - if (uptr->LPST & HDSFLG) { + if (dte_dev.flags & TYPE_RSX20 && uptr->LPST & HDSFLG) { data1[0] = 0; data1[1] = (uptr->LINE == 0) ? 0x1: 0; @@ -1838,12 +1853,12 @@ t_stat lp20_svc (UNIT *uptr) data1[2] = 0110200; //0100220; if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 4, data1) == 0) sim_activate(uptr, 1000); - if ((uptr->LPST & (EOFFLG)) == (EOFFLG)) { - data1[0] = 0; - if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) - sim_activate(uptr, 1000); +// if ((uptr->LPST & (EOFFLG)) == (EOFFLG)) { + // data1[0] = (PRI_EMLPT << 8); + // if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) + // sim_activate(uptr, 1000); // uptr->LPST &= ~ACKFLG; - } + // } uptr->LPST &= ~(HDSFLG|EOFFLG); } @@ -1921,11 +1936,13 @@ t_stat lp20_svc (UNIT *uptr) } if (lp20_queue.out_ptr == lp20_queue.in_ptr) { data1[0] = 0; - if (dte_queue(PRI_EMACK, PRI_EMLPT, 1, data1) == 0) - sim_activate(uptr, 1000); - if (uptr->LINE == 0) { - uptr->LPST |= HDSFLG; + if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) sim_activate(uptr, 1000); + if (dte_dev.flags & TYPE_RSX20) { + if (uptr->LINE == 0) { + uptr->LPST |= HDSFLG; + sim_activate(uptr, 1000); + } } } return SCPE_OK; From a6e87f40b8c2acd5ef7f45a87e6f5899114d7b30 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Mon, 20 Jan 2020 13:43:47 -0500 Subject: [PATCH 81/98] SCP: Updated to current. --- makefile | 1284 ++++++++++++++++++++++++++++++---------------- scp.c | 301 +++++++++-- scp.h | 6 +- sim_BuildROMs.c | 9 +- sim_card.c | 18 +- sim_console.c | 4 +- sim_defs.h | 12 +- sim_ether.c | 14 +- sim_fio.c | 25 +- sim_frontpanel.c | 2 +- 10 files changed, 1135 insertions(+), 540 deletions(-) diff --git a/makefile b/makefile index bcd15c2..48e17fb 100644 --- a/makefile +++ b/makefile @@ -99,7 +99,7 @@ endif BUILD_SINGLE := ${MAKECMDGOALS} $(BLANK_SUFFIX) BUILD_MULTIPLE_VERB = is # building the pdp1, pdp11, tx-0, or any microvax simulator could use video support -ifneq (,$(or $(findstring XXpdp1XX,$(addsuffix XX,$(addprefix XX,${MAKECMDGOALS}))),$(findstring pdp11,${MAKECMDGOALS}),$(findstring tx-0,${MAKECMDGOALS}),$(findstring microvax1,${MAKECMDGOALS}),$(findstring microvax2,${MAKECMDGOALS}),$(findstring microvax3900,${MAKECMDGOALS}),$(findstring XXvaxXX,$(addsuffix XX,$(addprefix XX,${MAKECMDGOALS}))))) +ifneq (,$(or $(findstring XXpdp1XX,$(addsuffix XX,$(addprefix XX,${MAKECMDGOALS}))),$(findstring pdp11,${MAKECMDGOALS}),$(findstring tx-0,${MAKECMDGOALS}),$(findstring microvax1,${MAKECMDGOALS}),$(findstring microvax2,${MAKECMDGOALS}),$(findstring microvax3900,${MAKECMDGOALS}),$(findstring microvax2000,${MAKECMDGOALS}),$(findstring vaxstation3100,${MAKECMDGOALS}),$(findstring XXvaxXX,$(addsuffix XX,$(addprefix XX,${MAKECMDGOALS}))))) VIDEO_USEFUL = true endif # building the besm6 needs both video support and fontfile support @@ -115,8 +115,12 @@ endif ifneq (,$(or $(findstring pdp10-ka,${MAKECMDGOALS}),$(findstring pdp10-ki,${MAKECMDGOALS},$(findstring pdp10-kl,${MAKECMDGOALS})))) NETWORK_USEFUL = true endif +# building the PDP-7 needs video support +ifneq (,$(findstring pdp7,${MAKECMDGOALS})) + VIDEO_USEFUL = true +endif # building the pdp11, pdp10, or any vax simulator could use networking support -ifneq (,$(or $(findstring pdp11,${MAKECMDGOALS}),$(findstring pdp10,${MAKECMDGOALS}),$(findstring vax,${MAKECMDGOALS}),$(findstring all,${MAKECMDGOALS}))) +ifneq (,$(or $(findstring pdp11,${MAKECMDGOALS}),$(findstring pdp10,${MAKECMDGOALS}),$(findstring vax,${MAKECMDGOALS}),$(findstring 3b2,${MAKECMDGOALS})$(findstring all,${MAKECMDGOALS}))) NETWORK_USEFUL = true ifneq (,$(findstring all,${MAKECMDGOALS})) BUILD_MULTIPLE = s @@ -596,6 +600,7 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin) DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/sim_ws.c DISPLAYVT = ${DISPLAYD}/vt11.c DISPLAY340 = ${DISPLAYD}/type340.c + DISPLAYNG = ${DISPLAYD}/ng.c DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS) $(info using libSDL2: $(call find_include,SDL2/SDL)) ifeq (Darwin,$(OSTYPE)) @@ -620,6 +625,7 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin) DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/sim_ws.c DISPLAYVT = ${DISPLAYD}/vt11.c DISPLAY340 = ${DISPLAYD}/type340.c + DISPLAYNG = ${DISPLAYD}/ng.c DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS) $(info using libSDL: $(call find_include,SDL/SDL)) ifeq (Darwin,$(OSTYPE)) @@ -639,21 +645,21 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin) ifeq (Darwin,$(OSTYPE)) $(info *** Info *** Install the MacPorts libSDL2 package to provide this) $(info *** Info *** functionality for your OS X system:) - $(info *** Info *** # port install libsdl2) + $(info *** Info *** # port install libsdl2 libpng zlib) ifeq (/usr/local/bin/brew,$(shell which brew)) $(info *** Info ***) $(info *** Info *** OR) $(info *** Info ***) $(info *** Info *** Install the HomeBrew libSDL2 package to provide this) $(info *** Info *** functionality for your OS X system:) - $(info *** Info *** $$ brew install sdl2) + $(info *** Info *** $$ brew install sdl2 libpng zlib) endif else ifneq (,$(and $(findstring Linux,$(OSTYPE)),$(call find_exe,apt-get))) $(info *** Info *** Install the development components of libSDL or libSDL2) $(info *** Info *** packaged for your operating system distribution for) $(info *** Info *** your Linux system:) - $(info *** Info *** $$ sudo apt-get install libsdl2-dev) + $(info *** Info *** $$ sudo apt-get install libsdl2-dev libpng-dev) $(info *** Info *** or) $(info *** Info *** $$ sudo apt-get install libsdl-dev) else @@ -892,7 +898,7 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin) NETWORK_OPT = $(NETWORK_CCDEFS) endif ifneq (binexists,$(shell if ${TEST} -e BIN/buildtools; then echo binexists; fi)) - MKDIRBIN = mkdir -p BIN/buildtools + MKDIRBIN = @mkdir -p BIN/buildtools endif ifeq (commit-id-exists,$(shell if ${TEST} -e .git-commit-id; then echo commit-id-exists; fi)) GIT_COMMIT_ID=$(shell grep 'SIM_GIT_COMMIT_ID' .git-commit-id | awk '{ print $$2 }') @@ -981,9 +987,18 @@ else ifneq (,$(VIDEO_USEFUL)) SDL_INCLUDE = $(word 1,$(shell dir /b /s ..\windows-build\libSDL\SDL.h)) ifeq (SDL.h,$(findstring SDL.h,$(SDL_INCLUDE))) - VIDEO_CCDEFS += -DHAVE_LIBSDL -I$(abspath $(dir $(SDL_INCLUDE))) - VIDEO_LDFLAGS += -lSDL2 -L$(abspath $(dir $(SDL_INCLUDE))\..\lib) + VIDEO_CCDEFS += -DHAVE_LIBSDL -DUSE_SIM_VIDEO -I$(abspath $(dir $(SDL_INCLUDE))) + ifneq ($(DEBUG),) + VIDEO_LDFLAGS += $(abspath $(dir $(SDL_INCLUDE))\..\..\..\lib\lib-VC2008\Debug)/SDL2.lib + else + VIDEO_LDFLAGS += $(abspath $(dir $(SDL_INCLUDE))\..\..\..\lib\lib-VC2008\Release)/SDL2.lib + endif VIDEO_FEATURES = - video capabilities provided by libSDL2 (Simple Directmedia Layer) + DISPLAYL = ${DISPLAYD}/display.c $(DISPLAYD)/sim_ws.c + DISPLAYVT = ${DISPLAYD}/vt11.c + DISPLAY340 = ${DISPLAYD}/type340.c + DISPLAYNG = ${DISPLAYD}/ng.c + DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS) else $(info ***********************************************************************) $(info ***********************************************************************) @@ -1001,12 +1016,41 @@ else OS_CCDEFS += -fms-extensions $(PTHREADS_CCDEFS) OS_LDFLAGS += -lm -lwsock32 -lwinmm $(PTHREADS_LDFLAGS) EXE = .exe - ifneq (binexists,$(shell if exist BIN echo binexists)) - MKDIRBIN = if not exist BIN mkdir BIN + ifneq (clean,${MAKECMDGOALS}) + ifneq (buildtoolsexists,$(shell if exist BIN\buildtools (echo buildtoolsexists) else (mkdir BIN\buildtools))) + MKDIRBIN= + endif endif ifneq ($(USE_NETWORK),) NETWORK_OPT += -DUSE_SHARED endif + ifeq (git-repo,$(shell if exist .git echo git-repo)) + GIT_PATH := $(shell where git) + ifeq (,$(GIT_PATH)) + $(error building using a git repository, but git is not available) + endif + ifeq (commit-id-exists,$(shell if exist .git-commit-id echo commit-id-exists)) + CURRENT_GIT_COMMIT_ID=$(shell for /F "tokens=2" %%i in ("$(shell findstr /C:"SIM_GIT_COMMIT_ID" .git-commit-id)") do echo %%i) + ACTUAL_GIT_COMMIT_ID=$(strip $(shell git log -1 --pretty=%H)) + ifneq ($(CURRENT_GIT_COMMIT_ID),$(ACTUAL_GIT_COMMIT_ID)) + NEED_COMMIT_ID = need-commit-id + # make sure that the invalidly formatted .git-commit-id file wasn't generated + # by legacy git hooks which need to be removed. + $(shell if exist .git\hooks\post-checkout del .git\hooks\post-checkout) + $(shell if exist .git\hooks\post-commit del .git\hooks\post-commit) + $(shell if exist .git\hooks\post-merge del .git\hooks\post-merge) + endif + else + NEED_COMMIT_ID = need-commit-id + endif + ifeq (need-commit-id,$(NEED_COMMIT_ID)) + commit_id=$(shell git log -1 --pretty=%H) + isodate=$(shell git log -1 --pretty=%ai) + commit_time=$(word 1,$(isodate))T$(word 2,$(isodate))$(word 3,$(isodate)) + $(shell echo SIM_GIT_COMMIT_ID $(commit_id)>.git-commit-id) + $(shell echo SIM_GIT_COMMIT_TIME $(commit_time)>>.git-commit-id) + endif + endif ifneq (,$(shell if exist .git-commit-id echo git-commit-id)) GIT_COMMIT_ID=$(shell for /F "tokens=2" %%i in ("$(shell findstr /C:"SIM_GIT_COMMIT_ID" .git-commit-id)") do echo %%i) GIT_COMMIT_TIME=$(shell for /F "tokens=2" %%i in ("$(shell findstr /C:"SIM_GIT_COMMIT_TIME" .git-commit-id)") do echo %%i) @@ -1017,32 +1061,15 @@ else endif endif ifneq (windows-build,$(shell if exist ..\windows-build\README.md echo windows-build)) - $(info ***********************************************************************) - $(info ***********************************************************************) - $(info ** This build is operating without the required windows-build **) - $(info ** components and therefore will produce less than optimal **) - $(info ** simulator operation and features. **) - $(info ** Download the file: **) - $(info ** https://github.com/simh/windows-build/archive/windows-build.zip **) - $(info ** Extract the windows-build-windows-build folder it contains to **) - $(info ** $(abspath ..\) **) - $(info ***********************************************************************) - $(info ***********************************************************************) - $(info .) - else - # Version check on windows-build - WINDOWS_BUILD = $(word 2,$(shell findstr WINDOWS-BUILD ..\windows-build\Windows-Build_Versions.txt)) - ifeq (,$(WINDOWS_BUILD)) - WINDOWS_BUILD = 00000000 - endif - ifneq (,$(or $(shell if 20150412 GTR $(WINDOWS_BUILD) echo old-windows-build),$(and $(shell if 20171112 GTR $(WINDOWS_BUILD) echo old-windows-build),$(findstring pthreadGC2,$(PTHREADS_LDFLAGS))))) - $(info .) - $(info windows-build components at: $(abspath ..\windows-build)) - $(info .) + ifneq (,$(GIT_PATH)) + $(info Cloning the windows-build dependencies into $(abspath ..)/windows-build) + $(shell git clone https://github.com/simh/windows-build ../windows-build) + else $(info ***********************************************************************) $(info ***********************************************************************) - $(info ** This currently available windows-build components are out of **) - $(info ** date. For the most functional and stable features you shoud **) + $(info ** This build is operating without the required windows-build **) + $(info ** components and therefore will produce less than optimal **) + $(info ** simulator operation and features. **) $(info ** Download the file: **) $(info ** https://github.com/simh/windows-build/archive/windows-build.zip **) $(info ** Extract the windows-build-windows-build folder it contains to **) @@ -1051,10 +1078,45 @@ else $(info ***********************************************************************) $(info .) endif + else + # Version check on windows-build + WINDOWS_BUILD = $(word 2,$(shell findstr WINDOWS-BUILD ..\windows-build\Windows-Build_Versions.txt)) + ifeq (,$(WINDOWS_BUILD)) + WINDOWS_BUILD = 00000000 + endif + ifneq (,$(or $(shell if 20190124 GTR $(WINDOWS_BUILD) echo old-windows-build),$(and $(shell if 20171112 GTR $(WINDOWS_BUILD) echo old-windows-build),$(findstring pthreadGC2,$(PTHREADS_LDFLAGS))))) + $(info .) + $(info windows-build components at: $(abspath ..\windows-build)) + $(info .) + $(info ***********************************************************************) + $(info ***********************************************************************) + $(info ** This currently available windows-build components are out of **) + ifneq (,$(GIT_PATH)) + $(info ** date. You need to update to the latest windows-build **) + $(info ** dependencies by executing these commands: **) + $(info ** **) + $(info ** > cd ..\windows-build **) + $(info ** > git pull **) + $(info ** **) + $(info ***********************************************************************) + $(info ***********************************************************************) + $(error .) + else + $(info ** date. For the most functional and stable features you shoud **) + $(info ** Download the file: **) + $(info ** https://github.com/simh/windows-build/archive/windows-build.zip **) + $(info ** Extract the windows-build-windows-build folder it contains to **) + $(info ** $(abspath ..\) **) + $(info ***********************************************************************) + $(info ***********************************************************************) + $(info .) + $(error Update windows-build) + endif + endif ifeq (pcre,$(shell if exist ..\windows-build\PCRE\include\pcre.h echo pcre)) - OS_CCDEFS += -DHAVE_PCREPOSIX_H -DPCRE_STATIC -I$(abspath ../windows-build/PCRE/include) - OS_LDFLAGS += -lpcreposix -lpcre -L../windows-build/PCRE/lib/ - $(info using libpcreposix: $(abspath ../windows-build/PCRE/lib/pcreposix.a) $(abspath ../windows-build/PCRE/include/pcreposix.h)) + OS_CCDEFS += -DHAVE_PCRE_H -DPCRE_STATIC -I$(abspath ../windows-build/PCRE/include) + OS_LDFLAGS += -lpcre -L../windows-build/PCRE/lib/ + $(info using libpcre: $(abspath ../windows-build/PCRE/lib/pcre.a) $(abspath ../windows-build/PCRE/include/pcre.h)) endif ifeq (slirp,slirp) NETWORK_OPT += -Islirp -Islirp_glue -Islirp_glue/qemu -DHAVE_SLIRP_NETWORK -DUSE_SIMH_SLIRP_DEBUG slirp/*.c slirp_glue/*.c -lIphlpapi @@ -1134,9 +1196,6 @@ ifneq (3,$(GCC_MAJOR_VERSION)) ifeq (,$(GCC_WARNINGS_CMD)) GCC_WARNINGS_CMD = ${GCC} --help=warnings endif - ifneq (,$(findstring -Wunused-result,$(shell $(GCC_WARNINGS_CMD)))) - CFLAGS_O += -Wno-unused-result - endif endif ifneq (clean,${MAKECMDGOALS}) BUILD_FEATURES := $(BUILD_FEATURES). $(COMPILER_NAME) @@ -1165,132 +1224,43 @@ endif ifneq ($(DONT_USE_ROMS),) ROMS_OPT = -DDONT_USE_INTERNAL_ROM else - BUILD_ROMS = ${BIN}BuildROMs${EXE} + BUILD_ROMS = ${BIN}buildtools/BuildROMs${EXE} endif ifneq ($(DONT_USE_READER_THREAD),) NETWORK_OPT += -DDONT_USE_READER_THREAD endif CC_OUTSPEC = -o $@ -CC := ${GCC} $(CC_STD) -U__STRICT_ANSI__ $(CFLAGS_G) $(CFLAGS_O) $(CFLAGS_GIT) $(CFLAGS_I) -DSIM_COMPILER="$(COMPILER_NAME)" -DSIM_BUILD_TOOL=simh-makefile -I . $(OS_CCDEFS) $(ROMS_OPT) -LDFLAGS := $(OS_LDFLAGS) $(NETWORK_LDFLAGS) $(LDFLAGS_O) +CC := ${GCC} ${CC_STD} -U__STRICT_ANSI__ ${CFLAGS_G} ${CFLAGS_O} ${CFLAGS_GIT} ${CFLAGS_I} -DSIM_COMPILER="${COMPILER_NAME}" -DSIM_BUILD_TOOL=simh-makefile -I . ${OS_CCDEFS} ${ROMS_OPT} +LDFLAGS := ${OS_LDFLAGS} ${NETWORK_LDFLAGS} ${LDFLAGS_O} # # Common Libraries # BIN = BIN/ -SIM = scp.c sim_console.c sim_fio.c sim_timer.c sim_sock.c \ - sim_tmxr.c sim_ether.c sim_tape.c sim_disk.c sim_serial.c \ - sim_video.c sim_imd.c sim_card.c +SIMHD = . +SIM = ${SIMHD}/scp.c ${SIMHD}/sim_console.c ${SIMHD}/sim_fio.c \ + ${SIMHD}/sim_timer.c ${SIMHD}/sim_sock.c ${SIMHD}/sim_tmxr.c \ + ${SIMHD}/sim_ether.c ${SIMHD}/sim_tape.c ${SIMHD}/sim_disk.c \ + ${SIMHD}/sim_serial.c ${SIMHD}/sim_video.c ${SIMHD}/sim_imd.c \ + ${SIMHD}/sim_card.c + +DISPLAYD = ${SIMHD}/display + +SCSI = ${SIMHD}/sim_scsi.c -DISPLAYD = display - # # Emulator source files and compile time options # -SEL32D = SEL32 -# -SEL32 = ${SEL32D}/sel32_cpu.c ${SEL32D}/sel32_sys.c ${SEL32D}/sel32_defs.h \ - ${SEL32D}/sel32_chan.c ${SEL32D}/sel32_iop.c ${SEL32D}/sel32_com.c \ - ${SEL32D}/sel32_con.c ${SEL32D}/sel32_clk.c ${SEL32D}/sel32_mt.c \ - ${SEL32D}/sel32_lpr.c ${SEL32D}/sel32_scfi.c ${SEL32D}/sel32_fltpt.c \ - ${SEL32D}/sel32_disk.c -SEL32_OPT = -I $(SEL32D) -DSEL32 -#SEL32_OPT = -I $(SEL32D) -DUSE_INT64 -DSEL32 - -ICL1900D = ICL1900 -ICL1900 = ${ICL1900D}/icl1900_cpu.c ${ICL1900D}/icl1900_sys.c \ - ${ICL1900D}/icl1900_stdio.c ${ICL1900D}/icl1900_cty.c \ - ${ICL1900D}/icl1900_tr.c ${ICL1900D}/icl1900_tp.c \ - ${ICL1900D}/icl1900_cr.c ${ICL1900D}/icl1900_cp.c \ - ${ICL1900D}/icl1900_lp.c ${ICL1900D}/icl1900_mta.c \ - ${ICL1900D}/icl1900_mt.c ${ICL1900D}/icl1900_eds8.c - -ICL1900_OPT = -I $(ICL1900D) -DICL1900 -DUSE_SIM_CARD - -IBM360D = IBM360 -IBM360 = ${IBM360D}/ibm360_cpu.c ${IBM360D}/ibm360_sys.c \ - ${IBM360D}/ibm360_con.c ${IBM360D}/ibm360_chan.c \ - ${IBM360D}/ibm360_cdr.c ${IBM360D}/ibm360_cdp.c \ - ${IBM360D}/ibm360_mt.c ${IBM360D}/ibm360_lpr.c \ - ${IBM360D}/ibm360_dasd.c ${IBM360D}/ibm360_com.c -IBM360_OPT = -I $(IBM360D) -DIBM360 -DUSE_64BIT -DUSE_SIM_CARD -IBM360_OPT32 = -I $(IBM360D) -DIBM360 -DUSE_SIM_CARD - -PDP6D = PDP10 -ifneq (,$(DISPLAY_OPT)) - PDP6_DISPLAY_OPT = -endif -PDP6 = ${PDP6D}/kx10_cpu.c ${PDP6D}/kx10_sys.c ${PDP6D}/kx10_cty.c \ - ${PDP6D}/kx10_lp.c ${PDP6D}/kx10_pt.c ${PDP6D}/kx10_cr.c \ - ${PDP6D}/kx10_cp.c ${PDP6D}/pdp6_dct.c ${PDP6D}/pdp6_dtc.c \ - ${PDP6D}/pdp6_mtc.c ${PDP6D}/pdp6_dsk.c ${PDP6D}/pdp6_dcs.c \ - ${PDP6D}/kx10_dpy.c ${DISPLAYL} $(DISPLAY340) -PDP6_OPT = -DPDP6=1 -DUSE_INT64 -I $(PDP6D) -DUSE_SIM_CARD $(DISPLAY_OPT) $(PDP6_DISPLAY_OPT) - -KA10D = PDP10 -ifneq (,$(DISPLAY_OPT)) - KA10_DISPLAY_OPT = -endif -KA10 = ${KA10D}/kx10_cpu.c ${KA10D}/kx10_sys.c ${KA10D}/kx10_df.c \ - ${KA10D}/kx10_dp.c ${KA10D}/kx10_mt.c ${KA10D}/kx10_cty.c \ - ${KA10D}/kx10_lp.c ${KA10D}/kx10_pt.c ${KA10D}/kx10_dc.c \ - ${KA10D}/kx10_rp.c ${KA10D}/kx10_rc.c ${KA10D}/kx10_dt.c \ - ${KA10D}/kx10_dk.c ${KA10D}/kx10_cr.c ${KA10D}/kx10_cp.c \ - ${KA10D}/kx10_tu.c ${KA10D}/kx10_rs.c ${KA10D}/ka10_pd.c \ - ${KA10D}/kx10_rh.c ${KA10D}/kx10_imp.c ${KA10D}/ka10_tk10.c \ - ${KA10D}/ka10_mty.c ${KA10D}/ka10_imx.c ${KA10D}/ka10_ch10.c \ - ${KA10D}/ka10_stk.c ${KA10D}/ka10_ten11.c ${KA10D}/ka10_auxcpu.c \ - $(KA10D)/ka10_pmp.c ${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c \ - ${KA10D}/pdp6_dtc.c ${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c \ - ${KA10D}/pdp6_dcs.c ${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c \ - ${PDP10D}/ka10_ai.c ${KA10D}/ka10_iii.c ${DISPLAYL} $(DISPLAY340) -KA10_OPT = -DKA=1 -DUSE_INT64 -I $(KA10D) -DUSE_SIM_CARD ${NETWORK_OPT} $(DISPLAY_OPT) $(KA10_DISPLAY_OPT) -ifneq ($(PANDA_LIGHTS),) -# ONLY for Panda display. -KA10_OPT += -DPANDA_LIGHTS -KA10 += ${KA10D}/ka10_lights.c -KA10_LDFLAGS += -lusb-1.0 -endif - -KI10D = PDP10 -ifneq (,$(DISPLAY_OPT)) -KI10_DISPLAY_OPT = -endif -KI10 = ${KI10D}/kx10_cpu.c ${KI10D}/kx10_sys.c ${KI10D}/kx10_df.c \ - ${KI10D}/kx10_dp.c ${KI10D}/kx10_mt.c ${KI10D}/kx10_cty.c \ - ${KI10D}/kx10_lp.c ${KI10D}/kx10_pt.c ${KI10D}/kx10_dc.c \ - ${KI10D}/kx10_rh.c ${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c \ - ${KI10D}/kx10_dt.c ${KI10D}/kx10_dk.c ${KI10D}/kx10_cr.c \ - ${KI10D}/kx10_cp.c ${KI10D}/kx10_tu.c ${KI10D}/kx10_rs.c \ - ${KI10D}/kx10_imp.c ${KI10D}/kx10_dpy.c ${DISPLAYL} $(DISPLAY340) -KI10_OPT = -DKI=1 -DUSE_INT64 -I $(KI10D) -DUSE_SIM_CARD ${NETWORK_OPT} $(DISPLAY_OPT) $(KI10_DISPLAY_OPT) -ifneq ($(PANDA_LIGHTS),) -# ONLY for Panda display. -KI10_OPT += -DPANDA_LIGHTS -KI10 += ${KA10D}/ka10_lights.c -KI10_LDFLAGS = -lusb-1.0 -endif - -KL10D = PDP10 -KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \ - ${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rh.c \ - ${KL10D}/kx10_rp.c ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c \ - ${KL10D}/kx10_imp.c ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c \ - ${KL10D}/ka10_ch10.c ${KL10D}/kx10_lp.c ${KL10D}/kl10_nia.c -KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT} - -PDP1D = PDP1 -ifneq (,$(DISPLAY_OPT)) - PDP1_DISPLAY_OPT = -DDISPLAY_TYPE=DIS_TYPE30 -DPIX_SCALE=RES_HALF -endif +PDP1D = ${SIMHD}/PDP1 +PDP1_DISPLAY_OPT = -DDISPLAY_TYPE=DIS_TYPE30 -DPIX_SCALE=RES_HALF PDP1 = ${PDP1D}/pdp1_lp.c ${PDP1D}/pdp1_cpu.c ${PDP1D}/pdp1_stddev.c \ ${PDP1D}/pdp1_sys.c ${PDP1D}/pdp1_dt.c ${PDP1D}/pdp1_drm.c \ ${PDP1D}/pdp1_clk.c ${PDP1D}/pdp1_dcs.c ${PDP1D}/pdp1_dpy.c ${DISPLAYL} -PDP1_OPT = -I ${PDP1D} $(DISPLAY_OPT) $(PDP1_DISPLAY_OPT) +PDP1_OPT = -I ${PDP1D} ${DISPLAY_OPT} $(PDP1_DISPLAY_OPT) -NOVAD = NOVA +NOVAD = ${SIMHD}/NOVA NOVA = ${NOVAD}/nova_sys.c ${NOVAD}/nova_cpu.c ${NOVAD}/nova_dkp.c \ ${NOVAD}/nova_dsk.c ${NOVAD}/nova_lp.c ${NOVAD}/nova_mta.c \ ${NOVAD}/nova_plt.c ${NOVAD}/nova_pt.c ${NOVAD}/nova_clk.c \ @@ -1305,20 +1275,24 @@ ECLIPSE = ${NOVAD}/eclipse_cpu.c ${NOVAD}/eclipse_tt.c ${NOVAD}/nova_sys.c \ ECLIPSE_OPT = -I ${NOVAD} -DECLIPSE -PDP18BD = PDP18B +PDP18BD = ${SIMHD}/PDP18B PDP18B = ${PDP18BD}/pdp18b_dt.c ${PDP18BD}/pdp18b_drm.c ${PDP18BD}/pdp18b_cpu.c \ ${PDP18BD}/pdp18b_lp.c ${PDP18BD}/pdp18b_mt.c ${PDP18BD}/pdp18b_rf.c \ ${PDP18BD}/pdp18b_rp.c ${PDP18BD}/pdp18b_stddev.c ${PDP18BD}/pdp18b_sys.c \ ${PDP18BD}/pdp18b_rb.c ${PDP18BD}/pdp18b_tt1.c ${PDP18BD}/pdp18b_fpp.c \ ${PDP18BD}/pdp18b_g2tty.c ${PDP18BD}/pdp18b_dr15.c +ifneq (,${DISPLAY_OPT}) + PDP7_DISPLAY_OPT = -DDISPLAY_TYPE=DIS_TYPE30 -DPIX_SCALE=RES_HALF +endif + PDP4_OPT = -DPDP4 -I ${PDP18BD} -PDP7_OPT = -DPDP7 -I ${PDP18BD} +PDP7_OPT = -DPDP7 -I ${PDP18BD} ${DISPLAY_OPT} $(PDP7_DISPLAY_OPT) PDP9_OPT = -DPDP9 -I ${PDP18BD} PDP15_OPT = -DPDP15 -I ${PDP18BD} -PDP11D = PDP11 +PDP11D = ${SIMHD}/PDP11 PDP11 = ${PDP11D}/pdp11_fp.c ${PDP11D}/pdp11_cpu.c ${PDP11D}/pdp11_dz.c \ ${PDP11D}/pdp11_cis.c ${PDP11D}/pdp11_lp.c ${PDP11D}/pdp11_rk.c \ ${PDP11D}/pdp11_rl.c ${PDP11D}/pdp11_rp.c ${PDP11D}/pdp11_rx.c \ @@ -1333,11 +1307,12 @@ PDP11 = ${PDP11D}/pdp11_fp.c ${PDP11D}/pdp11_cpu.c ${PDP11D}/pdp11_dz.c \ ${PDP11D}/pdp11_ke.c ${PDP11D}/pdp11_dc.c ${PDP11D}/pdp11_dmc.c \ ${PDP11D}/pdp11_kmc.c ${PDP11D}/pdp11_dup.c ${PDP11D}/pdp11_rs.c \ ${PDP11D}/pdp11_vt.c ${PDP11D}/pdp11_td.c ${PDP11D}/pdp11_io_lib.c \ - ${PDP11D}/pdp11_rom.c ${PDP11D}/pdp11_ch.c $(DISPLAYL) $(DISPLAYVT) -PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT} $(DISPLAY_OPT) + ${PDP11D}/pdp11_rom.c ${PDP11D}/pdp11_ch.c ${DISPLAYL} ${DISPLAYVT} \ + ${PDP11D}/pdp11_ng.c ${PDP11D}/pdp11_daz.c ${DISPLAYNG} +PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT} ${DISPLAY_OPT} -UC15D = PDP11 +UC15D = ${SIMHD}/PDP11 UC15 = ${UC15D}/pdp11_cis.c ${UC15D}/pdp11_cpu.c \ ${UC15D}/pdp11_cpumod.c ${UC15D}/pdp11_cr.c \ ${UC15D}/pdp11_fp.c ${UC15D}/pdp11_io.c \ @@ -1348,7 +1323,7 @@ UC15 = ${UC15D}/pdp11_cis.c ${UC15D}/pdp11_cpu.c \ UC15_OPT = -DVM_PDP11 -DUC15 -I ${UC15D} -I ${PDP18BD} -VAXD = VAX +VAXD = ${SIMHD}/VAX VAX = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c ${VAXD}/vax_io.c \ ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ ${VAXD}/vax_mmu.c ${VAXD}/vax_stddev.c ${VAXD}/vax_sysdev.c \ @@ -1361,6 +1336,65 @@ VAX = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c ${VAXD}/vax_io.c \ VAX_OPT = -DVM_VAX -DUSE_INT64 -DUSE_ADDR64 -DUSE_SIM_VIDEO -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} +VAX410 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ + ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ + ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ + ${VAXD}/vax_watch.c ${VAXD}/vax_nar.c ${VAXD}/vax4xx_stddev.c \ + ${VAXD}/vax410_sysdev.c ${VAXD}/vax410_syslist.c ${VAXD}/vax4xx_dz.c \ + ${VAXD}/vax4xx_rd.c ${VAXD}/vax4xx_rz80.c ${VAXD}/vax_xs.c \ + ${VAXD}/vax4xx_va.c ${VAXD}/vax4xx_vc.c ${VAXD}/vax_lk.c \ + ${VAXD}/vax_vs.c ${VAXD}/vax_gpx.c +VAX410_OPT = -DVM_VAX -DVAX_410 -DUSE_INT64 -DUSE_ADDR64 -DUSE_SIM_VIDEO -I ${VAXD} ${NETWORK_OPT} ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} + + +VAX420 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ + ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ + ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ + ${VAXD}/vax_watch.c ${VAXD}/vax_nar.c ${VAXD}/vax4xx_stddev.c \ + ${VAXD}/vax420_sysdev.c ${VAXD}/vax420_syslist.c ${VAXD}/vax4xx_dz.c \ + ${VAXD}/vax4xx_rd.c ${VAXD}/vax4xx_rz80.c ${VAXD}/vax_xs.c \ + ${VAXD}/vax4xx_va.c ${VAXD}/vax4xx_vc.c ${VAXD}/vax4xx_ve.c \ + ${VAXD}/vax_lk.c ${VAXD}/vax_vs.c ${VAXD}/vax_gpx.c +VAX420_OPT = -DVM_VAX -DVAX_420 -DUSE_INT64 -DUSE_ADDR64 -DUSE_SIM_VIDEO -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} +VAX411_OPT = ${VAX420_OPT} -DVAX_411 +VAX412_OPT = ${VAX420_OPT} -DVAX_412 +VAX41A_OPT = ${VAX420_OPT} -DVAX_41A +VAX41D_OPT = ${VAX420_OPT} -DVAX_41D +VAX42A_OPT = ${VAX420_OPT} -DVAX_42A +VAX42B_OPT = ${VAX420_OPT} -DVAX_42B + + +VAX43 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ + ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ + ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ + ${VAXD}/vax_watch.c ${VAXD}/vax_nar.c ${VAXD}/vax4xx_stddev.c \ + ${VAXD}/vax43_sysdev.c ${VAXD}/vax43_syslist.c ${VAXD}/vax4xx_dz.c \ + ${VAXD}/vax4xx_rz80.c ${VAXD}/vax_xs.c ${VAXD}/vax4xx_vc.c \ + ${VAXD}/vax4xx_ve.c ${VAXD}/vax_lk.c ${VAXD}/vax_vs.c +VAX43_OPT = -DVM_VAX -DVAX_43 -DUSE_INT64 -DUSE_ADDR64 -DUSE_SIM_VIDEO -I ${VAXD} ${NETWORK_OPT} ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} + + +VAX440 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ + ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ + ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ + ${VAXD}/vax_watch.c ${VAXD}/vax_nar.c ${VAXD}/vax4xx_stddev.c \ + ${VAXD}/vax440_sysdev.c ${VAXD}/vax440_syslist.c ${VAXD}/vax4xx_dz.c \ + ${VAXD}/vax_xs.c ${VAXD}/vax_lk.c ${VAXD}/vax_vs.c ${VAXD}/vax4xx_rz94.c +VAX440_OPT = -DVM_VAX -DVAX_440 -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} ${NETWORK_OPT} +VAX46_OPT = ${VAX440_OPT} -DVAX_46 +VAX47_OPT = ${VAX440_OPT} -DVAX_47 +VAX48_OPT = ${VAX440_OPT} -DVAX_48 + + +IS1000 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ + ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ + ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ + ${VAXD}/vax_watch.c ${VAXD}/vax_nar.c ${VAXD}/vax_xs.c \ + ${VAXD}/vax4xx_rz94.c ${VAXD}/vax4nn_stddev.c \ + ${VAXD}/is1000_sysdev.c ${VAXD}/is1000_syslist.c +IS1000_OPT = -DVM_VAX -DIS_1000 -DUSE_INT64 -DUSE_ADDR64 -I ${VAXD} ${NETWORK_OPT} + + VAX610 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ @@ -1373,12 +1407,14 @@ VAX610 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ ${PDP11D}/pdp11_td.c ${PDP11D}/pdp11_io_lib.c VAX610_OPT = -DVM_VAX -DVAX_610 -DUSE_INT64 -DUSE_ADDR64 -DUSE_SIM_VIDEO -I ${VAXD} -I ${PDP11D} ${NETWORK_OPT} ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} + VAX630 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ ${VAXD}/vax_watch.c ${VAXD}/vax630_stddev.c ${VAXD}/vax630_sysdev.c \ - ${VAXD}/vax630_io.c ${VAXD}/vax630_syslist.c ${VAXD}/vax_vc.c \ - ${VAXD}/vax_lk.c ${VAXD}/vax_vs.c ${VAXD}/vax_2681.c \ + ${VAXD}/vax630_io.c ${VAXD}/vax630_syslist.c ${VAXD}/vax_va.c \ + ${VAXD}/vax_vc.c ${VAXD}/vax_lk.c ${VAXD}/vax_vs.c \ + ${VAXD}/vax_2681.c ${VAXD}/vax_gpx.c \ ${PDP11D}/pdp11_rl.c ${PDP11D}/pdp11_rq.c ${PDP11D}/pdp11_ts.c \ ${PDP11D}/pdp11_dz.c ${PDP11D}/pdp11_lp.c ${PDP11D}/pdp11_tq.c \ ${PDP11D}/pdp11_xq.c ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_cr.c \ @@ -1434,6 +1470,21 @@ VAX780 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ VAX780_OPT = -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} +VAX8200 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ + ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ + ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ + ${VAXD}/vax_watch.c ${VAXD}/vax820_stddev.c ${VAXD}/vax820_bi.c \ + ${VAXD}/vax820_mem.c ${VAXD}/vax820_uba.c ${VAXD}/vax820_ka.c \ + ${VAXD}/vax820_syslist.c \ + ${PDP11D}/pdp11_rl.c ${PDP11D}/pdp11_rq.c ${PDP11D}/pdp11_ts.c \ + ${PDP11D}/pdp11_dz.c ${PDP11D}/pdp11_lp.c ${PDP11D}/pdp11_tq.c \ + ${PDP11D}/pdp11_xu.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_cr.c \ + ${PDP11D}/pdp11_hk.c ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_dmc.c \ + ${PDP11D}/pdp11_td.c ${PDP11D}/pdp11_tc.c ${PDP11D}/pdp11_rk.c \ + ${PDP11D}/pdp11_io_lib.c ${PDP11D}/pdp11_ch.c +VAX8200_OPT = -DVM_VAX -DVAX_820 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} + + VAX8600 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ ${VAXD}/vax_cis.c ${VAXD}/vax_octa.c ${VAXD}/vax_cmode.c \ ${VAXD}/vax_mmu.c ${VAXD}/vax_sys.c ${VAXD}/vax_syscm.c \ @@ -1450,7 +1501,7 @@ VAX8600 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ VAX8600_OPT = -DVM_VAX -DVAX_860 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} -PDP10D = PDP10 +PDP10D = ${SIMHD}/PDP10 PDP10 = ${PDP10D}/pdp10_fe.c ${PDP11D}/pdp11_dz.c ${PDP10D}/pdp10_cpu.c \ ${PDP10D}/pdp10_ksio.c ${PDP10D}/pdp10_lp20.c ${PDP10D}/pdp10_mdfp.c \ ${PDP10D}/pdp10_pag.c ${PDP10D}/pdp10_rp.c ${PDP10D}/pdp10_sys.c \ @@ -1461,7 +1512,7 @@ PDP10 = ${PDP10D}/pdp10_fe.c ${PDP11D}/pdp11_dz.c ${PDP10D}/pdp10_cpu.c \ PDP10_OPT = -DVM_PDP10 -DUSE_INT64 -I ${PDP10D} -I ${PDP11D} ${NETWORK_OPT} -PDP8D = PDP8 +PDP8D = ${SIMHD}/PDP8 PDP8 = ${PDP8D}/pdp8_cpu.c ${PDP8D}/pdp8_clk.c ${PDP8D}/pdp8_df.c \ ${PDP8D}/pdp8_dt.c ${PDP8D}/pdp8_lp.c ${PDP8D}/pdp8_mt.c \ ${PDP8D}/pdp8_pt.c ${PDP8D}/pdp8_rf.c ${PDP8D}/pdp8_rk.c \ @@ -1471,7 +1522,7 @@ PDP8 = ${PDP8D}/pdp8_cpu.c ${PDP8D}/pdp8_clk.c ${PDP8D}/pdp8_df.c \ PDP8_OPT = -I ${PDP8D} -H316D = H316 +H316D = ${SIMHD}/H316 H316 = ${H316D}/h316_stddev.c ${H316D}/h316_lp.c ${H316D}/h316_cpu.c \ ${H316D}/h316_sys.c ${H316D}/h316_mt.c ${H316D}/h316_fhd.c \ ${H316D}/h316_dp.c ${H316D}/h316_rtc.c ${H316D}/h316_imp.c \ @@ -1479,7 +1530,7 @@ H316 = ${H316D}/h316_stddev.c ${H316D}/h316_lp.c ${H316D}/h316_cpu.c \ H316_OPT = -I ${H316D} -D VM_IMPTIP -HP2100D = HP2100 +HP2100D = ${SIMHD}/HP2100 HP2100 = ${HP2100D}/hp2100_stddev.c ${HP2100D}/hp2100_dp.c ${HP2100D}/hp2100_dq.c \ ${HP2100D}/hp2100_dr.c ${HP2100D}/hp2100_lps.c ${HP2100D}/hp2100_ms.c \ ${HP2100D}/hp2100_mt.c ${HP2100D}/hp2100_mux.c ${HP2100D}/hp2100_cpu.c \ @@ -1492,7 +1543,7 @@ HP2100 = ${HP2100D}/hp2100_stddev.c ${HP2100D}/hp2100_dp.c ${HP2100D}/hp2100_dq. ${HP2100D}/hp2100_di_da.c ${HP2100D}/hp2100_disclib.c HP2100_OPT = -DHAVE_INT64 -I ${HP2100D} -HP3000D = HP3000 +HP3000D = ${SIMHD}/HP3000 HP3000 = ${HP3000D}/hp_disclib.c ${HP3000D}/hp_tapelib.c ${HP3000D}/hp3000_atc.c \ ${HP3000D}/hp3000_clk.c ${HP3000D}/hp3000_cpu.c ${HP3000D}/hp3000_cpu_base.c \ ${HP3000D}/hp3000_cpu_fp.c ${HP3000D}/hp3000_cpu_cis.c ${HP3000D}/hp3000_ds.c \ @@ -1502,20 +1553,20 @@ HP3000 = ${HP3000D}/hp_disclib.c ${HP3000D}/hp_tapelib.c ${HP3000D}/hp3000_atc.c HP3000_OPT = -I ${HP3000D} -I1401D = I1401 +I1401D = ${SIMHD}/I1401 I1401 = ${I1401D}/i1401_lp.c ${I1401D}/i1401_cpu.c ${I1401D}/i1401_iq.c \ ${I1401D}/i1401_cd.c ${I1401D}/i1401_mt.c ${I1401D}/i1401_dp.c \ ${I1401D}/i1401_sys.c I1401_OPT = -I ${I1401D} -I1620D = I1620 +I1620D = ${SIMHD}/I1620 I1620 = ${I1620D}/i1620_cd.c ${I1620D}/i1620_dp.c ${I1620D}/i1620_pt.c \ ${I1620D}/i1620_tty.c ${I1620D}/i1620_cpu.c ${I1620D}/i1620_lp.c \ ${I1620D}/i1620_fp.c ${I1620D}/i1620_sys.c I1620_OPT = -I ${I1620D} -I7000D = I7000 +I7000D = ${SIMHD}/I7000 I7090 = ${I7000D}/i7090_cpu.c ${I7000D}/i7090_sys.c ${I7000D}/i7090_chan.c \ ${I7000D}/i7090_cdr.c ${I7000D}/i7090_cdp.c ${I7000D}/i7090_lpr.c \ ${I7000D}/i7000_chan.c ${I7000D}/i7000_mt.c ${I7000D}/i7090_drum.c \ @@ -1523,7 +1574,7 @@ I7090 = ${I7000D}/i7090_cpu.c ${I7000D}/i7090_sys.c ${I7000D}/i7090_chan.c \ ${I7000D}/i7000_com.c ${I7000D}/i7000_ht.c I7090_OPT = -I $(I7000D) -DUSE_INT64 -DI7090 -DUSE_SIM_CARD -I7080D = I7000 +I7080D = ${SIMHD}/I7000 I7080 = ${I7000D}/i7080_cpu.c ${I7000D}/i7080_sys.c ${I7000D}/i7080_chan.c \ ${I7000D}/i7080_drum.c ${I7000D}/i7000_cdp.c ${I7000D}/i7000_cdr.c \ ${I7000D}/i7000_con.c ${I7000D}/i7000_chan.c ${I7000D}/i7000_lpr.c \ @@ -1531,7 +1582,7 @@ I7080 = ${I7000D}/i7080_cpu.c ${I7000D}/i7080_sys.c ${I7000D}/i7080_chan.c \ ${I7000D}/i7000_com.c ${I7000D}/i7000_ht.c I7080_OPT = -I $(I7000D) -DI7080 -DUSE_SIM_CARD -I7070D = I7000 +I7070D = ${SIMHD}/I7000 I7070 = ${I7000D}/i7070_cpu.c ${I7000D}/i7070_sys.c ${I7000D}/i7070_chan.c \ ${I7000D}/i7000_cdp.c ${I7000D}/i7000_cdr.c ${I7000D}/i7000_con.c \ ${I7000D}/i7000_chan.c ${I7000D}/i7000_lpr.c ${I7000D}/i7000_mt.c \ @@ -1539,7 +1590,7 @@ I7070 = ${I7000D}/i7070_cpu.c ${I7000D}/i7070_sys.c ${I7000D}/i7070_chan.c \ ${I7000D}/i7000_ht.c I7070_OPT = -I $(I7000D) -DUSE_INT64 -DI7070 -DUSE_SIM_CARD -I7010D = I7000 +I7010D = ${SIMHD}/I7000 I7010 = ${I7000D}/i7010_cpu.c ${I7000D}/i7010_sys.c ${I7000D}/i7010_chan.c \ ${I7000D}/i7000_cdp.c ${I7000D}/i7000_cdr.c ${I7000D}/i7000_con.c \ ${I7000D}/i7000_chan.c ${I7000D}/i7000_lpr.c ${I7000D}/i7000_mt.c \ @@ -1547,21 +1598,21 @@ I7010 = ${I7000D}/i7010_cpu.c ${I7000D}/i7010_sys.c ${I7000D}/i7010_chan.c \ ${I7000D}/i7000_ht.c I7010_OPT = -I $(I7010D) -DI7010 -DUSE_SIM_CARD -I704D = I7000 +I704D = ${SIMHD}/I7000 I704 = ${I7000D}/i7090_cpu.c ${I7000D}/i7090_sys.c ${I7000D}/i7090_chan.c \ ${I7000D}/i7090_cdr.c ${I7000D}/i7090_cdp.c ${I7000D}/i7090_lpr.c \ ${I7000D}/i7000_mt.c ${I7000D}/i7090_drum.c ${I7000D}/i7000_chan.c I704_OPT = -I $(I7000D) -DUSE_INT64 -DI704 -DUSE_SIM_CARD -I701D = I7000 +I701D = ${SIMHD}/I7000 I701 = ${I7000D}/i701_cpu.c ${I7000D}/i701_sys.c ${I7000D}/i701_chan.c \ ${I7000D}/i7090_cdr.c ${I7000D}/i7090_cdp.c ${I7000D}/i7090_lpr.c \ ${I7000D}/i7000_mt.c ${I7000D}/i7090_drum.c ${I7000D}/i7000_chan.c I701_OPT = -I $(I7000D) -DUSE_INT64 -DI701 -DUSE_SIM_CARD -I7094D = I7094 +I7094D = ${SIMHD}/I7094 I7094 = ${I7094D}/i7094_cpu.c ${I7094D}/i7094_cpu1.c ${I7094D}/i7094_io.c \ ${I7094D}/i7094_cd.c ${I7094D}/i7094_clk.c ${I7094D}/i7094_com.c \ ${I7094D}/i7094_drm.c ${I7094D}/i7094_dsk.c ${I7094D}/i7094_sys.c \ @@ -1569,13 +1620,13 @@ I7094 = ${I7094D}/i7094_cpu.c ${I7094D}/i7094_cpu1.c ${I7094D}/i7094_io.c \ I7094_OPT = -DUSE_INT64 -I ${I7094D} -I650D = I650 +I650D = ${SIMHD}/I650 I650 = ${I650D}/i650_cpu.c ${I650D}/i650_cdr.c ${I650D}/i650_cdp.c \ ${I650D}/i650_sys.c I650_OPT = -I ${I650D} -DUSE_INT64 -DUSE_SIM_CARD -IBM1130D = Ibm1130 +IBM1130D = ${SIMHD}/Ibm1130 IBM1130 = ${IBM1130D}/ibm1130_cpu.c ${IBM1130D}/ibm1130_cr.c \ ${IBM1130D}/ibm1130_disk.c ${IBM1130D}/ibm1130_stddev.c \ ${IBM1130D}/ibm1130_sys.c ${IBM1130D}/ibm1130_gdu.c \ @@ -1585,11 +1636,11 @@ IBM1130 = ${IBM1130D}/ibm1130_cpu.c ${IBM1130D}/ibm1130_cr.c \ ${IBM1130D}/ibm1130_t2741.c IBM1130_OPT = -I ${IBM1130D} ifneq (${WIN32},) -IBM1130_OPT += -DGUI_SUPPORT -lgdi32 +IBM1130_OPT += -DGUI_SUPPORT -lgdi32 ${BIN}ibm1130.o endif -ID16D = Interdata +ID16D = ${SIMHD}/Interdata ID16 = ${ID16D}/id16_cpu.c ${ID16D}/id16_sys.c ${ID16D}/id_dp.c \ ${ID16D}/id_fd.c ${ID16D}/id_fp.c ${ID16D}/id_idc.c ${ID16D}/id_io.c \ ${ID16D}/id_lp.c ${ID16D}/id_mt.c ${ID16D}/id_pas.c ${ID16D}/id_pt.c \ @@ -1597,7 +1648,7 @@ ID16 = ${ID16D}/id16_cpu.c ${ID16D}/id16_sys.c ${ID16D}/id_dp.c \ ID16_OPT = -I ${ID16D} -ID32D = Interdata +ID32D = ${SIMHD}/Interdata ID32 = ${ID32D}/id32_cpu.c ${ID32D}/id32_sys.c ${ID32D}/id_dp.c \ ${ID32D}/id_fd.c ${ID32D}/id_fp.c ${ID32D}/id_idc.c ${ID32D}/id_io.c \ ${ID32D}/id_lp.c ${ID32D}/id_mt.c ${ID32D}/id_pas.c ${ID32D}/id_pt.c \ @@ -1605,19 +1656,19 @@ ID32 = ${ID32D}/id32_cpu.c ${ID32D}/id32_sys.c ${ID32D}/id_dp.c \ ID32_OPT = -I ${ID32D} -S3D = S3 +S3D = ${SIMHD}/S3 S3 = ${S3D}/s3_cd.c ${S3D}/s3_cpu.c ${S3D}/s3_disk.c ${S3D}/s3_lp.c \ ${S3D}/s3_pkb.c ${S3D}/s3_sys.c S3_OPT = -I ${S3D} -ALTAIRD = ALTAIR +ALTAIRD = ${SIMHD}/ALTAIR ALTAIR = ${ALTAIRD}/altair_sio.c ${ALTAIRD}/altair_cpu.c ${ALTAIRD}/altair_dsk.c \ ${ALTAIRD}/altair_sys.c ALTAIR_OPT = -I ${ALTAIRD} -ALTAIRZ80D = AltairZ80 +ALTAIRZ80D = ${SIMHD}/AltairZ80 ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \ ${ALTAIRZ80D}/altairz80_dsk.c ${ALTAIRZ80D}/disasm.c \ ${ALTAIRZ80D}/altairz80_sio.c ${ALTAIRZ80D}/altairz80_sys.c \ @@ -1632,6 +1683,7 @@ ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \ ${ALTAIRZ80D}/s100_mdsad.c ${ALTAIRZ80D}/s100_selchan.c \ ${ALTAIRZ80D}/s100_ss1.c ${ALTAIRZ80D}/s100_64fdc.c \ ${ALTAIRZ80D}/s100_scp300f.c \ + ${ALTAIRZ80D}/s100_tarbell.c \ ${ALTAIRZ80D}/wd179x.c ${ALTAIRZ80D}/s100_hdc1001.c \ ${ALTAIRZ80D}/s100_if3.c ${ALTAIRZ80D}/s100_adcs6.c \ ${ALTAIRZ80D}/m68kcpu.c ${ALTAIRZ80D}/m68kdasm.c \ @@ -1640,25 +1692,25 @@ ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \ ALTAIRZ80_OPT = -I ${ALTAIRZ80D} -DUSE_SIM_IMD -GRID = GRI +GRID = ${SIMHD}/GRI GRI = ${GRID}/gri_cpu.c ${GRID}/gri_stddev.c ${GRID}/gri_sys.c GRI_OPT = -I ${GRID} -LGPD = LGP +LGPD = ${SIMHD}/LGP LGP = ${LGPD}/lgp_cpu.c ${LGPD}/lgp_stddev.c ${LGPD}/lgp_sys.c LGP_OPT = -I ${LGPD} -SDSD = SDS +SDSD = ${SIMHD}/SDS SDS = ${SDSD}/sds_cpu.c ${SDSD}/sds_drm.c ${SDSD}/sds_dsk.c ${SDSD}/sds_io.c \ ${SDSD}/sds_lp.c ${SDSD}/sds_mt.c ${SDSD}/sds_mux.c ${SDSD}/sds_rad.c \ ${SDSD}/sds_stddev.c ${SDSD}/sds_sys.c SDS_OPT = -I ${SDSD} -SWTP6800D = swtp6800/swtp6800 -SWTP6800C = swtp6800/common +SWTP6800D = ${SIMHD}/swtp6800/swtp6800 +SWTP6800C = ${SIMHD}/swtp6800/common SWTP6800MP-A = ${SWTP6800C}/mp-a.c ${SWTP6800C}/m6800.c ${SWTP6800C}/m6810.c \ ${SWTP6800C}/bootrom.c ${SWTP6800C}/dc-4.c ${SWTP6800C}/mp-s.c ${SWTP6800D}/mp-a_sys.c \ ${SWTP6800C}/mp-b2.c ${SWTP6800C}/mp-8m.c @@ -1667,70 +1719,146 @@ SWTP6800MP-A2 = ${SWTP6800C}/mp-a2.c ${SWTP6800C}/m6800.c ${SWTP6800C}/m6810.c \ ${SWTP6800C}/mp-b2.c ${SWTP6800C}/mp-8m.c ${SWTP6800C}/i2716.c SWTP6800_OPT = -I ${SWTP6800D} - -ISYS8010D = Intel-Systems/isys8010 -ISYS8010C = Intel-Systems/common +INTELSYSD = ${SIMHD}/Intel-Systems +ISYS8010D = ${INTELSYSD}/isys8010 +ISYS8010C = ${INTELSYSD}/common ISYS8010 = ${ISYS8010C}/i8080.c ${ISYS8010D}/isys8010_sys.c \ ${ISYS8010C}/i8251.c ${ISYS8010C}/i8255.c \ ${ISYS8010C}/ieprom.c ${ISYS8010C}/iram8.c \ ${ISYS8010C}/multibus.c ${ISYS8010D}/isbc8010.c \ ${ISYS8010C}/isbc064.c ${ISYS8010C}/isbc202.c \ - ${ISYS8010C}/isbc201.c ${ISYS8010C}/zx200a.c + ${ISYS8010C}/isbc201.c ${ISYS8010C}/zx200a.c \ + ${ISYS8010C}/isbc206.c ${ISYS8010C}/isbc464.c \ + ${ISYS8010C}/isbc208.c ISYS8010_OPT = -I ${ISYS8010D} -ISYS8020D = Intel-Systems/isys8020 -ISYS8020C = Intel-Systems/common +ISYS8020D = ${INTELSYSD}/isys8020 +ISYS8020C = ${INTELSYSD}/common ISYS8020 = ${ISYS8020C}/i8080.c ${ISYS8020D}/isys8020_sys.c \ ${ISYS8020C}/i8251.c ${ISYS8020C}/i8255.c \ ${ISYS8020C}/ieprom.c ${ISYS8020C}/iram8.c \ ${ISYS8020C}/multibus.c ${ISYS8020D}/isbc8020.c \ ${ISYS8020C}/isbc064.c ${ISYS8020C}/i8259.c \ - ${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \ - ${ISYS8010C}/zx200a.c + ${ISYS8020C}/isbc202.c ${ISYS8020C}/isbc201.c \ + ${ISYS8020C}/isbc206.c ${ISYS8020C}/isbc464.c \ + ${ISYS8020C}/zx200a.c ${ISYS8020C}/i8253.c \ + ${ISYS8020C}/isbc208.c ISYS8020_OPT = -I ${ISYS8020D} -ISYS8024D = Intel-Systems/isys8024 -ISYS8024C = Intel-Systems/common +ISYS8024D = ${INTELSYSD}/isys8024 +ISYS8024C = ${INTELSYSD}/common ISYS8024 = ${ISYS8024C}/i8080.c ${ISYS8024D}/isys8024_sys.c \ ${ISYS8024C}/i8251.c ${ISYS8024C}/i8253.c \ ${ISYS8024C}/i8255.c ${ISYS8024C}/i8259.c \ ${ISYS8024C}/ieprom.c ${ISYS8024C}/iram8.c \ ${ISYS8024C}/multibus.c ${ISYS8024D}/isbc8024.c \ ${ISYS8024C}/isbc064.c ${ISYS8024C}/isbc208.c \ - ${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \ - ${ISYS8010C}/zx200a.c + ${ISYS8024C}/isbc202.c ${ISYS8024C}/isbc201.c \ + ${ISYS8024C}/isbc206.c ${ISYS8024C}/isbc464.c \ + ${ISYS8024C}/zx200a.c ISYS8024_OPT = -I ${ISYS8024D} -ISYS8030D = Intel-Systems/isys8030 -ISYS8030C = Intel-Systems/common +ISYS8030D = ${INTELSYSD}/isys8030 +ISYS8030C = ${INTELSYSD}/common ISYS8030 = ${ISYS8030C}/i8080.c ${ISYS8030D}/isys8030_sys.c \ ${ISYS8030C}/i8251.c ${ISYS8030C}/i8255.c \ ${ISYS8030C}/i8259.c ${ISYS8030C}/i8253.c \ ${ISYS8030C}/ieprom.c ${ISYS8030C}/iram8.c \ ${ISYS8030C}/multibus.c ${ISYS8030D}/isbc8030.c \ - ${ISYS8010C}/isbc202.c ${ISYS8010C}/isbc201.c \ - ${ISYS8030C}/isbc064.c ${ISYS8010C}/zx200a.c + ${ISYS8030C}/isbc202.c ${ISYS8030C}/isbc201.c \ + ${ISYS8030C}/isbc206.c ${ISYS8030C}/isbc464.c \ + ${ISYS8030C}/isbc064.c ${ISYS8030C}/zx200a.c \ + ${ISYS8010C}/isbc208.c ISYS8030_OPT = -I ${ISYS8030D} -IMDS-225D = Intel-Systems/imds-225 -IMDS-225C = Intel-Systems/common -IMDS-225 = ${IMDS-225C}/i8080.c ${IMDS-225D}/imds-225_sys.c \ - ${IMDS-225C}/i8251.c ${IMDS-225C}/i8255.c \ - ${IMDS-225C}/i8259.c ${IMDS-225C}/i8253.c \ - ${IMDS-225C}/ieprom.c ${IMDS-225C}/iram8.c \ - ${IMDS-225C}/ipcmultibus.c ${IMDS-225D}/ipc.c \ - ${IMDS-225C}/ipc-cont.c ${IMDS-225C}/ioc-cont.c \ - ${IMDS-225C}/isbc202.c ${IMDS-225C}/isbc201.c \ - ${IMDS-225C}/zx200a.c -IMDS-225_OPT = -I ${IMDS-225D} +IMDS210D = ${INTELSYSD}/imds-210 +IMDS210C = ${INTELSYSD}/common +IMDS210 = ${IMDS210C}/i8080.c ${IMDS210D}/imds-210_sys.c \ + ${IMDS210C}/i8251.c ${IMDS210C}/i8255.c \ + ${IMDS210C}/i8259.c ${IMDS210C}/i8253.c \ + ${IMDS210C}/ieprom.c ${IMDS210C}/iram8.c \ + ${IMDS210C}/ipbmultibus.c ${IMDS210C}/ipb.c \ + ${IMDS210C}/ipc-cont.c ${IMDS210C}/ioc-cont.c \ + ${IMDS210C}/isbc202.c ${IMDS210C}/isbc201.c \ + ${IMDS210C}/isbc206.c ${IMDS210C}/isbc464.c \ + ${IMDS210C}/zx200a.c ${IMDS210C}/isbc064.c +IMDS210_OPT = -I ${IMDS210D} -IBMPCD = Intel-Systems/ibmpc -IBMPCC = Intel-Systems/common +IMDS220D = ${INTELSYSD}/imds-220 +IMDS220C = ${INTELSYSD}/common +IMDS220 = ${IMDS220C}/i8080.c ${IMDS220D}/imds-220_sys.c \ + ${IMDS220C}/i8251.c ${IMDS220C}/i8255.c \ + ${IMDS220C}/i8259.c ${IMDS220C}/i8253.c \ + ${IMDS220C}/ieprom.c ${IMDS220C}/iram8.c \ + ${IMDS220C}/ipbmultibus.c ${IMDS220C}/ipb.c \ + ${IMDS220C}/ipc-cont.c ${IMDS220C}/ioc-cont.c \ + ${IMDS220C}/isbc202.c ${IMDS220C}/isbc201.c \ + ${IMDS220C}/isbc206.c ${IMDS220C}/isbc464.c \ + ${IMDS220C}/zx200a.c ${IMDS220C}/isbc064.c +IMDS220_OPT = -I ${IMDS220D} + + +IMDS225D = ${INTELSYSD}/imds-225 +IMDS225C = ${INTELSYSD}/common +IMDS225 = ${IMDS225C}/i8080.c ${IMDS225D}/imds-225_sys.c \ + ${IMDS225C}/i8251.c ${IMDS225C}/i8255.c \ + ${IMDS225C}/i8259.c ${IMDS225C}/i8253.c \ + ${IMDS225C}/ieprom.c ${IMDS225C}/iram8.c \ + ${IMDS225C}/ipcmultibus.c ${IMDS225C}/ipc.c \ + ${IMDS225C}/ipc-cont.c ${IMDS225C}/ioc-cont.c \ + ${IMDS225C}/isbc202.c ${IMDS225C}/isbc201.c \ + ${IMDS225C}/zx200a.c ${IMDS225C}/isbc464.c \ + ${IMDS225C}/isbc206.c +IMDS225_OPT = -I ${IMDS225D} + + +IMDS230D = ${INTELSYSD}/imds-230 +IMDS230C = ${INTELSYSD}/common +IMDS230 = ${IMDS230C}/i8080.c ${IMDS230D}/imds-230_sys.c \ + ${IMDS230C}/i8251.c ${IMDS230C}/i8255.c \ + ${IMDS230C}/i8259.c ${IMDS230C}/i8253.c \ + ${IMDS230C}/ieprom.c ${IMDS230C}/iram8.c \ + ${IMDS230C}/ipbmultibus.c ${IMDS230C}/ipb.c \ + ${IMDS230C}/ipc-cont.c ${IMDS230C}/ioc-cont.c \ + ${IMDS230C}/isbc202.c ${IMDS230C}/isbc201.c \ + ${IMDS230C}/isbc206.c ${IMDS230C}/isbc464.c \ + ${IMDS230C}/zx200a.c ${IMDS230C}/isbc064.c +IMDS230_OPT = -I ${IMDS230D} + + +IMDS800D = ${INTELSYSD}/imds-800 +IMDS800C = ${INTELSYSD}/common +IMDS800 = ${IMDS800C}/i8080.c ${IMDS800D}/imds-800_sys.c \ + ${IMDS800D}/cpu.c ${IMDS800D}/front_panel.c \ + ${IMDS800D}/monitor.c ${IMDS800C}/ieprom1.c \ + ${IMDS800C}/i8251.c ${IMDS800C}/ieprom.c \ + ${IMDS800C}/m800multibus.c ${IMDS800C}/isbc064.c \ + ${IMDS800C}/isbc202.c ${IMDS800C}/isbc201.c \ + ${IMDS800C}/zx200a.c ${IMDS800C}/isbc464.c \ + ${IMDS800C}/isbc206.c ${IMDS800C}/i3214.c +IMDS800_OPT = -I ${IMDS800D} + + +IMDS810D = ${INTELSYSD}/imds-810 +IMDS810C = ${INTELSYSD}/common +IMDS810 = ${IMDS800C}/i8080.c ${IMDS810D}/imds-810_sys.c \ + ${IMDS810D}/cpu.c ${IMDS810D}/front_panel.c \ + ${IMDS810D}/monitor.c ${IMDS810C}/ieprom1.c \ + ${IMDS810C}/i8251.c ${IMDS810C}/ieprom.c \ + ${IMDS810C}/m800multibus.c ${IMDS810C}/isbc064.c \ + ${IMDS810C}/isbc202.c ${IMDS810C}/isbc201.c \ + ${IMDS810C}/zx200a.c ${IMDS810C}/isbc464.c \ + ${IMDS810C}/isbc206.c ${IMDS800C}/i3214.c +IMDS810_OPT = -I ${IMDS810D} + + +IBMPCD = ${INTELSYSD}/ibmpc +IBMPCC = ${INTELSYSD}/common IBMPC = ${IBMPCC}/i8255.c ${IBMPCD}/ibmpc.c \ ${IBMPCC}/i8088.c ${IBMPCD}/ibmpc_sys.c \ ${IBMPCC}/i8253.c ${IBMPCC}/i8259.c \ @@ -1739,8 +1867,8 @@ IBMPC = ${IBMPCC}/i8255.c ${IBMPCD}/ibmpc.c \ IBMPC_OPT = -I ${IBMPCD} -IBMPCXTD = Intel-Systems/ibmpcxt -IBMPCXTC = Intel-Systems/common +IBMPCXTD = ${INTELSYSD}/ibmpcxt +IBMPCXTC = ${INTELSYSD}/common IBMPCXT = ${IBMPCXTC}/i8088.c ${IBMPCXTD}/ibmpcxt_sys.c \ ${IBMPCXTC}/i8253.c ${IBMPCXTC}/i8259.c \ ${IBMPCXTC}/i8255.c ${IBMPCXTD}/ibmpcxt.c \ @@ -1749,29 +1877,29 @@ IBMPCXT = ${IBMPCXTC}/i8088.c ${IBMPCXTD}/ibmpcxt_sys.c \ IBMPCXT_OPT = -I ${IBMPCXTD} -SCELBID = Intel-Systems/scelbi -SCELBIC = Intel-Systems/common +SCELBID = ${INTELSYSD}/scelbi +SCELBIC = ${INTELSYSD}/common SCELBI = ${SCELBIC}/i8008.c ${SCELBID}/scelbi_sys.c ${SCELBID}/scelbi_io.c SCELBI_OPT = -I ${SCELBID} -TX0D = TX-0 +TX0D = ${SIMHD}/TX-0 TX0 = ${TX0D}/tx0_cpu.c ${TX0D}/tx0_dpy.c ${TX0D}/tx0_stddev.c \ ${TX0D}/tx0_sys.c ${TX0D}/tx0_sys_orig.c ${DISPLAYL} -TX0_OPT = -I ${TX0D} $(DISPLAY_OPT) +TX0_OPT = -I ${TX0D} ${DISPLAY_OPT} -SSEMD = SSEM +SSEMD = ${SIMHD}/SSEM SSEM = ${SSEMD}/ssem_cpu.c ${SSEMD}/ssem_sys.c SSEM_OPT = -I ${SSEMD} -B5500D = B5500 +B5500D = ${SIMHD}/B5500 B5500 = ${B5500D}/b5500_cpu.c ${B5500D}/b5500_io.c ${B5500D}/b5500_sys.c \ ${B5500D}/b5500_dk.c ${B5500D}/b5500_mt.c ${B5500D}/b5500_urec.c \ ${B5500D}/b5500_dr.c ${B5500D}/b5500_dtc.c B5500_OPT = -I.. -DUSE_INT64 -DB5500 -DUSE_SIM_CARD -BESM6D = BESM6 +BESM6D = ${SIMHD}/BESM6 BESM6 = ${BESM6D}/besm6_cpu.c ${BESM6D}/besm6_sys.c ${BESM6D}/besm6_mmu.c \ ${BESM6D}/besm6_arith.c ${BESM6D}/besm6_disk.c ${BESM6D}/besm6_drum.c \ ${BESM6D}/besm6_tty.c ${BESM6D}/besm6_panel.c ${BESM6D}/besm6_printer.c \ @@ -1841,11 +1969,111 @@ ifneq (,$(BESM6_BUILD)) endif endif +SEL32D = ${SIMHD}/SEL32 +SEL32 = ${SEL32D}/sel32_cpu.c ${SEL32D}/sel32_sys.c ${SEL32D}/sel32_defs.h \ + ${SEL32D}/sel32_chan.c ${SEL32D}/sel32_iop.c ${SEL32D}/sel32_com.c \ + ${SEL32D}/sel32_con.c ${SEL32D}/sel32_clk.c ${SEL32D}/sel32_mt.c \ + ${SEL32D}/sel32_lpr.c ${SEL32D}/sel32_scfi.c ${SEL32D}/sel32_fltpt.c \ + ${SEL32D}/sel32_disk.c +SEL32_OPT = -I $(SEL32D) -DSEL32 +#SEL32_OPT = -I $(SEL32D) -DUSE_INT64 -DSEL32 + +ICL1900D = ${SIMHD}/ICL1900 +ICL1900 = ${ICL1900D}/icl1900_cpu.c ${ICL1900D}/icl1900_sys.c \ + ${ICL1900D}/icl1900_stdio.c ${ICL1900D}/icl1900_cty.c \ + ${ICL1900D}/icl1900_tr.c ${ICL1900D}/icl1900_tp.c \ + ${ICL1900D}/icl1900_cr.c ${ICL1900D}/icl1900_cp.c \ + ${ICL1900D}/icl1900_lp.c ${ICL1900D}/icl1900_mta.c \ + ${ICL1900D}/icl1900_mt.c ${ICL1900D}/icl1900_eds8.c +ICL1900_OPT = -I $(ICL1900D) -DICL1900 -DUSE_SIM_CARD + +IBM360D = ${SIMHD}/IBM360 +IBM360 = ${IBM360D}/ibm360_cpu.c ${IBM360D}/ibm360_sys.c \ + ${IBM360D}/ibm360_con.c ${IBM360D}/ibm360_chan.c \ + ${IBM360D}/ibm360_cdr.c ${IBM360D}/ibm360_cdp.c \ + ${IBM360D}/ibm360_mt.c ${IBM360D}/ibm360_lpr.c \ + ${IBM360D}/ibm360_dasd.c ${IBM360D}/ibm360_com.c +IBM360_OPT = -I $(IBM360D) -DIBM360 -DUSE_64BIT -DUSE_SIM_CARD +IBM360_OPT32 = -I $(IBM360D) -DIBM360 -DUSE_SIM_CARD + +PDP6D = ${SIMHD}/PDP10 +ifneq (,${DISPLAY_OPT}) + PDP6_DISPLAY_OPT = +endif +PDP6 = ${PDP6D}/kx10_cpu.c ${PDP6D}/kx10_sys.c ${PDP6D}/kx10_cty.c \ + ${PDP6D}/kx10_lp.c ${PDP6D}/kx10_pt.c ${PDP6D}/kx10_cr.c \ + ${PDP6D}/kx10_cp.c ${PDP6D}/pdp6_dct.c ${PDP6D}/pdp6_dtc.c \ + ${PDP6D}/pdp6_mtc.c ${PDP6D}/pdp6_dsk.c ${PDP6D}/pdp6_dcs.c \ + ${PDP6D}/kx10_dpy.c ${DISPLAYL} $(DISPLAY340) +PDP6_OPT = -DPDP6=1 -DUSE_INT64 -I ${PDP6D} -DUSE_SIM_CARD ${DISPLAY_OPT} ${PDP6_DISPLAY_OPT} + +KA10D = ${SIMHD}/PDP10 +ifneq (,${DISPLAY_OPT}) + KA10_DISPLAY_OPT = +endif +KA10 = ${KA10D}/kx10_cpu.c ${KA10D}/kx10_sys.c ${KA10D}/kx10_df.c \ + ${KA10D}/kx10_dp.c ${KA10D}/kx10_mt.c ${KA10D}/kx10_cty.c \ + ${KA10D}/kx10_lp.c ${KA10D}/kx10_pt.c ${KA10D}/kx10_dc.c \ + ${KA10D}/kx10_rp.c ${KA10D}/kx10_rc.c ${KA10D}/kx10_dt.c \ + ${KA10D}/kx10_dk.c ${KA10D}/kx10_cr.c ${KA10D}/kx10_cp.c \ + ${KA10D}/kx10_tu.c ${KA10D}/kx10_rs.c ${KA10D}/ka10_pd.c \ + ${KA10D}/kx10_rh.c ${KA10D}/kx10_imp.c ${KA10D}/ka10_tk10.c \ + ${KA10D}/ka10_mty.c ${KA10D}/ka10_imx.c ${KA10D}/ka10_ch10.c \ + ${KA10D}/ka10_stk.c ${KA10D}/ka10_ten11.c ${KA10D}/ka10_auxcpu.c \ + $(KA10D)/ka10_pmp.c ${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c \ + ${KA10D}/pdp6_dtc.c ${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c \ + ${KA10D}/pdp6_dcs.c ${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c \ + ${PDP10D}/ka10_ai.c ${KA10D}/ka10_iii.c ${DISPLAYL} $(DISPLAY340) +KA10_OPT = -DKA=1 -DUSE_INT64 -I ${KA10D} -DUSE_SIM_CARD ${NETWORK_OPT} ${DISPLAY_OPT} ${KA10_DISPLAY_OPT} +ifneq (${PANDA_LIGHTS},) +# ONLY for Panda display. +KA10_OPT += -DPANDA_LIGHTS +KA10 += ${KA10D}/ka10_lights.c +KA10_LDFLAGS += -lusb-1.0 +endif + +KI10D = ${SIMHD}/PDP10 +ifneq (,${DISPLAY_OPT}) +KI10_DISPLAY_OPT = +endif +KI10 = ${KI10D}/kx10_cpu.c ${KI10D}/kx10_sys.c ${KI10D}/kx10_df.c \ + ${KI10D}/kx10_dp.c ${KI10D}/kx10_mt.c ${KI10D}/kx10_cty.c \ + ${KI10D}/kx10_lp.c ${KI10D}/kx10_pt.c ${KI10D}/kx10_dc.c \ + ${KI10D}/kx10_rh.c ${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c \ + ${KI10D}/kx10_dt.c ${KI10D}/kx10_dk.c ${KI10D}/kx10_cr.c \ + ${KI10D}/kx10_cp.c ${KI10D}/kx10_tu.c ${KI10D}/kx10_rs.c \ + ${KI10D}/kx10_imp.c ${KI10D}/kx10_dpy.c ${DISPLAYL} $(DISPLAY340) +KI10_OPT = -DKI=1 -DUSE_INT64 -I ${KI10D} -DUSE_SIM_CARD ${NETWORK_OPT} ${DISPLAY_OPT} ${KI10_DISPLAY_OPT} +ifneq (${PANDA_LIGHTS},) +# ONLY for Panda display. +KI10_OPT += -DPANDA_LIGHTS +KI10 += ${KA10D}/ka10_lights.c +KI10_LDFLAGS = -lusb-1.0 +endif + +KL10D = ${SIMHD}/PDP10 +KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \ + ${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rh.c \ + ${KL10D}/kx10_rp.c ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c \ + ${KL10D}/kx10_imp.c ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c \ + ${KL10D}/ka10_ch10.c ${KL10D}/kx10_lp.c ${KL10D}/kl10_nia.c +KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT} + +ATT3B2D = ${SIMHD}/3B2 +ATT3B2 = ${ATT3B2D}/3b2_cpu.c ${ATT3B2D}/3b2_mmu.c \ + ${ATT3B2D}/3b2_iu.c ${ATT3B2D}/3b2_if.c \ + ${ATT3B2D}/3b2_id.c ${ATT3B2D}/3b2_dmac.c \ + ${ATT3B2D}/3b2_sys.c ${ATT3B2D}/3b2_io.c \ + ${ATT3B2D}/3b2_ports.c ${ATT3B2D}/3b2_ctc.c \ + ${ATT3B2D}/3b2_ni.c ${ATT3B2D}/3b2_mau.c \ + ${ATT3B2D}/3b2_sysdev.c +ATT3B2_OPT = -DUSE_INT64 -DUSE_ADDR64 -I ${ATT3B2D} ${NETWORK_OPT} + ### ### Experimental simulators ### -CDC1700D = CDC1700 +CDC1700D = ${SIMHD}/CDC1700 CDC1700 = ${CDC1700D}/cdc1700_cpu.c ${CDC1700D}/cdc1700_dis.c \ ${CDC1700D}/cdc1700_io.c ${CDC1700D}/cdc1700_sys.c \ ${CDC1700D}/cdc1700_dev1.c ${CDC1700D}/cdc1700_mt.c \ @@ -1860,7 +2088,7 @@ CDC1700_OPT = -I ${CDC1700D} ### Unsupported/Incomplete simulators ### -SIGMAD = sigma +SIGMAD = ${SIMHD}/sigma SIGMA = ${SIGMAD}/sigma_cpu.c ${SIGMAD}/sigma_sys.c ${SIGMAD}/sigma_cis.c \ ${SIGMAD}/sigma_coc.c ${SIGMAD}/sigma_dk.c ${SIGMAD}/sigma_dp.c \ ${SIGMAD}/sigma_fp.c ${SIGMAD}/sigma_io.c ${SIGMAD}/sigma_lp.c \ @@ -1868,7 +2096,7 @@ SIGMA = ${SIGMAD}/sigma_cpu.c ${SIGMAD}/sigma_sys.c ${SIGMAD}/sigma_cis.c \ ${SIGMAD}/sigma_rad.c ${SIGMAD}/sigma_rtc.c ${SIGMAD}/sigma_tt.c SIGMA_OPT = -I ${SIGMAD} -ALPHAD = alpha +ALPHAD = ${SIMHD}/alpha ALPHA = ${ALPHAD}/alpha_500au_syslist.c ${ALPHAD}/alpha_cpu.c \ ${ALPHAD}/alpha_ev5_cons.c ${ALPHAD}/alpha_ev5_pal.c \ ${ALPHAD}/alpha_ev5_tlb.c ${ALPHAD}/alpha_fpi.c \ @@ -1876,7 +2104,7 @@ ALPHA = ${ALPHAD}/alpha_500au_syslist.c ${ALPHAD}/alpha_cpu.c \ ${ALPHAD}/alpha_mmu.c ${ALPHAD}/alpha_sys.c ALPHA_OPT = -I ${ALPHAD} -DUSE_ADDR64 -DUSE_INT64 -SAGED = SAGE +SAGED = ${SIMHD}/SAGE SAGE = ${SAGED}/sage_cpu.c ${SAGED}/sage_sys.c ${SAGED}/sage_stddev.c \ ${SAGED}/sage_cons.c ${SAGED}/sage_fd.c ${SAGED}/sage_lp.c \ ${SAGED}/m68k_cpu.c ${SAGED}/m68k_mem.c ${SAGED}/m68k_scp.c \ @@ -1884,55 +2112,50 @@ SAGE = ${SAGED}/sage_cpu.c ${SAGED}/sage_sys.c ${SAGED}/sage_stddev.c \ ${SAGED}/i8251.c ${SAGED}/i8253.c ${SAGED}/i8255.c ${SAGED}/i8259.c ${SAGED}/i8272.c SAGE_OPT = -I ${SAGED} -DHAVE_INT64 -DUSE_SIM_IMD -PDQ3D = PDQ-3 +PDQ3D = ${SIMHD}/PDQ-3 PDQ3 = ${PDQ3D}/pdq3_cpu.c ${PDQ3D}/pdq3_sys.c ${PDQ3D}/pdq3_stddev.c \ ${PDQ3D}/pdq3_mem.c ${PDQ3D}/pdq3_debug.c ${PDQ3D}/pdq3_fdc.c PDQ3_OPT = -I ${PDQ3D} -DUSE_SIM_IMD -ATT3B2D = 3B2 -ATT3B2 = ${ATT3B2D}/3b2_cpu.c ${ATT3B2D}/3b2_mmu.c \ - ${ATT3B2D}/3b2_iu.c ${ATT3B2D}/3b2_if.c \ - ${ATT3B2D}/3b2_id.c ${ATT3B2D}/3b2_dmac.c \ - ${ATT3B2D}/3b2_sys.c ${ATT3B2D}/3b2_io.c \ - ${ATT3B2D}/3b2_ports.c ${ATT3B2D}/3b2_ctc.c \ - ${ATT3B2D}/3b2_sysdev.c -ATT3B2_OPT = -I ${ATT3B2D} -DUSE_INT64 -DUSE_ADDR64 # # Build everything (not the unsupported/incomplete or experimental simulators) # +ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \ + vax microvax3900 microvax1 rtvax1000 microvax2 vax730 vax750 vax780 \ + vax8200 vax8600 besm6 \ + microvax2000 infoserver100 infoserver150vxt microvax3100 microvax3100e \ + vaxstation3100m30 vaxstation3100m38 vaxstation3100m76 vaxstation4000m60 \ + microvax3100m80 vaxstation4000vlc infoserver1000 \ + nova eclipse hp2100 hp3000 i1401 i1620 s3 altair altairz80 gri \ + i7094 ibm1130 id16 id32 sds lgp h316 cdc1700 \ + swtp6800mp-a swtp6800mp-a2 tx-0 ssem b5500 isys8010 isys8020 \ + isys8030 isys8024 imds-210 imds-220 imds-225 imds-230 imds-800 imds-810 \ + scelbi 3b2 i701 i704 i7010 i7070 i7080 i7090 \ + sigma uc15 pdp10-ka pdp10-ki pdp6 + ALL = b5500 i701 i704 i7010 i7070 i7080 i7090 pdp10-ka pdp10-ki pdp10-kl ibm360 ibm360_32 icl1900 pdp6 sel32 all : ${ALL} EXPERIMENTAL = cdc1700 -experimental : $(EXPERIMENTAL) +experimental : ${EXPERIMENTAL} clean : ifeq (${WIN32},) - ${RM} -r ${BIN} + ${RM} -rf ${BIN} else - if exist BIN\*.exe del /q BIN\*.exe - if exist BIN rmdir BIN + if exist BIN rmdir /s /q BIN endif -${BIN}BuildROMs${EXE} : +${BUILD_ROMS} : ${MKDIRBIN} -ifeq (agcc,$(findstring agcc,$(firstword $(CC)))) - gcc $(wordlist 2,1000,${CC}) sim_BuildROMs.c $(CC_OUTSPEC) -else - ${CC} sim_BuildROMs.c $(CC_OUTSPEC) -endif ifeq (${WIN32},) - $@ - ${RM} $@ - ifeq (Darwin,$(OSTYPE)) # remove Xcode's debugging symbols folder too - ${RM} -rf $@.dSYM - endif + @if ${TEST} \( ! -e $@ \) -o \( sim_BuildROMs.c -nt $@ \) ; then ${CC} sim_BuildROMs.c ${CC_OUTSPEC}; fi else - $(@D)\$(@F) - del $(@D)\$(@F) + @if not exist $@ ${CC} sim_BuildROMs.c ${CC_OUTSPEC} endif + @$@ # # Individual builds @@ -1941,233 +2164,314 @@ pdp1 : ${BIN}pdp1${EXE} ${BIN}pdp1${EXE} : ${PDP1} ${SIM} ${MKDIRBIN} - ${CC} ${PDP1} ${SIM} ${PDP1_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${PDP1} ${SIM} ${PDP1_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${PDP1D},pdp1)) - $@ $(call find_test,${PDP1D},pdp1) $(TEST_ARG) + $@ $(call find_test,${PDP1D},pdp1) ${TEST_ARG} endif pdp4 : ${BIN}pdp4${EXE} ${BIN}pdp4${EXE} : ${PDP18B} ${SIM} ${MKDIRBIN} - ${CC} ${PDP18B} ${SIM} ${PDP4_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${PDP18B} ${SIM} ${PDP4_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${PDP18BD},pdp4)) - $@ $(call find_test,${PDP18BD},pdp4) $(TEST_ARG) + $@ $(call find_test,${PDP18BD},pdp4) ${TEST_ARG} endif pdp7 : ${BIN}pdp7${EXE} -${BIN}pdp7${EXE} : ${PDP18B} ${SIM} +${BIN}pdp7${EXE} : ${PDP18B} ${PDP18BD}/pdp18b_dpy.c ${DISPLAYL} ${DISPLAY340} ${SIM} ${MKDIRBIN} - ${CC} ${PDP18B} ${SIM} ${PDP7_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${PDP18B} ${PDP18BD}/pdp18b_dpy.c ${DISPLAYL} ${DISPLAY340} ${SIM} ${PDP7_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${PDP18BD},pdp7)) - $@ $(call find_test,${PDP18BD},pdp7) $(TEST_ARG) + $@ $(call find_test,${PDP18BD},pdp7) ${TEST_ARG} endif pdp8 : ${BIN}pdp8${EXE} ${BIN}pdp8${EXE} : ${PDP8} ${SIM} ${MKDIRBIN} - ${CC} ${PDP8} ${SIM} ${PDP8_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${PDP8} ${SIM} ${PDP8_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${PDP8D},pdp8)) - $@ $(call find_test,${PDP8D},pdp8) $(TEST_ARG) + $@ $(call find_test,${PDP8D},pdp8) ${TEST_ARG} endif pdp9 : ${BIN}pdp9${EXE} ${BIN}pdp9${EXE} : ${PDP18B} ${SIM} ${MKDIRBIN} - ${CC} ${PDP18B} ${SIM} ${PDP9_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${PDP18B} ${SIM} ${PDP9_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${PDP18BD},pdp9)) - $@ $(call find_test,${PDP18BD},pdp9) $(TEST_ARG) + $@ $(call find_test,${PDP18BD},pdp9) ${TEST_ARG} endif pdp15 : ${BIN}pdp15${EXE} ${BIN}pdp15${EXE} : ${PDP18B} ${SIM} ${MKDIRBIN} - ${CC} ${PDP18B} ${SIM} ${PDP15_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${PDP18B} ${SIM} ${PDP15_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${PDP18BD},pdp15)) - $@ $(call find_test,${PDP18BD},pdp15) $(TEST_ARG) + $@ $(call find_test,${PDP18BD},pdp15) ${TEST_ARG} endif pdp10 : ${BIN}pdp10${EXE} ${BIN}pdp10${EXE} : ${PDP10} ${SIM} ${MKDIRBIN} - ${CC} ${PDP10} ${SIM} ${PDP10_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${PDP10} ${SIM} ${PDP10_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${PDP10D},pdp10)) - $@ $(call find_test,${PDP10D},pdp10) $(TEST_ARG) + $@ $(call find_test,${PDP10D},pdp10) ${TEST_ARG} endif -pdp6 : ${BIN}pdp6${EXE} - -${BIN}pdp6${EXE} : ${PDP6} ${SIM} - ${MKDIRBIN} - ${CC} ${PDP6} ${PDP6_DPY} ${SIM} ${PDP6_OPT} $(CC_OUTSPEC) ${LDFLAGS} ${PDP6_LDFLAGS} -ifneq (,$(call find_test,${PDP10D},pdp6)) - $@ $(call find_test,${PDP10D},pdp6) $(TEST_ARG) -endif - -pdp10-ka : ${BIN}pdp10-ka${EXE} - -${BIN}pdp10-ka${EXE} : ${KA10} ${SIM} - ${MKDIRBIN} - ${CC} ${KA10} ${KA10_DPY} ${SIM} ${KA10_OPT} $(CC_OUTSPEC) ${LDFLAGS} ${KA10_LDFLAGS} -ifneq (,$(call find_test,${PDP10D},ka10)) - $@ $(call find_test,${PDP10D},ka10) $(TEST_ARG) -endif - -pdp10-ki : ${BIN}pdp10-ki${EXE} - -${BIN}pdp10-ki${EXE} : ${KI10} ${SIM} - ${MKDIRBIN} - ${CC} ${KI10} ${KI10_DPY} ${SIM} ${KI10_OPT} $(CC_OUTSPEC) ${LDFLAGS} ${KI10_LDFLAGS} -ifneq (,$(call find_test,${PDP10D},ki10)) - $@ $(call find_test,${PDP10D},ki10) $(TEST_ARG) -endif - -pdp10-kl : ${BIN}pdp10-kl${EXE} - -${BIN}pdp10-kl${EXE} : ${KL10} ${SIM} - ${MKDIRBIN} - ${CC} ${KL10} ${SIM} ${KL10_OPT} $(CC_OUTSPEC) ${LDFLAGS} ${KL10_LDFLAGS} -ifneq (,$(call find_test,${PDP10D},kl10)) - $@ $(call find_test,${PDP10D},kl10) $(TEST_ARG) -endif - -pdp11 : ${BIN}BuildROMs${EXE} ${BIN}pdp11${EXE} +pdp11 : ${BIN}pdp11${EXE} ${BIN}pdp11${EXE} : ${PDP11} ${SIM} ${MKDIRBIN} - ${CC} ${PDP11} ${SIM} ${PDP11_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${PDP11} ${SIM} ${PDP11_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${PDP11D},pdp11)) - $@ $(call find_test,${PDP11D},pdp11) $(TEST_ARG) + $@ $(call find_test,${PDP11D},pdp11) ${TEST_ARG} endif uc15 : ${BIN}uc15${EXE} ${BIN}uc15${EXE} : ${UC15} ${SIM} ${MKDIRBIN} - ${CC} ${UC15} ${SIM} ${UC15_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${UC15} ${SIM} ${UC15_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${PDP11D},uc15)) - $@ $(call find_test,${PDP11D},uc15) $(TEST_ARG) + $@ $(call find_test,${PDP11D},uc15) ${TEST_ARG} endif -vax : microvax3900 +microvax3900 : vax -microvax3900 : ${BIN}BuildROMs${EXE} ${BIN}microvax3900${EXE} +vax : ${BIN}vax${EXE} -${BIN}microvax3900${EXE} : ${VAX} ${SIM} ${BUILD_ROMS} +${BIN}vax${EXE} : ${VAX} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${VAX} ${SIM} ${VAX_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${VAX} ${SIM} ${VAX_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifeq (${WIN32},) - cp ${BIN}microvax3900${EXE} ${BIN}vax${EXE} + cp ${BIN}vax${EXE} ${BIN}microvax3900${EXE} else - copy $(@D)\microvax3900${EXE} $(@D)\vax${EXE} + copy $(@D)\vax${EXE} $(@D)\microvax3900${EXE} endif -ifneq (,$(call find_test,$(VAXD),vax-diag)) - $@ $(call find_test,$(VAXD),vax-diag) $(TEST_ARG) +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} endif -microvax1 : ${BIN}BuildROMs${EXE} ${BIN}microvax1${EXE} +microvax2000 : ${BIN}microvax2000${EXE} + +${BIN}microvax2000${EXE} : ${VAX410} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX410} ${SCSI} ${SIM} ${VAX410_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +infoserver100 : ${BIN}infoserver100${EXE} + +${BIN}infoserver100${EXE} : ${VAX420} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX420} ${SCSI} ${SIM} ${VAX411_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +infoserver150vxt : ${BIN}infoserver150vxt${EXE} + +${BIN}infoserver150vxt${EXE} : ${VAX420} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX420} ${SCSI} ${SIM} ${VAX412_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +microvax3100 : ${BIN}microvax3100${EXE} + +${BIN}microvax3100${EXE} : ${VAX420} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX420} ${SCSI} ${SIM} ${VAX41A_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +microvax3100e : ${BIN}microvax3100e${EXE} + +${BIN}microvax3100e${EXE} : ${VAX420} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX420} ${SCSI} ${SIM} ${VAX41D_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +vaxstation3100m30 : ${BIN}vaxstation3100m30${EXE} + +${BIN}vaxstation3100m30${EXE} : ${VAX420} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX420} ${SCSI} ${SIM} ${VAX42A_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +vaxstation3100m38 : ${BIN}vaxstation3100m38${EXE} + +${BIN}vaxstation3100m38${EXE} : ${VAX420} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX420} ${SCSI} ${SIM} ${VAX42B_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +vaxstation3100m76 : ${BIN}vaxstation3100m76${EXE} + +${BIN}vaxstation3100m76${EXE} : ${VAX43} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX43} ${SCSI} ${SIM} ${VAX43_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +vaxstation4000m60 : ${BIN}vaxstation4000m60${EXE} + +${BIN}vaxstation4000m60${EXE} : ${VAX440} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX440} ${SCSI} ${SIM} ${VAX46_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +microvax3100m80 : ${BIN}microvax3100m80${EXE} + +${BIN}microvax3100m80${EXE} : ${VAX440} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX440} ${SCSI} ${SIM} ${VAX47_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +vaxstation4000vlc : ${BIN}vaxstation4000vlc${EXE} + +${BIN}vaxstation4000vlc${EXE} : ${VAX440} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX440} ${SCSI} ${SIM} ${VAX48_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +infoserver1000 : ${BIN}infoserver1000${EXE} + +${BIN}infoserver1000${EXE} : ${IS1000} ${SCSI} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IS1000} ${SCSI} ${SIM} ${IS1000_OPT} -o $@ ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +microvax1 : ${BIN}microvax1${EXE} ${BIN}microvax1${EXE} : ${VAX610} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} ${CC} ${VAX610} ${SIM} ${VAX610_OPT} -o $@ ${LDFLAGS} -ifneq (,$(call find_test,$(VAXD),vax-diag)) - $@ $(call find_test,$(VAXD),vax-diag) $(TEST_ARG) +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} endif -rtvax1000 : ${BIN}BuildROMs${EXE} ${BIN}rtvax1000${EXE} +rtvax1000 : ${BIN}rtvax1000${EXE} ${BIN}rtvax1000${EXE} : ${VAX630} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} ${CC} ${VAX630} ${SIM} ${VAX620_OPT} -o $@ ${LDFLAGS} -ifneq (,$(call find_test,$(VAXD),vax-diag)) - $@ $(call find_test,$(VAXD),vax-diag) $(TEST_ARG) +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} endif -microvax2 : ${BIN}BuildROMs${EXE} ${BIN}microvax2${EXE} +microvax2 : ${BIN}microvax2${EXE} ${BIN}microvax2${EXE} : ${VAX630} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} ${CC} ${VAX630} ${SIM} ${VAX630_OPT} -o $@ ${LDFLAGS} -ifneq (,$(call find_test,$(VAXD),vax-diag)) - $@ $(call find_test,$(VAXD),vax-diag) $(TEST_ARG) +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} endif -vax730 : ${BIN}BuildROMs${EXE} ${BIN}vax730${EXE} +vax730 : ${BIN}vax730${EXE} ${BIN}vax730${EXE} : ${VAX730} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} ${CC} ${VAX730} ${SIM} ${VAX730_OPT} -o $@ ${LDFLAGS} -ifneq (,$(call find_test,$(VAXD),vax-diag)) - $@ $(call find_test,$(VAXD),vax-diag) $(TEST_ARG) +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} endif -vax750 : ${BIN}BuildROMs${EXE} ${BIN}vax750${EXE} +vax750 : ${BIN}vax750${EXE} ${BIN}vax750${EXE} : ${VAX750} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} ${CC} ${VAX750} ${SIM} ${VAX750_OPT} -o $@ ${LDFLAGS} -ifneq (,$(call find_test,$(VAXD),vax-diag)) - $@ $(call find_test,$(VAXD),vax-diag) $(TEST_ARG) +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} endif -vax780 : ${BIN}BuildROMs${EXE} ${BIN}vax780${EXE} +vax780 : ${BIN}vax780${EXE} ${BIN}vax780${EXE} : ${VAX780} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${VAX780} ${SIM} ${VAX780_OPT} $(CC_OUTSPEC) ${LDFLAGS} -ifneq (,$(call find_test,$(VAXD),vax-diag)) - $@ $(call find_test,$(VAXD),vax-diag) $(TEST_ARG) + ${CC} ${VAX780} ${SIM} ${VAX780_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} endif -vax8600 : ${BIN}BuildROMs${EXE} ${BIN}vax8600${EXE} +vax8200 : ${BIN}vax8200${EXE} + +${BIN}vax8200${EXE} : ${VAX8200} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${VAX8200} ${SIM} ${VAX8200_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} +endif + +vax8600 : ${BIN}vax8600${EXE} ${BIN}vax8600${EXE} : ${VAX8600} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${VAX8600} ${SIM} ${VAX8600_OPT} $(CC_OUTSPEC) ${LDFLAGS} -ifneq (,$(call find_test,$(VAXD),vax-diag)) - $@ $(call find_test,$(VAXD),vax-diag) $(TEST_ARG) + ${CC} ${VAX8600} ${SIM} ${VAX8600_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (,$(call find_test,${VAXD},vax-diag)) + $@ $(call find_test,${VAXD},vax-diag) ${TEST_ARG} endif nova : ${BIN}nova${EXE} ${BIN}nova${EXE} : ${NOVA} ${SIM} ${MKDIRBIN} - ${CC} ${NOVA} ${SIM} ${NOVA_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${NOVA} ${SIM} ${NOVA_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${NOVAD},nova)) - $@ $(call find_test,${NOVAD},nova) $(TEST_ARG) + $@ $(call find_test,${NOVAD},nova) ${TEST_ARG} endif eclipse : ${BIN}eclipse${EXE} ${BIN}eclipse${EXE} : ${ECLIPSE} ${SIM} ${MKDIRBIN} - ${CC} ${ECLIPSE} ${SIM} ${ECLIPSE_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ECLIPSE} ${SIM} ${ECLIPSE_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${NOVAD},eclipse)) - $@ $(call find_test,${NOVAD},eclipse) $(TEST_ARG) + $@ $(call find_test,${NOVAD},eclipse) ${TEST_ARG} endif h316 : ${BIN}h316${EXE} ${BIN}h316${EXE} : ${H316} ${SIM} ${MKDIRBIN} - ${CC} ${H316} ${SIM} ${H316_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${H316} ${SIM} ${H316_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${H316D},h316)) - $@ $(call find_test,${H316D},h316) $(TEST_ARG) + $@ $(call find_test,${H316D},h316) ${TEST_ARG} endif hp2100 : ${BIN}hp2100${EXE} ${BIN}hp2100${EXE} : ${HP2100} ${SIM} -ifneq (1,$(CPP_BUILD)$(CPP_FORCE)) +ifneq (1,${CPP_BUILD}${CPP_FORCE}) ${MKDIRBIN} - ${CC} ${HP2100} ${SIM} ${HP2100_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${HP2100} ${SIM} ${HP2100_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${HP2100D},hp2100)) - $@ $(call find_test,${HP2100D},hp2100) $(TEST_ARG) + $@ $(call find_test,${HP2100D},hp2100) ${TEST_ARG} endif else $(info hp2100 can't be built using C++) @@ -2176,11 +2480,11 @@ endif hp3000 : ${BIN}hp3000${EXE} ${BIN}hp3000${EXE} : ${HP3000} ${SIM} -ifneq (1,$(CPP_BUILD)$(CPP_FORCE)) +ifneq (1,${CPP_BUILD}${CPP_FORCE}) ${MKDIRBIN} - ${CC} ${HP3000} ${SIM} ${HP3000_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${HP3000} ${SIM} ${HP3000_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${HP3000D},hp3000)) - $@ $(call find_test,${HP3000D},hp3000) $(TEST_ARG) + $@ $(call find_test,${HP3000D},hp3000) ${TEST_ARG} endif else $(info hp3000 can't be built using C++) @@ -2190,43 +2494,43 @@ i1401 : ${BIN}i1401${EXE} ${BIN}i1401${EXE} : ${I1401} ${SIM} ${MKDIRBIN} - ${CC} ${I1401} ${SIM} ${I1401_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${I1401} ${SIM} ${I1401_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${I1401D},i1401)) - $@ $(call find_test,${I1401D},i1401) $(TEST_ARG) + $@ $(call find_test,${I1401D},i1401) ${TEST_ARG} endif i1620 : ${BIN}i1620${EXE} ${BIN}i1620${EXE} : ${I1620} ${SIM} ${MKDIRBIN} - ${CC} ${I1620} ${SIM} ${I1620_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${I1620} ${SIM} ${I1620_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${I1620D},i1620)) - $@ $(call find_test,${I1620D},i1620) $(TEST_ARG) + $@ $(call find_test,${I1620D},i1620) ${TEST_ARG} endif i7094 : ${BIN}i7094${EXE} ${BIN}i7094${EXE} : ${I7094} ${SIM} ${MKDIRBIN} - ${CC} ${I7094} ${SIM} ${I7094_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${I7094} ${SIM} ${I7094_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${I7094D},i7094)) - $@ $(call find_test,${I7094D},i7094) $(TEST_ARG) + $@ $(call find_test,${I7094D},i7094) ${TEST_ARG} endif ibm1130 : ${BIN}ibm1130${EXE} ${BIN}ibm1130${EXE} : ${IBM1130} -ifneq (1,$(CPP_BUILD)$(CPP_FORCE)) +ifneq (1,${CPP_BUILD}${CPP_FORCE}) ${MKDIRBIN} ifneq (${WIN32},) - windres ${IBM1130D}/ibm1130.rc $(BIN)ibm1130.o - ${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} $(BIN)ibm1130.o $(CC_OUTSPEC) ${LDFLAGS} - del BIN\ibm1130.o -else - ${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} $(CC_OUTSPEC) ${LDFLAGS} -ifneq (,$(call find_test,${IBM1130D},ibm1130)) - $@ $(call find_test,${IBM1130D},ibm1130) $(TEST_ARG) + windres ${IBM1130D}/ibm1130.rc ${BIN}ibm1130.o endif + ${CC} ${IBM1130} ${SIM} ${IBM1130_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (${WIN32},) + del BIN\ibm1130.o +endif +ifneq (,$(call find_test,${IBM1130D},ibm1130)) + $@ $(call find_test,${IBM1130D},ibm1130) ${TEST_ARG} endif else $(info ibm1130 can't be built using C++) @@ -2269,185 +2573,231 @@ ifneq (,$(call find_test,${SEL32D},sel32)) $@ $(call find_test,${SEL32D},sel32) $(TEST_ARG) endif - s3 : ${BIN}s3${EXE} ${BIN}s3${EXE} : ${S3} ${SIM} ${MKDIRBIN} - ${CC} ${S3} ${SIM} ${S3_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${S3} ${SIM} ${S3_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${S3D},s3)) - $@ $(call find_test,${S3D},s3) $(TEST_ARG) + $@ $(call find_test,${S3D},s3) ${TEST_ARG} endif altair : ${BIN}altair${EXE} ${BIN}altair${EXE} : ${ALTAIR} ${SIM} ${MKDIRBIN} - ${CC} ${ALTAIR} ${SIM} ${ALTAIR_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ALTAIR} ${SIM} ${ALTAIR_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${ALTAIRD},altair)) - $@ $(call find_test,${ALTAIRD},altair) $(TEST_ARG) + $@ $(call find_test,${ALTAIRD},altair) ${TEST_ARG} endif altairz80 : ${BIN}altairz80${EXE} ${BIN}altairz80${EXE} : ${ALTAIRZ80} ${SIM} ${MKDIRBIN} - ${CC} ${ALTAIRZ80} ${SIM} ${ALTAIRZ80_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ALTAIRZ80} ${SIM} ${ALTAIRZ80_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${ALTAIRZ80D},altairz80)) - $@ $(call find_test,${ALTAIRZ80D},altairz80) $(TEST_ARG) + $@ $(call find_test,${ALTAIRZ80D},altairz80) ${TEST_ARG} endif gri : ${BIN}gri${EXE} ${BIN}gri${EXE} : ${GRI} ${SIM} ${MKDIRBIN} - ${CC} ${GRI} ${SIM} ${GRI_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${GRI} ${SIM} ${GRI_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${GRID},gri)) - $@ $(call find_test,${GRID},gri) $(TEST_ARG) + $@ $(call find_test,${GRID},gri) ${TEST_ARG} endif lgp : ${BIN}lgp${EXE} ${BIN}lgp${EXE} : ${LGP} ${SIM} ${MKDIRBIN} - ${CC} ${LGP} ${SIM} ${LGP_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${LGP} ${SIM} ${LGP_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${LGPD},lgp)) - $@ $(call find_test,${LGPD},lgp) $(TEST_ARG) + $@ $(call find_test,${LGPD},lgp) ${TEST_ARG} endif id16 : ${BIN}id16${EXE} ${BIN}id16${EXE} : ${ID16} ${SIM} ${MKDIRBIN} - ${CC} ${ID16} ${SIM} ${ID16_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ID16} ${SIM} ${ID16_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${ID32D},id16)) - $@ $(call find_test,${ID32D},id16) $(TEST_ARG) + $@ $(call find_test,${ID32D},id16) ${TEST_ARG} endif id32 : ${BIN}id32${EXE} ${BIN}id32${EXE} : ${ID32} ${SIM} ${MKDIRBIN} - ${CC} ${ID32} ${SIM} ${ID32_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ID32} ${SIM} ${ID32_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${ID32D},id32)) - $@ $(call find_test,${ID32D},id32) $(TEST_ARG) + $@ $(call find_test,${ID32D},id32) ${TEST_ARG} endif sds : ${BIN}sds${EXE} ${BIN}sds${EXE} : ${SDS} ${SIM} ${MKDIRBIN} - ${CC} ${SDS} ${SIM} ${SDS_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${SDS} ${SIM} ${SDS_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${SDSD},sds)) - $@ $(call find_test,${SDSD},sds) $(TEST_ARG) + $@ $(call find_test,${SDSD},sds) ${TEST_ARG} endif -swtp6800mp-a : ${BIN}BuildROMs${EXE} ${BIN}swtp6800mp-a${EXE} +swtp6800mp-a : ${BIN}swtp6800mp-a${EXE} ${BIN}swtp6800mp-a${EXE} : ${SWTP6800MP-A} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${SWTP6800MP-A} ${SIM} ${SWTP6800_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${SWTP6800MP-A} ${SIM} ${SWTP6800_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${SWTP6800D},swtp6800mp-a)) - $@ $(call find_test,${SWTP6800D},swtp6800mp-a) $(TEST_ARG) + $@ $(call find_test,${SWTP6800D},swtp6800mp-a) ${TEST_ARG} endif -swtp6800mp-a2 : ${BIN}BuildROMs${EXE} ${BIN}swtp6800mp-a2${EXE} +swtp6800mp-a2 : ${BIN}swtp6800mp-a2${EXE} ${BIN}swtp6800mp-a2${EXE} : ${SWTP6800MP-A2} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${SWTP6800MP-A2} ${SIM} ${SWTP6800_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${SWTP6800MP-A2} ${SIM} ${SWTP6800_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${SWTP6800D},swtp6800mp-a2)) - $@ $(call find_test,${SWTP6800D},swtp6800mp-a2) $(TEST_ARG) + $@ $(call find_test,${SWTP6800D},swtp6800mp-a2) ${TEST_ARG} endif isys8010: ${BIN}isys8010${EXE} ${BIN}isys8010${EXE} : ${ISYS8010} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${ISYS8010} ${SIM} ${ISYS8010_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ISYS8010} ${SIM} ${ISYS8010_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${ISYS8010D},isys8010)) - $@ $(call find_test,${ISYS8010D},isys8010) $(TEST_ARG) + $@ $(call find_test,${ISYS8010D},isys8010) ${TEST_ARG} endif isys8020: ${BIN}isys8020${EXE} ${BIN}isys8020${EXE} : ${ISYS8020} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${ISYS8020} ${SIM} ${ISYS8020_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ISYS8020} ${SIM} ${ISYS8020_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${ISYS8020D},isys8020)) - $@ $(call find_test,${ISYS8020D},isys8020) $(TEST_ARG) + $@ $(call find_test,${ISYS8020D},isys8020) ${TEST_ARG} endif isys8024: ${BIN}isys8024${EXE} ${BIN}isys8024${EXE} : ${ISYS8024} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${ISYS8024} ${SIM} ${ISYS8024_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ISYS8024} ${SIM} ${ISYS8024_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${ISYS8024D},isys8024)) - $@ $(call find_test,${ISYS8024D},isys8024) $(TEST_ARG) + $@ $(call find_test,${ISYS8024D},isys8024) ${TEST_ARG} endif isys8030: ${BIN}isys8030${EXE} ${BIN}isys8030${EXE} : ${ISYS8030} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${ISYS8030} ${SIM} ${ISYS8030_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ISYS8030} ${SIM} ${ISYS8030_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${ISYS8030D},isys8030)) - $@ $(call find_test,${ISYS8030D},isys8030) $(TEST_ARG) + $@ $(call find_test,${ISYS8030D},isys8030) ${TEST_ARG} +endif + +imds-210: ${BIN}imds-210${EXE} + +${BIN}imds-210${EXE} : ${IMDS210} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IMDS210} ${SIM} ${IMDS210_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (,$(call find_test,${IMDS210D},imds-210)) + $@ $(call find_test,${IMDS210D},imds-210) ${TEST_ARG} +endif + +imds-220: ${BIN}imds-220${EXE} + +${BIN}imds-220${EXE} : ${IMDS220} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IMDS220} ${SIM} ${IMDS220_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (,$(call find_test,${IMDS220D},imds-220)) + $@ $(call find_test,${IMDS220D},imds-220) ${TEST_ARG} endif imds-225: ${BIN}imds-225${EXE} -${BIN}imds-225${EXE} : ${IMDS-225} ${SIM} ${BUILD_ROMS} +${BIN}imds-225${EXE} : ${IMDS225} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${IMDS-225} ${SIM} ${IMDS-225_OPT} $(CC_OUTSPEC) ${LDFLAGS} -ifneq (,$(call find_test,${IMDS-225D},imds-225)) - $@ $(call find_test,${IMDS-225D},imds-225) $(TEST_ARG) + ${CC} ${IMDS225} ${SIM} ${IMDS225_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (,$(call find_test,${IMDS225D},imds-225)) + $@ $(call find_test,${IMDS225D},imds-225) ${TEST_ARG} +endif + +imds-230: ${BIN}imds-230${EXE} + +${BIN}imds-230${EXE} : ${IMDS230} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IMDS230} ${SIM} ${IMDS230_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (,$(call find_test,${IMDS230D},imds-230)) + $@ $(call find_test,${IMDS230D},imds-230) ${TEST_ARG} +endif + +imds-800: ${BIN}imds-800${EXE} + +${BIN}imds-800${EXE} : ${IMDS800} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IMDS800} ${SIM} ${IMDS800_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (,$(call find_test,${IMDS800D},imds-800)) + $@ $(call find_test,${IMDS800D},imds-800) ${TEST_ARG} +endif + +imds-810: ${BIN}imds-810${EXE} + +${BIN}imds-810${EXE} : ${IMDS810} ${SIM} ${BUILD_ROMS} + ${MKDIRBIN} + ${CC} ${IMDS810} ${SIM} ${IMDS810_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (,$(call find_test,${IMDS810D},imds-810)) + $@ $(call find_test,${IMDS810D},imds-810) ${TEST_ARG} endif ibmpc: ${BIN}ibmpc${EXE} ${BIN}ibmpc${EXE} : ${IBMPC} ${SIM} ${BUILD_ROMS} + #cmake:ignore-target ${MKDIRBIN} - ${CC} ${IBMPC} ${SIM} ${IBMPC_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${IBMPC} ${SIM} ${IBMPC_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${IBMPCD},ibmpc)) - $@ $(call find_test,${IBMPCD},ibmpc) $(TEST_ARG) + $@ $(call find_test,${IBMPCD},ibmpc) ${TEST_ARG} endif ibmpcxt: ${BIN}ibmpcxt${EXE} ${BIN}ibmpcxt${EXE} : ${IBMPCXT} ${SIM} ${BUILD_ROMS} + #cmake:ignore-target ${MKDIRBIN} - ${CC} ${IBMPCXT} ${SIM} ${IBMPCXT_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${IBMPCXT} ${SIM} ${IBMPCXT_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${IBMPCXTD},ibmpcxt)) - $@ $(call find_test,${IBMPCXTD},ibmpcxt) $(TEST_ARG) + $@ $(call find_test,${IBMPCXTD},ibmpcxt) ${TEST_ARG} endif scelbi: ${BIN}scelbi${EXE} ${BIN}scelbi${EXE} : ${SCELBI} ${SIM} ${MKDIRBIN} - ${CC} ${SCELBI} ${SIM} ${SCELBI_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${SCELBI} ${SIM} ${SCELBI_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${SCELBID},scelbi)) - $@ $(call find_test,${SCELBID},scelbi) $(TEST_ARG) + $@ $(call find_test,${SCELBID},scelbi) ${TEST_ARG} endif tx-0 : ${BIN}tx-0${EXE} ${BIN}tx-0${EXE} : ${TX0} ${SIM} ${MKDIRBIN} - ${CC} ${TX0} ${SIM} ${TX0_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${TX0} ${SIM} ${TX0_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${TX0D},tx-0)) - $@ $(call find_test,${TX0D},tx-0) $(TEST_ARG) + $@ $(call find_test,${TX0D},tx-0) ${TEST_ARG} endif ssem : ${BIN}ssem${EXE} ${BIN}ssem${EXE} : ${SSEM} ${SIM} ${MKDIRBIN} - ${CC} ${SSEM} ${SIM} ${SSEM_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${SSEM} ${SIM} ${SSEM_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${SSEMD},ssem)) - $@ $(call find_test,${SSEMD},ssem) $(TEST_ARG) + $@ $(call find_test,${SSEMD},ssem) ${TEST_ARG} endif cdc1700 : ${BIN}cdc1700${EXE} @@ -2456,17 +2806,17 @@ ${BIN}cdc1700${EXE} : ${CDC1700} ${SIM} ${MKDIRBIN} ${CC} ${CDC1700} ${SIM} ${CDC1700_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${CDC1700D},cdc1700)) - $@ $(call find_test,${CDC1700D},cdc1700) $(TEST_ARG) + $@ $(call find_test,${CDC1700D},cdc1700) ${TEST_ARG} endif besm6 : ${BIN}besm6${EXE} ${BIN}besm6${EXE} : ${BESM6} ${SIM} -ifneq (1,$(CPP_BUILD)$(CPP_FORCE)) +ifneq (1,${CPP_BUILD}${CPP_FORCE}) ${MKDIRBIN} - ${CC} ${BESM6} ${SIM} ${BESM6_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${BESM6} ${SIM} ${BESM6_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${BESM6D},besm6)) - $@ $(call find_test,${BESM6D},besm6) $(TEST_ARG) + $@ $(call find_test,${BESM6D},besm6) ${TEST_ARG} endif else $(info besm6 can't be built using C++) @@ -2476,117 +2826,154 @@ sigma : ${BIN}sigma${EXE} ${BIN}sigma${EXE} : ${SIGMA} ${SIM} ${MKDIRBIN} - ${CC} ${SIGMA} ${SIM} ${SIGMA_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${SIGMA} ${SIM} ${SIGMA_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${SIGMAD},sigma)) - $@ $(call find_test,${SIGMAD},sigma) $(TEST_ARG) + $@ $(call find_test,${SIGMAD},sigma) ${TEST_ARG} endif alpha : ${BIN}alpha${EXE} ${BIN}alpha${EXE} : ${ALPHA} ${SIM} ${MKDIRBIN} - ${CC} ${ALPHA} ${SIM} ${ALPHA_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ALPHA} ${SIM} ${ALPHA_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${ALPHAD},alpha)) - $@ $(call find_test,${ALPHAD},alpha) $(TEST_ARG) + $@ $(call find_test,${ALPHAD},alpha) ${TEST_ARG} endif sage : ${BIN}sage${EXE} ${BIN}sage${EXE} : ${SAGE} ${SIM} ${MKDIRBIN} - ${CC} ${SAGE} ${SIM} ${SAGE_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${SAGE} ${SIM} ${SAGE_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${SAGED},sage)) - $@ $(call find_test,${SAGED},sage) $(TEST_ARG) + $@ $(call find_test,${SAGED},sage) ${TEST_ARG} endif pdq3 : ${BIN}pdq3${EXE} ${BIN}pdq3${EXE} : ${PDQ3} ${SIM} ${MKDIRBIN} - ${CC} ${PDQ3} ${SIM} ${PDQ3_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${PDQ3} ${SIM} ${PDQ3_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${PDQ3D},pdq3)) - $@ $(call find_test,${PDQ3D},pdq3) $(TEST_ARG) + $@ $(call find_test,${PDQ3D},pdq3) ${TEST_ARG} endif -b5500 : $(BIN)b5500$(EXE) +b5500 : ${BIN}b5500${EXE} ${BIN}b5500${EXE} : ${B5500} ${SIM} ${MKDIRBIN} - ${CC} ${B5500} ${SIM} ${B5500_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${B5500} ${SIM} ${B5500_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${B5500D},b5500)) - $@ $(call find_test,${B5500D},b5500) $(TEST_ARG) + $@ $(call find_test,${B5500D},b5500) ${TEST_ARG} endif -3b2 : ${BIN}BuildROMs${EXE} $(BIN)3b2$(EXE) +3b2 : ${BIN}3b2${EXE} ${BIN}3b2${EXE} : ${ATT3B2} ${SIM} ${BUILD_ROMS} ${MKDIRBIN} - ${CC} ${ATT3B2} ${SIM} ${ATT3B2_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${ATT3B2} ${SIM} ${ATT3B2_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${ATT3B2D},3b2)) - $@ $(call find_test,${ATT3B2D},3b2) $(TEST_ARG) + $@ $(call find_test,${ATT3B2D},3b2) ${TEST_ARG} endif -i7090 : $(BIN)i7090$(EXE) +i7090 : ${BIN}i7090${EXE} ${BIN}i7090${EXE} : ${I7090} ${SIM} ${MKDIRBIN} - ${CC} ${I7090} ${SIM} ${I7090_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${I7090} ${SIM} ${I7090_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${I7000D},i7090)) - $@ $(call find_test,${I7000D},i7090) $(TEST_ARG) + $@ $(call find_test,${I7000D},i7090) ${TEST_ARG} endif -i7080 : $(BIN)i7080$(EXE) +i7080 : ${BIN}i7080${EXE} ${BIN}i7080${EXE} : ${I7080} ${SIM} ${MKDIRBIN} - ${CC} ${I7080} ${SIM} ${I7080_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${I7080} ${SIM} ${I7080_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${I7080D},i7080)) - $@ $(call find_test,${I7080D},i7080) $(TEST_ARG) + $@ $(call find_test,${I7080D},i7080) ${TEST_ARG} endif -i7070 : $(BIN)i7070$(EXE) +i7070 : ${BIN}i7070${EXE} ${BIN}i7070${EXE} : ${I7070} ${SIM} ${MKDIRBIN} - ${CC} ${I7070} ${SIM} ${I7070_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${I7070} ${SIM} ${I7070_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${I7070D},i7070)) - $@ $(call find_test,${I7070D},i7070) $(TEST_ARG) + $@ $(call find_test,${I7070D},i7070) ${TEST_ARG} endif -i7010 : $(BIN)i7010$(EXE) +i7010 : ${BIN}i7010${EXE} ${BIN}i7010${EXE} : ${I7010} ${SIM} ${MKDIRBIN} - ${CC} ${I7010} ${SIM} ${I7010_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${I7010} ${SIM} ${I7010_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${I7010D},i7010)) - $@ $(call find_test,${I7010D},i7010) $(TEST_ARG) + $@ $(call find_test,${I7010D},i7010) ${TEST_ARG} endif -i704 : $(BIN)i704$(EXE) +i704 : ${BIN}i704${EXE} ${BIN}i704${EXE} : ${I704} ${SIM} ${MKDIRBIN} - ${CC} ${I704} ${SIM} ${I704_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${I704} ${SIM} ${I704_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${I704D},i704)) - $@ $(call find_test,${I704D},i704) $(TEST_ARG) + $@ $(call find_test,${I704D},i704) ${TEST_ARG} endif -i701 : $(BIN)i701$(EXE) +i701 : ${BIN}i701${EXE} ${BIN}i701${EXE} : ${I701} ${SIM} ${MKDIRBIN} - ${CC} ${I701} ${SIM} ${I701_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${I701} ${SIM} ${I701_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${I701D},i701)) - $@ $(call find_test,${I701D},i701) $(TEST_ARG) + $@ $(call find_test,${I701D},i701) ${TEST_ARG} endif -i650 : $(BIN)i650$(EXE) +i650 : ${BIN}i650${EXE} ${BIN}i650${EXE} : ${I650} ${SIM} + #cmake:ignore-target ${MKDIRBIN} - ${CC} ${I650} ${SIM} ${I650_OPT} $(CC_OUTSPEC) ${LDFLAGS} + ${CC} ${I650} ${SIM} ${I650_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${I650D},i650)) - $@ $(call find_test,${I650D},i650) $(TEST_ARG) + $@ $(call find_test,${I650D},i650) ${TEST_ARG} +endif + +pdp6 : ${BIN}pdp6${EXE} + +${BIN}pdp6${EXE} : ${PDP6} ${SIM} + ${MKDIRBIN} + ${CC} ${PDP6} ${PDP6_DPY} ${SIM} ${PDP6_OPT} ${CC_OUTSPEC} ${LDFLAGS} ${PDP6_LDFLAGS} +ifneq (,$(call find_test,${PDP10D},pdp6)) + $@ $(call find_test,${PDP10D},pdp6) ${TEST_ARG} +endif + +pdp10-ka : ${BIN}pdp10-ka${EXE} + +${BIN}pdp10-ka${EXE} : ${KA10} ${SIM} + ${MKDIRBIN} + ${CC} ${KA10} ${KA10_DPY} ${SIM} ${KA10_OPT} ${CC_OUTSPEC} ${LDFLAGS} ${KA10_LDFLAGS} +ifneq (,$(call find_test,${PDP10D},ka10)) + $@ $(call find_test,${PDP10D},ka10) ${TEST_ARG} +endif + +pdp10-ki : ${BIN}pdp10-ki${EXE} + +${BIN}pdp10-ki${EXE} : ${KI10} ${SIM} + ${MKDIRBIN} + ${CC} ${KI10} ${KI10_DPY} ${SIM} ${KI10_OPT} ${CC_OUTSPEC} ${LDFLAGS} ${KI10_LDFLAGS} +ifneq (,$(call find_test,${PDP10D},ki10)) + $@ $(call find_test,${PDP10D},ki10) ${TEST_ARG} +endif + +pdp10-kl : ${BIN}pdp10-kl${EXE} + +${BIN}pdp10-kl${EXE} : ${KL10} ${SIM} + ${MKDIRBIN} + ${CC} ${KL10} ${SIM} ${KL10_OPT} ${CC_OUTSPEC} ${LDFLAGS} +ifneq (,$(call find_test,${PDP10D},kl10)) + $@ $(call find_test,${PDP10D},kl10) ${TEST_ARG} endif # Front Panel API Demo/Test program @@ -2594,6 +2981,7 @@ endif frontpaneltest : ${BIN}frontpaneltest${EXE} ${BIN}frontpaneltest${EXE} : frontpanel/FrontPanelTest.c sim_sock.c sim_frontpanel.c + #cmake:ignore-target ${MKDIRBIN} - ${CC} frontpanel/FrontPanelTest.c sim_sock.c sim_frontpanel.c $(CC_OUTSPEC) ${LDFLAGS} $(OS_CURSES_DEFS) + ${CC} frontpanel/FrontPanelTest.c sim_sock.c sim_frontpanel.c ${CC_OUTSPEC} ${LDFLAGS} ${OS_CURSES_DEFS} diff --git a/scp.c b/scp.c index d0ea586..7040d61 100644 --- a/scp.c +++ b/scp.c @@ -451,6 +451,7 @@ t_addr (*sim_vm_parse_addr) (DEVICE *dptr, CONST char *cptr, CONST char **tptr) t_value (*sim_vm_pc_value) (void) = NULL; t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs) = NULL; t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason) = NULL; +const char *sim_vm_release = NULL; const char **sim_clock_precalibrate_commands = NULL; @@ -479,6 +480,7 @@ t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char t_stat show_default (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat show_break (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat show_on (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); +t_stat show_runlimit (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_send (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat sim_show_expect (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); t_stat show_device (FILE *st, DEVICE *dptr, int32 flag); @@ -544,6 +546,7 @@ t_stat dep_addr (int32 flag, const char *cptr, t_addr addr, DEVICE *dptr, UNIT *uptr, int32 dfltinc); void fprint_fields (FILE *stream, t_value before, t_value after, BITFIELD* bitdefs); t_stat step_svc (UNIT *ptr); +t_stat runlimit_svc (UNIT *ptr); t_stat expect_svc (UNIT *ptr); t_stat flush_svc (UNIT *ptr); t_stat shift_args (char *do_arg[], size_t arg_count); @@ -556,6 +559,7 @@ t_stat sim_show_asynch (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST ch t_stat do_cmd_label (int32 flag, CONST char *cptr, CONST char *label); void int_handler (int signal); t_stat set_prompt (int32 flag, CONST char *cptr); +t_stat set_runlimit (int32 flag, CONST char *cptr); t_stat sim_set_asynch (int32 flag, CONST char *cptr); static const char *_get_dbg_verb (uint32 dbits, DEVICE* dptr, UNIT *uptr); static t_stat sim_library_unit_tests (void); @@ -563,6 +567,7 @@ static t_stat _sim_debug_flush (void); /* Global data */ +const char *sim_prog_name = NULL; /* pointer to the executable name */ DEVICE *sim_dflt_dev = NULL; UNIT *sim_clock_queue = QUEUE_LIST_END; int32 sim_interval = 0; @@ -594,6 +599,12 @@ int32 sim_brk_lnt = 0; int32 sim_brk_ins = 0; int32 sim_quiet = 0; int32 sim_step = 0; +int32 sim_runlimit = 0; +int32 sim_runlimit_initial = 0; +double sim_runlimit_d = 0.0; +double sim_runlimit_d_initial = 0.0; +int32 sim_runlimit_switches = 0; +t_bool sim_runlimit_enabled = FALSE; char *sim_sub_instr = NULL; /* Copy of pre-substitution buffer contents */ char *sim_sub_instr_buf = NULL; /* Buffer address that substitutions were saved in */ size_t sim_sub_instr_size = 0; /* substitution buffer size */ @@ -660,6 +671,31 @@ DEVICE sim_step_dev = { NULL, NULL, NULL, NULL, NULL, NULL, sim_int_step_description}; +static const char *sim_int_runlimit_description (DEVICE *dptr) +{ +return "Run time limit facility"; +} + +static t_stat sim_int_runlimit_reset (DEVICE *dptr) +{ +if (sim_runlimit_enabled) { + if (sim_runlimit_switches & SWMASK ('T')) + return sim_activate_after_d (dptr->units, sim_runlimit_d); + else + return sim_activate (dptr->units, sim_runlimit); + } +return SCPE_OK; +} + +static UNIT sim_runlimit_unit = { UDATA (&runlimit_svc, UNIT_IDLE, 0) }; +DEVICE sim_runlimit_dev = { + "INT-RUNLIMIT", &sim_runlimit_unit, NULL, NULL, + 1, 0, 0, 0, 0, 0, + NULL, NULL, &sim_int_runlimit_reset, NULL, NULL, NULL, + NULL, DEV_NOSAVE, 0, + NULL, NULL, NULL, NULL, NULL, NULL, + sim_int_runlimit_description}; + static const char *sim_int_expect_description (DEVICE *dptr) { return "Expect facility"; @@ -762,6 +798,7 @@ const struct scp_error { {"INVEXPR", "invalid expression"}, {"SIGTERM", "SIGTERM received"}, {"FSSIZE", "File System size larger than disk size"}, + {"RUNTIME", "Run time limit exhausted"}, }; const size_t size_map[] = { sizeof (int8), @@ -1070,6 +1107,25 @@ static const char simh_help[] = " \"SET NODEBUG\" commands. Additionally, support is provided that is\n" " equivalent to the \"SET DEBUG=opt1{;opt2}\" and\n" " \"SET NODEBUG=opt1{;opt2}\" commands.\n\n" +#define HLP_RUNLIMIT "*Commands Stopping_The_Simulator User_Specified_Stop_Conditions RUNLIMIT" + "4RUNLIMIT\n" + " A simulator user may want to limit the maximum execution time that a\n" + " simulator may run for. This might be appropriate to limit a runaway\n" + " diagnostic which didn't achieve explicit success or failure within\n" + " some user specified time. The RUNLIMIT command provides ways to\n" + " limit execution.\n\n" + "++RUNLIMIT n {CYCLES|MICROSECONDS|SECONDS|MINUTES|HOURS}\n" + "++NORUNLIMIT\n\n" + " Equivalently:\n\n" + "++SET RUNLIMIT n {CYCLES|MICROSECONDS|SECONDS|MINUTES|HOURS}\n" + "++SET NORUNLIMIT\n\n" + " The run limit state can be examined with:\n\n" + "++SHOW RUNLIMIT\n\n" + " If the units of the run limit are not specified, the default units are\n" + " cycles. Once an execution run limit has beenn reached, any subsequent\n" + " GO, RUN, CONTINUE, STEP or BOOT commands will cause the simulator to\n" + " exit. A previously defined RUNLIMIT can be cleared with the NORUNLIMIT\n" + " command or the establishment of a new run limit.\n" /***************** 80 character line width template *************************/ "2Connecting and Disconnecting Devices\n" " Except for main memory and network devices, units are simulated as\n" @@ -1483,6 +1539,7 @@ static const char simh_help[] = "+sh{ow} clocks show calibrated timer information\n" "+sh{ow} throttle show throttle info\n" "+sh{ow} on show on condition actions\n" + "+sh{ow} runlimit show execution limit states\n" "+h{elp} show displays the device specific show commands\n" "++++++++ available\n" #define HLP_SHOW_CONFIG "*Commands SHOW" @@ -1508,6 +1565,7 @@ static const char simh_help[] = #define HLP_SHOW_VIDEO "*Commands SHOW" #define HLP_SHOW_CLOCKS "*Commands SHOW" #define HLP_SHOW_ON "*Commands SHOW" +#define HLP_SHOW_RUNLIMIT "*Commands SHOW" #define HLP_SHOW_SEND "*Commands SHOW" #define HLP_SHOW_EXPECT "*Commands SHOW" #define HLP_HELP "*Commands HELP" @@ -1800,6 +1858,8 @@ static const char simh_help[] = " Invalid remote console command\n" "5 AMBREG\n" " Ambiguous register\n" + "5 RUNTIME\n" + " Run time limit exhausted\n" #define HLP_SHIFT "*Commands Executing_Command_Files SHIFT" "3SHIFT\n" "++shift shift the command file's positional parameters\n" @@ -2059,15 +2119,11 @@ static const char simh_help[] = " as a regular expression applied to the output data stream. This regular\n" " expression may contain parentheses delimited sub-groups.\n\n" /***************** 80 character line width template *************************/ -#if defined (HAVE_PCREPOSIX_H) +#if defined (HAVE_PCRE_H) " The syntax of the regular expressions available are those supported by\n" " the Perl Compatible Regular Expression package (aka PCRE). As the name\n" " implies, the syntax is generally the same as Perl regular expressions.\n" " See http://perldoc.perl.org/perlre.html for more details\n" -#elif defined (HAVE_REGEX_H) - " The syntax of the regular expressions available are those supported by\n" - " your local system's Regular Expression library using the Extended POSIX\n" - " Regular Expressiona\n" #else " Regular expression support is not currently available on your environment.\n" " This simulator could use regular expression support provided by the\n" @@ -2391,6 +2447,8 @@ static CTAB cmd_table[] = { #if defined(USE_SIM_VIDEO) { "SCREENSHOT", &screenshot_cmd,0, HLP_SCREENSHOT, NULL, NULL }, #endif + { "RUNLIMIT", &runlimit_cmd, 1, HLP_RUNLIMIT, NULL, NULL }, + { "NORUNLIMIT", &runlimit_cmd, 0, HLP_RUNLIMIT, NULL, NULL }, { NULL, NULL, 0, NULL, NULL, NULL } }; @@ -2423,6 +2481,8 @@ static CTAB set_glob_tab[] = { { "QUIET", &set_quiet, 1, HLP_SET_QUIET }, { "NOQUIET", &set_quiet, 0, HLP_SET_QUIET }, { "PROMPT", &set_prompt, 0, HLP_SET_PROMPT }, + { "RUNLIMIT", &set_runlimit, 1, HLP_RUNLIMIT }, + { "NORUNLIMIT", &set_runlimit, 0, HLP_RUNLIMIT }, { NULL, NULL, 0 } }; @@ -2476,6 +2536,7 @@ static SHTAB show_glob_tab[] = { { "SEND", &sim_show_send, 0, HLP_SHOW_SEND }, { "EXPECT", &sim_show_expect, 0, HLP_SHOW_EXPECT }, { "ON", &show_on, 0, HLP_SHOW_ON }, + { "RUNLIMIT", &show_runlimit, 0, HLP_SHOW_RUNLIMIT }, { NULL, NULL, 0 } }; @@ -2546,6 +2607,7 @@ set_prompt (0, "sim>"); /* start with set standa sim_switches = 0; /* init switches */ lookswitch = TRUE; stdnul = fopen(NULL_DEVICE,"wb"); +sim_prog_name = argv [0]; /* save a pointer to the program name */ for (i = 1; i < argc; i++) { /* loop thru args */ if (argv[i] == NULL) /* paranoia */ continue; @@ -2597,6 +2659,7 @@ sim_register_internal_device (&sim_scp_dev); sim_register_internal_device (&sim_expect_dev); sim_register_internal_device (&sim_step_dev); sim_register_internal_device (&sim_flush_dev); +sim_register_internal_device (&sim_runlimit_dev); if ((stat = sim_ttinit ()) != SCPE_OK) { fprintf (stderr, "Fatal terminal initialization error\n%s\n", @@ -2630,10 +2693,8 @@ if (!sim_quiet) { } sim_timer_precalibrate_execution_rate (); show_version (stdnul, NULL, NULL, 1, NULL); /* Quietly set SIM_OSTYPE */ -#if defined (HAVE_PCREPOSIX_H) -setenv ("SIM_REGEX_TYPE", "PCREPOSIX", 1); /* Publish regex type */ -#elif defined (HAVE_REGEX_H) -setenv ("SIM_REGEX_TYPE", "REGEX", 1); /* Publish regex type */ +#if defined (HAVE_PCRE_H) +setenv ("SIM_REGEX_TYPE", "PCRE", 1); /* Publish regex type */ #endif if (*argv[0]) { /* sim name arg? */ char *np; /* "path.ini" */ @@ -5803,6 +5864,10 @@ setenv ("SIM_MINOR", vmin_s, 1); sprintf (vpat_s, "%d", vpat); setenv ("SIM_PATCH", vpat_s, 1); fprintf (st, "%s simulator V%d.%d-%d", sim_name, vmaj, vmin, vpat); +if (sim_vm_release != NULL) { /* if a release string is defined */ + setenv ("SIM_VM_RELEASE", sim_vm_release, 1); + fprintf (st, " Release %s", sim_vm_release); /* then display it */ + } if (vdelt) { sprintf (vdelt_s, "%d", vdelt); setenv ("SIM_DELTA", vdelt_s, 1); @@ -5907,10 +5972,8 @@ if (flag) { fprintf (st, "\n Memory Pointer Size: %d bits", (int)sizeof(dptr)*8); fprintf (st, "\n %s", sim_toffset_64 ? "Large File (>2GB) support" : "No Large File support"); fprintf (st, "\n SDL Video support: %s", vid_version()); -#if defined (HAVE_PCREPOSIX_H) +#if defined (HAVE_PCRE_H) fprintf (st, "\n PCRE RegEx (Version %s) support for EXPECT commands", pcre_version()); -#elif defined (HAVE_REGEX_H) - fprintf (st, "\n RegEx support for EXPECT commands"); #else fprintf (st, "\n No RegEx support for EXPECT commands"); #endif @@ -6058,7 +6121,6 @@ t_stat show_queue (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, CONST { DEVICE *dptr; UNIT *uptr; -int32 accum; MEMFILE buf; memset (&buf, 0, sizeof (buf)); @@ -6073,7 +6135,6 @@ else { fprintf (st, "%s event queue status, time = %.0f, executing %s instructions/sec\n", sim_name, sim_time, sim_fmt_numeric (inst_per_sec)); - accum = 0; for (uptr = sim_clock_queue; uptr != QUEUE_LIST_END; uptr = uptr->next) { if (uptr == &sim_step_unit) fprintf (st, " Step timer"); @@ -6089,16 +6150,15 @@ else { else fprintf (st, " Unknown"); if (inst_per_sec != 0.0) - tim = sim_fmt_secs(((accum + uptr->time) / sim_timer_inst_per_sec ()) + (uptr->usecs_remaining / 1000000.0)); + tim = sim_fmt_secs(((_sim_activate_queue_time (uptr) - 1) / sim_timer_inst_per_sec ()) + (uptr->usecs_remaining / 1000000.0)); if (uptr->usecs_remaining) - fprintf (st, " at %d plus %.0f usecs%s%s%s%s\n", accum + uptr->time, uptr->usecs_remaining, + fprintf (st, " at %d plus %.0f usecs%s%s%s%s\n", _sim_activate_queue_time (uptr) - 1, uptr->usecs_remaining, (*tim) ? " (" : "", tim, (*tim) ? " total)" : "", (uptr->flags & UNIT_IDLE) ? " (Idle capable)" : ""); else - fprintf (st, " at %d%s%s%s%s\n", accum + uptr->time, + fprintf (st, " at %d%s%s%s%s\n", _sim_activate_queue_time (uptr) - 1, (*tim) ? " (" : "", tim, (*tim) ? ")" : "", (uptr->flags & UNIT_IDLE) ? " (Idle capable)" : ""); - accum = accum + uptr->time; } } sim_show_clock_queues (st, dnotused, unotused, flag, cptr); @@ -6828,6 +6888,108 @@ if (dptr->reset != NULL) else return SCPE_OK; } +t_stat runlimit_cmd (int32 flag, CONST char *cptr) +{ +char gbuf[CBUFSIZE]; +int32 num; +t_stat r; +double usec_factor = 1.0; + +GET_SWITCHES (cptr); /* get switches */ +if (0 == flag) { + if (*cptr) + return sim_messagef (SCPE_ARG, "NORUNLIMIT expects no arguments: %s\n", cptr); + sim_runlimit = 0; + sim_runlimit_switches = 0; + sim_runlimit_enabled = FALSE; + sim_cancel (&sim_runlimit_unit); + return SCPE_OK; + } + +cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ +num = (int32) get_uint (gbuf, 10, INT_MAX, &r); +if ((r != SCPE_OK) || (num == 0)) /* error? */ + return sim_messagef (SCPE_ARG, "Invalid argument: %s\n", gbuf); +cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ +if ((gbuf[0] == '\0') || + (MATCH_CMD (gbuf, "CYCLES") == 0)) + sim_switches &= ~SWMASK ('T'); +else { + int i; + struct { + const char *name; + double usec_factor; + } time_units[] = { + {"MICROSECONDS", 1.0}, + {"USECONDS", 1.0}, + {"SECONDS", 1000000.0}, + {"MINUTES", 60*1000000.0}, + {"HOURS", 60*60*1000000.0}, + {NULL, 0.0}}; + + for (i=0; time_units[i].name; i++) { + if (MATCH_CMD (gbuf, time_units[i].name) == 0) { + sim_switches |= SWMASK ('T'); + usec_factor = time_units[i].usec_factor; + break; + } + } + if (time_units[i].name == NULL) + return sim_messagef (SCPE_2MARG, "Too many arguments: %s %s\n", gbuf, cptr); + } +if (*cptr) + return sim_messagef (SCPE_2MARG, "Too many arguments: %s\n", cptr); +sim_runlimit_enabled = TRUE; +sim_cancel (&sim_runlimit_unit); +sim_runlimit_switches = sim_switches; +if (sim_runlimit_switches & SWMASK ('T')) { + sim_runlimit_d_initial = sim_runlimit_d = num * usec_factor; + return sim_activate_after_d (&sim_runlimit_unit, sim_runlimit_d); + } +else { + sim_runlimit_initial = sim_runlimit = num; + return sim_activate (&sim_runlimit_unit, sim_runlimit); + } +} + +t_stat set_runlimit (int32 flag, CONST char *cptr) +{ +return runlimit_cmd (flag, cptr); +} + +t_stat show_runlimit (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr) +{ +if (sim_runlimit_enabled) { + if (sim_runlimit_switches & SWMASK ('T')) { + double inst_per_sec = sim_timer_inst_per_sec (); + + if (sim_runlimit_d_initial != sim_runlimit_d) { + fprintf (st, "%s initially, ", sim_fmt_secs (sim_runlimit_d_initial / 1000000.0)); + if (sim_is_active (&sim_runlimit_unit)) + fprintf (st, "and %s remaining\n", sim_fmt_secs (sim_runlimit_d / 1000000.0)); + else + fprintf (st, "expired now\n"); + } + else + fprintf (st, "%s\n", sim_fmt_secs (sim_runlimit_d_initial / 1000000.0)); + } + else { + if (sim_runlimit_initial != sim_runlimit) { + fprintf (st, "%d cycles initially, ", sim_runlimit_initial); + if (sim_is_active (&sim_runlimit_unit)) + fprintf (st, "and %d cycles remaining\n", sim_activate_time (&sim_runlimit_unit)); + else + fprintf (st, "expired now\n"); + } + else + fprintf (st, "%d cycles\n", sim_runlimit_initial); + } + } +else + fprintf (st, "Run Limit Disabled\n"); +return SCPE_OK; +} + /* Reset devices start..end Inputs: @@ -7951,6 +8113,11 @@ t_stat r; DEVICE *dptr; UNIT *uptr; +if (sim_runlimit_enabled && /* If the run limit has been hit? */ + (!sim_is_active (&sim_runlimit_unit))) { + sim_messagef (SCPE_RUNTIME, "Execution limit exceeded, can't proceed. Exiting...\n"); + exit (SCPE_RUNTIME); /* Execution can't proceed */ + } GET_SWITCHES (cptr); /* get switches */ sim_step = 0; if ((flag == RU_RUN) || (flag == RU_GO)) { /* run or go */ @@ -8169,6 +8336,13 @@ if ((SCPE_BARE_STATUS(r) == SCPE_STOP) && sigterm_received) r = SCPE_SIGTERM; +if (sim_runlimit_enabled) { + if (sim_runlimit_switches & SWMASK ('T')) + sim_runlimit_d = sim_activate_time_usecs (&sim_runlimit_unit); + else + sim_runlimit = sim_activate_time (&sim_runlimit_unit) - 1; + } + if ((SCPE_BARE_STATUS(r) == SCPE_STOP) && /* WRU exit from sim_instr() */ (sim_on_actions[sim_do_depth][SCPE_STOP] == NULL) &&/* without a handler for a STOP condition */ (sim_on_actions[sim_do_depth][0] == NULL)) @@ -8299,6 +8473,14 @@ t_stat step_svc (UNIT *uptr) return SCPE_STEP; } +/* Unit service for run for timeout, originally scheduled by RUNFOR n command + Return runlimit timeout SCP code, will cause simulation to stop */ + +t_stat runlimit_svc (UNIT *uptr) +{ +return SCPE_RUNTIME; +} + /* Unit service to facilitate expect matching to stop simulation. Return expect SCP code, will cause simulation to stop */ @@ -10894,13 +11076,14 @@ do { } AIO_EVENT_COMPLETE(uptr, reason); bare_reason = SCPE_BARE_STATUS (reason); - if ((bare_reason != SCPE_OK) && /* Provide context for unexpected errors */ - (bare_reason >= SCPE_BASE) && - (bare_reason != SCPE_EXPECT) && - (bare_reason != SCPE_REMOTE) && - (bare_reason != SCPE_MTRLNT) && - (bare_reason != SCPE_STOP) && - (bare_reason != SCPE_STEP) && + if ((bare_reason != SCPE_OK) && /* Provide context for unexpected errors */ + (bare_reason >= SCPE_BASE) && + (bare_reason != SCPE_EXPECT) && + (bare_reason != SCPE_REMOTE) && + (bare_reason != SCPE_MTRLNT) && + (bare_reason != SCPE_STOP) && + (bare_reason != SCPE_STEP) && + (bare_reason != SCPE_RUNTIME) && (bare_reason != SCPE_EXIT)) sim_messagef (reason, "\nUnexpected internal error while processing event for %s which returned %d - %s\n", sim_uname (uptr), reason, sim_error_text (reason)); } while ((reason == SCPE_OK) && @@ -11140,7 +11323,7 @@ return (((uptr->next) || AIO_IS_ACTIVE(uptr) || ((uptr->dynflags & UNIT_TMR_UNIT result = absolute activation time + 1, 0 if inactive */ -int32 _sim_activate_time (UNIT *uptr) +int32 _sim_activate_queue_time (UNIT *uptr) { UNIT *cptr; int32 accum; @@ -11154,11 +11337,20 @@ for (cptr = sim_clock_queue; cptr != QUEUE_LIST_END; cptr = cptr->next) { else accum = accum + cptr->time; if (cptr == uptr) - return accum + 1 + (int32)((uptr->usecs_remaining * sim_timer_inst_per_sec ()) / 1000000.0); + return accum + 1; } return 0; } +int32 _sim_activate_time (UNIT *uptr) +{ +int32 accum = _sim_activate_queue_time (uptr); + +if (accum) + return accum + (int32)((uptr->usecs_remaining * sim_timer_inst_per_sec ()) / 1000000.0); +return 0; +} + int32 sim_activate_time (UNIT *uptr) { int32 accum; @@ -11908,7 +12100,7 @@ free (ep->match_pattern); /* deallocate the displa free (ep->act); /* deallocate action */ #if defined(USE_REGEX) if (ep->switches & EXP_TYP_REGEX) - regfree (&ep->regex); /* release compiled regex */ + pcre_free (ep->regex); /* release compiled regex */ #endif exp->size -= 1; /* decrement count */ for (i=ep-exp->rules; isize; i++) /* shuffle up remaining rules */ @@ -11943,7 +12135,7 @@ for (i=0; isize; i++) { free (exp->rules[i].act); /* deallocate action */ #if defined(USE_REGEX) if (exp->rules[i].switches & EXP_TYP_REGEX) - regfree (&exp->rules[i].regex); /* release compiled regex */ + pcre_free (exp->rules[i].regex); /* release compiled regex */ #endif } free (exp->rules); @@ -11975,25 +12167,21 @@ if (switches & EXP_TYP_REGEX) { return sim_messagef (SCPE_ARG, "RegEx support not available\n"); } #else /* USE_REGEX */ - int res; - regex_t re; + pcre *re; + const char *errmsg; + int erroffset, re_nsub; - memset (&re, 0, sizeof(re)); memcpy (match_buf, match+1, strlen(match)-2); /* extract string without surrounding quotes */ match_buf[strlen(match)-2] = '\0'; - res = regcomp (&re, (char *)match_buf, REG_EXTENDED | ((switches & EXP_TYP_REGEX_I) ? REG_ICASE : 0)); - if (res) { - size_t err_size = regerror (res, &re, NULL, 0); - char *err_buf = (char *)calloc (err_size+1, 1); - - regerror (res, &re, err_buf, err_size); - sim_messagef (SCPE_ARG, "Regular Expression Error: %s\n", err_buf); - free (err_buf); + re = pcre_compile ((char *)match_buf, (switches & EXP_TYP_REGEX_I) ? PCRE_CASELESS : 0, &errmsg, &erroffset, NULL); + if (re == NULL) { + sim_messagef (SCPE_ARG, "Regular Expression Error: %s\n", errmsg); free (match_buf); return SCPE_ARG|SCPE_NOMESSAGE; } - sim_debug (exp->dbit, exp->dptr, "Expect Regular Expression: \"%s\" has %d sub expressions\n", match_buf, (int)re.re_nsub); - regfree (&re); + (void)pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &re_nsub); + sim_debug (exp->dbit, exp->dptr, "Expect Regular Expression: \"%s\" has %d sub expressions\n", match_buf, re_nsub); + pcre_free (re); } #endif else { @@ -12033,9 +12221,13 @@ if ((match_buf == NULL) || (ep->match_pattern == NULL)) { } if (switches & EXP_TYP_REGEX) { #if defined(USE_REGEX) + const char *errmsg; + int erroffset; + memcpy (match_buf, match+1, strlen(match)-2); /* extract string without surrounding quotes */ match_buf[strlen(match)-2] = '\0'; - regcomp (&ep->regex, (char *)match_buf, REG_EXTENDED); + ep->regex = pcre_compile ((char *)match_buf, (switches & EXP_TYP_REGEX_I) ? PCRE_CASELESS : 0, &errmsg, &erroffset, NULL); + (void)pcre_fullinfo(ep->regex, NULL, PCRE_INFO_CAPTURECOUNT, &ep->re_nsub); #endif free (match_buf); match_buf = NULL; @@ -12170,7 +12362,8 @@ for (i=0; i < exp->size; i++) { ep = &exp->rules[i]; if (ep->switches & EXP_TYP_REGEX) { #if defined (USE_REGEX) - regmatch_t *matches; + int *ovector = NULL; + int rc; char *cbuf = (char *)exp->buf; static size_t sim_exp_match_sub_count = 0; @@ -12188,23 +12381,24 @@ for (i=0; i < exp->size; i++) { } } ++regex_checks; - matches = (regmatch_t *)calloc ((ep->regex.re_nsub + 1), sizeof(*matches)); + ovector = (int *)malloc (3 * (ep->re_nsub + 1) * sizeof (*ovector)); if (sim_deb && exp->dptr && (exp->dptr->dctrl & exp->dbit)) { char *estr = sim_encode_quoted_string (exp->buf, exp->buf_ins); sim_debug (exp->dbit, exp->dptr, "Checking String: %s\n", estr); sim_debug (exp->dbit, exp->dptr, "Against RegEx Match Rule: %s\n", ep->match_pattern); free (estr); } - if (!regexec (&ep->regex, cbuf, ep->regex.re_nsub + 1, matches, REG_NOTBOL)) { + rc = pcre_exec (ep->regex, NULL, cbuf, exp->buf_ins, 0, PCRE_NOTBOL, ovector, 3 * (ep->re_nsub + 1)); + if (rc >= 0) { size_t j; char *buf = (char *)malloc (1 + exp->buf_ins); - for (j=0; jregex.re_nsub + 1; j++) { + for (j=0; j < (size_t)rc; j++) { char env_name[32]; sprintf (env_name, "_EXPECT_MATCH_GROUP_%d", (int)j); - memcpy (buf, &cbuf[matches[j].rm_so], matches[j].rm_eo-matches[j].rm_so); - buf[matches[j].rm_eo-matches[j].rm_so] = '\0'; + memcpy (buf, &cbuf[ovector[2 * j]], ovector[2 * j + 1] - ovector[2 * j]); + buf[ovector[2 * j + 1] - ovector[2 * j]] = '\0'; setenv (env_name, buf, 1); /* Make the match and substrings available as environment variables */ sim_debug (exp->dbit, exp->dptr, "%s=%s\n", env_name, buf); } @@ -12214,12 +12408,13 @@ for (i=0; i < exp->size; i++) { sprintf (env_name, "_EXPECT_MATCH_GROUP_%d", (int)j); setenv (env_name, "", 1); /* Remove previous extra environment variables */ } - sim_exp_match_sub_count = ep->regex.re_nsub; - free (matches); + sim_exp_match_sub_count = ep->re_nsub; + free (ovector); + ovector = NULL; free (buf); break; } - free (matches); + free (ovector); #endif } else { @@ -13620,7 +13815,7 @@ rewind (tmp); /* Discard leading blank lines/redundant titles */ for (i =0; i < skiplines; i++) - fgets (tbuf, sizeof (tbuf), tmp); + if (fgets (tbuf, sizeof (tbuf), tmp)) {}; while (fgets (tbuf, sizeof (tbuf), tmp)) { if (tbuf[0] != '\n') diff --git a/scp.h b/scp.h index 8beaa05..ae7b5b2 100644 --- a/scp.h +++ b/scp.h @@ -116,6 +116,7 @@ t_stat spawn_cmd (int32 flag, CONST char *ptr); t_stat echo_cmd (int32 flag, CONST char *ptr); t_stat echof_cmd (int32 flag, CONST char *ptr); t_stat debug_cmd (int32 flag, CONST char *ptr); +t_stat runlimit_cmd (int32 flag, CONST char *ptr); /* Allow compiler to help validate printf style format arguments */ #if !defined __GNUC__ @@ -141,6 +142,7 @@ t_stat _sim_activate_after_abs (UNIT *uptr, double usecs_walltime); t_stat sim_cancel (UNIT *uptr); t_bool sim_is_active (UNIT *uptr); int32 sim_activate_time (UNIT *uptr); +int32 _sim_activate_queue_time (UNIT *uptr); int32 _sim_activate_time (UNIT *uptr); double sim_activate_time_usecs (UNIT *uptr); t_stat sim_run_boot_prep (int32 flag); @@ -388,7 +390,8 @@ extern uint32 sim_brk_dflt; extern uint32 sim_brk_summ; extern uint32 sim_brk_match_type; extern t_addr sim_brk_match_addr; -extern BRKTYPTAB *sim_brk_type_desc; /* type descriptions */ +extern BRKTYPTAB *sim_brk_type_desc; /* type descriptions */ +extern const char *sim_prog_name; /* executable program name */ extern FILE *stdnul; extern t_bool sim_asynch_enabled; #if defined(SIM_ASYNCH_IO) @@ -399,6 +402,7 @@ void sim_aio_activate (ACTIVATE_API caller, UNIT *uptr, int32 event_time); /* VM interface */ extern char sim_name[64]; +extern const char *sim_vm_release; extern DEVICE *sim_devices[]; extern REG *sim_PC; extern const char *sim_stop_messages[SCPE_BASE]; diff --git a/sim_BuildROMs.c b/sim_BuildROMs.c index 2d6878d..e1a4cf5 100644 --- a/sim_BuildROMs.c +++ b/sim_BuildROMs.c @@ -172,7 +172,7 @@ unsigned int checksum = 0; char *c; int i; char cleaned_rom_filename[512]; -char include_filename[512]; +char *include_filename; char array_name[512]; if (NULL == (rFile = fopen (rom_filename, "rb"))) { @@ -207,15 +207,16 @@ if ((c = strchr (array_name, '.'))) *c = '_'; if ((c = strchr (array_name, '/'))) *c = '_'; -include_filename[sizeof (include_filename) - 1] = '\0'; -snprintf (include_filename, sizeof (include_filename) - 1, "%s.h", cleaned_rom_filename); +include_filename = (char *)calloc (3 + strlen (cleaned_rom_filename), sizeof (*include_filename)); +sprintf (include_filename, "%s.h", cleaned_rom_filename); if ((c = strrchr (include_filename, '/'))) sprintf (c+1, "%s.h", array_name); else - snprintf (include_filename, sizeof (include_filename) - 1, "%s.h", array_name); + sprintf (include_filename, "%s.h", array_name); printf ("The ROMs array entry for this new ROM image file should look something like:\n"); printf ("{\"%s\", \"%s\", %d, 0x%08X, \"%s\"}\n", rom_filename, include_filename, (int)(statb.st_size), checksum, array_name); +free (include_filename); free (ROMData); return 1; } diff --git a/sim_card.c b/sim_card.c index 0923bb2..e6618c0 100644 --- a/sim_card.c +++ b/sim_card.c @@ -1318,7 +1318,7 @@ sim_card_attach(UNIT * uptr, CONST char *cptr) sprintf (uptr->filename, "%s-F %s %s", (eof)?"-E ": "", fmt, cptr); } r = sim_messagef(SCPE_OK, "%s: %d card Deck Loaded from %s\n", - sim_uname(uptr), data->hopper_cards - previous_cards, cptr); + sim_uname(uptr), (int)(data->hopper_cards - previous_cards), cptr); } else { if (uptr->dynflags & UNIT_ATTMULT) uptr->flags |= UNIT_ATT; @@ -1430,22 +1430,22 @@ sprintf (cmd, "%s -S -E File40.deck", dptr->name); SIM_TEST(attach_cmd (0, cmd)); sprintf (saved_filename, "%s %s", dptr->name, dptr->units->filename); show_cmd (0, dptr->name); -sim_printf ("Input Hopper Count: %d\n", sim_card_input_hopper_count(dptr->units)); -sim_printf ("Output Hopper Count: %d\n", sim_card_output_hopper_count(dptr->units)); +sim_printf ("Input Hopper Count: %d\n", (int)sim_card_input_hopper_count(dptr->units)); +sim_printf ("Output Hopper Count: %d\n", (int)sim_card_output_hopper_count(dptr->units)); while (!sim_card_eof (dptr->units)) SIM_TEST(sim_read_card (dptr->units, card_image)); -sim_printf ("Input Hopper Count: %d\n", sim_card_input_hopper_count(dptr->units)); -sim_printf ("Output Hopper Count: %d\n", sim_card_output_hopper_count(dptr->units)); +sim_printf ("Input Hopper Count: %d\n", (int)sim_card_input_hopper_count(dptr->units)); +sim_printf ("Output Hopper Count: %d\n", (int)sim_card_output_hopper_count(dptr->units)); sim_printf ("Detaching %s\n", dptr->name); SIM_TEST(detach_cmd (0, dptr->name)); show_cmd (0, dptr->name); -sim_printf ("Input Hopper Count: %d\n", sim_card_input_hopper_count(dptr->units)); -sim_printf ("Output Hopper Count: %d\n", sim_card_output_hopper_count(dptr->units)); +sim_printf ("Input Hopper Count: %d\n", (int)sim_card_input_hopper_count(dptr->units)); +sim_printf ("Output Hopper Count: %d\n", (int)sim_card_output_hopper_count(dptr->units)); sim_printf ("Attaching Saved Filenames: %s\n", saved_filename + strlen(dptr->name)); SIM_TEST(attach_cmd (0, saved_filename)); show_cmd (0, dptr->name); -sim_printf ("Input Hopper Count: %d\n", sim_card_input_hopper_count(dptr->units)); -sim_printf ("Output Hopper Count: %d\n", sim_card_output_hopper_count(dptr->units)); +sim_printf ("Input Hopper Count: %d\n", (int)sim_card_input_hopper_count(dptr->units)); +sim_printf ("Output Hopper Count: %d\n", (int)sim_card_output_hopper_count(dptr->units)); SIM_TEST(detach_cmd (0, dptr->name)); (void)remove ("file10.deck"); (void)remove ("file20.deck"); diff --git a/sim_console.c b/sim_console.c index 6a0674b..b084e6c 100644 --- a/sim_console.c +++ b/sim_console.c @@ -437,7 +437,7 @@ if (*cptr == 0) { /* show all */ while (*cptr != 0) { cptr = get_glyph (cptr, gbuf, ','); /* get modifier */ if ((shptr = find_shtab (show_con_tab, gbuf))) - shptr->action (st, dptr, uptr, shptr->arg, cptr); + shptr->action (st, dptr, uptr, shptr->arg, NULL); else return SCPE_NOPARAM; } return SCPE_OK; @@ -4219,7 +4219,7 @@ static t_stat sim_os_putchar (int32 out) char c; c = out; -(void)write (1, &c, 1); +if (write (1, &c, 1)) {}; return SCPE_OK; } diff --git a/sim_defs.h b/sim_defs.h index e400c6e..a90eb2d 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -146,13 +146,9 @@ extern int sim_vax_snprintf(char *buf, size_t buf_size, const char *fmt, ...); #ifdef USE_REGEX #undef USE_REGEX #endif -#if defined(HAVE_PCREPOSIX_H) -#include +#if defined(HAVE_PCRE_H) #include #define USE_REGEX 1 -#elif defined(HAVE_REGEX_H) -#include -#define USE_REGEX 1 #endif #ifdef __cplusplus @@ -417,8 +413,9 @@ typedef uint32 t_addr; #define SCPE_INVEXPR (SCPE_BASE + 47) /* invalid expression */ #define SCPE_SIGTERM (SCPE_BASE + 48) /* SIGTERM has been received */ #define SCPE_FSSIZE (SCPE_BASE + 49) /* File System size larger than disk size */ +#define SCPE_RUNTIME (SCPE_BASE + 50) /* Run Time Limit Exhausted */ -#define SCPE_MAX_ERR (SCPE_BASE + 49) /* Maximum SCPE Error Value */ +#define SCPE_MAX_ERR (SCPE_BASE + 50) /* Maximum SCPE Error Value */ #define SCPE_KFLAG 0x10000000 /* tti data flag */ #define SCPE_BREAK 0x20000000 /* tti break flag */ #define SCPE_NOMESSAGE 0x40000000 /* message display supression flag */ @@ -818,7 +815,8 @@ struct EXPTAB { #define EXP_TYP_REGEX_I (SWMASK ('I')) /* regular expression pattern matching should be case independent */ #define EXP_TYP_TIME (SWMASK ('T')) /* halt delay is in microseconds instead of instructions */ #if defined(USE_REGEX) - regex_t regex; /* compiled regular expression */ + pcre *regex; /* compiled regular expression */ + int re_nsub; /* regular expression sub expression count */ #endif char *act; /* action string */ }; diff --git a/sim_ether.c b/sim_ether.c index f242e90..fd02d25 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -417,7 +417,7 @@ t_stat eth_mac_scan_ex (ETH_MAC* mac, const char* strmac, UNIT *uptr) memset (&state, 0, sizeof(state)); _eth_get_system_id (state.system_id, sizeof(state.system_id)); strlcpy (state.sim, sim_name, sizeof(state.sim)); - getcwd (state.cwd, sizeof(state.cwd)); + if (getcwd (state.cwd, sizeof(state.cwd))) {}; if (uptr) strlcpy (state.uname, sim_uname (uptr), sizeof(state.uname)); cptr = strchr (strmac, '>'); @@ -426,7 +426,7 @@ t_stat eth_mac_scan_ex (ETH_MAC* mac, const char* strmac, UNIT *uptr) strlcpy (state.file, cptr + 1, sizeof(state.file)); if ((f = fopen (state.file, "r"))) { filebuf[sizeof(filebuf)-1] = '\0'; - fgets (filebuf, sizeof(filebuf)-1, f); + if (fgets (filebuf, sizeof(filebuf)-1, f)) {}; strmac = filebuf; fclose (f); strcpy (state.file, ""); /* avoid saving */ @@ -1573,10 +1573,10 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname) memset(command, 0, sizeof(command)); /* try to force an otherwise unused interface to be turned on */ snprintf(command, sizeof(command)-1, "ifconfig %.*s up", (int)(sizeof(command) - 14), devname); - (void)system(command); + if (system(command)) {}; for (i=0; patterns[i] && (0 == dev->have_host_nic_phy_addr); ++i) { snprintf(command, sizeof(command)-1, "ifconfig %.*s | %s >NIC.hwaddr", (int)(sizeof(command) - (26 + strlen(patterns[i]))), devname, patterns[i]); - (void)system(command); + if (system(command)) {}; if (NULL != (f = fopen("NIC.hwaddr", "r"))) { while (0 == dev->have_host_nic_phy_addr) { if (fgets(command, sizeof(command)-1, f)) { @@ -1662,12 +1662,12 @@ FILE *f; memset (buf, 0, buf_size); if ((f = fopen ("/etc/machine-id", "r"))) { - fread (buf, 1, buf_size, f); + if (fread (buf, 1, buf_size - 1, f)) {}; fclose (f); } else { if ((f = popen ("hostname", "r"))) { - fread (buf, 1, buf_size, f); + if (fread (buf, 1, buf_size - 1, f)) {}; pclose (f); } } @@ -2165,7 +2165,7 @@ else { /* !tap: */ /* try to force an otherwise unused interface to be turned on */ memset(command, 0, sizeof(command)); snprintf(command, sizeof(command)-1, "ifconfig %s up", savname); - (void)system(command); + if (system(command)) {}; errbuf[0] = '\0'; *handle = (void*) pcap_open_live(savname, bufsz, ETH_PROMISC, PCAP_READ_TIMEOUT, errbuf); } diff --git a/sim_fio.c b/sim_fio.c index 6fef8ea..44ccea4 100644 --- a/sim_fio.c +++ b/sim_fio.c @@ -953,6 +953,7 @@ glob_t paths; #else DIR *dir; #endif +int found_count = 0; struct stat filestat; char *c; char DirName[PATH_MAX + 1], WholeName[PATH_MAX + 1], WildName[PATH_MAX + 1]; @@ -982,7 +983,7 @@ if (dir) { struct dirent *ent; #endif t_offset FileSize; - char FileName[PATH_MAX + 1]; + char *FileName; const char *MatchName = 1 + strrchr (cptr, '/'); char *p_name; struct tm *local; @@ -992,24 +993,29 @@ if (dir) { #if defined (HAVE_GLOB) for (i=0; id_name, 0)) continue; -#else - /* only match exact name without fnmatch support */ - if (strcmp(MatchName, ent->d_name) != 0) +#else /* !defined (HAVE_FNMATCH) */ + /* only match all names or exact name without fnmatch support */ + if ((strcmp(MatchName, "*") != 0) && + (strcmp(MatchName, ent->d_name) != 0)) continue; -#endif +#endif /* defined (HAVE_FNMATCH) */ + FileName = (char *)malloc (1 + strlen (DirName) + strlen (ent->d_name)); sprintf (FileName, "%s%s", DirName, ent->d_name); -#endif +#endif /* defined (HAVE_GLOB) */ p_name = FileName + strlen (DirName); memset (&filestat, 0, sizeof (filestat)); (void)stat (FileName, &filestat); FileSize = (t_offset)((filestat.st_mode & S_IFDIR) ? 0 : sim_fsize_name_ex (FileName)); entry (DirName, p_name, FileSize, &filestat, context); + free (FileName); + ++found_count; } #if defined (HAVE_GLOB) globfree (&paths); @@ -1019,6 +1025,9 @@ if (dir) { } else return SCPE_ARG; -return SCPE_OK; +if (found_count) + return SCPE_OK; +else + return SCPE_ARG; } #endif /* !defined(_WIN32) */ diff --git a/sim_frontpanel.c b/sim_frontpanel.c index 2ad2a2c..32b2b0f 100644 --- a/sim_frontpanel.c +++ b/sim_frontpanel.c @@ -867,7 +867,7 @@ if (!simulator_panel) { p->pidProcess = fork(); if (p->pidProcess == 0) { close (0); close (1); close (2); /* make sure not to pass the open standard handles */ - dup (dup (open ("/dev/null", O_RDWR))); /* open standard handles to /dev/null */ + if (dup (dup (open ("/dev/null", O_RDWR)))) {}; /* open standard handles to /dev/null */ if (execlp (sim_path, sim_path, p->temp_config, NULL, NULL)) { perror ("execl"); exit(errno); From dd395f16536c49db5690e5eb056eb194a7bfda0b Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Mon, 20 Jan 2020 13:45:33 -0500 Subject: [PATCH 82/98] KA10: Added start of NIA20 device. --- PDP10/kl10_nia.c | 585 ++++++++++++++++++++++++++++++++++++++++++++++ PDP10/kx10_cpu.c | 18 +- PDP10/kx10_defs.h | 9 + PDP10/kx10_dt.c | 2 + PDP10/kx10_rh.c | 13 +- PDP10/kx10_sys.c | 3 + README.md | 5 +- 7 files changed, 623 insertions(+), 12 deletions(-) create mode 100644 PDP10/kl10_nia.c diff --git a/PDP10/kl10_nia.c b/PDP10/kl10_nia.c new file mode 100644 index 0000000..30b8e59 --- /dev/null +++ b/PDP10/kl10_nia.c @@ -0,0 +1,585 @@ +/* kl10_NIA.c: NIA 20 Network interface. + + Copyright (c) 2019, Richard Cornwell. + + 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 + RICHARD CORNWELL 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. + + This emulates the MIT-AI/ML/MC Host/IMP interface. +*/ + + +#include "kx10_defs.h" +#include "sim_ether.h" + +#if NUM_DEVS_NIA > 0 +#define NIA_DEVNUM (0540 + (5 * 4)) + +/* NIA Bits */ + +/* CONI */ +#define NIA_PPT 0400000000000LL /* Port present */ +#define NIA_DCC 0100000000000LL /* Diag CSR */ +#define NIA_CPE 0004000000000LL /* CRAM Parity error */ +#define NIA_MBE 0002000000000LL /* MBUS error */ +#define NIA_ILD 0000100000000LL /* Idle */ +#define NIA_DCP 0000040000000LL /* Disable complete */ +#define NIA_ECP 0000020000000LL /* Enable complete */ +#define NIA_PID 0000007000000LL /* Port ID */ + +/* CONO/ CONI */ +#define NIA_CPT 0000000400000LL /* Clear Port */ +#define NIA_SEB 0000000200000LL /* Diag Select EBUF */ +#define NIA_GEB 0000000100000LL /* Diag Gen Ebus PE */ +#define NIA_LAR 0000000040000LL /* Diag select LAR */ +#define NIA_SSC 0000000020000LL /* Diag Single Cycle */ +#define NIA_EPE 0000000004000LL /* Ebus parity error */ +#define NIA_FQE 0000000002000LL /* Free Queue Error */ +#define NIA_DME 0000000001000LL /* Data mover error */ +#define NIA_CQA 0000000000400LL /* Command Queue Available */ +#define NIA_RQA 0000000000200LL /* Response Queue Available */ +#define NIA_DIS 0000000000040LL /* Disable */ +#define NIA_ENB 0000000000020LL /* Enable */ +#define NIA_MRN 0000000000010LL /* RUN */ +#define NIA_PIA 0000000000007LL /* PIA */ + +#define NIA_LRA 0400000000000LL /* Load Ram address */ +#define NIA_RAR 0377760000000LL /* Microcode address mask */ +#define NIA_MSB 0000020000000LL /* Half word select */ + +#define PCB_CQI 0 /* Command queue interlock */ +#define PCB_CQF 1 /* Command queue flink */ +#define PCB_CQB 2 /* Command queue blink */ +#define PCB_RS0 3 /* Reserved */ +#define PCB_RSI 4 /* Response queue interlock */ +#define PCB_RSF 5 /* Response queue flink */ +#define PCB_RSB 6 /* Response queue blink */ +#define PCB_RS1 7 /* Reserved */ +#define PCB_UPI 010 /* Unknown protocol queue interlock */ +#define PCB_UPF 011 /* Unknown protocol queue flink */ +#define PCB_UPB 012 /* Unknown protocol queue blink */ +#define PCB_UPL 013 /* Unknown protocol queue length */ +#define PCB_RS2 014 /* Reserved */ +#define PCB_PTT 015 /* Protocol Type Table */ +#define PCB_MCT 016 /* Multicast Table */ +#define PCB_RS3 017 /* Reserved */ +#define PCB_ER0 020 /* Error Log out 0 */ +#define PCB_ER1 021 /* Error Log out 1 */ +#define PCB_EPA 022 /* EPT Channel logout word 1 address */ +#define PCB_EPW 023 /* EPT Channel logout word 1 contents */ +#define PCB_PCB 024 /* PCB Base Address */ +#define PCB_PIA 025 /* PIA */ +#define PCB_RS4 026 /* Reserved */ +#define PCB_CCW 027 /* Channel command word */ +#define PCB_RCB 030 /* Counters base address */ + +#define CHNERR 07762 +#define SLFTST 07751 +#define INTERR 07750 + +#define NIA_FLG_RESP 0001 /* Command wants a response */ +#define NIA_FLG_CLRC 0002 /* Clear counters (Read counters) */ +#define NIA_FLG_BSD 0010 /* Send BSD packet */ +#define NIA_FLG_PAD 0040 /* Send pad */ +#define NIA_FLG_ICRC 0100 /* Send use host CRC */ +#define NIA_FLG_PACK 0200 /* Send Pack */ +#define NIA_STS_CPE 0200 /* CRAM PE */ +#define NIA_STS_SR 0100 /* Send receive */ +#define NIA_STS_ERR 0001 /* Error bits valid */ + +#define NIA_ERR_ECL 000 /* Excessive collisions */ +#define NIA_ERR_CAR 001 /* Carrier check failed */ +#define NIA_ERR_COL 002 /* Collision detect failed */ +#define NIA_ERR_SHT 003 /* Short circuit */ +#define NIA_ERR_OPN 004 /* Open circuit */ +#define NIA_ERR_LNG 005 /* Frame to long */ +#define NIA_ERR_RMT 006 /* Remote failure */ +#define NIA_ERR_BLK 007 /* Block check error */ +#define NIA_ERR_FRM 010 /* Framing error */ +#define NIA_ERR_OVR 011 /* Data Overrun */ +#define NIA_ERR_PRO 012 /* Unrecongized protocol */ +#define NIA_ERR_RUN 013 /* Frame too short */ +#define NIA_ERR_WCZ 030 /* Word count not zero */ +#define NIA_ERR_QLV 031 /* Queue length violation */ +#define NIA_ERR_PLI 032 /* Illegal PLI function */ +#define NIA_ERR_UNK 033 /* Unknown command */ +#define NIA_ERR_BLV 034 /* Buffer length violation */ +#define NIA_ERR_PAR 036 /* Parity error */ +#define NIA_ERR_INT 037 /* Internal error */ + +struct nia_device { + ETH_PCALLBACK rcallback; /* read callback routine */ + ETH_PCALLBACK wcallback; /* write callback routine */ + ETH_MAC macs[2]; /* Hardware MAC addresses */ + ETH_DEV etherface; + ETH_QUE ReadQ; +#define mac macs[0] +#define bcast macs[1] + + uint8 rec_buff[2000]; /* Buffer for recieved packet */ + uint8 snd_buff[2000]; /* Buffer for sending packet */ + t_addr cmd_entry; /* Pointer to current command entry */ + t_addr rec_entry; /* Pointer to current recieve entry */ + t_addr free_hdr; /* Queue to save command entry */ + t_addr rec_hdr; /* Queue to get free entry from */ + t_addr pcb; /* Address of PCB */ + t_addr rcb; /* Read count buffer address */ +#define cmd_hdr pcb /* Command queue is at PCB */ + t_addr resp_hdr; /* Head of response queue */ + t_addr unk_hdr; /* Unknown protocol free queue */ + int unk_len; /* Length of Unknown entries */ + t_addr ptt_addr; /* Address of Protocol table */ + t_addr mat_addr; /* Address of Multicast table */ + int pia; /* Interrupt channel */ + t_addr cnt_addr; /* Address of counters */ + + int ptt_n; /* Number of Protocol entries */ + uint16 ptt_proto[17]; /* Protocol for entry */ + t_addr ptt_head[17]; /* Head of protocol queue */ + int mat_n; /* Number of multi-cast addresses */ + ETH_MAC mat_mac[17]; /* Watched Multi-cast addresses */ + int rar; + uint64 ebuf; + uint32 uver; + uint32 uedit; +} nia_data; + +#define STATUS u3 +extern int32 tmxr_poll; + +static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff}; + +t_stat nia_devio(uint32 dev, uint64 *data); +void nia_start(UNIT *); +void nia_stop(UNIT *); +void nia_enable(UNIT *); +void nia_error(UNIT *, int); +t_stat nia_srv(UNIT *); +t_stat nia_eth_srv(UNIT *); +t_stat nia_tim_srv(UNIT *); +t_stat nia_reset (DEVICE *dptr); +t_stat nia_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc); +t_stat nia_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc); +t_stat nia_attach (UNIT * uptr, CONST char * cptr); +t_stat nia_detach (UNIT * uptr); +t_stat nia_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); +const char *nia_description (DEVICE *dptr); + +struct rh_if nia_rh = { NULL, NULL, NULL}; + +UNIT nia_unit[] = { + {UDATA(nia_srv, UNIT_IDLE+UNIT_ATTABLE, 0)}, /* 0 */ + {UDATA(nia_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ + {UDATA(nia_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ +}; + +DIB nia_dib = {NIA_DEVNUM | RH20_DEV, 1, &nia_devio, NULL, &nia_rh }; + +MTAB nia_mod[] = { + { MTAB_XTD|MTAB_VDV|MTAB_VALR|MTAB_NC, 0, "MAC", "MAC=xx:xx:xx:xx:xx:xx", + &nia_set_mac, &nia_show_mac, NULL, "MAC address" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "ETH", NULL, NULL, + ð_show, NULL, "Display attachedable devices" }, + { 0 } + }; + +/* Simulator debug controls */ +DEBTAB nia_debug[] = { + {"CMD", DEBUG_CMD, "Show command execution to devices"}, + {"DATA", DEBUG_DATA, "Show data transfers"}, + {"DETAIL", DEBUG_DETAIL, "Show details about device"}, + {"EXP", DEBUG_EXP, "Show exception information"}, + {"CONI", DEBUG_CONI, "Show coni instructions"}, + {"CONO", DEBUG_CONO, "Show coni instructions"}, + {"DATAIO", DEBUG_DATAIO, "Show datai and datao instructions"}, + {"IRQ", DEBUG_IRQ, "Show IRQ requests"}, +#define DEBUG_ETHER (DEBUG_IRQ<<1) + {"ETHER", DEBUG_ETHER, "Show ETHER activities"}, + {0, 0} +}; + + + +DEVICE nia_dev = { + "NI", nia_unit, NULL, nia_mod, + 3, 8, 0, 1, 8, 36, + NULL, NULL, &nia_reset, NULL, &nia_attach, &nia_detach, + &nia_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, nia_debug, + NULL, NULL, &nia_help, NULL, NULL, &nia_description +}; + + +t_stat nia_devio(uint32 dev, uint64 *data) +{ + DEVICE *dptr = &nia_dev; + UNIT *uptr = nia_unit; + + switch(dev & 07) { + case CONO: + if (*data & NIA_CPT) + nia_reset(dptr); + + uptr->STATUS &= ~(NIA_SEB|NIA_LAR|NIA_SSC|NIA_CQA|NIA_DIS|NIA_ENB|NIA_PIA); + uptr->STATUS |= *data & (NIA_SEB|NIA_LAR|NIA_SSC|NIA_CQA|NIA_DIS|NIA_ENB|NIA_PIA); + uptr->STATUS &= ~(*data & (NIA_EPE|NIA_FQE|NIA_DME|NIA_RQA)); + if (*data & NIA_MRN ) { + if ((uptr->STATUS & NIA_MRN) == 0) + nia_start(uptr); + } else { + if ((uptr->STATUS & NIA_MRN) != 0) + nia_stop(uptr); + } + if (*data & NIA_ENB) { + if ((uptr->STATUS & NIA_MRN) != 0) + nia_enable(uptr); + else + uptr->STATUS |= NIA_ECP; + } else + uptr->STATUS &= ~NIA_ECP; + if (*data & NIA_CQA && (uptr->STATUS & NIA_MRN) != 0) + sim_activate(uptr, 100); + sim_debug(DEBUG_CONO, dptr, "IMP %03o CONO %06o PC=%o\n", dev, + (uint32)*data, PC); + break; + case CONI: + *data = (uint64)uptr->STATUS; + *data = NIA_PPT|NIA_PID; + sim_debug(DEBUG_CONI, dptr, "IMP %03o CONI %012llo PC=%o\n", dev, + *data, PC); + break; + case DATAO: + if (uptr->STATUS & NIA_SEB) { + nia_data.ebuf = *data; + } else { + if (*data & NIA_LRA) + nia_data.rar = (uint32)((*data & NIA_RAR) >> 20); + else { + if(nia_data.rar = 0275) + nia_data.uver = (uint32)(*data & RMASK); + else if(nia_data.rar = 0277) + nia_data.uedit = (uint32)(*data & RMASK); + } + } + sim_debug(DEBUG_DATAIO, dptr, "IMP %03o DATO %012llo PC=%o\n", + dev, *data, PC); + break; + case DATAI: + if (uptr->STATUS & NIA_SEB) { + *data = nia_data.ebuf; + } else { + if (uptr->STATUS & NIA_LAR) { + *data = ((uint64)nia_data.rar) << 20; + *data &= ~NIA_MSB; + *data |= NIA_LRA; + } else { + if(nia_data.rar == 0275) + *data = (uint64)(nia_data.uver); + else if(nia_data.rar == 0277) + *data = (uint64)(nia_data.uedit); + } + } + sim_debug(DEBUG_DATAIO, dptr, "IMP %03o DATI %012llo PC=%o\n", + dev, *data, PC); + break; + } + + return SCPE_OK; +} + +void nia_error(UNIT * uptr, int err) +{ + nia_data.rar = err; + uptr->STATUS |= NIA_CPE; + set_interrupt(NIA_DEVNUM, uptr->STATUS & NIA_PIA); +} + +void nia_start(UNIT * uptr) +{ + nia_rh.stcr = BIT7; + nia_rh.imode = 2; + rh20_setup(&nia_rh); + /* Read PCB address */ + if (!rh_read(&nia_rh)) { + nia_error(uptr, CHNERR); + return; + } + nia_data.pcb = (t_addr)(nia_rh.buf & AMASK); + /* Read PIA value */ + if (!rh_read(&nia_rh)) { + nia_error(uptr, CHNERR); + return; + } + nia_data.pia = (int)(nia_rh.buf & 7); + /* Read reserve word */ + if (!rh_read(&nia_rh)) { + nia_error(uptr, CHNERR); + return; + } + uptr->STATUS |= NIA_MRN; +} + +void nia_stop(UNIT *uptr) +{ + uptr->STATUS &= ~NIA_MRN; +} + +void nia_enable(UNIT *uptr) +{ + /* Load Unknown queue len */ + /* Load PTT */ + /* Load MCT */ + /* Load read count buffer address */ +} + +/* Get next entry off a queue. Returns 0 if fail */ +int nia_getq(t_addr head, t_addr *entry) +{ + uint64 temp; + uint64 flink; + *entry = 0; /* For safty */ + + temp = M[head]; + /* Check if entry locked */ + if ((temp & SMASK) == 0) + return 0; + + /* Increment lock here */ + + /* Get forward link */ + flink = M[head+1]; + /* Check if queue empty */ + if (flink == (head+1)) { + /* Decrement lock here */ + return 1; + } + temp = M[flink]; + M[head+1] = temp; /* Set Head Flink to point to next */ + M[temp + 1] = head + 1; /* Set Next Blink to head */ + *entry = temp; + /* Decrement lock here */ + return 1; +} + +/* Put entry on head of queue. */ +int nia_putq(UNIT *uptr, t_addr head, t_addr *entry) +{ + uint64 temp; + uint64 blink; + + temp = M[head]; + /* Check if entry locked */ + if ((temp & SMASK) == 0) + return 0; + + /* Increment lock here */ + + /* Set up entry. */ + M[*entry] = head+1; /* Flink is head of queue */ + blink = M[head+2]; /* Get back link */ + M[*entry+1] = blink; + temp = M[blink]; /* Old prevous entry */ + M[temp] = *entry; /* Old forward is new */ + + *entry = 0; + /* Decement lock here */ + + /* Check if Queue was empty, and response queue */ + if (temp == (head+1) && head == nia_data.resp_hdr) { + uptr->STATUS |= NIA_RQA; + set_interrupt(NIA_DEVNUM, nia_data.pia); + } + return 1; +} + +t_stat nia_srv(UNIT * uptr) +{ + + /* Check if we are running */ + if ((uptr->STATUS & NIA_MRN) == 0) + return SCPE_OK; + /* See if we have command to process */ + if (nia_data.cmd_entry != 0) { + /* Have to put this either on response queue or free queue */ + if (nia_putq(uptr, nia_data.resp_hdr, &nia_data.cmd_entry) == 0) { + sim_activate(uptr, 100); /* Reschedule ourselves to deal with it */ + return SCPE_OK; + } + } + /* Try to get command off queue */ + if (nia_getq(nia_data.cmd_hdr, &nia_data.cmd_entry) == 0) { + sim_activate(uptr, 100); /* Reschedule ourselves to deal with it */ + return SCPE_OK; + } + /* Check if we got one */ + if (nia_data.cmd_entry == 0) { + /* Nothing to do */ + uptr->STATUS &= ~NIA_CQA; + return SCPE_OK; + } + return SCPE_OK; +} + + +t_stat nia_eth_srv(UNIT * uptr) +{ + sim_clock_coschedule(uptr, 1000); /* continue poll */ + + return SCPE_OK; +} + +t_stat nia_tim_srv(UNIT * uptr) +{ + sim_clock_coschedule(uptr, 1000); /* continue poll */ + + return SCPE_OK; +} + + + +t_stat nia_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc) +{ + char buffer[20]; + eth_mac_fmt(&nia_data.mac, buffer); + fprintf(st, "MAC=%s", buffer); + return SCPE_OK; +} + +t_stat nia_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc) +{ + t_stat status; + + if (!cptr) return SCPE_IERR; + if (uptr->flags & UNIT_ATT) return SCPE_ALATT; + + status = eth_mac_scan_ex(&nia_data.mac, cptr, uptr); + if (status != SCPE_OK) + return status; + + memcpy(&nia_data.bcast, &broadcast_ethaddr, 6); + return SCPE_OK; +} + +t_stat nia_reset (DEVICE *dptr) +{ + int i; + struct nia_packet *p; + + for (i = 0; i < 6; i++) { + if (nia_data.mac[i] != 0) + break; + } + if (i == 6) { /* First call to reset? */ + /* Set a default MAC address in a BBN assigned OID range no longer in use */ + nia_set_mac (dptr->units, 0, "00:00:02:00:00:00/24", NULL); + } + return SCPE_OK; +} + +/* attach device: */ +t_stat nia_attach(UNIT* uptr, CONST char* cptr) +{ + t_stat status; + char* tptr; + char buf[32]; + + tptr = (char *) malloc(strlen(cptr) + 1); + if (tptr == NULL) return SCPE_MEM; + strcpy(tptr, cptr); + + status = eth_open(&nia_data.etherface, cptr, &nia_dev, DEBUG_ETHER); + if (status != SCPE_OK) { + free(tptr); + return status; + } + eth_mac_fmt(&nia_data.mac, buf); /* format ethernet mac address */ + if (SCPE_OK != eth_check_address_conflict (&nia_data.etherface, &nia_data.mac)) { + eth_close(&nia_data.etherface); + free(tptr); + return sim_messagef (SCPE_NOATT, "%s: MAC Address Conflict on LAN for address %s\n", + nia_dev.name, buf); + } + if (SCPE_OK != eth_filter(&nia_data.etherface, 2, &nia_data.mac, 0, 0)) { + eth_close(&nia_data.etherface); + free(tptr); + return sim_messagef (SCPE_NOATT, "%s: Can't set packet filter for MAC Address %s\n", + nia_dev.name, buf); + } + + uptr->filename = tptr; + uptr->flags |= UNIT_ATT; + eth_setcrc(&nia_data.etherface, 0); /* Don't need CRC */ + + /* init read queue (first time only) */ + status = ethq_init(&nia_data.ReadQ, 8); + if (status != SCPE_OK) { + eth_close(&nia_data.etherface); + uptr->filename = NULL; + free(tptr); + return sim_messagef (status, "%s: Can't initialize receive queue\n", nia_dev.name); + } + + + eth_set_async (&nia_data.etherface, 0); /* Allow Asynchronous inbound packets */ + return SCPE_OK; +} + +/* detach device: */ + +t_stat nia_detach(UNIT* uptr) +{ + + if (uptr->flags & UNIT_ATT) { + /* If DHCP, release our IP address */ + eth_close (&nia_data.etherface); + free(uptr->filename); + uptr->filename = NULL; + uptr->flags &= ~UNIT_ATT; + sim_cancel (uptr+1); /* stop the packet timing services */ + sim_cancel (uptr+2); /* stop the clock timer services */ + } + return SCPE_OK; +} + +t_stat nia_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "NIA interface\n\n"); +fprintf (st, "The IMP acted as an interface to the early internet. "); +fprintf (st, "This interface operated\nat the TCP/IP level rather than the "); +fprintf (st, "Ethernet level. This interface allows for\nITS or Tenex to be "); +fprintf (st, "placed on the internet. The interface connects up to a TAP\n"); +fprintf (st, "or direct ethernet connection. If the host is to be run at an "); +fprintf (st, "arbitrary IP\naddress, then the HOST should be set to the IP "); +fprintf (st, "of ITS. The network interface\nwill translate this IP address "); +fprintf (st, "to the one set in IP. If HOST is set to 0.0.0.0,\nno "); +fprintf (st, "translation will take place. IP should be set to the external "); +fprintf (st, "address of\nthe IMP, along the number of bits in the net mask. "); +fprintf (st, "GW points to the default\nrouter. If DHCP is enabled these "); +fprintf (st, "will be set from DHCP when the IMP is attached.\nIf IP is set "); +fprintf (st, "and DHCP is enabled, when the IMP is attached it will inform\n"); +fprintf (st, "the local DHCP server of it's address.\n\n"); +fprint_set_help (st, dptr); +fprint_show_help (st, dptr); +eth_attach_help(st, dptr, uptr, flag, cptr); +return SCPE_OK; +} + + +const char *nia_description (DEVICE *dptr) +{ + return "KL NIA interface"; +} +#endif diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index aea011e..0af0e3c 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -23,7 +23,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Richard Cornwell - cpu KA10/KL10 central processor + cpu KA10/KI10/KL10 central processor The 36b system family had six different implementions: PDP-6, KA10, KI10, @@ -283,6 +283,9 @@ DEVICE *rh_devs[] = { #endif #if (NUM_DEVS_TU > 0) &tua_dev, +#endif +#if (NUM_DEVS_NIA > 0) + &nia_dev, #endif NULL, }; @@ -10275,6 +10278,7 @@ if (QBBN) dev_tab[024>>2] = &dev_pag; #endif + /* Assign all RH10 & RH20 devices */ rh20 = 0540; rh_idx = 0; @@ -10288,9 +10292,21 @@ for (i = 0; (dptr = rh_devs[i]) != NULL; i++) { sim_printf ("To many RH10 devices %s\n", sim_dname (dptr)); return TRUE; } +#if KL } else if (d & RH20_DEV) { /* RH20, grab next device */ +#if NUM_DEVS_NIA > 0 + /* If NIA20 installed, skip this slot */ + if ((nia_dev.flags & DEV_DIS) == 0 && dptr != &nia_dev && + rh20 == (((DIB *)nia_dev.ctxt)->dev_num & 0777)) + rh20 += 4; + /* If NIA20, then assign it to it's requested address */ + if ((nia_dev.flags & DEV_DIS) == 0 && dptr == &nia_dev) + d = dibp->dev_num & 0777; + else +#endif d = rh20; rh20 += 4; +#endif } dev_tab[(d >> 2)] = dibp->io; dev_irqv[(d >> 2)] = dibp->irq; diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 3c351db..ed75db5 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -403,6 +403,7 @@ extern int Mem_write_byte(int n, uint16 *data); extern DEVICE dte_dev; extern DEVICE lp20_dev; extern DEVICE tty_dev; +extern DEVICE nia_dev; #else extern DEVICE cty_dev; #endif @@ -531,14 +532,20 @@ t_stat rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc); t_stat rh_devio(uint32 dev, t_uint64 *data); t_addr rh_devirq(uint32 dev, t_addr addr); +#if KL +void rh20_setup(struct rh_if *rhc); +#endif +void rh_setup(struct rh_if *rh, uint32 addr); void rh_setattn(struct rh_if *rh, int unit); void rh_error(struct rh_if *rh); int rh_blkend(struct rh_if *rh); void rh_setirq(struct rh_if *rh); +void rh_writecw(struct rh_if *rh, int nxm); void rh_finish_op(struct rh_if *rh, int flags); int rh_read(struct rh_if *rh); int rh_write(struct rh_if *rh); + int ten11_read (t_addr addr, t_uint64 *data); int ten11_write (t_addr addr, t_uint64 data); @@ -582,6 +589,7 @@ int auxcpu_write (t_addr addr, t_uint64); #define NUM_DEVS_LP20 1 #define NUM_DEVS_TTY 1 #define NUM_LINES_TTY 40 +#define NUM_DEVS_NIA 1 #else #define NUM_DEVS_RC 1 #define NUM_DEVS_DT 1 @@ -589,6 +597,7 @@ int auxcpu_write (t_addr addr, t_uint64); #define NUM_DEVS_DP 2 #define NUM_DEVS_LP20 0 #define NUM_DEVS_TTY 0 +#define NUM_DEVS_NIA 0 #endif #define NUM_DEVS_RP 4 #define NUM_DEVS_RS 1 diff --git a/PDP10/kx10_dt.c b/PDP10/kx10_dt.c index 15e4643..a665020 100644 --- a/PDP10/kx10_dt.c +++ b/PDP10/kx10_dt.c @@ -1061,6 +1061,7 @@ dt_boot(int32 unit_num, DEVICE * dptr) addr = (addr + 1) & RMASK; word = ((uint64)fbuf[off++]) << 18; word |= (uint64)fbuf[off++]; +fprintf(stderr, "%06o %012llo %06o\n\r", addr, word, wc); if (addr < 020) FM[addr] = word; else @@ -1073,6 +1074,7 @@ dt_boot(int32 unit_num, DEVICE * dptr) uptr->DSTATE = (1 << DTC_V_BLK) | DTC_BLOCK | DTC_MOT; sim_activate(uptr,30000); PC = word & RMASK; +fprintf(stderr, "%06o\n\r", PC); return SCPE_OK; } diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index 209fe7d..bf6350d 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -146,10 +146,6 @@ */ extern uint32 eb_ptr; -void rh20_setup(struct rh_if *rhc); -void rh_setup(struct rh_if *rh, uint32 addr); -void rh_writecw(struct rh_if *rh, int nxm); - t_stat rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc) @@ -618,12 +614,10 @@ void rh20_setup(struct rh_if *rhc) rhc->status &= ~(RH20_DATA_OVR|RH20_CHAN_RDY|RH20_DR_RESP|RH20_CHAN_ERR|RH20_SHRT_WC|\ RH20_LONG_WC|RH20_DR_EXC|RH20_SCR_FULL|PI_ENABLE|RH20_XEND); rhc->status |= RH20_PCR_FULL; -// reg = rhc->dev_read(dptr, rhc, 1); - // if ((reg & (DS_DRY|DS_DPR|DS_ERR)) != (DS_DRY|DS_DPR)) - // return; if (rhc->status & RH20_SBAR) { rhc->drive = (rhc->pbar >> 18) & 07; - rhc->dev_write(dptr, rhc, 5, (rhc->pbar & 0177777)); + if (rhc->dev_write != NULL) + rhc->dev_write(dptr, rhc, 5, (rhc->pbar & 0177777)); rhc->status &= ~RH20_SBAR; } if (rhc->ptcr & BIT7) { /* If RCPL reset I/O pointers */ @@ -633,7 +627,8 @@ void rh20_setup(struct rh_if *rhc) /* Hold block count in cia */ rhc->drive = (rhc->ptcr >> 18) & 07; rhc->cia = (rhc->ptcr >> 6) & 01777; - rhc->dev_write(dptr, rhc, 0, (rhc->ptcr & 077)); + if (rhc->dev_write != NULL) + rhc->dev_write(dptr, rhc, 0, (rhc->ptcr & 077)); rhc->cop = 0; rhc->wcr = 0; rhc->status &= ~RH20_CHAN_RDY; diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index 77819db..d1c83b5 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -168,6 +168,9 @@ DEVICE *sim_devices[] = { #if NUM_DEVS_IMP > 0 &imp_dev, #endif +#if NUM_DEVS_NIA > 0 + &nia_dev, +#endif #if NUM_DEVS_CH10 > 0 &ch10_dev, #endif diff --git a/README.md b/README.md index cfcdd02..dec5847 100644 --- a/README.md +++ b/README.md @@ -97,9 +97,9 @@ The PDP6 runs TOPS 10 4.5 off Dectape. # Dec KA10 & KI10 & KL10 -The KA10 sim has successfully run Tops 10 4.5, 5.03 and Tops 10 6.03, ITS and WAITS. +The KA10 sim has successfully run Tops 10 4.5, 5.03 and 6.03, ITS and WAITS. The KI10 sim has successfully run Tops 10 6.03 with VMSER. -The KL10 sim has successfully run Tops 10 6.03 with VMSER and ITS. Tops 10 7.03, Tops 20 V2-V7. +The KL10 sim has successfully run Tops 10 6.03-7.03, ITS and Tops 20 V2-V7. Disk * RC10 RD10/RM10 @@ -127,6 +127,7 @@ The KL10 sim has successfully run Tops 10 6.03 with VMSER and ITS. Tops 10 7.03 * LP20 Line printer on KL10 Front End. * IMP networking support for ITS and TENEX. + * NIA20 networking support for KL10 (in progress). * CH10 networking support for ITS. * 340 Display Station support. From 634547b304da80543d015cbbd4a7537c5f45055e Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 30 Jan 2020 21:52:45 -0500 Subject: [PATCH 83/98] SCP: Updated SCP to current. --- makefile | 123 ++++++++++++++++++++++++++++------------------------ scp.h | 2 +- sim_card.c | 8 ++-- sim_defs.h | 16 ++++--- sim_ether.c | 62 +++++++++++++++----------- sim_ether.h | 1 - 6 files changed, 118 insertions(+), 94 deletions(-) diff --git a/makefile b/makefile index 48e17fb..d3e7f16 100644 --- a/makefile +++ b/makefile @@ -32,6 +32,10 @@ # installed, gmake should be invoked with LPATH=/usr/lib:/usr/local/lib # defined (adjusted as needed depending on where they may be installed). # +# In the unlikely event that someone wants to build network capable +# simulators without networking support, invoking GNU make with +# NONETWORK=1 will do the trick. +# # The default build will build compiler optimized binaries. # If debugging is desired, then GNU make can be invoked with # DEBUG=1 on the command line. @@ -66,12 +70,6 @@ # Internal ROM support can be disabled if GNU make is invoked with # DONT_USE_ROMS=1 on the command line. # -# The use of pthreads for various things can be disabled if GNU make is -# invoked with NOPTHREADS=1 on the command line. -# -# Asynchronous I/O support can be disabled if GNU make is invoked with -# NOASYNCH=1 on the command line. -# # For linting (or other code analyzers) make may be invoked similar to: # # make GCC=cppcheck CC_OUTSPEC= LDFLAGS= CFLAGS_G="--enable=all --template=gcc" CC_STD=--std=c99 @@ -143,6 +141,10 @@ else BESM6_BUILD = true endif endif +# someone may want to explicitly build simulators without network support +ifneq ($(NONETWORK),) + NETWORK_USEFUL = +endif find_exe = $(abspath $(strip $(firstword $(foreach dir,$(strip $(subst :, ,${PATH})),$(wildcard $(dir)/$(1)))))) find_lib = $(abspath $(strip $(firstword $(foreach dir,$(strip ${LIBPATH}),$(wildcard $(dir)/lib$(1).${LIBEXT}))))) find_include = $(abspath $(strip $(firstword $(foreach dir,$(strip ${INCPATH}),$(wildcard $(dir)/$(1).h))))) @@ -253,10 +255,7 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin) LTO_EXCLUDE_VERSIONS = PCAPLIB = pcap ifeq (agcc,$(findstring agcc,${GCC})) # Android target build? - OS_CCDEFS = -D_GNU_SOURCE - ifeq (,$(NOASYNCH)) - OS_CCDEFS += -DSIM_ASYNCH_IO - endif + OS_CCDEFS = -D_GNU_SOURCE -DSIM_ASYNCH_IO OS_LDFLAGS = -lm else # Non-Android (or Native Android) Builds ifeq (,$(INCLUDES)$(LIBRARIES)) @@ -463,38 +462,25 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin) OS_LDFLAGS += -lrt $(info using librt: $(call find_lib,rt)) endif - ifneq (,$(NOPTHREADS)) - OS_CCDEFS += -DDONT_USE_READER_THREAD - else - ifneq (,$(call find_include,pthread)) + ifneq (,$(call find_include,pthread)) + ifneq (,$(call find_lib,pthread)) + OS_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO + OS_LDFLAGS += -lpthread + $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) + else + LIBEXTSAVE := ${LIBEXT} + LIBEXT = a ifneq (,$(call find_lib,pthread)) - OS_CCDEFS += -DUSE_READER_THREAD - ifeq (,$(NOASYNCH)) - OS_CCDEFS += -DSIM_ASYNCH_IO - endif + OS_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO OS_LDFLAGS += -lpthread $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) else - LIBEXTSAVE := ${LIBEXT} - LIBEXT = a - ifneq (,$(call find_lib,pthread)) - OS_CCDEFS += -DUSE_READER_THREAD - ifeq (,$(NOASYNCH)) - OS_CCDEFS += -DSIM_ASYNCH_IO - endif - OS_LDFLAGS += -lpthread - $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) - else - ifneq (,$(findstring Haiku,$(OSTYPE))) - OS_CCDEFS += -DUSE_READER_THREAD - ifeq (,$(NOASYNCH)) - OS_CCDEFS += -DSIM_ASYNCH_IO - endif - $(info using libpthread: $(call find_include,pthread)) - endif + ifneq (,$(findstring Haiku,$(OSTYPE))) + OS_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO + $(info using libpthread: $(call find_include,pthread)) endif - LIBEXT = $(LIBEXTSAVE) endif + LIBEXT = $(LIBEXTSAVE) endif endif # Find PCRE RegEx library. @@ -656,14 +642,12 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin) endif else ifneq (,$(and $(findstring Linux,$(OSTYPE)),$(call find_exe,apt-get))) - $(info *** Info *** Install the development components of libSDL or libSDL2) - $(info *** Info *** packaged for your operating system distribution for) - $(info *** Info *** your Linux system:) + $(info *** Info *** Install the development components of libSDL2 packaged for) + $(info *** Info *** your operating system distribution for your Linux) + $(info *** Info *** system:) $(info *** Info *** $$ sudo apt-get install libsdl2-dev libpng-dev) - $(info *** Info *** or) - $(info *** Info *** $$ sudo apt-get install libsdl-dev) else - $(info *** Info *** Install the development components of libSDL packaged by your) + $(info *** Info *** Install the development components of libSDL2 packaged by your) $(info *** Info *** operating system distribution and rebuild your simulator to) $(info *** Info *** enable this extra functionality.) endif @@ -957,17 +941,11 @@ else $(info include paths are: ${INCPATH}) # Give preference to any MinGW provided threading (if available) ifneq (,$(call find_include,pthread)) - PTHREADS_CCDEFS = -DUSE_READER_THREAD - ifeq (,$(NOASYNCH)) - PTHREADS_CCDEFS += -DSIM_ASYNCH_IO - endif + PTHREADS_CCDEFS = -DUSE_READER_THREAD -DSIM_ASYNCH_IO PTHREADS_LDFLAGS = -lpthread else ifeq (pthreads,$(shell if exist ..\windows-build\pthreads\Pre-built.2\include\pthread.h echo pthreads)) - PTHREADS_CCDEFS = -DUSE_READER_THREAD -DPTW32_STATIC_LIB -D_POSIX_C_SOURCE -I../windows-build/pthreads/Pre-built.2/include - ifeq (,$(NOASYNCH)) - PTHREADS_CCDEFS += -DSIM_ASYNCH_IO - endif + PTHREADS_CCDEFS = -DUSE_READER_THREAD -DPTW32_STATIC_LIB -D_POSIX_C_SOURCE -I../windows-build/pthreads/Pre-built.2/include -DSIM_ASYNCH_IO PTHREADS_LDFLAGS = -lpthreadGC2 -L..\windows-build\pthreads\Pre-built.2\lib endif endif @@ -1158,11 +1136,15 @@ else ifneq (3,$(GCC_MAJOR_VERSION)) ifeq (,$(GCC_OPTIMIZERS_CMD)) GCC_OPTIMIZERS_CMD = ${GCC} --help=optimizers + GCC_COMMON_CMD = ${GCC} --help=common endif endif ifneq (,$(GCC_OPTIMIZERS_CMD)) GCC_OPTIMIZERS = $(shell $(GCC_OPTIMIZERS_CMD)) endif + ifneq (,$(GCC_COMMON_CMD)) + GCC_OPTIMIZERS += $(shell $(GCC_COMMON_CMD)) + endif ifneq (,$(findstring $(GCC_VERSION),$(LTO_EXCLUDE_VERSIONS))) NO_LTO = 1 endif @@ -1184,6 +1166,9 @@ else ifneq (,$(findstring -fstrict-overflow,$(GCC_OPTIMIZERS))) CFLAGS_O += -fno-strict-overflow endif + ifneq (,$(findstring -fcommon,$(GCC_OPTIMIZERS))$(findstring -fno-common,$(GCC_OPTIMIZERS))) + CFLAGS_O += -fcommon + endif ifeq (,$(NO_LTO)) ifneq (,$(findstring -flto,$(GCC_OPTIMIZERS))) CFLAGS_O += -flto -fwhole-program @@ -1906,10 +1891,36 @@ BESM6 = ${BESM6D}/besm6_cpu.c ${BESM6D}/besm6_sys.c ${BESM6D}/besm6_mmu.c \ ${BESM6D}/besm6_punch.c ${BESM6D}/besm6_punchcard.c ifneq (,$(BESM6_BUILD)) + BESM6_OPT = -I ${BESM6D} -DUSE_INT64 $(BESM6_PANEL_OPT) ifneq (,$(and ${SDLX_CONFIG},${VIDEO_LDFLAGS}, $(or $(and $(call find_include,SDL2/SDL_ttf),$(call find_lib,SDL2_ttf)), $(and $(call find_include,SDL/SDL_ttf),$(call find_lib,SDL_ttf))))) FONTPATH += /usr/share/fonts /Library/Fonts /usr/lib/jvm /System/Library/Frameworks/JavaVM.framework/Versions C:/Windows/Fonts FONTPATH := $(dir $(foreach dir,$(strip $(FONTPATH)),$(wildcard $(dir)/.))) FONTNAME += DejaVuSans.ttf LucidaSansRegular.ttf FreeSans.ttf AppleGothic.ttf tahoma.ttf +#cmake-insert:set(BESM6_FONT) +#cmake-insert:foreach (fdir IN ITEMS +#cmake-insert: "/usr/share/fonts" "/Library/Fonts" "/usr/lib/jvm" +#cmake-insert: "/System/Library/Frameworks/JavaVM.framework/Versions" +#cmake-insert: "$ENV{WINDIR}/Fonts") +#cmake-insert: foreach (font IN ITEMS +#cmake-insert: "DejaVuSans.ttf" "LucidaSansRegular.ttf" "FreeSans.ttf" "AppleGothic.ttf" "tahoma.ttf") +#cmake-insert: if (EXISTS ${fdir}) +#cmake-insert: file(GLOB_RECURSE found_font ${fdir}/${font}) +#cmake-insert: if (found_font) +#cmake-insert: get_filename_component(fontfile ${found_font} ABSOLUTE) +#cmake-insert: list(APPEND BESM6_FONT ${fontfile}) +#cmake-insert: endif () +#cmake-insert: endif () +#cmake-insert: endforeach() +#cmake-insert:endforeach() +#cmake-insert: +#cmake-insert:if (NOT BESM6_FONT) +#cmake-insert: message("No font file available, BESM-6 video panel disabled") +#cmake-insert: set(BESM6_PANEL_OPT) +#cmake-insert:endif () +#cmake-insert: +#cmake-insert:if (BESM6_FONT AND WITH_VIDEO) +#cmake-insert: list(GET BESM6_FONT 0 BESM6_FONT) +#cmake-insert:endif () $(info font paths are: $(FONTPATH)) $(info font names are: $(FONTNAME)) find_fontfile = $(strip $(firstword $(foreach dir,$(strip $(FONTPATH)),$(wildcard $(dir)/$(1))$(wildcard $(dir)/*/$(1))$(wildcard $(dir)/*/*/$(1))$(wildcard $(dir)/*/*/*/$(1))))) @@ -1959,13 +1970,11 @@ ifneq (,$(BESM6_BUILD)) else ifneq (,$(and $(findstring sdl2,${VIDEO_LDFLAGS}),$(call find_include,SDL2/SDL_ttf),$(call find_lib,SDL2_ttf))) $(info using libSDL2_ttf: $(call find_lib,SDL2_ttf) $(call find_include,SDL2/SDL_ttf)) $(info ***) - BESM6_OPT = -I ${BESM6D} -DFONTFILE=${FONTFILE} -DUSE_INT64 ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} -lSDL2_ttf + BESM6_PANEL_OPT = -DFONTFILE=${FONTFILE} ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} -lSDL2_ttf else ifneq (,$(and $(call find_include,SDL/SDL_ttf),$(call find_lib,SDL_ttf))) $(info using libSDL_ttf: $(call find_lib,SDL_ttf) $(call find_include,SDL/SDL_ttf)) $(info ***) - BESM6_OPT = -I ${BESM6D} -DFONTFILE=${FONTFILE} -DUSE_INT64 ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} -lSDL_ttf - else - BESM6_OPT = -I ${BESM6D} -DUSE_INT64 + BESM6_PANEL_OPT = -DFONTFILE=${FONTFILE} ${VIDEO_CCDEFS} ${VIDEO_LDFLAGS} -lSDL_ttf endif endif @@ -2004,7 +2013,7 @@ PDP6 = ${PDP6D}/kx10_cpu.c ${PDP6D}/kx10_sys.c ${PDP6D}/kx10_cty.c \ ${PDP6D}/kx10_lp.c ${PDP6D}/kx10_pt.c ${PDP6D}/kx10_cr.c \ ${PDP6D}/kx10_cp.c ${PDP6D}/pdp6_dct.c ${PDP6D}/pdp6_dtc.c \ ${PDP6D}/pdp6_mtc.c ${PDP6D}/pdp6_dsk.c ${PDP6D}/pdp6_dcs.c \ - ${PDP6D}/kx10_dpy.c ${DISPLAYL} $(DISPLAY340) + ${PDP6D}/kx10_dpy.c ${DISPLAYL} ${DISPLAY340} PDP6_OPT = -DPDP6=1 -DUSE_INT64 -I ${PDP6D} -DUSE_SIM_CARD ${DISPLAY_OPT} ${PDP6_DISPLAY_OPT} KA10D = ${SIMHD}/PDP10 @@ -2023,7 +2032,7 @@ KA10 = ${KA10D}/kx10_cpu.c ${KA10D}/kx10_sys.c ${KA10D}/kx10_df.c \ $(KA10D)/ka10_pmp.c ${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c \ ${KA10D}/pdp6_dtc.c ${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c \ ${KA10D}/pdp6_dcs.c ${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c \ - ${PDP10D}/ka10_ai.c ${KA10D}/ka10_iii.c ${DISPLAYL} $(DISPLAY340) + ${PDP10D}/ka10_ai.c ${KA10D}/ka10_iii.c ${DISPLAYL} ${DISPLAY340} KA10_OPT = -DKA=1 -DUSE_INT64 -I ${KA10D} -DUSE_SIM_CARD ${NETWORK_OPT} ${DISPLAY_OPT} ${KA10_DISPLAY_OPT} ifneq (${PANDA_LIGHTS},) # ONLY for Panda display. @@ -2042,7 +2051,7 @@ KI10 = ${KI10D}/kx10_cpu.c ${KI10D}/kx10_sys.c ${KI10D}/kx10_df.c \ ${KI10D}/kx10_rh.c ${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c \ ${KI10D}/kx10_dt.c ${KI10D}/kx10_dk.c ${KI10D}/kx10_cr.c \ ${KI10D}/kx10_cp.c ${KI10D}/kx10_tu.c ${KI10D}/kx10_rs.c \ - ${KI10D}/kx10_imp.c ${KI10D}/kx10_dpy.c ${DISPLAYL} $(DISPLAY340) + ${KI10D}/kx10_imp.c ${KI10D}/kx10_dpy.c ${DISPLAYL} ${DISPLAY340} KI10_OPT = -DKI=1 -DUSE_INT64 -I ${KI10D} -DUSE_SIM_CARD ${NETWORK_OPT} ${DISPLAY_OPT} ${KI10_DISPLAY_OPT} ifneq (${PANDA_LIGHTS},) # ONLY for Panda display. diff --git a/scp.h b/scp.h index ae7b5b2..409c3a1 100644 --- a/scp.h +++ b/scp.h @@ -417,7 +417,7 @@ extern t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val /* The per-simulator init routine is a weak global that defaults to NULL The other per-simulator pointers can be overrriden by the init routine */ -WEAK extern void (*sim_vm_init) (void); +extern void (*sim_vm_init) (void); extern char *(*sim_vm_read) (char *ptr, int32 size, FILE *stream); extern void (*sim_vm_post) (t_bool from_scp); extern CTAB *sim_vm_cmd; diff --git a/sim_card.c b/sim_card.c index e6618c0..fc75797 100644 --- a/sim_card.c +++ b/sim_card.c @@ -931,9 +931,9 @@ _sim_read_deck(UNIT * uptr, int eof) if (data->hopper_cards >= data->hopper_size) { data->hopper_size += DECK_SIZE; data->images = (uint16 (*)[1][80])realloc(data->images, - data->hopper_size * sizeof(*(data->images))); + (size_t)data->hopper_size * sizeof(*(data->images))); memset(&data->images[data->hopper_cards], 0, - (data->hopper_size - data->hopper_cards) * + (size_t)(data->hopper_size - data->hopper_cards) * sizeof(*(data->images))); } @@ -961,9 +961,9 @@ _sim_read_deck(UNIT * uptr, int eof) if (data->hopper_cards >= data->hopper_size) { data->hopper_size += DECK_SIZE; data->images = (uint16 (*)[1][80])realloc(data->images, - data->hopper_size * sizeof(*(data->images))); + (size_t)data->hopper_size * sizeof(*(data->images))); memset(&data->images[data->hopper_cards], 0, - (data->hopper_size - data->hopper_cards) * + (size_t)(data->hopper_size - data->hopper_cards) * sizeof(*(data->images))); } diff --git a/sim_defs.h b/sim_defs.h index a90eb2d..a60fad3 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -322,12 +322,16 @@ typedef uint32 t_addr; #define WEAK __attribute__((weak)) #elif defined(_MSC_VER) #define WEAK __declspec(selectany) -#else -#define WEAK extern -#endif -#else -#define WEAK -#endif +#else /* !defined(__GNUC__) && !defined(_MSC_VER) */ +#define WEAK +#endif /* __GNUC__ */ +#else /* !defined(__cplusplus) */ +#if defined(__GNUC__) +#define WEAK __attribute__((common)) +#else /* !defined(__GNUC__) */ +#define WEAK +#endif /* defined(__GNUC__) */ +#endif /* defined(__cplusplus) */ /* System independent definitions */ diff --git a/sim_ether.c b/sim_ether.c index fd02d25..2d304d6 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -379,6 +379,7 @@ /* Internal routines - forward declarations */ static int _eth_get_system_id (char *buf, size_t buf_size); +static int _eth_devices (int max, ETH_LIST* dev); /* get ethernet devices on host */ /*============================================================================*/ /* OS-independant ethernet routines */ @@ -657,10 +658,10 @@ void eth_packet_trace_detail(ETH_DEV* dev, const uint8 *msg, int len, const char eth_packet_trace_ex(dev, msg, len, txt, 1 , dev->dbit); } -const char* eth_getname(int number, char* name, char *desc) +static const char* _eth_getname(int number, char* name, char *desc) { ETH_LIST list[ETH_MAX_DEVICE]; - int count = eth_devices(ETH_MAX_DEVICE, list); + int count = _eth_devices(ETH_MAX_DEVICE, list); if ((number < 0) || (count <= number)) return NULL; @@ -677,7 +678,7 @@ const char* eth_getname(int number, char* name, char *desc) const char* eth_getname_bydesc(const char* desc, char* name, char *ndesc) { ETH_LIST list[ETH_MAX_DEVICE]; - int count = eth_devices(ETH_MAX_DEVICE, list); + int count = _eth_devices(ETH_MAX_DEVICE, list); int i; size_t j=strlen(desc); @@ -703,7 +704,7 @@ const char* eth_getname_bydesc(const char* desc, char* name, char *ndesc) char* eth_getname_byname(const char* name, char* temp, char *desc) { ETH_LIST list[ETH_MAX_DEVICE]; - int count = eth_devices(ETH_MAX_DEVICE, list); + int count = _eth_devices(ETH_MAX_DEVICE, list); size_t n; int i, found; @@ -723,7 +724,7 @@ char* eth_getname_byname(const char* name, char* temp, char *desc) char* eth_getdesc_byname(char* name, char* temp) { ETH_LIST list[ETH_MAX_DEVICE]; - int count = eth_devices(ETH_MAX_DEVICE, list); + int count = _eth_devices(ETH_MAX_DEVICE, list); size_t n; int i, found; @@ -777,7 +778,7 @@ t_stat eth_show (FILE* st, UNIT* uptr, int32 val, CONST void* desc) ETH_LIST list[ETH_MAX_DEVICE]; int number; - number = eth_devices(ETH_MAX_DEVICE, list); + number = _eth_devices(ETH_MAX_DEVICE, list); fprintf(st, "ETH devices:\n"); if (number == -1) fprintf(st, " network support not available in simulator\n"); @@ -956,7 +957,7 @@ t_stat eth_filter (ETH_DEV* dev, int addr_count, ETH_MAC* const addresses, t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, ETH_MAC* const addresses, ETH_BOOL all_multicast, ETH_BOOL promiscuous, ETH_MULTIHASH* const hash) {return SCPE_NOFNC;} -int eth_devices (int max, ETH_LIST* dev) +int _eth_devices (int max, ETH_LIST* dev) {return -1;} const char *eth_version (void) {return NULL;} @@ -1062,22 +1063,28 @@ static HINSTANCE hLib = NULL; /* handle to DLL */ static void *hLib = 0; /* handle to Library */ #endif static int lib_loaded = 0; /* 0=not loaded, 1=loaded, 2=library load failed, 3=Func load failed */ + +#define __STR_QUOTE(tok) #tok +#define __STR(tok) __STR_QUOTE(tok) static const char* lib_name = #if defined(_WIN32) || defined(__CYGWIN__) "wpcap.dll"; #elif defined(__APPLE__) "/usr/lib/libpcap.A.dylib"; #else -#define __STR_QUOTE(tok) #tok -#define __STR(tok) __STR_QUOTE(tok) "libpcap." __STR(HAVE_DLOPEN); #endif -static const char* no_pcap = + +static char no_pcap[PCAP_ERRBUF_SIZE] = #if defined(_WIN32) || defined(__CYGWIN__) - "wpcap load failure"; + "wpcap.dll failed to load, install Npcap or WinPcap 4.x to use pcap networking"; +#elif defined(__APPLE__) + "/usr/lib/libpcap.A.dylib failed to load, install libpcap to use pcap networking"; #else - "libpcap load failure"; + "libpcap." __STR(HAVE_DLOPEN) " failed to load, install libpcap to use pcap networking"; #endif +#undef __STR +#undef __STR_QUOTE /* define pointers to pcap functions needed */ static void (*p_pcap_close) (pcap_t *); @@ -1147,12 +1154,6 @@ int load_pcap(void) { #endif if (hLib == 0) { /* failed to load DLL */ - sim_printf ("Eth: Failed to load %s\n", lib_name); -#ifdef _WIN32 - sim_printf ("Eth: You must install Npcap or WinPcap 4.x to use networking\n"); -#else - sim_printf ("Eth: You must install libpcap to use networking\n"); -#endif lib_loaded = 2; break; } else { @@ -1212,10 +1213,19 @@ int pcap_compile(pcap_t* a, struct bpf_program* b, const char* c, int d, bpf_u_i } const char *pcap_lib_version(void) { + static char buf[256]; + if ((load_pcap() != 0) && (p_pcap_lib_version != NULL)) { return p_pcap_lib_version(); } else { - return NULL; + sprintf (buf, "%s not installed", +#if defined(_WIN32) + "npcap or winpcap" +#else + "libpcap" +#endif + ); + return buf; } } @@ -1241,6 +1251,7 @@ int pcap_findalldevs(pcap_if_t** a, char* b) { } else { *a = 0; strcpy(b, no_pcap); + no_pcap[0] = '\0'; return -1; } } @@ -1643,7 +1654,7 @@ static int _eth_get_system_id (char *buf, size_t buf_size) if ((status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Cryptography", 0, KEY_QUERY_VALUE|KEY_WOW64_64KEY, ®hnd)) != ERROR_SUCCESS) return -1; reglen = buf_size; - if ((status = RegQueryValueExA (reghnd, "MachineGuid", NULL, ®type, buf, ®len)) != ERROR_SUCCESS) { + if ((status = RegQueryValueExA (reghnd, "MachineGuid", NULL, ®type, (LPBYTE)buf, ®len)) != ERROR_SUCCESS) { RegCloseKey (reghnd); return -1; } @@ -2278,7 +2289,7 @@ if ((strlen(name) == 4) && isdigit(name[3]) ) { num = atoi(&name[3]); - savname = eth_getname(num, temp, desc); + savname = _eth_getname(num, temp, desc); if (savname == NULL) /* didn't translate */ return SCPE_OPENERR; } @@ -3934,7 +3945,7 @@ return SCPE_OK; returned by pcap_findalldevs. */ -int eth_host_devices(int used, int max, ETH_LIST* list) +static int eth_host_devices(int used, int max, ETH_LIST* list) { pcap_t* conn = NULL; int i, j, datalink = 0; @@ -4037,7 +4048,7 @@ if (used < max) { return used; } -int eth_devices(int max, ETH_LIST* list) +static int _eth_devices(int max, ETH_LIST* list) { int i = 0; char errbuf[PCAP_ERRBUF_SIZE] = ""; @@ -4049,7 +4060,8 @@ memset(list, 0, max*sizeof(*list)); errbuf[0] = '\0'; /* retrieve the device list */ if (pcap_findalldevs(&alldevs, errbuf) == -1) { - sim_printf ("Eth: error in pcap_findalldevs: %s\n", errbuf); + if (errbuf[0]) + sim_printf ("Eth: %s\n", errbuf); } else { /* copy device list into the passed structure */ @@ -4241,7 +4253,7 @@ int bpf_compile_skip_count = 0; memset (ð_tst, 0, sizeof(eth_tst)); -eth_device_count = eth_devices(ETH_MAX_DEVICE, eth_list); +eth_device_count = _eth_devices(ETH_MAX_DEVICE, eth_list); eth_opened = 0; for (eth_num=0; eth_num Date: Thu, 30 Jan 2020 21:53:08 -0500 Subject: [PATCH 84/98] KA10: Temporarily disabled III device. --- PDP10/kx10_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index ed75db5..5129038 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -604,7 +604,7 @@ int auxcpu_write (t_addr addr, t_uint64); #define NUM_DEVS_TU 1 #define NUM_DEVS_PMP WAITS #define NUM_DEVS_DKB WAITS -#define NUM_DEVS_III (WAITS * USE_DISPLAY) +#define NUM_DEVS_III 0 /* (WAITS * USE_DISPLAY) *//* Disabled until working */ #define NUM_DEVS_PD ITS | KL_ITS #define NUM_DEVS_IMX ITS #define NUM_DEVS_STK ITS From 079c2e26ce9dcaaea050d515cde644936ff37311 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 2 Feb 2020 21:12:07 -0500 Subject: [PATCH 85/98] SCP: Updated to current. --- scp.c | 9 ++++-- sim_ether.c | 91 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 67 insertions(+), 33 deletions(-) diff --git a/scp.c b/scp.c index 7040d61..39e82af 100644 --- a/scp.c +++ b/scp.c @@ -7680,8 +7680,13 @@ for (i = 0; i < (device_count + sim_internal_device_count); i++) {/* loop thru d fputc ('\n', sfile); /* end registers */ } fputc ('\n', sfile); /* end devices */ -if (!ferror (sfile)) - sim_set_fsize (sfile, (t_addr)sim_ftell (sfile)); /* truncate the save file */ +if (!ferror (sfile)) { + t_offset pos = sim_ftell (sfile); /* get current position */ + + if (pos < 0) /* error? */ + return SCPE_IOERR; /* done! */ + sim_set_fsize (sfile, (t_addr)pos); /* truncate the save file */ + } return (ferror (sfile))? SCPE_IOERR: SCPE_OK; /* error during save? */ } diff --git a/sim_ether.c b/sim_ether.c index 2d304d6..e339d6d 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -1194,7 +1194,7 @@ int load_pcap(void) { /* define functions with dynamic revectoring */ void pcap_close(pcap_t* a) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { p_pcap_close(a); } } @@ -1205,7 +1205,7 @@ int pcap_compile(pcap_t* a, struct bpf_program* b, char* c, int d, bpf_u_int32 e #else int pcap_compile(pcap_t* a, struct bpf_program* b, const char* c, int d, bpf_u_int32 e) { #endif - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_compile(a, b, c, d, e); } else { return 0; @@ -1230,7 +1230,7 @@ const char *pcap_lib_version(void) { } int pcap_datalink(pcap_t* a) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_datalink(a); } else { return 0; @@ -1238,7 +1238,7 @@ int pcap_datalink(pcap_t* a) { } int pcap_dispatch(pcap_t* a, int b, pcap_handler c, u_char* d) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_dispatch(a, b, c, d); } else { return 0; @@ -1246,7 +1246,7 @@ int pcap_dispatch(pcap_t* a, int b, pcap_handler c, u_char* d) { } int pcap_findalldevs(pcap_if_t** a, char* b) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_findalldevs(a, b); } else { *a = 0; @@ -1257,19 +1257,19 @@ int pcap_findalldevs(pcap_if_t** a, char* b) { } void pcap_freealldevs(pcap_if_t* a) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { p_pcap_freealldevs(a); } } void pcap_freecode(struct bpf_program* a) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { p_pcap_freecode(a); } } char* pcap_geterr(pcap_t* a) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_geterr(a); } else { return (char*) ""; @@ -1294,7 +1294,7 @@ pcap_t* pcap_open_live(const char* a, int b, int c, int d, char* e) { #ifdef _WIN32 int pcap_setmintocopy(pcap_t* a, int b) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_setmintocopy(a, b); } else { return -1; @@ -1302,7 +1302,7 @@ int pcap_setmintocopy(pcap_t* a, int b) { } HANDLE pcap_getevent(pcap_t* a) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_getevent(a); } else { return (HANDLE) 0; @@ -1312,7 +1312,7 @@ HANDLE pcap_getevent(pcap_t* a) { #else #ifdef MUST_DO_SELECT int pcap_get_selectable_fd(pcap_t* a) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_get_selectable_fd(a); } else { return 0; @@ -1321,7 +1321,7 @@ int pcap_get_selectable_fd(pcap_t* a) { #endif int pcap_fileno(pcap_t * a) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_fileno(a); } else { return 0; @@ -1330,7 +1330,7 @@ int pcap_fileno(pcap_t * a) { #endif int pcap_sendpacket(pcap_t* a, const u_char* b, int c) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_sendpacket(a, b, c); } else { return 0; @@ -1338,7 +1338,7 @@ int pcap_sendpacket(pcap_t* a, const u_char* b, int c) { } int pcap_setfilter(pcap_t* a, struct bpf_program* b) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_setfilter(a, b); } else { return 0; @@ -1346,7 +1346,7 @@ int pcap_setfilter(pcap_t* a, struct bpf_program* b) { } int pcap_setnonblock(pcap_t* a, int nonblock, char *errbuf) { - if (a && (load_pcap() != 0)) { + if (load_pcap() != 0) { return p_pcap_setnonblock(a, nonblock, errbuf); } else { return 0; @@ -1616,7 +1616,7 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname) break; } fclose(f); - remove("NIC.hwaddr"); + (void)remove("NIC.hwaddr"); } } } @@ -1673,13 +1673,17 @@ FILE *f; memset (buf, 0, buf_size); if ((f = fopen ("/etc/machine-id", "r"))) { - if (fread (buf, 1, buf_size - 1, f)) {}; - fclose (f); + if (fread (buf, 1, buf_size - 1, f)) + fclose (f); + else + fclose (f); } else { if ((f = popen ("hostname", "r"))) { - if (fread (buf, 1, buf_size - 1, f)) {}; - pclose (f); + if (fread (buf, 1, buf_size - 1, f)) + pclose (f); + else + pclose (f); } } while ((strlen (buf) > 0) && sim_isspace(buf[strlen (buf) - 1])) @@ -1936,8 +1940,15 @@ while (dev->handle) { /* Put buffer on free buffer list */ request->next = dev->write_buffers; dev->write_buffers = request; + request = NULL; } } +/* If we exited these loops with a request allocated, */ +/* avoid buffer leaking by putting it on free buffer list */ +if (request) { + request->next = dev->write_buffers; + dev->write_buffers = request; + } pthread_mutex_unlock (&dev->writer_lock); sim_debug(dev->dbit, dev->dptr, "Writer Thread Exiting\n"); @@ -2020,7 +2031,7 @@ if (0 == strncmp("tap:", savname, 4)) { memset(&ifr, 0, sizeof(ifr)); /* Set up interface flags */ - strcpy(ifr.ifr_name, devname); + strlcpy(ifr.ifr_name, devname, sizeof(ifr.ifr_name)); ifr.ifr_flags = IFF_TAP|IFF_NO_PI; /* Send interface requests to TUN/TAP driver. */ @@ -2028,9 +2039,10 @@ if (0 == strncmp("tap:", savname, 4)) { if (ioctl(tun, FIONBIO, &on)) { strlcpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE); close(tun); + tun = -1; } else { - *fd_handle = tun; + *fd_handle = (SOCKET)tun; strcpy(savname, ifr.ifr_name); } } @@ -2039,6 +2051,10 @@ if (0 == strncmp("tap:", savname, 4)) { } else strlcpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE); + if ((tun >= 0) && (errbuf[0] != 0)) { + close(tun); + tun = -1; + } #elif defined(HAVE_BSDTUNTAP) && defined(HAVE_TAP_NETWORK) if (1) { char dev_name[64] = ""; @@ -2050,9 +2066,10 @@ if (0 == strncmp("tap:", savname, 4)) { if (ioctl(tun, FIONBIO, &on)) { strlcpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE); close(tun); + tun = -1; } else { - *fd_handle = tun; + *fd_handle = (SOCKET)tun; strcpy(savname, devname); } #if defined (__APPLE__) @@ -2069,6 +2086,7 @@ if (0 == strncmp("tap:", savname, 4)) { if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr)) { strlcpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE); close(tun); + tun = -1; } } close(s); @@ -2078,7 +2096,11 @@ if (0 == strncmp("tap:", savname, 4)) { } else strlcpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE); - } + if ((tun >= 0) && (errbuf[0] != 0)) { + close(tun); + tun = -1; + } + } #else strlcpy(errbuf, "No support for tap: devices", PCAP_ERRBUF_SIZE); #endif /* !defined(__linux) && !defined(HAVE_BSDTUNTAP) */ @@ -2116,7 +2138,7 @@ else { /* !tap: */ strlcpy(errbuf, strerror(errno), PCAP_ERRBUF_SIZE); else { *eth_api = ETH_API_VDE; - *fd_handle = vde_datafd((VDECONN*)(*handle)); + *fd_handle = (SOCKET)vde_datafd((VDECONN*)(*handle)); } #else strlcpy(errbuf, "No support for vde: network devices", PCAP_ERRBUF_SIZE); @@ -3066,15 +3088,22 @@ cksum += (cksum >> 16); return (uint16)(~cksum); } +/* + * src_addr and dest_addr are presented in network byte order + */ + static uint16 -pseudo_checksum(uint16 len, uint16 proto, uint16 *src_addr, uint16 *dest_addr, uint8 *buff) +pseudo_checksum(uint16 len, uint16 proto, void *nsrc_addr, void *ndest_addr, uint8 *buff) { uint32 sum; +uint16 *src_addr = (uint16 *)nsrc_addr; +uint16 *dest_addr = (uint16 *)ndest_addr; /* Sum the data first */ sum = 0xffff&(~ip_checksum((uint16 *)buff, len)); -/* add the pseudo header which contains the IP source and destinationn addresses */ +/* add the pseudo header which contains the IP source and + destination addresses already in network byte order */ sum += src_addr[0]; sum += src_addr[1]; sum += dest_addr[0]; @@ -3135,7 +3164,7 @@ switch (IP->proto) { break; /* UDP Checksums are disabled */ orig_checksum = UDP->checksum; UDP->checksum = 0; - UDP->checksum = pseudo_checksum(ntohs(UDP->length), IPPROTO_UDP, (uint16 *)(&IP->source_ip), (uint16 *)(&IP->dest_ip), (uint8 *)UDP); + UDP->checksum = pseudo_checksum(ntohs(UDP->length), IPPROTO_UDP, &IP->source_ip, &IP->dest_ip, (uint8 *)UDP); if (orig_checksum != UDP->checksum) eth_packet_trace (dev, msg, len, "reading jumbo UDP header Checksum Fixed"); break; @@ -3244,7 +3273,7 @@ switch (IP->proto) { IP->checksum = 0; IP->checksum = ip_checksum((uint16 *)IP, IP_HLEN(IP)); TCP->checksum = 0; - TCP->checksum = pseudo_checksum(ntohs(IP->total_len)-IP_HLEN(IP), IPPROTO_TCP, (uint16 *)(&IP->source_ip), (uint16 *)(&IP->dest_ip), (uint8 *)TCP); + TCP->checksum = pseudo_checksum(ntohs(IP->total_len)-IP_HLEN(IP), IPPROTO_TCP, &IP->source_ip, &IP->dest_ip, (uint8 *)TCP); header.caplen = header.len = 14 + ntohs(IP->total_len); eth_packet_trace_ex (dev, ((u_char *)IP)-14, header.len, "reading TCP segment", 1, dev->dbit); #if ETH_MIN_JUMBO_FRAME < ETH_MAX_PACKET @@ -3316,7 +3345,7 @@ switch (IP->proto) { return; /* UDP Checksums are disabled */ orig_checksum = UDP->checksum; UDP->checksum = 0; - UDP->checksum = pseudo_checksum(ntohs(UDP->length), IPPROTO_UDP, (uint16 *)(&IP->source_ip), (uint16 *)(&IP->dest_ip), (uint8 *)UDP); + UDP->checksum = pseudo_checksum(ntohs(UDP->length), IPPROTO_UDP, &IP->source_ip, &IP->dest_ip, (uint8 *)UDP); if (orig_checksum != UDP->checksum) eth_packet_trace (dev, msg, len, "reading UDP header Checksum Fixed"); break; @@ -3324,7 +3353,7 @@ switch (IP->proto) { TCP = (struct TCPHeader *)(((char *)IP)+IP_HLEN(IP)); orig_checksum = TCP->checksum; TCP->checksum = 0; - TCP->checksum = pseudo_checksum(ntohs(IP->total_len)-IP_HLEN(IP), IPPROTO_TCP, (uint16 *)(&IP->source_ip), (uint16 *)(&IP->dest_ip), (uint8 *)TCP); + TCP->checksum = pseudo_checksum(ntohs(IP->total_len)-IP_HLEN(IP), IPPROTO_TCP, &IP->source_ip, &IP->dest_ip, (uint8 *)TCP); if (orig_checksum != TCP->checksum) eth_packet_trace (dev, msg, len, "reading TCP header Checksum Fixed"); break; From 1c965678182306c0af00415448b4648a605b743c Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 12 Feb 2020 00:02:53 -0500 Subject: [PATCH 86/98] KA10: Fixed bugs in KL10, added memory interface for devices. --- PDP10/ka10_pmp.c | 42 +++++++++++++---------------- PDP10/kx10_cpu.c | 46 ++++++++++++++++++++++++++------ PDP10/kx10_defs.h | 19 ++++++++++---- PDP10/kx10_df.c | 20 +++++++++----- PDP10/kx10_rh.c | 67 +++++++++++++++++++++++++++++------------------ PDP10/kx10_rp.c | 1 - PDP10/kx10_rs.c | 1 - PDP10/kx10_tu.c | 1 - 8 files changed, 124 insertions(+), 73 deletions(-) diff --git a/PDP10/ka10_pmp.c b/PDP10/ka10_pmp.c index ea3e69b..66839a4 100644 --- a/PDP10/ka10_pmp.c +++ b/PDP10/ka10_pmp.c @@ -142,7 +142,7 @@ #define DK_MSK_SKNONE 0x18 /* Allow no seeks */ #define DK_MSK_SK 0x18 /* Seek mask */ -#define POS u4 +#define POS u4 /* u4 */ /* Holds the current track and head */ #define DK_V_TRACK 8 @@ -348,9 +348,9 @@ uint64 pmp_status; /* CONI status for device 500 */ int pmp_statusb; uint32 pmp_cmd_hold; /* Command hold register */ uint32 pmp_wc_hold; /* Word count hold */ -uint32 pmp_addr_hold; /* Address register hold */ +t_addr pmp_addr_hold; /* Address register hold */ uint32 pmp_wc; /* Current word count register */ -uint32 pmp_addr; /* Current address register */ +t_addr pmp_addr; /* Current address register */ uint64 pmp_data; /* Data assembly register */ int pmp_cnt; /* Character count in asm register */ int pmp_cmd; /* Current command */ @@ -382,7 +382,7 @@ t_stat pmp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); const char *pmp_description (DEVICE *dptr); -DIB pmp_dib[] = { +DIB pmp_dib[] = { {PMP_DEV, 2, &pmp_devio, NULL}}; @@ -433,13 +433,13 @@ pmp_devio(uint32 dev, uint64 *data) { if ((pmp_statusb & (WCMA_LD|CMD_LD)) != (WCMA_LD|CMD_LD)) *data |= HOLD_EMPTY; if (pmp_cur_unit != NULL) - *data |= ((uint64)GET_UADDR(pmp_cur_unit->flags)) << 24; + *data |= ((uint64)GET_UADDR(pmp_cur_unit->flags)) << 24; if ((pmp_status & (NXM_ERR|CHA_ERR|SEL_ERR)) != 0) *data |= UNU_END; sim_debug(DEBUG_CONI, &pmp_dev, "PMP %03o CONI %012llo PC=%o\n", dev, *data, PC); break; - + case CONO: sim_debug(DEBUG_CONO, &pmp_dev, "PMP %03o CONO %012llo PC=%06o\n", dev, *data, PC); @@ -597,9 +597,8 @@ chan_read_byte(uint8 *data) { pmp_statusb |= TRANS_CH; /* Tranfer in progress */ /* Read in next work if buffer is in empty status */ if (pmp_cnt & BUFF_EMPTY) { - if (pmp_addr >= (int)MEMSIZE) + if (Mem_read_word(pmp_addr, &pmp_data, 0)) return pmp_posterror(NXM_ERR); - pmp_data = M[pmp_addr]; sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read %06o %012llo\n", pmp_addr, pmp_data); pmp_addr++; pmp_cnt = 0; @@ -616,10 +615,9 @@ chan_read_byte(uint8 *data) { if ((pmp_cnt & 0xf) > 0x3) { if ((pmp_cnt & 0xf) == 0x4) { /* Split byte */ byte = (pmp_data << 4) & 0xf0; - if (pmp_addr >= (int)MEMSIZE) + if (Mem_read_word(pmp_addr, &pmp_data, 0)) return pmp_posterror(NXM_ERR); - pmp_data = M[pmp_addr]; - sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read %06o %012llo\n", pmp_addr, pmp_data); + sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read %06o %012llo\n", pmp_addr, pmp_data); pmp_addr++; xfer = 1; /* Read in a word */ byte |= pmp_data & 0xf; @@ -639,7 +637,7 @@ chan_read_byte(uint8 *data) { } else if (xfer) { pmp_wc ++; } - if (pmp_wc & 07000000) + if (pmp_wc & 07000000) pmp_cnt |= BUFF_CHNEND; return 0; #if 0 @@ -693,11 +691,10 @@ chan_write_byte(uint8 *data) { pmp_cnt |= BUFF_DIRTY; if ((pmp_cnt & 03) == 0) { pmp_cnt &= ~(BUFF_DIRTY|7); - if (pmp_addr >= (int)MEMSIZE) + if (Mem_write_word(pmp_addr, &pmp_data, 0)) return pmp_posterror(NXM_ERR); - M[pmp_addr] = pmp_data; - sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo\n", pmp_addr, pmp_data); - pmp_addr++; + sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo\n", pmp_addr, pmp_data); + pmp_addr++; xfer = 1; } } else { @@ -705,9 +702,8 @@ chan_write_byte(uint8 *data) { if ((pmp_cnt & 0xf) == 0x4) { /* Split byte */ pmp_data &= ~0xf; pmp_data |= (uint64)((*data >> 4) & 0xf); - if (pmp_addr >= (int)MEMSIZE) + if (Mem_write_word(pmp_addr, &pmp_data, 0)) return pmp_posterror(NXM_ERR); - M[pmp_addr] = pmp_data; sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo %2x\n", pmp_addr, pmp_data, pmp_cnt); pmp_addr++; xfer = 1; /* Read in a word */ @@ -726,9 +722,8 @@ chan_write_byte(uint8 *data) { pmp_cnt++; if ((pmp_cnt & 0xf) == 9) { pmp_cnt = BUFF_EMPTY; - if (pmp_addr >= (int)MEMSIZE) + if (Mem_write_word(pmp_addr, &pmp_data, 0)) return pmp_posterror(NXM_ERR); - M[pmp_addr] = pmp_data; sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo %2x\n", pmp_addr, pmp_data, pmp_cnt); pmp_addr++; xfer = 1; /* Read in a word */ @@ -774,16 +769,15 @@ chan_end(uint8 flags) { /* Flush buffer if there was any change */ if (pmp_cnt & BUFF_DIRTY) { pmp_cnt = BUFF_EMPTY; - if (pmp_addr >= (int)MEMSIZE) { + if (Mem_write_word(pmp_addr, &pmp_data, 0)) { (void) pmp_posterror(NXM_ERR); return; } - M[pmp_addr] = pmp_data; sim_debug(DEBUG_DATA, &pmp_dev, "chan_write %012llo\n", pmp_data); pmp_addr++; } pmp_statusb &= ~TRANS_CH; /* Clear transfer in progress */ - pmp_statusb |= IDLE_CH; + pmp_statusb |= IDLE_CH; pmp_status |= NEW_STS | CHN_END | ((uint64)flags) << 5; if (pmp_status & (BSY|UNIT_CHK)) @@ -798,7 +792,7 @@ chan_end(uint8 flags) { if (pmp_cmd & DATCH_ON) { (void) pmp_posterror(CHA_ERR); return; - } + } if (pmp_cmd & CMDCH_ON) { pmp_startcmd(); diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 0af0e3c..1df9a8b 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2992,7 +2992,7 @@ int its_load_tlb(uint32 reg, int page, uint32 *tlb) { fault_data |= 0200; return 1; } - if (entry > (int)MEMSIZE) { + if (entry >= (int)MEMSIZE) { nxm_flag = 1; fault_data |= 0400; return 1; @@ -3924,6 +3924,34 @@ int Mem_write_nopage() { return 0; } +/* + * Access main memory. Returns 0 if access ok, 1 if out of memory range. + * On KI10 and KL10, optional EPT flag indicates address relative to ept. + */ +int Mem_read_word(t_addr addr, uint64 *data, int ept) +{ +#if KL | KI + if (ept) + addr += eb_ptr; +#endif + if (addr >= MEMSIZE) + return 1; + *data = M[addr]; + return 0; +} + +int Mem_write_word(t_addr addr, uint64 *data, int ept) +{ +#if KL | KI + if (ept) + addr += eb_ptr; +#endif + if (addr >= MEMSIZE) + return 1; + M[addr] = *data; + return 0; +} + /* * Function to determine number of leading zero bits in a work @@ -4403,7 +4431,7 @@ st_pi: goto last; AB = MB & (SECTM|RMASK); if (IR & 1) { - AR = get_reg(AC); + MB = get_reg(AC); if (Mem_write_nopage()) goto last; } else { @@ -4632,7 +4660,7 @@ unasign: case 0076: /* LMR */ if (QITS && (FLAGS & USER) == 0) { /* Load store ITS pager info */ - if ((AB + 8) > MEMSIZE) { + if ((AB + 8) >= MEMSIZE) { break; } MB = M[AB]; /* WD 0 */ @@ -4657,7 +4685,7 @@ unasign: goto unasign; case 0077: /* SPM */ if (QITS && (FLAGS & USER) == 0) { - if ((AB + 8) > MEMSIZE) { + if ((AB + 8) >= MEMSIZE) { break; } MB = (uint64)jpc; @@ -5546,7 +5574,7 @@ dpnorm: /* Load store ITS pager info */ /* AC & 1 = Store */ if (AC & 1) { - if ((AB + 8) > MEMSIZE) { + if ((AB + 8) >= MEMSIZE) { fault_data |= 0400; mem_prot = 1; break; @@ -5579,7 +5607,7 @@ dpnorm: MB = (uint64)ac_stack; M[AB] = MB; } else { - if ((AB + 8) > MEMSIZE) { + if ((AB + 8) >= MEMSIZE) { fault_data |= 0400; mem_prot = 1; break; @@ -5863,10 +5891,10 @@ unasign: case 0134: /* ILDB */ case 0136: /* IDPB */ if ((FLAGS & BYTI) == 0) { /* BYF6 */ - modify = 1; #if KL if (Mem_read(0, 0, 0)) { #else + modify = 1; if (Mem_read(0, !QITS, 0)) { #endif #if PDP6 @@ -5943,6 +5971,7 @@ unasign: goto last; if ((IR & 04) == 0) break; + modify = 0; goto ldb_ptr; } /* Fall through */ @@ -7563,7 +7592,7 @@ jrstf: } else AR = (f & 01740) ? 0 : 0377777LL; AR |= BIT8; -//fprintf(stderr, "Map ok %012llo %06o\r\n", AR, AB); +//fprintf(stderr, "Map ok %012llo %03o %06o\r\n", AR, cur_sect, AB); #else /* Check if Paging Enabled */ if (!page_enable || AB < 020) { @@ -10313,6 +10342,7 @@ for (i = 0; (dptr = rh_devs[i]) != NULL; i++) { rh[rh_idx].dev_num = d; rh[rh_idx].dev = dptr; rh[rh_idx].rh = dibp->rh; + dibp->rh->devnum = d; rh_idx++; } } diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 5129038..730a0fe 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -379,6 +379,20 @@ extern DEBTAB crd_debug[]; #define TYPE_RH10 (0 << DEV_V_RH) #define TYPE_RH20 (1 << DEV_V_RH) +#if KL +/* DTE memory access functions, n = DTE# */ +extern int Mem_examine_word(int n, int wrd, uint64 *data); +extern int Mem_deposit_word(int n, int wrd, uint64 *data); +extern int Mem_read_byte(int n, uint16 *data, int byte); +extern int Mem_write_byte(int n, uint16 *data); +#endif + +/* + * Access main memory. Returns 0 if access ok, 1 if out of memory range. + * On KI10 and KL10, optional EPT flag indicates address relative to ept. + */ +extern int Mem_read_word(t_addr addr, uint64 *data, int ept); +extern int Mem_write_word(t_addr addr, uint64 *data, int ept); #if MPX_DEV extern void set_interrupt_mpx(int dev, int lvl, int mpx); @@ -395,11 +409,6 @@ extern UNIT cpu_unit[]; extern UNIT ten11_unit[]; extern UNIT auxcpu_unit[]; #if KL -/* DTE memory access functions, n = DTE# */ -extern int Mem_examine_word(int n, int wrd, uint64 *data); -extern int Mem_deposit_word(int n, int wrd, uint64 *data); -extern int Mem_read_byte(int n, uint16 *data, int byte); -extern int Mem_write_byte(int n, uint16 *data); extern DEVICE dte_dev; extern DEVICE lp20_dev; extern DEVICE tty_dev; diff --git a/PDP10/kx10_df.c b/PDP10/kx10_df.c index 841ca9f..90564ea 100644 --- a/PDP10/kx10_df.c +++ b/PDP10/kx10_df.c @@ -32,10 +32,12 @@ void df10_setirq(struct df10 *df) { /* Generate the DF10 complete word */ void df10_writecw(struct df10 *df) { + uint64 wrd; df->status |= 1 << df->ccw_comp; if (df->wcr != 0) df->cda++; - M[df->cia|1] = ((uint64)(df->ccw & WMASK) << CSHIFT) | ((uint64)(df->cda) & AMASK); + wrd = ((uint64)(df->ccw & WMASK) << CSHIFT) | ((uint64)(df->cda) & AMASK); + (void)Mem_write_word(df->cia|1, &wrd, 0); } /* Finish off a DF10 transfer */ @@ -58,22 +60,20 @@ void df10_setup(struct df10 *df, uint32 addr) { /* Fetch the next IO control word */ int df10_fetch(struct df10 *df) { uint64 data; - if (df->ccw > MEMSIZE) { + if (Mem_read_word(df->ccw, &data, 0)) { df10_finish_op(df, df->nxmerr); return 0; } - data = M[df->ccw]; while((data & (WMASK << CSHIFT)) == 0) { if ((data & AMASK) == 0 || (uint32)(data & AMASK) == df->ccw) { df10_finish_op(df,0); return 0; } df->ccw = (uint32)(data & AMASK); - if (df->ccw > MEMSIZE) { + if (Mem_read_word(df->ccw, &data, 0)) { df10_finish_op(df, 1<nxmerr); return 0; } - data = M[df->ccw]; } #if KA & ITS if (cpu_unit[0].flags & UNIT_ITSPAGE) { @@ -109,7 +109,10 @@ int df10_read(struct df10 *df) { else #endif df->cda = (uint32)((df->cda + 1) & AMASK); - data = M[df->cda]; + if (Mem_read_word(df->cda, &data, 0)) { + df10_finish_op(df, 1<nxmerr); + return 0; + } } else { data = 0; } @@ -138,7 +141,10 @@ int df10_write(struct df10 *df) { else #endif df->cda = (uint32)((df->cda + 1) & AMASK); - M[df->cda] = df->buf; + if (Mem_write_word(df->cda, &df->buf, 0)) { + df10_finish_op(df, 1<nxmerr); + return 0; + } } if (df->wcr == 0) { return df10_fetch(df); diff --git a/PDP10/kx10_rh.c b/PDP10/kx10_rh.c index bf6350d..924ea6e 100644 --- a/PDP10/kx10_rh.c +++ b/PDP10/kx10_rh.c @@ -192,7 +192,6 @@ t_stat rh_devio(uint32 dev, uint64 *data) { } if (rhc == NULL) return SCPE_OK; - rhc->devnum = dev & 0774; #if KL if (dptr->flags & TYPE_RH20) { switch(dev & 3) { @@ -526,6 +525,7 @@ void rh_setirq(struct rh_if *rhc) { /* Generate the DF10 complete word */ void rh_writecw(struct rh_if *rhc, int nxm) { + uint64 wrd1; #if KL if (rhc->imode == 2) { uint32 chan = (rhc->devnum - 0540); @@ -534,7 +534,8 @@ void rh_writecw(struct rh_if *rhc, int nxm) { rhc->status &= ~(RH20_PCR_FULL); if (wc != 0 || (rhc->status & RH20_XEND) == 0 || (rhc->ptcr & BIT10) != 0 || nxm) { - uint64 wrd1 = SMASK|(uint64)(rhc->ccw); + uint64 wrd2; + wrd1 = SMASK|(uint64)(rhc->ccw); if ((rhc->ptcr & BIT10) == 0 || (rhc->status & RH20_DR_EXC) != 0) return; if (nxm) { @@ -559,11 +560,11 @@ void rh_writecw(struct rh_if *rhc, int nxm) { if ((rhc->status & RH20_CHAN_ERR) == 0 && (rhc->ptcr & BIT10) == 0) return; wrd1 |= RH20_NADR_PAR; - M[eb_ptr|chan|1] = wrd1; - M[eb_ptr|chan|2] = ((uint64)rhc->cop << 33) | - (((uint64)wc) << CSHIFT) | + wrd2 = ((uint64)rhc->cop << 33) | (((uint64)wc) << CSHIFT) | ((uint64)(rhc->cda) & AMASK); -//fprintf(stderr, "RH20 final %012llo %012llo %06o\n\r", M[eb_ptr|chan|1], M[eb_ptr|chan|2], wc); + (void)Mem_write_word(chan+1, &wrd1, 1); + (void)Mem_write_word(chan+2, &wrd2, 1); +//fprintf(stderr, "RH20 final %012llo %012llo %06o\n\r", wrd1, wrd2, wc); } return; } @@ -573,7 +574,8 @@ void rh_writecw(struct rh_if *rhc, int nxm) { rhc->status |= CCW_COMP_1; if (rhc->wcr != 0) rhc->cda++; - M[rhc->cia|1] = ((uint64)(rhc->ccw & WMASK) << CSHIFT) | ((uint64)(rhc->cda) & AMASK); + wrd1 = ((uint64)(rhc->ccw & WMASK) << CSHIFT) | ((uint64)(rhc->cda) & AMASK); + (void)Mem_write_word(rhc->cia|1, &wrd1, 0); } /* Finish off a DF10 transfer */ @@ -596,8 +598,8 @@ void rh_finish_op(struct rh_if *rhc, int nxm) { /* Set up for a RH20 transfer */ void rh20_setup(struct rh_if *rhc) { - int reg; - DEVICE *dptr; + DEVICE *dptr = NULL; + int reg; for (reg = 0; rh[reg].dev_num != 0; reg++) { if (rh[reg].rh == rhc) { @@ -648,9 +650,9 @@ void rh_setup(struct rh_if *rhc, uint32 addr) /* Fetch the next IO control word */ int rh_fetch(struct rh_if *rhc) { - uint64 data; - int reg; - DEVICE *dptr = NULL; + uint64 data; + int reg; + DEVICE *dptr = NULL; for (reg = 0; rh[reg].dev_num != 0; reg++) { if (rh[reg].rh == rhc) { @@ -660,29 +662,25 @@ int rh_fetch(struct rh_if *rhc) { } #if KL if (rhc->imode == 2 && (rhc->cop & 2) != 0) { -// rh_finish_op(rhc, 0); return 0; } #endif - if (rhc->ccw > MEMSIZE) { + if (Mem_read_word(rhc->ccw, &data, 0)) { rh_finish_op(rhc, 1); return 0; } - data = M[rhc->ccw]; sim_debug(DEBUG_EXP, dptr, "%s fetch %06o %012llo\n\r", dptr->name, rhc->ccw, data); #if KL if (rhc->imode == 2) { while((data & RH20_XFER) == 0) { rhc->ccw = (uint32)(data & AMASK); if ((data & (BIT1|BIT2)) == 0) { -// rh_finish_op(rhc, 0); return 0; } - if (rhc->ccw > MEMSIZE) { + if (Mem_read_word(rhc->ccw, &data, 0)) { rh_finish_op(rhc, 1); return 0; } - data = M[rhc->ccw]; sim_debug(DEBUG_EXP, dptr, "%s fetch2 %06o %012llo\n\r", dptr->name, rhc->ccw, data); //fprintf(stderr, "RH20 fetch2 %06o %012llo\n\r", rhc->ccw, data); } @@ -699,11 +697,10 @@ int rh_fetch(struct rh_if *rhc) { return 0; } rhc->ccw = (uint32)(data & AMASK); - if (rhc->ccw > MEMSIZE) { + if (Mem_read_word(rhc->ccw, &data, 0)) { rh_finish_op(rhc, 1); return 0; } - data = M[rhc->ccw]; sim_debug(DEBUG_EXP, dptr, "%s fetch2 %06o %012llo\n\r", dptr->name, rhc->ccw, data); } rhc->wcr = (uint32)((data >> CSHIFT) & WMASK); @@ -727,18 +724,27 @@ int rh_read(struct rh_if *rhc) { } #if KL if (rhc->imode == 2) { - data = M[rhc->cda]; + if (Mem_read_word(rhc->cda, &data, 0)) { + rh_finish_op(rhc, 1); + return 0; + } if (rhc->cop & 01) rhc->cda = (uint32)((rhc->cda - 1) & AMASK); else rhc->cda = (uint32)((rhc->cda + 1) & AMASK); } else { rhc->cda = (uint32)((rhc->cda + 1) & AMASK); - data = M[rhc->cda]; + if (Mem_read_word(rhc->cda, &data, 0)) { + rh_finish_op(rhc, 1); + return 0; + } } #else rhc->cda = (uint32)((rhc->cda + 1) & AMASK); - data = M[rhc->cda]; + if (Mem_read_word(rhc->cda, &data, 0)) { + rh_finish_op(rhc, 1); + return 0; + } #endif } else { data = 0; @@ -764,18 +770,27 @@ int rh_write(struct rh_if *rhc) { } #if KL if (rhc->imode == 2) { - M[rhc->cda] = rhc->buf; + if (Mem_write_word(rhc->cda, &rhc->buf, 0)) { + rh_finish_op(rhc, 1); + return 0; + } if (rhc->cop & 01) rhc->cda = (uint32)((rhc->cda - 1) & AMASK); else rhc->cda = (uint32)((rhc->cda + 1) & AMASK); } else { rhc->cda = (uint32)((rhc->cda + 1) & AMASK); - M[rhc->cda] = rhc->buf; + if (Mem_write_word(rhc->cda, &rhc->buf, 0)) { + rh_finish_op(rhc, 1); + return 0; + } } #else rhc->cda = (uint32)((rhc->cda + 1) & AMASK); - M[rhc->cda] = rhc->buf; + if (Mem_write_word(rhc->cda, &rhc->buf, 0)) { + rh_finish_op(rhc, 1); + return 0; + } #endif } if (rhc->wcr == 0) { diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index d0d93a2..4512573 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -1001,7 +1001,6 @@ rp_reset(DEVICE * rptr) { int ctlr; for (ctlr = 0; ctlr < NUM_DEVS_RP; ctlr++) { - rp_rh[ctlr].devnum = rp_dib[ctlr].dev_num; rp_rh[ctlr].status = 0; rp_rh[ctlr].attn = 0; rp_rh[ctlr].rae = 0; diff --git a/PDP10/kx10_rs.c b/PDP10/kx10_rs.c index c553791..d334edc 100644 --- a/PDP10/kx10_rs.c +++ b/PDP10/kx10_rs.c @@ -603,7 +603,6 @@ rs_reset(DEVICE * rstr) { int ctlr; for (ctlr = 0; ctlr < NUM_DEVS_RS; ctlr++) { - rs_rh[ctlr].devnum = rs_dib[ctlr].dev_num; rs_rh[ctlr].status = 0; rs_rh[ctlr].attn = 0; rs_rh[ctlr].rae = 0; diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index 381954b..fc948e5 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -797,7 +797,6 @@ tu_reset(DEVICE * dptr) { int ctlr; for (ctlr = 0; ctlr < NUM_DEVS_TU; ctlr++) { - tu_rh[ctlr].devnum = tu_dib[ctlr].dev_num; tu_rh[ctlr].attn = 0; tu_rh[ctlr].rae = 0; } From a5d29b2dbade5e233ef6bf7a3dc3c190a85c38f6 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 12 Feb 2020 00:03:35 -0500 Subject: [PATCH 87/98] KA10: NIA device starting to work. --- PDP10/kl10_nia.c | 1871 +++++++++++++++++++++++++++++++--------------- 1 file changed, 1286 insertions(+), 585 deletions(-) diff --git a/PDP10/kl10_nia.c b/PDP10/kl10_nia.c index 30b8e59..72e537e 100644 --- a/PDP10/kl10_nia.c +++ b/PDP10/kl10_nia.c @@ -1,585 +1,1286 @@ -/* kl10_NIA.c: NIA 20 Network interface. - - Copyright (c) 2019, Richard Cornwell. - - 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 - RICHARD CORNWELL 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. - - This emulates the MIT-AI/ML/MC Host/IMP interface. -*/ - - -#include "kx10_defs.h" -#include "sim_ether.h" - -#if NUM_DEVS_NIA > 0 -#define NIA_DEVNUM (0540 + (5 * 4)) - -/* NIA Bits */ - -/* CONI */ -#define NIA_PPT 0400000000000LL /* Port present */ -#define NIA_DCC 0100000000000LL /* Diag CSR */ -#define NIA_CPE 0004000000000LL /* CRAM Parity error */ -#define NIA_MBE 0002000000000LL /* MBUS error */ -#define NIA_ILD 0000100000000LL /* Idle */ -#define NIA_DCP 0000040000000LL /* Disable complete */ -#define NIA_ECP 0000020000000LL /* Enable complete */ -#define NIA_PID 0000007000000LL /* Port ID */ - -/* CONO/ CONI */ -#define NIA_CPT 0000000400000LL /* Clear Port */ -#define NIA_SEB 0000000200000LL /* Diag Select EBUF */ -#define NIA_GEB 0000000100000LL /* Diag Gen Ebus PE */ -#define NIA_LAR 0000000040000LL /* Diag select LAR */ -#define NIA_SSC 0000000020000LL /* Diag Single Cycle */ -#define NIA_EPE 0000000004000LL /* Ebus parity error */ -#define NIA_FQE 0000000002000LL /* Free Queue Error */ -#define NIA_DME 0000000001000LL /* Data mover error */ -#define NIA_CQA 0000000000400LL /* Command Queue Available */ -#define NIA_RQA 0000000000200LL /* Response Queue Available */ -#define NIA_DIS 0000000000040LL /* Disable */ -#define NIA_ENB 0000000000020LL /* Enable */ -#define NIA_MRN 0000000000010LL /* RUN */ -#define NIA_PIA 0000000000007LL /* PIA */ - -#define NIA_LRA 0400000000000LL /* Load Ram address */ -#define NIA_RAR 0377760000000LL /* Microcode address mask */ -#define NIA_MSB 0000020000000LL /* Half word select */ - -#define PCB_CQI 0 /* Command queue interlock */ -#define PCB_CQF 1 /* Command queue flink */ -#define PCB_CQB 2 /* Command queue blink */ -#define PCB_RS0 3 /* Reserved */ -#define PCB_RSI 4 /* Response queue interlock */ -#define PCB_RSF 5 /* Response queue flink */ -#define PCB_RSB 6 /* Response queue blink */ -#define PCB_RS1 7 /* Reserved */ -#define PCB_UPI 010 /* Unknown protocol queue interlock */ -#define PCB_UPF 011 /* Unknown protocol queue flink */ -#define PCB_UPB 012 /* Unknown protocol queue blink */ -#define PCB_UPL 013 /* Unknown protocol queue length */ -#define PCB_RS2 014 /* Reserved */ -#define PCB_PTT 015 /* Protocol Type Table */ -#define PCB_MCT 016 /* Multicast Table */ -#define PCB_RS3 017 /* Reserved */ -#define PCB_ER0 020 /* Error Log out 0 */ -#define PCB_ER1 021 /* Error Log out 1 */ -#define PCB_EPA 022 /* EPT Channel logout word 1 address */ -#define PCB_EPW 023 /* EPT Channel logout word 1 contents */ -#define PCB_PCB 024 /* PCB Base Address */ -#define PCB_PIA 025 /* PIA */ -#define PCB_RS4 026 /* Reserved */ -#define PCB_CCW 027 /* Channel command word */ -#define PCB_RCB 030 /* Counters base address */ - -#define CHNERR 07762 -#define SLFTST 07751 -#define INTERR 07750 - -#define NIA_FLG_RESP 0001 /* Command wants a response */ -#define NIA_FLG_CLRC 0002 /* Clear counters (Read counters) */ -#define NIA_FLG_BSD 0010 /* Send BSD packet */ -#define NIA_FLG_PAD 0040 /* Send pad */ -#define NIA_FLG_ICRC 0100 /* Send use host CRC */ -#define NIA_FLG_PACK 0200 /* Send Pack */ -#define NIA_STS_CPE 0200 /* CRAM PE */ -#define NIA_STS_SR 0100 /* Send receive */ -#define NIA_STS_ERR 0001 /* Error bits valid */ - -#define NIA_ERR_ECL 000 /* Excessive collisions */ -#define NIA_ERR_CAR 001 /* Carrier check failed */ -#define NIA_ERR_COL 002 /* Collision detect failed */ -#define NIA_ERR_SHT 003 /* Short circuit */ -#define NIA_ERR_OPN 004 /* Open circuit */ -#define NIA_ERR_LNG 005 /* Frame to long */ -#define NIA_ERR_RMT 006 /* Remote failure */ -#define NIA_ERR_BLK 007 /* Block check error */ -#define NIA_ERR_FRM 010 /* Framing error */ -#define NIA_ERR_OVR 011 /* Data Overrun */ -#define NIA_ERR_PRO 012 /* Unrecongized protocol */ -#define NIA_ERR_RUN 013 /* Frame too short */ -#define NIA_ERR_WCZ 030 /* Word count not zero */ -#define NIA_ERR_QLV 031 /* Queue length violation */ -#define NIA_ERR_PLI 032 /* Illegal PLI function */ -#define NIA_ERR_UNK 033 /* Unknown command */ -#define NIA_ERR_BLV 034 /* Buffer length violation */ -#define NIA_ERR_PAR 036 /* Parity error */ -#define NIA_ERR_INT 037 /* Internal error */ - -struct nia_device { - ETH_PCALLBACK rcallback; /* read callback routine */ - ETH_PCALLBACK wcallback; /* write callback routine */ - ETH_MAC macs[2]; /* Hardware MAC addresses */ - ETH_DEV etherface; - ETH_QUE ReadQ; -#define mac macs[0] -#define bcast macs[1] - - uint8 rec_buff[2000]; /* Buffer for recieved packet */ - uint8 snd_buff[2000]; /* Buffer for sending packet */ - t_addr cmd_entry; /* Pointer to current command entry */ - t_addr rec_entry; /* Pointer to current recieve entry */ - t_addr free_hdr; /* Queue to save command entry */ - t_addr rec_hdr; /* Queue to get free entry from */ - t_addr pcb; /* Address of PCB */ - t_addr rcb; /* Read count buffer address */ -#define cmd_hdr pcb /* Command queue is at PCB */ - t_addr resp_hdr; /* Head of response queue */ - t_addr unk_hdr; /* Unknown protocol free queue */ - int unk_len; /* Length of Unknown entries */ - t_addr ptt_addr; /* Address of Protocol table */ - t_addr mat_addr; /* Address of Multicast table */ - int pia; /* Interrupt channel */ - t_addr cnt_addr; /* Address of counters */ - - int ptt_n; /* Number of Protocol entries */ - uint16 ptt_proto[17]; /* Protocol for entry */ - t_addr ptt_head[17]; /* Head of protocol queue */ - int mat_n; /* Number of multi-cast addresses */ - ETH_MAC mat_mac[17]; /* Watched Multi-cast addresses */ - int rar; - uint64 ebuf; - uint32 uver; - uint32 uedit; -} nia_data; - -#define STATUS u3 -extern int32 tmxr_poll; - -static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff}; - -t_stat nia_devio(uint32 dev, uint64 *data); -void nia_start(UNIT *); -void nia_stop(UNIT *); -void nia_enable(UNIT *); -void nia_error(UNIT *, int); -t_stat nia_srv(UNIT *); -t_stat nia_eth_srv(UNIT *); -t_stat nia_tim_srv(UNIT *); -t_stat nia_reset (DEVICE *dptr); -t_stat nia_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc); -t_stat nia_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc); -t_stat nia_attach (UNIT * uptr, CONST char * cptr); -t_stat nia_detach (UNIT * uptr); -t_stat nia_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); -const char *nia_description (DEVICE *dptr); - -struct rh_if nia_rh = { NULL, NULL, NULL}; - -UNIT nia_unit[] = { - {UDATA(nia_srv, UNIT_IDLE+UNIT_ATTABLE, 0)}, /* 0 */ - {UDATA(nia_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ - {UDATA(nia_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ -}; - -DIB nia_dib = {NIA_DEVNUM | RH20_DEV, 1, &nia_devio, NULL, &nia_rh }; - -MTAB nia_mod[] = { - { MTAB_XTD|MTAB_VDV|MTAB_VALR|MTAB_NC, 0, "MAC", "MAC=xx:xx:xx:xx:xx:xx", - &nia_set_mac, &nia_show_mac, NULL, "MAC address" }, - { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "ETH", NULL, NULL, - ð_show, NULL, "Display attachedable devices" }, - { 0 } - }; - -/* Simulator debug controls */ -DEBTAB nia_debug[] = { - {"CMD", DEBUG_CMD, "Show command execution to devices"}, - {"DATA", DEBUG_DATA, "Show data transfers"}, - {"DETAIL", DEBUG_DETAIL, "Show details about device"}, - {"EXP", DEBUG_EXP, "Show exception information"}, - {"CONI", DEBUG_CONI, "Show coni instructions"}, - {"CONO", DEBUG_CONO, "Show coni instructions"}, - {"DATAIO", DEBUG_DATAIO, "Show datai and datao instructions"}, - {"IRQ", DEBUG_IRQ, "Show IRQ requests"}, -#define DEBUG_ETHER (DEBUG_IRQ<<1) - {"ETHER", DEBUG_ETHER, "Show ETHER activities"}, - {0, 0} -}; - - - -DEVICE nia_dev = { - "NI", nia_unit, NULL, nia_mod, - 3, 8, 0, 1, 8, 36, - NULL, NULL, &nia_reset, NULL, &nia_attach, &nia_detach, - &nia_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, nia_debug, - NULL, NULL, &nia_help, NULL, NULL, &nia_description -}; - - -t_stat nia_devio(uint32 dev, uint64 *data) -{ - DEVICE *dptr = &nia_dev; - UNIT *uptr = nia_unit; - - switch(dev & 07) { - case CONO: - if (*data & NIA_CPT) - nia_reset(dptr); - - uptr->STATUS &= ~(NIA_SEB|NIA_LAR|NIA_SSC|NIA_CQA|NIA_DIS|NIA_ENB|NIA_PIA); - uptr->STATUS |= *data & (NIA_SEB|NIA_LAR|NIA_SSC|NIA_CQA|NIA_DIS|NIA_ENB|NIA_PIA); - uptr->STATUS &= ~(*data & (NIA_EPE|NIA_FQE|NIA_DME|NIA_RQA)); - if (*data & NIA_MRN ) { - if ((uptr->STATUS & NIA_MRN) == 0) - nia_start(uptr); - } else { - if ((uptr->STATUS & NIA_MRN) != 0) - nia_stop(uptr); - } - if (*data & NIA_ENB) { - if ((uptr->STATUS & NIA_MRN) != 0) - nia_enable(uptr); - else - uptr->STATUS |= NIA_ECP; - } else - uptr->STATUS &= ~NIA_ECP; - if (*data & NIA_CQA && (uptr->STATUS & NIA_MRN) != 0) - sim_activate(uptr, 100); - sim_debug(DEBUG_CONO, dptr, "IMP %03o CONO %06o PC=%o\n", dev, - (uint32)*data, PC); - break; - case CONI: - *data = (uint64)uptr->STATUS; - *data = NIA_PPT|NIA_PID; - sim_debug(DEBUG_CONI, dptr, "IMP %03o CONI %012llo PC=%o\n", dev, - *data, PC); - break; - case DATAO: - if (uptr->STATUS & NIA_SEB) { - nia_data.ebuf = *data; - } else { - if (*data & NIA_LRA) - nia_data.rar = (uint32)((*data & NIA_RAR) >> 20); - else { - if(nia_data.rar = 0275) - nia_data.uver = (uint32)(*data & RMASK); - else if(nia_data.rar = 0277) - nia_data.uedit = (uint32)(*data & RMASK); - } - } - sim_debug(DEBUG_DATAIO, dptr, "IMP %03o DATO %012llo PC=%o\n", - dev, *data, PC); - break; - case DATAI: - if (uptr->STATUS & NIA_SEB) { - *data = nia_data.ebuf; - } else { - if (uptr->STATUS & NIA_LAR) { - *data = ((uint64)nia_data.rar) << 20; - *data &= ~NIA_MSB; - *data |= NIA_LRA; - } else { - if(nia_data.rar == 0275) - *data = (uint64)(nia_data.uver); - else if(nia_data.rar == 0277) - *data = (uint64)(nia_data.uedit); - } - } - sim_debug(DEBUG_DATAIO, dptr, "IMP %03o DATI %012llo PC=%o\n", - dev, *data, PC); - break; - } - - return SCPE_OK; -} - -void nia_error(UNIT * uptr, int err) -{ - nia_data.rar = err; - uptr->STATUS |= NIA_CPE; - set_interrupt(NIA_DEVNUM, uptr->STATUS & NIA_PIA); -} - -void nia_start(UNIT * uptr) -{ - nia_rh.stcr = BIT7; - nia_rh.imode = 2; - rh20_setup(&nia_rh); - /* Read PCB address */ - if (!rh_read(&nia_rh)) { - nia_error(uptr, CHNERR); - return; - } - nia_data.pcb = (t_addr)(nia_rh.buf & AMASK); - /* Read PIA value */ - if (!rh_read(&nia_rh)) { - nia_error(uptr, CHNERR); - return; - } - nia_data.pia = (int)(nia_rh.buf & 7); - /* Read reserve word */ - if (!rh_read(&nia_rh)) { - nia_error(uptr, CHNERR); - return; - } - uptr->STATUS |= NIA_MRN; -} - -void nia_stop(UNIT *uptr) -{ - uptr->STATUS &= ~NIA_MRN; -} - -void nia_enable(UNIT *uptr) -{ - /* Load Unknown queue len */ - /* Load PTT */ - /* Load MCT */ - /* Load read count buffer address */ -} - -/* Get next entry off a queue. Returns 0 if fail */ -int nia_getq(t_addr head, t_addr *entry) -{ - uint64 temp; - uint64 flink; - *entry = 0; /* For safty */ - - temp = M[head]; - /* Check if entry locked */ - if ((temp & SMASK) == 0) - return 0; - - /* Increment lock here */ - - /* Get forward link */ - flink = M[head+1]; - /* Check if queue empty */ - if (flink == (head+1)) { - /* Decrement lock here */ - return 1; - } - temp = M[flink]; - M[head+1] = temp; /* Set Head Flink to point to next */ - M[temp + 1] = head + 1; /* Set Next Blink to head */ - *entry = temp; - /* Decrement lock here */ - return 1; -} - -/* Put entry on head of queue. */ -int nia_putq(UNIT *uptr, t_addr head, t_addr *entry) -{ - uint64 temp; - uint64 blink; - - temp = M[head]; - /* Check if entry locked */ - if ((temp & SMASK) == 0) - return 0; - - /* Increment lock here */ - - /* Set up entry. */ - M[*entry] = head+1; /* Flink is head of queue */ - blink = M[head+2]; /* Get back link */ - M[*entry+1] = blink; - temp = M[blink]; /* Old prevous entry */ - M[temp] = *entry; /* Old forward is new */ - - *entry = 0; - /* Decement lock here */ - - /* Check if Queue was empty, and response queue */ - if (temp == (head+1) && head == nia_data.resp_hdr) { - uptr->STATUS |= NIA_RQA; - set_interrupt(NIA_DEVNUM, nia_data.pia); - } - return 1; -} - -t_stat nia_srv(UNIT * uptr) -{ - - /* Check if we are running */ - if ((uptr->STATUS & NIA_MRN) == 0) - return SCPE_OK; - /* See if we have command to process */ - if (nia_data.cmd_entry != 0) { - /* Have to put this either on response queue or free queue */ - if (nia_putq(uptr, nia_data.resp_hdr, &nia_data.cmd_entry) == 0) { - sim_activate(uptr, 100); /* Reschedule ourselves to deal with it */ - return SCPE_OK; - } - } - /* Try to get command off queue */ - if (nia_getq(nia_data.cmd_hdr, &nia_data.cmd_entry) == 0) { - sim_activate(uptr, 100); /* Reschedule ourselves to deal with it */ - return SCPE_OK; - } - /* Check if we got one */ - if (nia_data.cmd_entry == 0) { - /* Nothing to do */ - uptr->STATUS &= ~NIA_CQA; - return SCPE_OK; - } - return SCPE_OK; -} - - -t_stat nia_eth_srv(UNIT * uptr) -{ - sim_clock_coschedule(uptr, 1000); /* continue poll */ - - return SCPE_OK; -} - -t_stat nia_tim_srv(UNIT * uptr) -{ - sim_clock_coschedule(uptr, 1000); /* continue poll */ - - return SCPE_OK; -} - - - -t_stat nia_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc) -{ - char buffer[20]; - eth_mac_fmt(&nia_data.mac, buffer); - fprintf(st, "MAC=%s", buffer); - return SCPE_OK; -} - -t_stat nia_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc) -{ - t_stat status; - - if (!cptr) return SCPE_IERR; - if (uptr->flags & UNIT_ATT) return SCPE_ALATT; - - status = eth_mac_scan_ex(&nia_data.mac, cptr, uptr); - if (status != SCPE_OK) - return status; - - memcpy(&nia_data.bcast, &broadcast_ethaddr, 6); - return SCPE_OK; -} - -t_stat nia_reset (DEVICE *dptr) -{ - int i; - struct nia_packet *p; - - for (i = 0; i < 6; i++) { - if (nia_data.mac[i] != 0) - break; - } - if (i == 6) { /* First call to reset? */ - /* Set a default MAC address in a BBN assigned OID range no longer in use */ - nia_set_mac (dptr->units, 0, "00:00:02:00:00:00/24", NULL); - } - return SCPE_OK; -} - -/* attach device: */ -t_stat nia_attach(UNIT* uptr, CONST char* cptr) -{ - t_stat status; - char* tptr; - char buf[32]; - - tptr = (char *) malloc(strlen(cptr) + 1); - if (tptr == NULL) return SCPE_MEM; - strcpy(tptr, cptr); - - status = eth_open(&nia_data.etherface, cptr, &nia_dev, DEBUG_ETHER); - if (status != SCPE_OK) { - free(tptr); - return status; - } - eth_mac_fmt(&nia_data.mac, buf); /* format ethernet mac address */ - if (SCPE_OK != eth_check_address_conflict (&nia_data.etherface, &nia_data.mac)) { - eth_close(&nia_data.etherface); - free(tptr); - return sim_messagef (SCPE_NOATT, "%s: MAC Address Conflict on LAN for address %s\n", - nia_dev.name, buf); - } - if (SCPE_OK != eth_filter(&nia_data.etherface, 2, &nia_data.mac, 0, 0)) { - eth_close(&nia_data.etherface); - free(tptr); - return sim_messagef (SCPE_NOATT, "%s: Can't set packet filter for MAC Address %s\n", - nia_dev.name, buf); - } - - uptr->filename = tptr; - uptr->flags |= UNIT_ATT; - eth_setcrc(&nia_data.etherface, 0); /* Don't need CRC */ - - /* init read queue (first time only) */ - status = ethq_init(&nia_data.ReadQ, 8); - if (status != SCPE_OK) { - eth_close(&nia_data.etherface); - uptr->filename = NULL; - free(tptr); - return sim_messagef (status, "%s: Can't initialize receive queue\n", nia_dev.name); - } - - - eth_set_async (&nia_data.etherface, 0); /* Allow Asynchronous inbound packets */ - return SCPE_OK; -} - -/* detach device: */ - -t_stat nia_detach(UNIT* uptr) -{ - - if (uptr->flags & UNIT_ATT) { - /* If DHCP, release our IP address */ - eth_close (&nia_data.etherface); - free(uptr->filename); - uptr->filename = NULL; - uptr->flags &= ~UNIT_ATT; - sim_cancel (uptr+1); /* stop the packet timing services */ - sim_cancel (uptr+2); /* stop the clock timer services */ - } - return SCPE_OK; -} - -t_stat nia_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) -{ -fprintf (st, "NIA interface\n\n"); -fprintf (st, "The IMP acted as an interface to the early internet. "); -fprintf (st, "This interface operated\nat the TCP/IP level rather than the "); -fprintf (st, "Ethernet level. This interface allows for\nITS or Tenex to be "); -fprintf (st, "placed on the internet. The interface connects up to a TAP\n"); -fprintf (st, "or direct ethernet connection. If the host is to be run at an "); -fprintf (st, "arbitrary IP\naddress, then the HOST should be set to the IP "); -fprintf (st, "of ITS. The network interface\nwill translate this IP address "); -fprintf (st, "to the one set in IP. If HOST is set to 0.0.0.0,\nno "); -fprintf (st, "translation will take place. IP should be set to the external "); -fprintf (st, "address of\nthe IMP, along the number of bits in the net mask. "); -fprintf (st, "GW points to the default\nrouter. If DHCP is enabled these "); -fprintf (st, "will be set from DHCP when the IMP is attached.\nIf IP is set "); -fprintf (st, "and DHCP is enabled, when the IMP is attached it will inform\n"); -fprintf (st, "the local DHCP server of it's address.\n\n"); -fprint_set_help (st, dptr); -fprint_show_help (st, dptr); -eth_attach_help(st, dptr, uptr, flag, cptr); -return SCPE_OK; -} - - -const char *nia_description (DEVICE *dptr) -{ - return "KL NIA interface"; -} -#endif +/* kl10_NIA.c: NIA 20 Network interface. + + Copyright (c) 2019, Richard Cornwell. + + 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 + RICHARD CORNWELL 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. + + This emulates the MIT-AI/ML/MC Host/IMP interface. +*/ + + +#include "kx10_defs.h" +#include "sim_ether.h" + +#if NUM_DEVS_NIA > 0 +#define NIA_DEVNUM (0540 + (5 * 4)) + +/* NIA Bits */ + +/* CONI */ +#define NIA_PPT 0400000000000LL /* Port present */ +#define NIA_DCC 0100000000000LL /* Diag CSR */ +#define NIA_CPE 0004000000000LL /* CRAM Parity error */ +#define NIA_MBE 0002000000000LL /* MBUS error */ +#define NIA_ILD 0000100000000LL /* Idle */ +#define NIA_DCP 0000040000000LL /* Disable complete */ +#define NIA_ECP 0000020000000LL /* Enable complete */ +#define NIA_PID 0000007000000LL /* Port ID */ + +/* CONO/ CONI */ +#define NIA_CPT 0000000400000LL /* Clear Port */ +#define NIA_SEB 0000000200000LL /* Diag Select EBUF */ +#define NIA_GEB 0000000100000LL /* Diag Gen Ebus PE */ +#define NIA_LAR 0000000040000LL /* Diag select LAR */ +#define NIA_SSC 0000000020000LL /* Diag Single Cycle */ +#define NIA_EPE 0000000004000LL /* Ebus parity error */ +#define NIA_FQE 0000000002000LL /* Free Queue Error */ +#define NIA_DME 0000000001000LL /* Data mover error */ +#define NIA_CQA 0000000000400LL /* Command Queue Available */ +#define NIA_RQA 0000000000200LL /* Response Queue Available */ +#define NIA_DIS 0000000000040LL /* Disable */ +#define NIA_ENB 0000000000020LL /* Enable */ +#define NIA_MRN 0000000000010LL /* RUN */ +#define NIA_PIA 0000000000007LL /* PIA */ + +#define NIA_LRA 0400000000000LL /* Load Ram address */ +#define NIA_RAR 0377760000000LL /* Microcode address mask */ +#define NIA_MSB 0000020000000LL /* Half word select */ + +#define PCB_CQI 0 /* Command queue interlock */ +#define PCB_CQF 1 /* Command queue flink */ +#define PCB_CQB 2 /* Command queue blink */ +#define PCB_RS0 3 /* Reserved */ +#define PCB_RSI 4 /* Response queue interlock */ +#define PCB_RSF 5 /* Response queue flink */ +#define PCB_RSB 6 /* Response queue blink */ +#define PCB_RS1 7 /* Reserved */ +#define PCB_UPI 010 /* Unknown protocol queue interlock */ +#define PCB_UPF 011 /* Unknown protocol queue flink */ +#define PCB_UPB 012 /* Unknown protocol queue blink */ +#define PCB_UPL 013 /* Unknown protocol queue length */ +#define PCB_RS2 014 /* Reserved */ +#define PCB_PTT 015 /* Protocol Type Table */ +#define PCB_MCT 016 /* Multicast Table */ +#define PCB_RS3 017 /* Reserved */ +#define PCB_ER0 020 /* Error Log out 0 */ +#define PCB_ER1 021 /* Error Log out 1 */ +#define PCB_EPA 022 /* EPT Channel logout word 1 address */ +#define PCB_EPW 023 /* EPT Channel logout word 1 contents */ +#define PCB_PCB 024 /* PCB Base Address */ +#define PCB_PIA 025 /* PIA */ +#define PCB_RS4 026 /* Reserved */ +#define PCB_CCW 027 /* Channel command word */ +#define PCB_RCB 030 /* Counters base address */ + +#define CHNERR 07762 +#define SLFTST 07751 +#define INTERR 07750 + +/* 12 Bit Shift */ +#define NIA_CMD_SND 0001 /* Send a datagram */ +#define NIA_CMD_LMAC 0002 /* Load Multicast table */ +#define NIA_CMD_LPTT 0003 /* Load Protocol Type table */ +#define NIA_CMD_RCNT 0004 /* Read counts */ +#define NIA_CMD_RCV 0005 /* Received datagram */ +#define NIA_CMD_WPLI 0006 /* Write PLI */ +#define NIA_CMD_RPLI 0007 /* Read PLI */ +#define NIA_CMD_RNSA 0010 /* Read Station Address */ +#define NIA_CMD_WNSA 0011 /* Write Station Address */ + +/* 20 Bit shift */ +#define NIA_FLG_RESP 0001 /* Command wants a response */ +#define NIA_FLG_CLRC 0002 /* Clear counters (Read counters) */ +#define NIA_FLG_BSD 0010 /* Send BSD packet */ +#define NIA_FLG_PAD 0040 /* Send pad */ +#define NIA_FLG_ICRC 0100 /* Send use host CRC */ +#define NIA_FLG_PACK 0200 /* Send Pack */ +#define NIA_STS_CPE 0200 /* CRAM PE */ +#define NIA_STS_SR 0100 /* Send receive */ +#define NIA_STS_ERR 0001 /* Error bits valid */ + +/* 28 bit shift ERR +1 */ +#define NIA_ERR_ECL 000 /* Excessive collisions */ +#define NIA_ERR_CAR 001 /* Carrier check failed */ +#define NIA_ERR_COL 002 /* Collision detect failed */ +#define NIA_ERR_SHT 003 /* Short circuit */ +#define NIA_ERR_OPN 004 /* Open circuit */ +#define NIA_ERR_LNG 005 /* Frame to long */ +#define NIA_ERR_RMT 006 /* Remote failure */ +#define NIA_ERR_BLK 007 /* Block check error */ +#define NIA_ERR_FRM 010 /* Framing error */ +#define NIA_ERR_OVR 011 /* Data Overrun */ +#define NIA_ERR_PRO 012 /* Unrecongized protocol */ +#define NIA_ERR_RUN 013 /* Frame too short */ +#define NIA_ERR_WCZ 030 /* Word count not zero */ +#define NIA_ERR_QLV 031 /* Queue length violation */ +#define NIA_ERR_PLI 032 /* Illegal PLI function */ +#define NIA_ERR_UNK 033 /* Unknown command */ +#define NIA_ERR_BLV 034 /* Buffer length violation */ +#define NIA_ERR_PAR 036 /* Parity error */ +#define NIA_ERR_INT 037 /* Internal error */ + +#ifdef _MSC_VER +# define PACKED_BEGIN __pragma( pack(push, 1) ) +# define PACKED_END __pragma( pack(pop) ) +# define QEMU_PACKED +#else +# define PACKED_BEGIN +#if defined(_WIN32) +# define PACKED_END __attribute__((gcc_struct, packed)) +# define QEMU_PACKED __attribute__((gcc_struct, packed)) +#else +# define PACKED_END __attribute__((packed)) +# define QEMU_PACKED __attribute__((packed)) +#endif +#endif + +typedef uint32 in_addr_T; + +#define ETHTYPE_ARP 0x0806 +#define ETHTYPE_IP 0x0800 + +PACKED_BEGIN +struct nia_eth_hdr { + ETH_MAC dest; + ETH_MAC src; + uint16 type; +} PACKED_END; + +/* + * Structure of an internet header, naked of options. + */ +PACKED_BEGIN +struct ip { + uint8 ip_v_hl; /* version,header length */ + uint8 ip_tos; /* type of service */ + uint16 ip_len; /* total length */ + uint16 ip_id; /* identification */ + uint16 ip_off; /* fragment offset field */ +#define IP_DF 0x4000 /* don't fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + uint8 ip_ttl; /* time to live */ + uint8 ip_p; /* protocol */ + uint16 ip_sum; /* checksum */ + in_addr_T ip_src; + in_addr_T ip_dst; /* source and dest address */ +} PACKED_END; + +#define TCP_PROTO 6 +PACKED_BEGIN +struct tcp { + uint16 tcp_sport; /* Source port */ + uint16 tcp_dport; /* Destination port */ + uint32 seq; /* Sequence number */ + uint32 ack; /* Ack number */ + uint16 flags; /* Flags */ +#define TCP_FL_FIN 0x01 +#define TCP_FL_SYN 0x02 +#define TCP_FL_RST 0x04 +#define TCP_FL_PSH 0x08 +#define TCP_FL_ACK 0x10 +#define TCP_FL_URG 0x20 + uint16 window; /* Window size */ + uint16 chksum; /* packet checksum */ + uint16 urgent; /* Urgent pointer */ +} PACKED_END; + +#define UDP_PROTO 17 +PACKED_BEGIN +struct udp { + uint16 udp_sport; /* Source port */ + uint16 udp_dport; /* Destination port */ + uint16 len; /* Length */ + uint16 chksum; /* packet checksum */ +} PACKED_END; + +PACKED_BEGIN +struct udp_hdr { + in_addr_T ip_src; + in_addr_T ip_dst; /* source and dest address */ + uint8 zero; + uint8 proto; /* Protocol */ + uint16 hlen; /* Length of header and data */ +} PACKED_END; + +#define ICMP_PROTO 1 +PACKED_BEGIN +struct icmp { + uint8 type; /* Type of packet */ + uint8 code; /* Code */ + uint16 chksum; /* packet checksum */ +} PACKED_END; + +PACKED_BEGIN +struct ip_hdr { + struct nia_eth_hdr ethhdr; + struct ip iphdr; +} PACKED_END; + +#define ARP_REQUEST 1 +#define ARP_REPLY 2 +#define ARP_HWTYPE_ETH 1 + +PACKED_BEGIN +struct arp_hdr { + struct nia_eth_hdr ethhdr; + uint16 hwtype; + uint16 protocol; + uint8 hwlen; + uint8 protolen; + uint16 opcode; + ETH_MAC shwaddr; + in_addr_T sipaddr; + ETH_MAC dhwaddr; + in_addr_T dipaddr; + uint8 padding[18]; +} PACKED_END; + +struct nia_device { + ETH_PCALLBACK rcallback; /* read callback routine */ + ETH_PCALLBACK wcallback; /* write callback routine */ + ETH_MAC mac; /* Hardware MAC addresses */ + ETH_DEV etherface; + ETH_QUE ReadQ; + ETH_PACK rec_buff; /* Buffer for recieved packet */ + ETH_PACK snd_buff; /* Buffer for sending packet */ + t_addr cmd_entry; /* Pointer to current command entry */ + t_addr cmd_rply; /* Pointer to reply entry */ + uint8 cmd_status; /* Status feild of current command */ + t_addr rec_entry; /* Pointer to current recieve entry */ + t_addr pcb; /* Address of PCB */ + t_addr rcb; /* Read count buffer address */ +#define cmd_hdr pcb /* Command queue is at PCB */ + t_addr resp_hdr; /* Head of response queue */ + t_addr unk_hdr; /* Unknown protocol free queue */ + int unk_len; /* Length of Unknown entries */ + t_addr ptt_addr; /* Address of Protocol table */ + t_addr mcast_addr; /* Address of Multicast table */ + int pia; /* Interrupt channel */ + t_addr cnt_addr; /* Address of counters */ + + int ptt_n; /* Number of Protocol entries */ + uint16 ptt_proto[17]; /* Protocol for entry */ + t_addr ptt_head[17]; /* Head of protocol queue */ + int macs_n; /* Number of multi-cast addresses */ + ETH_MAC macs[20]; /* Watched Multi-cast addresses */ + int rar; + uint64 ebuf; + uint32 uver[4]; /* Version information */ + int r_pkt; /* Packet pending */ +} nia_data; + + +#define STATUS u3 +extern int32 tmxr_poll; + +static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff}; + +t_stat nia_devio(uint32 dev, uint64 *data); +void nia_start(UNIT *); +void nia_stop(UNIT *); +void nia_enable(UNIT *); +void nia_disable(UNIT *); +void nia_error(UNIT *, int); +t_stat nia_srv(UNIT *); +t_stat nia_eth_srv(UNIT *); +t_stat nia_tim_srv(UNIT *); +t_stat nia_reset (DEVICE *dptr); +t_stat nia_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc); +t_stat nia_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc); +t_stat nia_attach (UNIT * uptr, CONST char * cptr); +t_stat nia_detach (UNIT * uptr); +t_stat nia_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr); +const char *nia_description (DEVICE *dptr); + +struct rh_if nia_rh = { NULL, NULL, NULL}; + +UNIT nia_unit[] = { + {UDATA(nia_srv, UNIT_IDLE+UNIT_ATTABLE, 0)}, /* 0 */ + {UDATA(nia_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ + {UDATA(nia_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ +}; + +DIB nia_dib = {NIA_DEVNUM | RH20_DEV, 1, &nia_devio, NULL, &nia_rh }; + +MTAB nia_mod[] = { + { MTAB_XTD|MTAB_VDV|MTAB_VALR|MTAB_NC, 0, "MAC", "MAC=xx:xx:xx:xx:xx:xx", + &nia_set_mac, &nia_show_mac, NULL, "MAC address" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "ETH", NULL, NULL, + ð_show, NULL, "Display attachedable devices" }, + { 0 } + }; + +/* Simulator debug controls */ +DEBTAB nia_debug[] = { + {"CMD", DEBUG_CMD, "Show command execution to devices"}, + {"DATA", DEBUG_DATA, "Show data transfers"}, + {"DETAIL", DEBUG_DETAIL, "Show details about device"}, + {"EXP", DEBUG_EXP, "Show exception information"}, + {"CONI", DEBUG_CONI, "Show coni instructions"}, + {"CONO", DEBUG_CONO, "Show coni instructions"}, + {"DATAIO", DEBUG_DATAIO, "Show datai and datao instructions"}, + {"IRQ", DEBUG_IRQ, "Show IRQ requests"}, +#define DEBUG_ARP (DEBUG_IRQ<<1) + {"ARP", DEBUG_ARP, "Show ARP activities"}, +#define DEBUG_TCP (DEBUG_ARP<<1) + {"TCP", DEBUG_TCP, "Show TCP packet activities"}, +#define DEBUG_UDP (DEBUG_TCP<<1) + {"UDP", DEBUG_UDP, "Show UDP packet activities"}, +#define DEBUG_ICMP (DEBUG_UDP<<1) + {"ICMP", DEBUG_ICMP, "Show ICMP packet activities"}, +#define DEBUG_ETHER (DEBUG_ICMP<<1) + {"ETHER", DEBUG_ETHER, "Show ETHER activities"}, + {0, 0} +}; + +DEVICE nia_dev = { + "NI", nia_unit, NULL, nia_mod, + 3, 8, 0, 1, 8, 36, + NULL, NULL, &nia_reset, NULL, &nia_attach, &nia_detach, + &nia_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, nia_debug, + NULL, NULL, &nia_help, NULL, NULL, &nia_description +}; + +static char * +ipv4_inet_ntoa(struct in_addr ip) +{ + static char str[20]; + + if (sim_end) + sprintf (str, "%d.%d.%d.%d", ip.s_addr & 0xFF, (ip.s_addr >> 8) & 0xFF, + (ip.s_addr >> 16) & 0xFF, (ip.s_addr >> 24) & 0xFF); + else + sprintf (str, "%d.%d.%d.%d", (ip.s_addr >> 24) & 0xFF, (ip.s_addr >> 16) & 0xFF, + (ip.s_addr >> 8) & 0xFF, ip.s_addr & 0xFF); + return str; +} + + + +t_stat nia_devio(uint32 dev, uint64 *data) +{ + DEVICE *dptr = &nia_dev; + UNIT *uptr = nia_unit; + + switch(dev & 03) { + case CONO: + if (*data & NIA_CPT) + nia_reset(dptr); + + uptr->STATUS &= ~(NIA_SEB|NIA_LAR|NIA_SSC|NIA_DIS|NIA_ENB|NIA_PIA); + uptr->STATUS |= *data & (NIA_SEB|NIA_LAR|NIA_SSC|NIA_DIS|NIA_ENB|NIA_PIA); + uptr->STATUS &= ~(*data & (NIA_EPE|NIA_FQE|NIA_DME|NIA_RQA)); + clr_interrupt(NIA_DEVNUM); + if (*data & NIA_MRN) { + if ((uptr->STATUS & NIA_MRN) == 0) + nia_start(uptr); + } else { + if ((uptr->STATUS & NIA_MRN) != 0) + nia_stop(uptr); + } + if (*data & NIA_ENB) { + if ((uptr->STATUS & NIA_MRN) != 0 && (uptr->STATUS & NIA_ECP) == 0) + nia_enable(uptr); + else + uptr->STATUS |= NIA_ECP; + } else + uptr->STATUS &= ~NIA_ECP; + if (*data & NIA_DIS) { + if ((uptr->STATUS & NIA_MRN) != 0 && (uptr->STATUS & NIA_DCP) == 0) + nia_disable(uptr); + else + uptr->STATUS |= NIA_DCP; + } else + uptr->STATUS &= ~NIA_DCP; + if (*data & NIA_CQA && + (uptr->STATUS & NIA_CQA) == 0 && + (uptr->STATUS & NIA_MRN) != 0) { + uptr->STATUS |= NIA_CQA; + sim_activate(uptr, 200); + } + if (uptr->STATUS & (NIA_CPE|NIA_RQA)) + set_interrupt(NIA_DEVNUM, uptr->STATUS & NIA_PIA); + sim_debug(DEBUG_CONO, dptr, "NIA %03o CONO %06o PC=%o %06o\n", dev, + (uint32)*data, PC, uptr->STATUS); + break; + case CONI: + *data = (uint64)uptr->STATUS; + *data |= NIA_PPT|NIA_PID; +// *data &= ~NIA_CQA; + sim_debug(DEBUG_CONI, dptr, "NIA %03o CONI %012llo PC=%o\n", dev, + *data, PC); + break; + case DATAO: + if (uptr->STATUS & NIA_SEB) { + nia_data.ebuf = *data; + } else { + if (*data & NIA_LRA) { + nia_data.rar = (uint32)((*data & NIA_RAR) >> 22); + sim_debug(DEBUG_DETAIL, dptr, "NIA %03o set RAR=%o\n", + dev, nia_data.rar); + } else { + if (nia_data.rar >= 0274 && nia_data.rar <= 0277) + nia_data.uver[nia_data.rar - 0274] = (uint32)(*data & RMASK); + sim_debug(DEBUG_DETAIL, dptr, "NIA %03o set data=%o %06o\n", + dev, nia_data.rar, (uint32)(*data & RMASK)); + } + } + sim_debug(DEBUG_DATAIO, dptr, "NIA %03o DATO %012llo PC=%o\n", + dev, *data, PC); + break; + case DATAI: + if (uptr->STATUS & NIA_SEB) { + *data = nia_data.ebuf; + } else { + if (uptr->STATUS & NIA_LAR) { + *data = ((uint64)nia_data.rar) << 20; + *data &= ~NIA_MSB; + *data |= NIA_LRA; + } else if (nia_data.rar >= 0274 && nia_data.rar <= 0277) { + *data = (uint64)nia_data.uver[nia_data.rar - 0274]; + } + } + sim_debug(DEBUG_DATAIO, dptr, "NIA %03o DATI %012llo PC=%o\n", + dev, *data, PC); + break; + } + + return SCPE_OK; +} + +void nia_error(UNIT * uptr, int err) +{ + nia_data.rar = err; + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA error %03o\n", err); + uptr->STATUS |= NIA_CPE; + set_interrupt(NIA_DEVNUM, uptr->STATUS & NIA_PIA); +} + +void nia_start(UNIT * uptr) +{ + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA start\n"); + nia_rh.stcr = BIT7; + nia_rh.imode = 2; + rh20_setup(&nia_rh); + /* Read PCB address */ + if (!rh_read(&nia_rh)) { + nia_error(uptr, CHNERR); + return; + } + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA PCB %012llo %o\n", nia_rh.buf, nia_rh.wcr); + nia_data.pcb = (t_addr)(nia_rh.buf & AMASK); + nia_data.resp_hdr = (t_addr)((nia_rh.buf + 4) & AMASK); + nia_data.unk_hdr = (t_addr)((nia_rh.buf + 8) & AMASK); + /* Read PIA value */ + if (!rh_read(&nia_rh)) { + nia_error(uptr, CHNERR); + return; + } + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA PIA %012llo %o\n", nia_rh.buf, nia_rh.wcr); + nia_data.pia = (int)(nia_rh.buf & 7); + uptr->STATUS |= NIA_MRN; + memcpy(&nia_data.macs[0], &nia_data.mac, sizeof (ETH_MAC)); + memcpy(&nia_data.macs[1], &broadcast_ethaddr, sizeof(ETH_MAC)); +} + +void nia_stop(UNIT *uptr) +{ + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA stop\n"); + uptr->STATUS &= ~NIA_MRN; +} + +void nia_cpy_mac(UNIT *uptr, uint64 word1, uint64 word2, ETH_MAC *mac) +{ + ETH_MAC m; + m[0] = (unsigned char)((word1 >> 28) & 0xff); + m[1] = (unsigned char)((word1 >> 20) & 0xff); + m[2] = (unsigned char)((word1 >> 12) & 0xff); + m[3] = (unsigned char)((word1 >> 4) & 0xff); + m[4] = (unsigned char)((word2 >> 28) & 0xff); + m[5] = (unsigned char)((word2 >> 20) & 0xff); + memcpy(mac, &m, sizeof(ETH_MAC)); +} + +uint8 *nia_cpy_to(UNIT *uptr, t_addr addr, uint8 *data, int len) +{ + uint64 word; + while (len > 3) { + word = M[addr++]; + *data++ = (uint8)((word >> 28) & 0xff); + *data++ = (uint8)((word >> 20) & 0xff); + *data++ = (uint8)((word >> 12) & 0xff); + *data++ = (uint8)((word >> 4) & 0xff); + len -= 4; + } + if (len) { + word = M[addr++]; + switch (len) { + case 3: + *data++ = (uint8)((word >> 28) & 0xff); + *data++ = (uint8)((word >> 20) & 0xff); + *data++ = (uint8)((word >> 12) & 0xff); + break; + case 2: + *data++ = (uint8)((word >> 28) & 0xff); + *data++ = (uint8)((word >> 20) & 0xff); + break; + case 1: + *data++ = (uint8)((word >> 28) & 0xff); + break; + } + } + return data; +} + +uint8 *nia_cpy_from(UNIT *uptr, t_addr addr, uint8 *data, int len) +{ + uint64 word; + + while (len > 3) { + word = (uint64)(*data++) << 28; + word |= (uint64)(*data++) << 20; + word |= (uint64)(*data++) << 12; + word |= (uint64)(*data++) << 4; + M[addr++] = word; + len -= 4; + } + if (len) { + switch (len) { + case 3: + word = (uint64)(*data++) << 28; + word |= (uint64)(*data++) << 20; + word |= (uint64)(*data++) << 12; + break; + case 2: + word = (uint64)(*data++) << 28; + word |= (uint64)(*data++) << 20; + break; + case 1: + word = (uint64)(*data++) << 28; + break; + } + } + M[addr++] = word; + return data; +} + +/* + * Load in the protocol type table + */ +void nia_load_ptt(UNIT *uptr) +{ + int i; + int n = 0; + t_addr addr = nia_data.ptt_addr; + + for (i = 0; i < 17; i++) { + uint64 word1, word2; + + word1 = M[addr++]; + word2 = M[addr++]; + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %012llo %012llo\n\r",n, word1, word2); + if (word1 & SMASK) { + uint16 type; + type = (uint16)(word1 >> 12) & 0xff; + type |= (uint16)(word1 << 4) & 0xff00; + nia_data.ptt_proto[n] = type; + nia_data.ptt_head[n] = (t_addr)(word2 &AMASK) - 1; + n++; + } + addr++; + } + for (i = 0; i < n; i++) { + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %04x %010o\n\r",n, nia_data.ptt_proto[i], nia_data.ptt_head[i]); + } + nia_data.ptt_n = n; +} + +/* + * Load in the multi-cast table + */ +void nia_load_mcast(UNIT *uptr) +{ + int i; + int n = 0; + char buffer[20]; + t_addr addr = nia_data.mcast_addr; + + memcpy(&nia_data.macs[n], &nia_data.mac, sizeof (ETH_MAC)); + n++; + memcpy(&nia_data.macs[n], &broadcast_ethaddr, sizeof (ETH_MAC)); + n++; + for (i = 0; i < 17; i++) { + uint64 word1, word2; + + word1 = M[addr++]; + word2 = M[addr++]; + if (word2 & 1) { + nia_cpy_mac(uptr, word1, word2, &nia_data.macs[n]); + n++; + } + } + for(i = 0; i< n; i++) { + eth_mac_fmt(&nia_data.macs[i], buffer); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load mcast%d: %s\n\r",i, buffer); + } + nia_data.macs_n = n - 2; + if (uptr->flags & UNIT_ATT) + eth_filter (&nia_data.etherface, n, nia_data.macs, 0, 0); +} + +void nia_packet_debug(struct nia_device *nia, const char *action, ETH_PACK *packet) { + struct nia_eth_hdr *eth = (struct nia_eth_hdr *)&packet->msg[0]; + struct arp_hdr *arp = (struct arp_hdr *)eth; + struct ip *ip = (struct ip *)&packet->msg[sizeof(struct nia_eth_hdr)]; + struct udp *udp; + struct tcp *tcp; + struct icmp *icmp; + uint8 *payload; + struct in_addr ipaddr; + size_t len; + int flag; + char src_ip[20]; + char dst_ip[20]; + char src_port[8]; + char dst_port[8]; + char mac_buf[20]; + char flags[64]; + static struct tcp_flag_bits { + const char *name; + uint16 bitmask; + } bits[] = { + {"FIN", TCP_FL_FIN}, + {"SYN", TCP_FL_SYN}, + {"RST", TCP_FL_RST}, + {"PSH", TCP_FL_PSH}, + {"ACK", TCP_FL_ACK}, + {"URG", TCP_FL_URG}, + {NULL, 0} + }; + static const char *icmp_types[] = { + "Echo Reply", // Type 0 + "Type 1 - Unassigned", + "Type 2 - Unassigned", + "Destination Unreachable", // Type 3 + "Source Quench (Deprecated)", // Type 4 + "Redirect", // Type 5 + "Type 6 - Alternate Host Address (Deprecated)", + "Type 7 - Unassigned", + "Echo Request", // Type 8 + "Router Advertisement", // Type 9 + "Router Selection", // Type 10 + "Time Exceeded", // Type 11 + "Type 12 - Parameter Problem", + "Type 13 - Timestamp", + "Type 14 - Timestamp Reply", + "Type 15 - Information Request (Deprecated)", + "Type 16 - Information Reply (Deprecated)", + "Type 17 - Address Mask Request (Deprecated)", + "Type 18 - Address Mask Reply (Deprecated)", + "Type 19 - Reserved (for Security)", + "Type 20 - Reserved (for Robustness Experiment)", + "Type 21 - Reserved (for Robustness Experiment)", + "Type 22 - Reserved (for Robustness Experiment)", + "Type 23 - Reserved (for Robustness Experiment)", + "Type 24 - Reserved (for Robustness Experiment)", + "Type 25 - Reserved (for Robustness Experiment)", + "Type 26 - Reserved (for Robustness Experiment)", + "Type 27 - Reserved (for Robustness Experiment)", + "Type 28 - Reserved (for Robustness Experiment)", + "Type 29 - Reserved (for Robustness Experiment)", + "Type 30 - Traceroute (Deprecated)", + "Type 31 - Datagram Conversion Error (Deprecated)", + "Type 32 - Mobile Host Redirect (Deprecated)", + "Type 33 - IPv6 Where-Are-You (Deprecated)", + "Type 34 - IPv6 I-Am-Here (Deprecated)", + "Type 35 - Mobile Registration Request (Deprecated)", + "Type 36 - Mobile Registration Reply (Deprecated)", + "Type 37 - Domain Name Request (Deprecated)", + "Type 38 - Domain Name Reply (Deprecated)", + "Type 39 - SKIP (Deprecated)", + "Type 40 - Photuris", + "Type 41 - ICMP messages utilized by experimental mobility protocols such as Seamoby", + "Type 42 - Extended Echo Request", + "Type 43 - Extended Echo Reply" + }; + + if (ntohs(eth->type) == ETHTYPE_ARP) { + struct in_addr in_addr; + const char *arp_op = (ARP_REQUEST == ntohs(arp->opcode)) ? "REQUEST" : ((ARP_REPLY == ntohs(arp->opcode)) ? "REPLY" : "Unknown"); + char eth_src[20], eth_dst[20]; + char arp_shwaddr[20], arp_dhwaddr[20]; + char arp_sipaddr[20], arp_dipaddr[20]; + + if (!(nia_dev.dctrl & DEBUG_ARP)) + return; + eth_mac_fmt(&arp->ethhdr.src, eth_src); + eth_mac_fmt(&arp->ethhdr.dest, eth_dst); + eth_mac_fmt(&arp->shwaddr, arp_shwaddr); + memcpy(&in_addr, &arp->sipaddr, sizeof(in_addr)); + strlcpy(arp_sipaddr, ipv4_inet_ntoa(in_addr), sizeof(arp_sipaddr)); + eth_mac_fmt(&arp->dhwaddr, arp_dhwaddr); + memcpy(&in_addr, &arp->dipaddr, sizeof(in_addr)); + strlcpy(arp_dipaddr, ipv4_inet_ntoa(in_addr), sizeof(arp_dipaddr)); + sim_debug(DEBUG_ARP, &nia_dev, + "%s %s EthDst=%s EthSrc=%s shwaddr=%s sipaddr=%s dhwaddr=%s dipaddr=%s\n", + action, arp_op, eth_dst, eth_src, arp_shwaddr, arp_sipaddr, arp_dhwaddr, arp_dipaddr); + return; + } + if (ntohs(eth->type) != ETHTYPE_IP) { + payload = (uint8 *)&packet->msg[sizeof(struct nia_eth_hdr)]; + len = packet->len - sizeof(struct nia_eth_hdr); + sim_data_trace(&nia_dev, nia_unit, payload, "", len, "", DEBUG_DATA); + return; + } + if (!(nia_dev.dctrl & (DEBUG_TCP|DEBUG_UDP|DEBUG_ICMP))) + return; + memcpy(&ipaddr, &ip->ip_src, sizeof(ipaddr)); + strlcpy(src_ip, ipv4_inet_ntoa(ipaddr), sizeof(src_ip)); + memcpy(&ipaddr, &ip->ip_dst, sizeof(ipaddr)); + strlcpy(dst_ip, ipv4_inet_ntoa(ipaddr), sizeof(dst_ip)); + payload = (uint8 *)&packet->msg[sizeof(struct nia_eth_hdr) + (ip->ip_v_hl & 0xf) * 4]; + switch (ip->ip_p) { + case UDP_PROTO: + udp = (struct udp *)payload; + snprintf(src_port, sizeof(src_port), "%d", ntohs(udp->udp_sport)); + snprintf(dst_port, sizeof(dst_port), "%d", ntohs(udp->udp_dport)); + sim_debug(DEBUG_UDP, &nia_dev, "%s %d byte packet from %s:%s to %s:%s\n", action, + ntohs(udp->len), src_ip, src_port, dst_ip, dst_port); + if (udp->len && (nia_dev.dctrl & DEBUG_UDP)) + sim_data_trace(&nia_dev, nia_unit, payload + sizeof(struct udp), "", + ntohs(udp->len), "", DEBUG_DATA); + break; + case TCP_PROTO: + tcp = (struct tcp *)payload; + snprintf(src_port, sizeof(src_port), "%d", ntohs(tcp->tcp_sport)); + snprintf(dst_port, sizeof(dst_port), "%d", ntohs(tcp->tcp_dport)); + strlcpy(flags, "", sizeof(flags)); + for (flag=0; bits[flag].name; flag++) { + if (ntohs(tcp->flags) & bits[flag].bitmask) { + if (*flags) + strlcat(flags, ",", sizeof(flags)); + strlcat(flags, bits[flag].name, sizeof(flags)); + } + + } + len = ntohs(ip->ip_len) - ((ip->ip_v_hl & 0xf) * 4 + (ntohs(tcp->flags) >> 12) * 4); + sim_debug(DEBUG_TCP, &nia_dev, "%s %s%s %d byte packet from %s:%s to %s:%s\n", action, + flags, *flags ? ":" : "", (int)len, src_ip, src_port, dst_ip, dst_port); + if (len && (nia_dev.dctrl & DEBUG_TCP)) + sim_data_trace(&nia_dev, nia_unit, payload + 4 * (ntohs(tcp->flags) >> 12), "", len, "", DEBUG_DATA); + break; + case ICMP_PROTO: + icmp = (struct icmp *)payload; + len = ntohs(ip->ip_len) - (ip->ip_v_hl & 0xf) * 4; + sim_debug(DEBUG_ICMP, &nia_dev, "%s %s %d byte packet from %s to %s\n", action, + (icmp->type < sizeof(icmp_types)/sizeof(icmp_types[0])) ? icmp_types[icmp->type] : "", (int)len, src_ip, dst_ip); + if (len && (nia_dev.dctrl & DEBUG_ICMP)) + sim_data_trace(&nia_dev, nia_unit, payload + sizeof(struct icmp), "", len, "", DEBUG_DATA); + break; + } +} + + +/* + * Send out a packet. + */ +void nia_send_pkt(UNIT *uptr, int len) +{ + uint64 word1, word2, cmd; + struct nia_eth_hdr *hdr = (struct nia_eth_hdr *)(&nia_data.snd_buff.msg[0]); + uint8 *data = &nia_data.snd_buff.msg[sizeof(struct nia_eth_hdr)]; + ETH_MAC dest; + uint16 type; + int blen; + + /* flink 0 */ + /* blink 1 */ + /* resv 2 */ + /* cmd 3 */ + /* len 4 */ + /* prot 5 */ + /* freeq 6 */ + /* dest 7 */ + /* text/bsd 9 */ + /* flink 0 */ + /* blink 1 */ + /* resv 2 */ + /* cmd 3 */ + /* len 4 */ + /* prot 5, 8 */ + /* freeq 6, 5 */ + /* dest 7, 6 */ + /* text/bsd 9 */ + /* Load destination address */ + word1 = M[nia_data.cmd_entry+7]; + word2 = M[nia_data.cmd_entry+8]; + nia_cpy_mac(uptr, word1, word2, &dest); + memcpy(hdr->dest, dest, sizeof(ETH_MAC)); + /* Copy our address over */ + memcpy(hdr->src, nia_data.mac, sizeof(ETH_MAC)); + /* Copy protocol type */ + word1 = M[nia_data.cmd_entry+5]; + type = (uint16)(word1 >> 12) & 0xff; + type |= (uint16)(word1 << 4) & 0xff00; + hdr->type = htons(type); + nia_data.snd_buff.len = len + sizeof(struct nia_eth_hdr); + /* Copy over rest of packet */ + cmd = (M[nia_data.cmd_entry + 3] >> 20); + if (cmd & NIA_FLG_BSD) { + word1 = M[nia_data.cmd_entry + 9] & AMASK; + while (len > 0) { + word2 = M[word1] & AMASK; + blen = (int)(M[word1+2] & 0177777); + data = nia_cpy_to(uptr, word2, data, blen); + len -= blen; + word1 = M[word1+1] & AMASK; + } + } else { + data = nia_cpy_to(uptr, nia_data.cmd_entry + 9, data, len); + } + if (cmd & NIA_FLG_PAD && nia_data.snd_buff.len < ETH_MIN_PACKET) { + while (nia_data.snd_buff.len < ETH_MIN_PACKET) { + *data = 0; + nia_data.snd_buff.len++; + } + } + nia_packet_debug(&nia_data, "send", &nia_data.snd_buff); + eth_write(&nia_data.etherface, &nia_data.snd_buff, NULL); +} + +void nia_enable(UNIT *uptr) +{ + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA enable\n"); + /* Load pointers to various table */ + nia_data.unk_len = (int)(M[(nia_data.unk_hdr + 3) & AMASK] & AMASK); + /* Load PTT */ + nia_data.ptt_addr = (t_addr)(M[(nia_data.pcb + 015) & AMASK] & AMASK); + nia_load_ptt(uptr); + /* Load MCT */ + nia_data.mcast_addr = (t_addr)(M[(nia_data.pcb + 016) & AMASK] & AMASK); + nia_load_mcast(uptr); + /* Load read count buffer address */ + nia_data.rcb = (t_addr)(M[(nia_data.pcb + 030) & AMASK] & AMASK); + uptr->STATUS |= NIA_ECP; + uptr->STATUS &= ~NIA_DCP; + sim_activate(&nia_unit[1], 200); +} + +void nia_disable(UNIT *uptr) +{ + uptr->STATUS |= NIA_DCP; + uptr->STATUS &= ~NIA_ECP; + sim_cancel(&nia_unit[1]); +} + +/* Get next entry off a queue. Returns 0 if fail */ +int nia_getq(t_addr head, t_addr *entry) +{ + uint64 temp; + uint64 flink; + uint64 blink; + int i; + *entry = 0; /* For safty */ + + temp = M[head]; + /* Check if entry locked */ + if ((temp & SMASK) == 0) + return 0; + + /* Increment lock here */ + + flink = M[head+1] & AMASK; + /* Check if queue empty */ + if (flink == (head+1)) { + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA empty %08o\n", head); + /* Decrement lock here */ + return 1; + } + blink = M[flink] & AMASK; + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA head: %08o %08llo %012llo\n", head, blink, M[flink+1]); + M[head+1] = blink; /* Set Head Flink to point to next */ + M[blink+1] = head + 1; /* Set Next Blink to head */ + *entry = flink; + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA get head: %08o %08o %012llo %012llo\n", head, head+1, M[head+1], M[head+2]); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA get entry: %08o %08o %012llo %012llo\n", head, *entry, M[*entry], M[*entry+1]); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA get next: %08o %08llo %012llo %012llo\n", head, blink, M[blink], M[blink+1]); + /* Decrement lock here */ + return 1; +} + +/* Put entry on head of queue. */ +int nia_putq(UNIT *uptr, t_addr head, t_addr *entry) +{ + uint64 temp; + uint64 blink; + + temp = M[head]; + /* Check if entry locked */ + if ((temp & SMASK) == 0) + return 0; + + /* Increment lock here */ + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put: %08o %08o %012llo %012llo\n", head, *entry, M[head+1], M[head+2]); + + /* Set up entry. */ + blink = M[head+2]; /* Get back link */ + M[blink] = *entry; /* Old prevous entry */ + M[*entry+1] = blink; /* Back link points to previous */ + M[*entry] = head+1; /* Flink is head of queue */ + M[head+2] = *entry; /* Old forward is new */ + + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put head: %08o %08o %012llo %012llo\n", head, head+1, M[head+1], M[head+2]); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put entry: %08o %08o %012llo %012llo\n", head, *entry, M[*entry], M[*entry+1]); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put next: %08o %08llo %012llo %012llo\n", head, blink, M[blink], M[blink+1]); + *entry = 0; + /* Decement lock here */ + + /* Check if Queue was empty, and response queue */ + if (blink == (head+1) && head == nia_data.resp_hdr) { + uptr->STATUS |= NIA_RQA; + set_interrupt(NIA_DEVNUM, nia_data.pia); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA set response\n"); + } + return 1; +} + +t_stat nia_srv(UNIT * uptr) +{ + t_addr free_q = nia_data.unk_hdr; + uint64 cmd, word1, word2; + int len, i; + + /* See if we have command to process */ + if (nia_data.cmd_entry != 0) { + /* Have to put this either on response queue or free queue */ + if (nia_putq(uptr, nia_data.cmd_rply, &nia_data.cmd_entry) == 0) { + sim_activate(uptr, 200); /* Reschedule ourselves to deal with it */ + return SCPE_OK; + } + nia_data.cmd_rply = 0; + } + /* Check if we are running */ + if ((uptr->STATUS & NIA_MRN) == 0 || (uptr->STATUS & NIA_CQA) == 0) { + return SCPE_OK; + } + /* or no commands pending, just idle out */ + /* Try to get command off queue */ + if (nia_getq(nia_data.cmd_hdr, &nia_data.cmd_entry) == 0) { + sim_activate(uptr, 200); /* Reschedule ourselves to deal with it */ + return SCPE_OK; + } + /* Check if we got one */ + if (nia_data.cmd_entry == 0) { + /* Nothing to do */ + uptr->STATUS &= ~NIA_CQA; + return SCPE_OK; + } + /* Preform function of command */ + cmd = M[nia_data.cmd_entry + 3]; + nia_data.cmd_status = (uint8)((M[nia_data.cmd_entry + 3] >> 20) & 0xff); +// cmd &= ~(0xFFLL<<20); /* Clear status field */ + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA cmd: %08x\n", (uint32)(cmd >> 12)); + len = 5; + switch((cmd >> 12) & 0xff) { + case NIA_CMD_SND: /* Send a datagram */ + len = (int)(M[nia_data.cmd_entry + 4] & 0177777) + sizeof(struct nia_eth_hdr); + if (len < ETH_MIN_PACKET && (cmd & (NIA_FLG_PAD << 20)) == 0) { + cmd |= (((uint64)NIA_ERR_RUN) << 29) | ((uint64)NIA_STS_ERR << 28); + break; + } if (len > ETH_MAX_PACKET) { + cmd |= (((uint64)NIA_ERR_LNG) << 29) | ((uint64)NIA_STS_ERR << 28); + break; + } else + nia_send_pkt(uptr, len - sizeof(struct nia_eth_hdr)); + cmd |= (uint64)NIA_STS_SR << 28; + len = 10; + break; + case NIA_CMD_LPTT: /* Load Protocol Type table */ + nia_load_ptt(uptr); + break; + case NIA_CMD_LMAC: /* Load Multicast table */ + nia_load_mcast(uptr); + break; + case NIA_CMD_RCNT: /* Read counts */ + break; + case NIA_CMD_WPLI: /* Write PLI */ + break; + case NIA_CMD_RPLI: /* Read PLI */ + break; + case NIA_CMD_RNSA: /* Read Station Address */ + len = 8; + word1 = ((uint64)nia_data.mac[0]) << 28; + word1 |= ((uint64)nia_data.mac[1]) << 20; + word1 |= ((uint64)nia_data.mac[2]) << 12; + word1 |= ((uint64)nia_data.mac[3]) << 4; + M[nia_data.cmd_entry + 4] = word1; + word2 = ((uint64)nia_data.mac[4]) << 28; + word2 |= ((uint64)nia_data.mac[5]) << 20; + M[nia_data.cmd_entry + 5] = word2; + M[nia_data.cmd_entry + 6] = 0; + M[nia_data.cmd_entry + 7] = (nia_data.uver[3] << 12) | (0xF << 6) | 0xF; + break; + case NIA_CMD_WNSA: /* Write Station Address */ + len = 8; + word1 = M[nia_data.cmd_entry+4]; + word2 = M[nia_data.cmd_entry+5]; + nia_cpy_mac(uptr, word1, word2, &nia_data.mac); + memcpy(&nia_data.macs[0], &nia_data.mac, sizeof (ETH_MAC)); + eth_filter (&nia_data.etherface, nia_data.macs_n + 2, nia_data.macs, 0, 0); + break; + + case NIA_CMD_RCV: /* Received datagram */ + default: /* Invalid command */ + break; + } + + nia_data.cmd_rply = nia_data.unk_hdr; + M[nia_data.cmd_entry+3] = cmd; + if ((nia_data.cmd_status & 1) || ((M[nia_data.cmd_entry+3] >> 28) & 0xFF) != 0) { + nia_data.cmd_rply = nia_data.resp_hdr; + } else if (((cmd >> 12) & 0xff) == NIA_CMD_SND) { + nia_data.cmd_rply = M[nia_data.cmd_entry + 5]; + } + for(i = 0; i < len; i++) + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA rcmd: %d %09llx %012llo\n", i, M[nia_data.cmd_entry + i], + M[nia_data.cmd_entry + i]); + (void)nia_putq(uptr, nia_data.cmd_rply, &nia_data.cmd_entry); + sim_activate(uptr, 500); + return SCPE_OK; +} + + +t_stat nia_eth_srv(UNIT * uptr) +{ + struct nia_eth_hdr *hdr; + uint16 type; + int i; + int len; + t_addr queue; + t_addr bsd; + t_addr word; + uint8 *data; + sim_clock_coschedule(uptr, 100); /* continue poll */ + /* Check if we are running */ + if ((nia_unit[0].STATUS & NIA_MRN) == 0) + return SCPE_OK; + /* See if we have command to process */ + if (nia_data.rec_entry != 0) { + /* Have to put this response queue */ + if (nia_putq(&nia_unit[0], nia_data.resp_hdr, &nia_data.rec_entry) == 0) + return SCPE_OK; + } +loop: + /* Check if we need to get a packet */ + if (nia_data.r_pkt == 0) { + if (eth_read(&nia_data.etherface, &nia_data.rec_buff, NULL) <= 0) + return SCPE_OK; + hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]); + type = ntohs(hdr->type); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA read packet: %d %04x\n", + nia_data.rec_buff.len, type); + nia_data.r_pkt = 1; + nia_packet_debug(&nia_data, "recv", &nia_data.rec_buff); + } + + /* Determine which queue to get free packet from */ + hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]); + type = ntohs(hdr->type); + + + queue = nia_data.unk_hdr; + for (i = 0; i < nia_data.ptt_n; i++) { + if (nia_data.ptt_proto[i] == type) { + queue = nia_data.ptt_head[i]; + break; + } + } + + /* Try to grab place to save packet */ + if (nia_getq(queue, &nia_data.rec_entry) == 0) { + return SCPE_OK; + } + + if (nia_data.rec_entry == 0) { + if (queue == nia_data.unk_hdr) { + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA drop packet\n"); + nia_data.r_pkt = 0; /* Drop packet it queue empty */ + } + return SCPE_OK; + } + /* Got one, now fill in data */ + M[nia_data.rec_entry + 3] = (uint64)(NIA_CMD_RCV << 12); + (void)nia_cpy_from(&nia_unit[0], nia_data.rec_entry + 5, (uint8 *)&hdr->dest, sizeof(ETH_MAC)); + (void)nia_cpy_from(&nia_unit[0], nia_data.rec_entry + 7, (uint8 *)&hdr->src, sizeof(ETH_MAC)); + M[nia_data.rec_entry + 9] = (uint64)(((type & 0xff00) >> 4) | ((type & 0xff) << 12)); + data = &nia_data.rec_buff.msg[sizeof(struct nia_eth_hdr)]; + len = nia_data.rec_buff.len - sizeof(struct nia_eth_hdr); + M[nia_data.rec_entry + 4] = len + 4; + bsd = (t_addr)(M[nia_data.rec_entry + 10] & AMASK); + while (len > 0) { + int blen; + word = (t_addr)(M[bsd] & AMASK); + blen = (int)(M[bsd+2] & 0177777); + if (blen > len) + blen = len; + data = nia_cpy_from(&nia_unit[0], word, data, blen); + len -= blen; + bsd = M[bsd+1] & AMASK; + } + + for(i = 0; i < 10; i++) + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA recv: %d %09llx %012llo\n", i, M[nia_data.rec_entry + i], + M[nia_data.rec_entry + i]); + /* Put on response queue */ + if (nia_putq(&nia_unit[0], nia_data.resp_hdr, &nia_data.rec_entry) == 0) + return SCPE_OK; + nia_data.r_pkt = 0; + goto loop; +// return SCPE_OK; +} + +t_stat nia_tim_srv(UNIT * uptr) +{ + sim_clock_coschedule(uptr, 1000); /* continue poll */ + + return SCPE_OK; +} + + + +t_stat nia_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc) +{ + char buffer[20]; + eth_mac_fmt(&nia_data.mac, buffer); + fprintf(st, "MAC=%s", buffer); + return SCPE_OK; +} + +t_stat nia_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc) +{ + t_stat status; + + if (!cptr) return SCPE_IERR; + if (uptr->flags & UNIT_ATT) return SCPE_ALATT; + + status = eth_mac_scan_ex(&nia_data.mac, cptr, uptr); + if (status != SCPE_OK) + return status; + + return SCPE_OK; +} + +t_stat nia_reset (DEVICE *dptr) +{ + int i; + struct nia_packet *p; + + for (i = 0; i < 6; i++) { + if (nia_data.mac[i] != 0) + break; + } + if (i == 6) { /* First call to reset? */ + /* Set a default MAC address in a BBN assigned OID range no longer in use */ + nia_set_mac (dptr->units, 0, "00:00:02:00:00:00/24", NULL); + } + return SCPE_OK; +} + +/* attach device: */ +t_stat nia_attach(UNIT* uptr, CONST char* cptr) +{ + t_stat status; + char* tptr; + char buf[32]; + + tptr = (char *) malloc(strlen(cptr) + 1); + if (tptr == NULL) return SCPE_MEM; + strcpy(tptr, cptr); + + memcpy(&nia_data.macs[0], &nia_data.mac, sizeof (ETH_MAC)); + memcpy(&nia_data.macs[1], &broadcast_ethaddr, 6); + status = eth_open(&nia_data.etherface, cptr, &nia_dev, DEBUG_ETHER); + if (status != SCPE_OK) { + free(tptr); + return status; + } + eth_mac_fmt(&nia_data.mac, buf); /* format ethernet mac address */ + if (SCPE_OK != eth_check_address_conflict (&nia_data.etherface, &nia_data.mac)) { + eth_close(&nia_data.etherface); + free(tptr); + return sim_messagef (SCPE_NOATT, "%s: MAC Address Conflict on LAN for address %s\n", + nia_dev.name, buf); + } + if (SCPE_OK != eth_filter(&nia_data.etherface, 2, nia_data.macs, 0, 0)) { + eth_close(&nia_data.etherface); + free(tptr); + return sim_messagef (SCPE_NOATT, "%s: Can't set packet filter for MAC Address %s\n", + nia_dev.name, buf); + } + + uptr->filename = tptr; + uptr->flags |= UNIT_ATT; + eth_setcrc(&nia_data.etherface, 0); /* Don't need CRC */ + + /* init read queue (first time only) */ + status = ethq_init(&nia_data.ReadQ, 8); + if (status != SCPE_OK) { + eth_close(&nia_data.etherface); + uptr->filename = NULL; + free(tptr); + return sim_messagef (status, "%s: Can't initialize receive queue\n", nia_dev.name); + } + + + eth_set_async (&nia_data.etherface, 0); /* Allow Asynchronous inbound packets */ + return SCPE_OK; +} + +/* detach device: */ + +t_stat nia_detach(UNIT* uptr) +{ + + if (uptr->flags & UNIT_ATT) { + eth_close (&nia_data.etherface); + free(uptr->filename); + uptr->filename = NULL; + uptr->flags &= ~UNIT_ATT; + sim_cancel (uptr+1); /* stop the packet timing services */ + sim_cancel (uptr+2); /* stop the clock timer services */ + } + return SCPE_OK; +} + +t_stat nia_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "NIA interface\n\n"); +fprintf (st, "The IMP acted as an interface to the early internet. "); +fprint_set_help (st, dptr); +fprint_show_help (st, dptr); +eth_attach_help(st, dptr, uptr, flag, cptr); +return SCPE_OK; +} + +const char *nia_description (DEVICE *dptr) +{ + return "KL NIA interface"; +} +#endif + From ae8a6faacc4160ac7f27bfda8f18f9d4baed07ec Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Wed, 12 Feb 2020 22:20:18 -0500 Subject: [PATCH 88/98] KA10: Added counters to NIA device. --- PDP10/kl10_nia.c | 354 +++++++++++++++++++++++++++++++---------------- 1 file changed, 235 insertions(+), 119 deletions(-) diff --git a/PDP10/kl10_nia.c b/PDP10/kl10_nia.c index 72e537e..9c9ae59 100644 --- a/PDP10/kl10_nia.c +++ b/PDP10/kl10_nia.c @@ -61,6 +61,7 @@ #define NIA_RAR 0377760000000LL /* Microcode address mask */ #define NIA_MSB 0000020000000LL /* Half word select */ +/* PCB Offsets */ #define PCB_CQI 0 /* Command queue interlock */ #define PCB_CQF 1 /* Command queue flink */ #define PCB_CQB 2 /* Command queue blink */ @@ -134,6 +135,68 @@ #define NIA_ERR_PAR 036 /* Parity error */ #define NIA_ERR_INT 037 /* Internal error */ +/* Counters */ +#define NIA_CNT_BR 000 /* Bytes received */ +#define NIA_CNT_BX 001 /* Bytes transmitted */ +#define NIA_CNT_FR 002 /* Frames received */ +#define NIA_CNT_FX 003 /* Frames transmitted */ +#define NIA_CNT_MCB 004 /* Multicast bytes received */ +#define NIA_CNT_MCF 005 /* Multicast frames received */ +#define NIA_CNT_FXD 006 /* Frames xmitted, initially deferred */ +#define NIA_CNT_FXS 007 /* Frames xmitted, single collision */ +#define NIA_CNT_FXM 010 /* Frames xmitted, multiple collisions */ +#define NIA_CNT_XF 011 /* Transmit failures */ +#define NIA_CNT_XFM 012 /* Transmit failure bit mask */ +#define NIA_XFM_LOC 04000 /* B24 - Loss of carrier */ +#define NIA_XFM_XBP 02000 /* B25 - Xmit buffer parity error */ +#define NIA_XFM_RFD 01000 /* B26 - Remote failure to defer */ +#define NIA_XFM_XFL 00400 /* B27 - Xmitted frame too long */ +#define NIA_XFM_OC 00200 /* B28 - Open circuit */ +#define NIA_XFM_SC 00100 /* B29 - Short circuit */ +#define NIA_XFM_CCF 00040 /* B30 - Collision detect check failed */ +#define NIA_XFM_EXC 00020 /* B31 - Excessive collisions */ + +#define NIA_CNT_CDF 013 /* Carrier detect check failed */ +#define NIA_CNT_RF 014 /* Receive failures */ +#define NIA_CNT_RFM 015 /* Receive failure bit mask */ +#define NIA_RFM_FLE 0400 /* B27 - free list parity error */ +#define NIA_RFM_NFB 0200 /* B28 - no free buffers */ +#define NIA_RFM_FTL 0100 /* B29 - frame too long */ +#define NIA_RFM_FER 0040 /* B30 - framing error */ +#define NIA_RFM_BCE 0020 /* B31 - block check error */ + +#define NIA_CNT_DUN 016 /* Discarded unknown */ +#define NIA_CNT_D01 017 /* Discarded position 1 */ +#define NIA_CNT_D02 020 /* Discarded position 2 */ +#define NIA_CNT_D03 021 /* Discarded position 3 */ +#define NIA_CNT_D04 022 /* Discarded position 4 */ +#define NIA_CNT_D05 023 /* Discarded position 5 */ +#define NIA_CNT_D06 024 /* Discarded position 6 */ +#define NIA_CNT_D07 025 /* Discarded position 7 */ +#define NIA_CNT_D08 026 /* Discarded position 8 */ +#define NIA_CNT_D09 027 /* Discarded position 9 */ +#define NIA_CNT_D10 030 /* Discarded position 10 */ +#define NIA_CNT_D11 031 /* Discarded position 11 */ +#define NIA_CNT_D12 032 /* Discarded position 12 */ +#define NIA_CNT_D13 033 /* Discarded position 13 */ +#define NIA_CNT_D14 034 /* Discarded position 14 */ +#define NIA_CNT_D15 035 /* Discarded position 15 */ +#define NIA_CNT_D16 036 /* Discarded position 16 */ +#define NIA_CNT_UFD 037 /* Unrecognized frame dest */ +#define NIA_CNT_DOV 040 /* Data overrun */ +#define NIA_CNT_SBU 041 /* System buffer unavailable */ +#define NIA_CNT_UBU 042 /* User buffer unavailable */ +#define NIA_CNT_RS0 043 /* Pli reg rd par error,,pli parity error */ +#define NIA_CNT_RS1 044 /* Mover parity error,,cbus parity error */ +#define NIA_CNT_RS2 045 /* Ebus parity error,,ebus que parity error */ +#define NIA_CNT_RS3 046 /* Channel error,,spur channel error */ +#define NIA_CNT_RS4 047 /* Spur xmit attn error,,cbus req timout error */ +#define NIA_CNT_RS5 050 /* Ebus req timeout error,,csr grnt timeout error */ +#define NIA_CNT_RS6 051 /* Used buff parity error,,xmit buff parity error */ +#define NIA_CNT_RS7 052 /* Reserved for ucode */ +#define NIA_CNT_RS8 053 /* Reserved for ucode */ +#define NIA_CNT_LEN 054 /* # of counters */ + #ifdef _MSC_VER # define PACKED_BEGIN __pragma( pack(push, 1) ) # define PACKED_END __pragma( pack(pop) ) @@ -273,12 +336,16 @@ struct nia_device { t_addr mcast_addr; /* Address of Multicast table */ int pia; /* Interrupt channel */ t_addr cnt_addr; /* Address of counters */ + uint64 pcnt[NIA_CNT_LEN]; /* Counters */ int ptt_n; /* Number of Protocol entries */ uint16 ptt_proto[17]; /* Protocol for entry */ t_addr ptt_head[17]; /* Head of protocol queue */ int macs_n; /* Number of multi-cast addresses */ ETH_MAC macs[20]; /* Watched Multi-cast addresses */ + int amc; /* Recieve all multicast packets */ + int prmsc; /* Recieve all packets */ + int h4000; /* Heart beat detection */ int rar; uint64 ebuf; uint32 uver[4]; /* Version information */ @@ -299,7 +366,6 @@ void nia_disable(UNIT *); void nia_error(UNIT *, int); t_stat nia_srv(UNIT *); t_stat nia_eth_srv(UNIT *); -t_stat nia_tim_srv(UNIT *); t_stat nia_reset (DEVICE *dptr); t_stat nia_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc); t_stat nia_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc); @@ -313,7 +379,6 @@ struct rh_if nia_rh = { NULL, NULL, NULL}; UNIT nia_unit[] = { {UDATA(nia_srv, UNIT_IDLE+UNIT_ATTABLE, 0)}, /* 0 */ {UDATA(nia_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ - {UDATA(nia_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ }; DIB nia_dib = {NIA_DEVNUM | RH20_DEV, 1, &nia_devio, NULL, &nia_rh }; @@ -351,28 +416,12 @@ DEBTAB nia_debug[] = { DEVICE nia_dev = { "NI", nia_unit, NULL, nia_mod, - 3, 8, 0, 1, 8, 36, + 2, 8, 0, 1, 8, 36, NULL, NULL, &nia_reset, NULL, &nia_attach, &nia_detach, &nia_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, nia_debug, NULL, NULL, &nia_help, NULL, NULL, &nia_description }; -static char * -ipv4_inet_ntoa(struct in_addr ip) -{ - static char str[20]; - - if (sim_end) - sprintf (str, "%d.%d.%d.%d", ip.s_addr & 0xFF, (ip.s_addr >> 8) & 0xFF, - (ip.s_addr >> 16) & 0xFF, (ip.s_addr >> 24) & 0xFF); - else - sprintf (str, "%d.%d.%d.%d", (ip.s_addr >> 24) & 0xFF, (ip.s_addr >> 16) & 0xFF, - (ip.s_addr >> 8) & 0xFF, ip.s_addr & 0xFF); - return str; -} - - - t_stat nia_devio(uint32 dev, uint64 *data) { DEVICE *dptr = &nia_dev; @@ -422,7 +471,6 @@ t_stat nia_devio(uint32 dev, uint64 *data) case CONI: *data = (uint64)uptr->STATUS; *data |= NIA_PPT|NIA_PID; -// *data &= ~NIA_CQA; sim_debug(DEBUG_CONI, dptr, "NIA %03o CONI %012llo PC=%o\n", dev, *data, PC); break; @@ -464,6 +512,23 @@ t_stat nia_devio(uint32 dev, uint64 *data) return SCPE_OK; } +static char * +ipv4_inet_ntoa(struct in_addr ip) +{ + static char str[20]; + + if (sim_end) + sprintf (str, "%d.%d.%d.%d", ip.s_addr & 0xFF, (ip.s_addr >> 8) & 0xFF, + (ip.s_addr >> 16) & 0xFF, (ip.s_addr >> 24) & 0xFF); + else + sprintf (str, "%d.%d.%d.%d", (ip.s_addr >> 24) & 0xFF, (ip.s_addr >> 16) & 0xFF, + (ip.s_addr >> 8) & 0xFF, ip.s_addr & 0xFF); + return str; +} + +/* + * Set error code and stop. + */ void nia_error(UNIT * uptr, int err) { nia_data.rar = err; @@ -472,9 +537,13 @@ void nia_error(UNIT * uptr, int err) set_interrupt(NIA_DEVNUM, uptr->STATUS & NIA_PIA); } +/* + * Start NIA device, load in 2 words using RH20 mode. + */ void nia_start(UNIT * uptr) { sim_debug(DEBUG_DETAIL, &nia_dev, "NIA start\n"); + /* Set up RH20 to read 2 words */ nia_rh.stcr = BIT7; nia_rh.imode = 2; rh20_setup(&nia_rh); @@ -505,6 +574,9 @@ void nia_stop(UNIT *uptr) uptr->STATUS &= ~NIA_MRN; } +/* + * Copy a MAC address from string to memory word. + */ void nia_cpy_mac(UNIT *uptr, uint64 word1, uint64 word2, ETH_MAC *mac) { ETH_MAC m; @@ -517,9 +589,13 @@ void nia_cpy_mac(UNIT *uptr, uint64 word1, uint64 word2, ETH_MAC *mac) memcpy(mac, &m, sizeof(ETH_MAC)); } +/* + * Copy memory to a packet. + */ uint8 *nia_cpy_to(UNIT *uptr, t_addr addr, uint8 *data, int len) { uint64 word; + /* Copy full words */ while (len > 3) { word = M[addr++]; *data++ = (uint8)((word >> 28) & 0xff); @@ -528,6 +604,7 @@ uint8 *nia_cpy_to(UNIT *uptr, t_addr addr, uint8 *data, int len) *data++ = (uint8)((word >> 4) & 0xff); len -= 4; } + /* Grab last partial word */ if (len) { word = M[addr++]; switch (len) { @@ -548,10 +625,14 @@ uint8 *nia_cpy_to(UNIT *uptr, t_addr addr, uint8 *data, int len) return data; } +/* + * Copy a packet to memory. + */ uint8 *nia_cpy_from(UNIT *uptr, t_addr addr, uint8 *data, int len) { uint64 word; + /* Copy full words */ while (len > 3) { word = (uint64)(*data++) << 28; word |= (uint64)(*data++) << 20; @@ -560,6 +641,7 @@ uint8 *nia_cpy_from(UNIT *uptr, t_addr addr, uint8 *data, int len) M[addr++] = word; len -= 4; } + /* Copy last partial word */ if (len) { switch (len) { case 3: @@ -594,7 +676,7 @@ void nia_load_ptt(UNIT *uptr) word1 = M[addr++]; word2 = M[addr++]; - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %012llo %012llo\n\r",n, word1, word2); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %012llo %012llo\n\r",n, word1, word2); if (word1 & SMASK) { uint16 type; type = (uint16)(word1 >> 12) & 0xff; @@ -606,7 +688,8 @@ void nia_load_ptt(UNIT *uptr) addr++; } for (i = 0; i < n; i++) { - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %04x %010o\n\r",n, nia_data.ptt_proto[i], nia_data.ptt_head[i]); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %04x %010o\n\r",n, nia_data.ptt_proto[i], + nia_data.ptt_head[i]); } nia_data.ptt_n = n; } @@ -621,6 +704,7 @@ void nia_load_mcast(UNIT *uptr) char buffer[20]; t_addr addr = nia_data.mcast_addr; + /* Start with our own address. */ memcpy(&nia_data.macs[n], &nia_data.mac, sizeof (ETH_MAC)); n++; memcpy(&nia_data.macs[n], &broadcast_ethaddr, sizeof (ETH_MAC)); @@ -637,13 +721,16 @@ void nia_load_mcast(UNIT *uptr) } for(i = 0; i< n; i++) { eth_mac_fmt(&nia_data.macs[i], buffer); - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load mcast%d: %s\n\r",i, buffer); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load mcast%d: %s\n\r",i, buffer); } nia_data.macs_n = n - 2; if (uptr->flags & UNIT_ATT) - eth_filter (&nia_data.etherface, n, nia_data.macs, 0, 0); + eth_filter (&nia_data.etherface, n, nia_data.macs, nia_data.amc, nia_data.prmsc); } +/* + * Pretty print a packet for debugging. + */ void nia_packet_debug(struct nia_device *nia, const char *action, ETH_PACK *packet) { struct nia_eth_hdr *eth = (struct nia_eth_hdr *)&packet->msg[0]; struct arp_hdr *arp = (struct arp_hdr *)eth; @@ -800,33 +887,30 @@ void nia_packet_debug(struct nia_device *nia, const char *action, ETH_PACK *pack /* * Send out a packet. */ -void nia_send_pkt(UNIT *uptr, int len) +int nia_send_pkt(UNIT *uptr) { uint64 word1, word2, cmd; struct nia_eth_hdr *hdr = (struct nia_eth_hdr *)(&nia_data.snd_buff.msg[0]); uint8 *data = &nia_data.snd_buff.msg[sizeof(struct nia_eth_hdr)]; ETH_MAC dest; uint16 type; + int len; int blen; - /* flink 0 */ - /* blink 1 */ - /* resv 2 */ - /* cmd 3 */ - /* len 4 */ - /* prot 5 */ - /* freeq 6 */ - /* dest 7 */ - /* text/bsd 9 */ - /* flink 0 */ - /* blink 1 */ - /* resv 2 */ - /* cmd 3 */ - /* len 4 */ - /* prot 5, 8 */ - /* freeq 6, 5 */ - /* dest 7, 6 */ - /* text/bsd 9 */ + len = (int)(M[nia_data.cmd_entry + 4] & 0177777) + sizeof(struct nia_eth_hdr); + /* Check for runt packet */ + if (len < ETH_MIN_PACKET && (cmd & (NIA_FLG_PAD << 20)) == 0) { + return NIA_ERR_RUN; + } + /* Check for too long of a packet */ + if (len > ETH_MAX_PACKET) { + nia_data.pcnt[NIA_CNT_XF]++; + nia_data.pcnt[NIA_CNT_XFM] |= NIA_XFM_XFL; + return NIA_ERR_LNG; + } + if ((uptr->flags & UNIT_ATT) == 0) + return 0; + len -= sizeof(struct nia_eth_hdr); /* Load destination address */ word1 = M[nia_data.cmd_entry+7]; word2 = M[nia_data.cmd_entry+8]; @@ -861,31 +945,47 @@ void nia_send_pkt(UNIT *uptr, int len) } } nia_packet_debug(&nia_data, "send", &nia_data.snd_buff); - eth_write(&nia_data.etherface, &nia_data.snd_buff, NULL); + if (eth_write(&nia_data.etherface, &nia_data.snd_buff, NULL) != SCPE_OK) { + nia_data.pcnt[NIA_CNT_XF]++; + nia_data.pcnt[NIA_CNT_XFM] |= NIA_XFM_LOC; + } + nia_data.pcnt[NIA_CNT_BX] += nia_data.snd_buff.len; + nia_data.pcnt[NIA_CNT_FX] ++; + return 0; } +/* + * Enable NIA 20. + * + * Read in PTT and MACS table. + */ void nia_enable(UNIT *uptr) { sim_debug(DEBUG_DETAIL, &nia_dev, "NIA enable\n"); /* Load pointers to various table */ - nia_data.unk_len = (int)(M[(nia_data.unk_hdr + 3) & AMASK] & AMASK); + nia_data.unk_len = (int)(M[(nia_data.unk_hdr + PCB_UPL) & AMASK] & AMASK); /* Load PTT */ - nia_data.ptt_addr = (t_addr)(M[(nia_data.pcb + 015) & AMASK] & AMASK); + nia_data.ptt_addr = (t_addr)(M[(nia_data.pcb + PCB_PTT) & AMASK] & AMASK); nia_load_ptt(uptr); /* Load MCT */ - nia_data.mcast_addr = (t_addr)(M[(nia_data.pcb + 016) & AMASK] & AMASK); + nia_data.mcast_addr = (t_addr)(M[(nia_data.pcb + PCB_MCT) & AMASK] & AMASK); nia_load_mcast(uptr); /* Load read count buffer address */ - nia_data.rcb = (t_addr)(M[(nia_data.pcb + 030) & AMASK] & AMASK); + nia_data.rcb = (t_addr)(M[(nia_data.pcb + PCB_RCB) & AMASK] & AMASK); uptr->STATUS |= NIA_ECP; uptr->STATUS &= ~NIA_DCP; + /* Start receiver */ sim_activate(&nia_unit[1], 200); } +/* + * Disable NIA 20. + */ void nia_disable(UNIT *uptr) { uptr->STATUS |= NIA_DCP; uptr->STATUS &= ~NIA_ECP; + /* Stop receiver */ sim_cancel(&nia_unit[1]); } @@ -893,8 +993,8 @@ void nia_disable(UNIT *uptr) int nia_getq(t_addr head, t_addr *entry) { uint64 temp; - uint64 flink; - uint64 blink; + t_addr flink; + t_addr nlink; int i; *entry = 0; /* For safty */ @@ -905,21 +1005,19 @@ int nia_getq(t_addr head, t_addr *entry) /* Increment lock here */ - flink = M[head+1] & AMASK; + flink = (t_addr)(M[head+1] & AMASK); /* Check if queue empty */ if (flink == (head+1)) { sim_debug(DEBUG_DETAIL, &nia_dev, "NIA empty %08o\n", head); /* Decrement lock here */ return 1; } - blink = M[flink] & AMASK; - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA head: %08o %08llo %012llo\n", head, blink, M[flink+1]); - M[head+1] = blink; /* Set Head Flink to point to next */ - M[blink+1] = head + 1; /* Set Next Blink to head */ + nlink = (t_addr)(M[flink] & AMASK); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA head: q=%08o f=%08o n=%08o\n", head, flink, nlink); + M[head+1] = (uint64)nlink; /* Set Head Flink to point to next */ + M[nlink+1] = (uint64)(head + 1); /* Set Next Blink to head */ *entry = flink; - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA get head: %08o %08o %012llo %012llo\n", head, head+1, M[head+1], M[head+2]); - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA get entry: %08o %08o %012llo %012llo\n", head, *entry, M[*entry], M[*entry+1]); - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA get next: %08o %08llo %012llo %012llo\n", head, blink, M[blink], M[blink+1]); + /* Decrement lock here */ return 1; } @@ -928,7 +1026,7 @@ int nia_getq(t_addr head, t_addr *entry) int nia_putq(UNIT *uptr, t_addr head, t_addr *entry) { uint64 temp; - uint64 blink; + t_addr blink; temp = M[head]; /* Check if entry locked */ @@ -936,18 +1034,14 @@ int nia_putq(UNIT *uptr, t_addr head, t_addr *entry) return 0; /* Increment lock here */ - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put: %08o %08o %012llo %012llo\n", head, *entry, M[head+1], M[head+2]); /* Set up entry. */ - blink = M[head+2]; /* Get back link */ - M[blink] = *entry; /* Old prevous entry */ - M[*entry+1] = blink; /* Back link points to previous */ - M[*entry] = head+1; /* Flink is head of queue */ - M[head+2] = *entry; /* Old forward is new */ - - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put head: %08o %08o %012llo %012llo\n", head, head+1, M[head+1], M[head+2]); - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put entry: %08o %08o %012llo %012llo\n", head, *entry, M[*entry], M[*entry+1]); - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put next: %08o %08llo %012llo %012llo\n", head, blink, M[blink], M[blink+1]); + blink = (t_addr)(M[head+2] & AMASK); /* Get back link */ + M[blink] = (uint64)*entry; /* Old prevous entry */ + M[*entry] = (uint64)(head+1); /* Flink is head of queue */ + M[*entry+1] = (uint64)blink; /* Back link points to previous */ + M[head+2] = (uint64)*entry; /* Old forward is new */ + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put: q=%08o i=%08o b=%08o\n", head, *entry, blink); *entry = 0; /* Decement lock here */ @@ -960,11 +1054,16 @@ int nia_putq(UNIT *uptr, t_addr head, t_addr *entry) return 1; } +/* + * Process commands. + */ t_stat nia_srv(UNIT * uptr) { t_addr free_q = nia_data.unk_hdr; - uint64 cmd, word1, word2; + uint64 word1, word2; + uint32 cmd; int len, i; + int err; /* See if we have command to process */ if (nia_data.cmd_entry != 0) { @@ -975,40 +1074,39 @@ t_stat nia_srv(UNIT * uptr) } nia_data.cmd_rply = 0; } + /* Check if we are running */ if ((uptr->STATUS & NIA_MRN) == 0 || (uptr->STATUS & NIA_CQA) == 0) { return SCPE_OK; } + /* or no commands pending, just idle out */ /* Try to get command off queue */ if (nia_getq(nia_data.cmd_hdr, &nia_data.cmd_entry) == 0) { sim_activate(uptr, 200); /* Reschedule ourselves to deal with it */ return SCPE_OK; } + /* Check if we got one */ if (nia_data.cmd_entry == 0) { /* Nothing to do */ uptr->STATUS &= ~NIA_CQA; return SCPE_OK; } + /* Preform function of command */ - cmd = M[nia_data.cmd_entry + 3]; - nia_data.cmd_status = (uint8)((M[nia_data.cmd_entry + 3] >> 20) & 0xff); -// cmd &= ~(0xFFLL<<20); /* Clear status field */ - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA cmd: %08x\n", (uint32)(cmd >> 12)); + cmd = (uint32)(M[nia_data.cmd_entry + 3] >> 12); + /* Save initial status */ + nia_data.cmd_status = ((uint8)(cmd >> 16)) & 0xff; + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA cmd: %08x\n", cmd); + cmd &= 0xffff; len = 5; - switch((cmd >> 12) & 0xff) { + switch(cmd & 0xff) { case NIA_CMD_SND: /* Send a datagram */ - len = (int)(M[nia_data.cmd_entry + 4] & 0177777) + sizeof(struct nia_eth_hdr); - if (len < ETH_MIN_PACKET && (cmd & (NIA_FLG_PAD << 20)) == 0) { - cmd |= (((uint64)NIA_ERR_RUN) << 29) | ((uint64)NIA_STS_ERR << 28); - break; - } if (len > ETH_MAX_PACKET) { - cmd |= (((uint64)NIA_ERR_LNG) << 29) | ((uint64)NIA_STS_ERR << 28); - break; - } else - nia_send_pkt(uptr, len - sizeof(struct nia_eth_hdr)); - cmd |= (uint64)NIA_STS_SR << 28; + err = nia_send_pkt(uptr); + if (err != 0) + cmd |= ((err<<1)|1) << 16; + cmd |= NIA_STS_SR << 16; len = 10; break; case NIA_CMD_LPTT: /* Load Protocol Type table */ @@ -1018,6 +1116,11 @@ t_stat nia_srv(UNIT * uptr) nia_load_mcast(uptr); break; case NIA_CMD_RCNT: /* Read counts */ + for (i = 0; i < NIA_CNT_LEN; i++) { + M[nia_data.cnt_addr + i] = nia_data.pcnt[i]; + if ((cmd & (NIA_FLG_CLRC << 20)) != 0) + nia_data.pcnt[i] = 0; + } break; case NIA_CMD_WPLI: /* Write PLI */ break; @@ -1033,7 +1136,8 @@ t_stat nia_srv(UNIT * uptr) word2 = ((uint64)nia_data.mac[4]) << 28; word2 |= ((uint64)nia_data.mac[5]) << 20; M[nia_data.cmd_entry + 5] = word2; - M[nia_data.cmd_entry + 6] = 0; + M[nia_data.cmd_entry + 6] = (uint64)((nia_data.amc << 2)| + (nia_data.h4000 << 1) |nia_data.prmsc); M[nia_data.cmd_entry + 7] = (nia_data.uver[3] << 12) | (0xF << 6) | 0xF; break; case NIA_CMD_WNSA: /* Write Station Address */ @@ -1041,31 +1145,40 @@ t_stat nia_srv(UNIT * uptr) word1 = M[nia_data.cmd_entry+4]; word2 = M[nia_data.cmd_entry+5]; nia_cpy_mac(uptr, word1, word2, &nia_data.mac); + word1 = M[nia_data.cmd_entry+6]; + nia_data.prmsc = (int)(word1 & 1); + nia_data.h4000 = (int)((word1 & 2) != 0); + nia_data.amc = (int)((word1 & 4) != 0); memcpy(&nia_data.macs[0], &nia_data.mac, sizeof (ETH_MAC)); - eth_filter (&nia_data.etherface, nia_data.macs_n + 2, nia_data.macs, 0, 0); + if (uptr->flags & UNIT_ATT) + eth_filter (&nia_data.etherface, nia_data.macs_n + 2, + nia_data.macs, 0, 0); break; case NIA_CMD_RCV: /* Received datagram */ default: /* Invalid command */ + cmd |= ((NIA_ERR_UNK<<1)|1) << 16; break; } nia_data.cmd_rply = nia_data.unk_hdr; - M[nia_data.cmd_entry+3] = cmd; - if ((nia_data.cmd_status & 1) || ((M[nia_data.cmd_entry+3] >> 28) & 0xFF) != 0) { + M[nia_data.cmd_entry+3] = ((uint64)cmd) << 12; + if (((cmd >> 16) & 1) != 0 || (cmd & (NIA_FLG_RESP << 8)) != 0) { nia_data.cmd_rply = nia_data.resp_hdr; - } else if (((cmd >> 12) & 0xff) == NIA_CMD_SND) { + } else if ((cmd & 0xff) == NIA_CMD_SND) { nia_data.cmd_rply = M[nia_data.cmd_entry + 5]; } for(i = 0; i < len; i++) - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA rcmd: %d %09llx %012llo\n", i, M[nia_data.cmd_entry + i], - M[nia_data.cmd_entry + i]); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA rcmd: %d %09llx %012llo\n", i, M[nia_data.cmd_entry + i], + M[nia_data.cmd_entry + i]); (void)nia_putq(uptr, nia_data.cmd_rply, &nia_data.cmd_entry); sim_activate(uptr, 500); return SCPE_OK; } - +/* + * Receive ether net packets. + */ t_stat nia_eth_srv(UNIT * uptr) { struct nia_eth_hdr *hdr; @@ -1076,34 +1189,43 @@ t_stat nia_eth_srv(UNIT * uptr) t_addr bsd; t_addr word; uint8 *data; + sim_clock_coschedule(uptr, 100); /* continue poll */ + /* Check if we are running */ if ((nia_unit[0].STATUS & NIA_MRN) == 0) return SCPE_OK; + /* See if we have command to process */ if (nia_data.rec_entry != 0) { /* Have to put this response queue */ if (nia_putq(&nia_unit[0], nia_data.resp_hdr, &nia_data.rec_entry) == 0) return SCPE_OK; } + loop: /* Check if we need to get a packet */ if (nia_data.r_pkt == 0) { if (eth_read(&nia_data.etherface, &nia_data.rec_buff, NULL) <= 0) return SCPE_OK; - hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]); - type = ntohs(hdr->type); + nia_packet_debug(&nia_data, "recv", &nia_data.rec_buff); + hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]); + type = ntohs(hdr->type); sim_debug(DEBUG_DETAIL, &nia_dev, "NIA read packet: %d %04x\n", nia_data.rec_buff.len, type); nia_data.r_pkt = 1; - nia_packet_debug(&nia_data, "recv", &nia_data.rec_buff); + nia_data.pcnt[NIA_CNT_BR] += nia_data.rec_buff.len; + nia_data.pcnt[NIA_CNT_FR] ++; + if (hdr->dest[0] & 1) { + nia_data.pcnt[NIA_CNT_MCB] += nia_data.rec_buff.len; + nia_data.pcnt[NIA_CNT_MCF] ++; + } } /* Determine which queue to get free packet from */ hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]); type = ntohs(hdr->type); - queue = nia_data.unk_hdr; for (i = 0; i < nia_data.ptt_n; i++) { if (nia_data.ptt_proto[i] == type) { @@ -1113,17 +1235,20 @@ loop: } /* Try to grab place to save packet */ - if (nia_getq(queue, &nia_data.rec_entry) == 0) { + if (nia_getq(queue, &nia_data.rec_entry) == 0) + return SCPE_OK; /* Could not get lock, try later */ + + if (nia_data.rec_entry == 0) { + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA drop packet\n"); + nia_data.r_pkt = 0; /* Drop packet it queue empty */ + if (queue == nia_data.unk_hdr) + nia_data.pcnt[NIA_CNT_DUN]++; + else + nia_data.pcnt[NIA_CNT_D01 + i]++; + nia_data.pcnt[NIA_CNT_UBU] += nia_data.rec_buff.len; return SCPE_OK; } - if (nia_data.rec_entry == 0) { - if (queue == nia_data.unk_hdr) { - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA drop packet\n"); - nia_data.r_pkt = 0; /* Drop packet it queue empty */ - } - return SCPE_OK; - } /* Got one, now fill in data */ M[nia_data.rec_entry + 3] = (uint64)(NIA_CMD_RCV << 12); (void)nia_cpy_from(&nia_unit[0], nia_data.rec_entry + 5, (uint8 *)&hdr->dest, sizeof(ETH_MAC)); @@ -1145,20 +1270,12 @@ loop: } for(i = 0; i < 10; i++) - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA recv: %d %09llx %012llo\n", i, M[nia_data.rec_entry + i], - M[nia_data.rec_entry + i]); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA recv: %d %09llx %012llo\n", i, M[nia_data.rec_entry + i], + M[nia_data.rec_entry + i]); /* Put on response queue */ if (nia_putq(&nia_unit[0], nia_data.resp_hdr, &nia_data.rec_entry) == 0) - return SCPE_OK; + return SCPE_OK; /* Could not get lock, try again */ nia_data.r_pkt = 0; - goto loop; -// return SCPE_OK; -} - -t_stat nia_tim_srv(UNIT * uptr) -{ - sim_clock_coschedule(uptr, 1000); /* continue poll */ - return SCPE_OK; } @@ -1262,8 +1379,7 @@ t_stat nia_detach(UNIT* uptr) free(uptr->filename); uptr->filename = NULL; uptr->flags &= ~UNIT_ATT; - sim_cancel (uptr+1); /* stop the packet timing services */ - sim_cancel (uptr+2); /* stop the clock timer services */ + sim_cancel (uptr+1); /* stop the packet receiving services */ } return SCPE_OK; } @@ -1271,7 +1387,7 @@ t_stat nia_detach(UNIT* uptr) t_stat nia_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) { fprintf (st, "NIA interface\n\n"); -fprintf (st, "The IMP acted as an interface to the early internet. "); +fprintf (st, "The NIA interfaces to the network. Setting MAC defines default MAC address\n"); fprint_set_help (st, dptr); fprint_show_help (st, dptr); eth_attach_help(st, dptr, uptr, flag, cptr); From 2b49d85421aa0c633adf593a9c0a780e82173167 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 14 Feb 2020 18:41:56 -0500 Subject: [PATCH 89/98] SCP: Updated to current. --- display/display.c | 12 + display/display.h | 5 + sim_disk.c | 563 ++++++++++++++++++++++++++++++++++++++++++---- sim_rev.h | 8 + sim_video.c | 191 +++++++++++++++- sim_video.h | 3 + 6 files changed, 736 insertions(+), 46 deletions(-) diff --git a/display/display.c b/display/display.c index 5ad0691..22efa6e 100644 --- a/display/display.c +++ b/display/display.c @@ -975,6 +975,18 @@ display_init(enum display_type type, int sf, void *dptr) fprintf(stderr, "Display initialization failed\r\n"); return 0; } + +void +display_close(void *dptr) +{ + if (!initialized) + return; + + free (points); + ws_shutdown(); + + initialized = 0; +} void display_reset(void) diff --git a/display/display.h b/display/display.h index 391bf4e..239d102 100644 --- a/display/display.h +++ b/display/display.h @@ -65,6 +65,11 @@ enum display_type { */ extern int display_init(enum display_type, int scale, void *dptr); +/* + * close display + */ +extern void display_close(void *dptr); + /* return size of virtual display */ extern int display_xpoints(void); extern int display_ypoints(void); diff --git a/sim_disk.c b/sim_disk.c index a66dc1c..346a8de 100644 --- a/sim_disk.c +++ b/sim_disk.c @@ -1241,12 +1241,10 @@ if (Scb->scb_b_bitmapblks < 127) ret_val = (((t_offset)Scb->scb_r_blocks[Scb->scb_b_bitmapblks].scb_w_freeblks << 16) + Scb->scb_r_blocks[Scb->scb_b_bitmapblks].scb_w_freeptr) * 512; else ret_val = (((t_offset)Scb->scb_r_blocks[0].scb_w_freeblks << 16) + Scb->scb_r_blocks[0].scb_w_freeptr) * 512; -if (!sim_quiet) { - sim_printf ("%s%d: '%s' Contains an ODS1 File system\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename); - sim_printf ("%s%d: Volume Name: %12.12s ", sim_dname (dptr), (int)(uptr-dptr->units), Home.hm1_t_volname); - sim_printf ("Format: %12.12s ", Home.hm1_t_format); - sim_printf ("Sectors In Volume: %u\n", (uint32)(ret_val / 512)); - } +sim_messagef (SCPE_OK, "%s%d: '%s' Contains an ODS1 File system\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename); +sim_messagef (SCPE_OK, "%s%d: Volume Name: %12.12s ", sim_dname (dptr), (int)(uptr-dptr->units), Home.hm1_t_volname); +sim_messagef (SCPE_OK, "Format: %12.12s ", Home.hm1_t_format); +sim_messagef (SCPE_OK, "Sectors In Volume: %u\n", (uint32)(ret_val / 512)); Return_Cleanup: uptr->capac = saved_capac; @@ -1297,10 +1295,8 @@ for (i = 0; i < 8; i++) { max_lbn_partnum = i; } } -if (!sim_quiet) { - sim_printf ("%s%d: '%s' Contains Ultrix partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename); - sim_printf ("Partition with highest sector: %c, Sectors On Disk: %u\n", 'a' + max_lbn_partnum, max_lbn); - } +sim_messagef (SCPE_OK, "%s%d: '%s' Contains Ultrix partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename); +sim_messagef (SCPE_OK, "Partition with highest sector: %c, Sectors On Disk: %u\n", 'a' + max_lbn_partnum, max_lbn); ret_val = ((t_offset)max_lbn) * 512; Return_Cleanup: @@ -1308,6 +1304,475 @@ uptr->capac = saved_capac; return ret_val; } +#pragma pack(push,1) +/* + * The first logical block of device cluster 1 is either: + * 1. MFD label entry (RSTS versions through 7.x) + * 2. Disk Pack label (RSTS version 8.0 and later) + */ +typedef struct _RSTS_MFDLABEL { + uint16 ml_ulnk; + uint16 ml_mbm1; + uint16 ml_reserved1; + uint16 ml_reserved2; + uint16 ml_pcs; + uint16 ml_pstat; + uint16 ml_packid[2]; + } RSTS_MFDLABEL; + +typedef struct _RSTS_PACKLABEL { + uint16 pk_mb01; + uint16 pk_mbm1; + uint16 pk_mdcn; + uint16 pk_plvl; +#define PK_LVL0 0000 +#define PK_LVL11 0401 +#define PK_LVL12 0402 + uint16 pk_ppcs; + uint16 pk_pstat; +#define PK_UC_NEW 0020000 + uint16 pk_packid[2]; + uint16 pk_tapgvn[2]; + uint16 pk_bckdat; + uint16 pk_bcktim; + } RSTS_PACKLABEL; + +typedef union _RSTS_ROOT { + RSTS_MFDLABEL rt_mfd; + RSTS_PACKLABEL rt_pack; + uint8 rt_block[512]; + } RSTS_ROOT; + +typedef struct _RSTS_MFDBLOCKETTE { + uint16 mb_ulnk; + uint16 mb_mbm1; + uint16 mb_reserved1; + uint16 mb_reserved2; + uint16 mb_reserved3; + uint16 mb_malnk; + uint16 mb_lppn; + uint16 mb_lid; +#define MB_ID 0051064 + } RSTS_MFDBLOCKETTE; +#define IS_VALID_RSTS_MFD(b) \ + ((((b)->mb_ulnk == 0) || ((b)->mb_ulnk == 1)) && \ + ((b)->mb_mbm1 == 0177777) && \ + ((b)->mb_reserved1 == 0) && \ + ((b)->mb_reserved2 == 0) && \ + ((b)->mb_reserved3 == 0) && \ + ((b)->mb_lppn == 0177777) && \ + ((b)->mb_lid == MB_ID)) + +typedef struct _RSTS_GFDBLOCKETTE { + uint16 gb_ulnk; + uint16 gb_mbm1; + uint16 gb_reserved1; + uint16 gb_reserved2; + uint16 gb_reserved3; + uint16 gb_reserved4; + uint16 gb_lppn; + uint16 gb_lid; +#define GB_ID 0026264 + } RSTS_GFDBLOCKETTE; +#define IS_VALID_RSTS_GFD(b, g) \ + ((((b)->gb_ulnk == 0) || ((b)->gb_ulnk == 1)) && \ + ((b)->gb_mbm1 == 0177777) && \ + ((b)->gb_reserved1 == 0) && \ + ((b)->gb_reserved2 == 0) && \ + ((b)->gb_reserved3 == 0) && \ + ((b)->gb_reserved4 == 0) && \ + ((b)->gb_lppn == (((g) << 8) | 0377)) && \ + ((b)->gb_lid == GB_ID)) + +typedef struct _RSTS_UFDBLOCKETTE { + uint16 ub_ulnk; + uint16 ub_mbm1; + uint16 ub_reserved1; + uint16 ub_reserved2; + uint16 ub_reserved3; + uint16 ub_reserved4; + uint16 ub_lppn; + uint16 ub_lid; +#define UB_ID 0102064 + } RSTS_UFDBLOCKETTE; +#define IS_VALID_RSTS_UFD(b, g, u) \ + (((b)->ub_mbm1 == 0177777) && \ + ((b)->ub_reserved1 == 0) && \ + ((b)->ub_reserved2 == 0) && \ + ((b)->ub_reserved3 == 0) && \ + ((b)->ub_reserved4 == 0) && \ + ((b)->ub_lppn == (((g) << 8) | (u))) && \ + ((b)->ub_lid == UB_ID)) + +typedef struct _RSTS_UNAME { + uint16 un_ulnk; + uint16 un_unam; + uint16 un_reserved1; + uint16 un_reserved2; + uint16 un_ustat; + uint16 un_uacnt; + uint16 un_uaa; + uint16 un_uar; + } RSTS_UNAME; + +typedef struct _RSTS_FNAME { + uint16 fn_ulnk; + uint16 fn_unam[3]; + uint16 fn_ustat; + uint16 fn_uacnt; + uint16 fn_uaa; + uint16 fn_uar; + } RSTS_FNAME; + +typedef struct _RSTS_ACNT { + uint16 ac_ulnk; + uint16 ac_udla; + uint16 ac_usiz; + uint16 ac_udc; + uint16 ac_utc; + uint16 ac_urts[2]; + uint16 ac_uclus; + } RSTS_ACNT; + +typedef struct _RSTS_RETR { + uint16 rt_ulnk; + uint16 rt_uent[7]; +#define RT_ENTRIES 7 + } RSTS_RETR; + +typedef struct _RSTS_DCMAP { + uint16 dc_clus; +#define DC_MASK 0077777 + uint16 dc_map[7]; + } RSTS_DCMAP; + +/* + * Directory link definitions + */ +#define DL_USE 0000001 +#define DL_BAD 0000002 +#define DL_CHE 0000004 +#define DL_CLN 0000010 +#define DL_ENO 0000760 +#define DL_CLO 0007000 +#define DL_BLO 0170000 + +#define DLSH_ENO 4 +#define DLSH_CLO 9 +#define DLSH_BLO 12 + +#define BLOCKETTE_SZ (8 * sizeof(uint16)) +#define MAP_OFFSET (31 * BLOCKETTE_SZ) + +#define SATT0 0073374 +#define SATT1 0076400 +#define SATT2 0075273 + +#pragma pack(pop) + +typedef struct _rstsContext { + UNIT *uptr; + int dcshift; + int pcs; + char packid[8]; + t_seccnt sects; + RSTS_DCMAP map; +} rstsContext; + +static char rad50[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ$.%0123456789"; + +static void r50Asc(uint16 val, char *buf) +{ +buf[2] = rad50[val % 050]; +val /= 050; +buf[1] = rad50[val % 050]; +buf[0] = rad50[val / 050]; +} + +static t_stat rstsReadBlock(rstsContext *context, uint16 cluster, uint16 block, void *buf) +{ +t_lba blk = (cluster << context->dcshift) + block; +t_seccnt sects_read; + +if ((sim_disk_rdsect(context->uptr, blk * context->sects, (uint8 *)buf, §s_read, context->sects) == SCPE_OK) && + (sects_read == context->sects)) + return SCPE_OK; + +return SCPE_IOERR; +} + +static t_stat rstsReadBlockette(rstsContext *context, uint16 link, void *buf) +{ +uint16 block = (link & DL_BLO) >> DLSH_BLO; +uint16 dcn = (link & DL_CLO) >> DLSH_CLO; +uint16 blockette = (link & DL_ENO) >> DLSH_ENO; +uint8 temp[512]; + +if ((dcn != 7) && (blockette != 31) && + (block <= (context->map.dc_clus & DC_MASK))) { + if (rstsReadBlock(context, context->map.dc_map[dcn], block, temp) == SCPE_OK) { + memcpy(buf, &temp[blockette * BLOCKETTE_SZ], BLOCKETTE_SZ); + return SCPE_OK; + } + } +return SCPE_IOERR; +} + +static t_stat rstsFind01UFD(rstsContext *context, uint16 *ufd, uint16 *level) +{ +uint16 dcs = 1 << context->dcshift; +RSTS_ROOT root; +uint16 buf[256]; + +if (rstsReadBlock(context, 1, 0, &root) == SCPE_OK) { + /* + * First validate fields which are common to both the MFD label and + * Pack label - we'll use Pack label offsets here. + */ + if ((root.rt_pack.pk_mbm1 == 0177777) && (root.rt_pack.pk_ppcs >= dcs)) { + char ch, *tmp = &context->packid[1]; + uint16 mfd, gfd; + + context->pcs = root.rt_pack.pk_ppcs; + + r50Asc(root.rt_pack.pk_packid[0], &context->packid[0]); + r50Asc(root.rt_pack.pk_packid[1], &context->packid[3]); + context->packid[6] = '\0'; + + /* + * The Pack ID must consist of 1 - 6 alphanumeric characters + * padded at the end with spaces. + */ + if (!isalnum(context->packid[0])) + return SCPE_IOERR; + + while ((ch = *tmp++) != 0) { + if (!isalnum(ch)) { + if (ch != ' ') + return SCPE_IOERR; + + while (*tmp) + if (*tmp++ != ' ') + return SCPE_IOERR; + break; + } + } + + /* + * Determine the pack revision level and, therefore, the path to + * [0,1]satt.sys which will allow us to determine the size of the + * pack used by RSTS. + */ + if ((root.rt_pack.pk_pstat & PK_UC_NEW) == 0) { + uint16 link = root.rt_mfd.ml_ulnk; + RSTS_UNAME uname; + + /* + * Old format used by RSTS up through V07.x + */ + if (dcs > 16) + return SCPE_IOERR; + + *level = PK_LVL0; + + memcpy(&context->map, &root.rt_block[MAP_OFFSET], BLOCKETTE_SZ); + + /* + * Scan the MFD name entries looking for [0,1]. Note there will + * always be at least 1 entry. + */ + do { + if (rstsReadBlockette(context, link, &uname) != SCPE_OK) + break; + + if (uname.un_unam == ((0 << 8) | 1)) { + *ufd = uname.un_uar; + return SCPE_OK; + } + } while ((link = uname.un_ulnk) != 0); + } + else { + /* + * New format used by RSTS V08 and later + */ + switch (root.rt_pack.pk_plvl) { + case PK_LVL11: + if (dcs > 16) + return SCPE_IOERR; + break; + + case PK_LVL12: + if (dcs > 64) + return SCPE_IOERR; + break; + + default: + return SCPE_IOERR; + } + *level = root.rt_pack.pk_plvl; + + mfd = root.rt_pack.pk_mdcn; + + if (rstsReadBlock(context, mfd, 0, buf) == SCPE_OK) { + if (IS_VALID_RSTS_MFD((RSTS_MFDBLOCKETTE *)buf)) { + if (rstsReadBlock(context, mfd, 1, buf) == SCPE_OK) + if ((gfd = buf[0]) != 0) + if (rstsReadBlock(context, gfd, 0, buf) == SCPE_OK) + if (IS_VALID_RSTS_GFD((RSTS_GFDBLOCKETTE *)buf, 0)) { + if (rstsReadBlock(context, gfd, 1, buf) == SCPE_OK) + if ((*ufd = buf[1]) != 0) + return SCPE_OK; + } + } + } + } + } + } +return SCPE_IOERR; +} + +static t_stat rstsLoadAndScanSATT(rstsContext *context, uint16 uaa, uint16 uar, t_offset *result) +{ +t_offset blocks = 0; +uint8 bitmap[8192]; +int i, j; +RSTS_ACNT acnt; +RSTS_RETR retr; + +if (uar != 0) { + if (rstsReadBlockette(context, uaa, &acnt) == SCPE_OK) { + uint16 blocks = acnt.ac_usiz; + uint16 offset = 0; + + memset(bitmap, 0xFF, sizeof(bitmap)); + + if (blocks != 0) { + do { + int i, j; + uint16 fcl; + + if (rstsReadBlockette(context, uar, &retr) != SCPE_OK) + return SCPE_IOERR; + + for (i = 0; i < RT_ENTRIES; i++) { + if ((fcl = retr.rt_uent[i]) == 0) + goto scanBitmap; + + for (j = 0; j < acnt.ac_uclus; j++) { + if ((blocks == 0) || (offset >= sizeof(bitmap))) + goto scanBitmap; + + if (rstsReadBlock(context, fcl, j, &bitmap[offset]) != SCPE_OK) + return SCPE_IOERR; + + offset += 512; + blocks--; + } + } + } while ((uar = retr.rt_ulnk) != 0); + + scanBitmap: + for (i = sizeof(bitmap) - 1; i != 0; i--) + if (bitmap[i] != 0xFF) { + blocks = i * 8; + for (j = 7; j >= 0; j--) + if ((bitmap[i] & (1 << j)) == 0) { + blocks += j + 1; + goto scanDone; + } + } + scanDone: + *result = (blocks + 1) * context->pcs; + return SCPE_OK; + } + } + } +return SCPE_IOERR; +} + +static t_offset get_rsts_filesystem_size (UNIT *uptr) +{ +DEVICE *dptr; +t_addr saved_capac; +struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; +t_addr temp_capac = (sim_toffset_64 ? (t_addr)0xFFFFFFFFu : (t_addr)0x7FFFFFFFu); /* Make sure we can access the largest sector */ +uint8 buf[512]; +t_offset ret_val = (t_offset)-1; +rstsContext context; + +if ((dptr = find_dev_from_unit (uptr)) == NULL) + return ret_val; +saved_capac = uptr->capac; +uptr->capac = temp_capac; + +context.uptr = uptr; +context.sects = 512 / ctx->sector_size; + +/* + * Check all possible device cluster sizes + */ +for (context.dcshift = 0; context.dcshift < 8; context.dcshift++) { + uint16 ufd, level; + + /* + * We need to find [0,1]SATT.SYS to compute the actual size of the disk. + * First find the DCN of the [0,1] UFD. + */ + if (rstsFind01UFD(&context, &ufd, &level) == SCPE_OK) { + if (rstsReadBlock(&context, ufd, 0, buf) == SCPE_OK) { + if (IS_VALID_RSTS_UFD((RSTS_UFDBLOCKETTE *)buf, 0, 1)) { + uint16 link = ((RSTS_UFDBLOCKETTE *)buf)->ub_ulnk; + RSTS_FNAME fname; + + memcpy(&context.map, &buf[MAP_OFFSET], BLOCKETTE_SZ); + + /* + * Scan the UFD looking for SATT.SYS - the allocation bitmap + */ + do { + if (rstsReadBlockette(&context, link, &fname) != SCPE_OK) + break; + + if ((fname.fn_unam[0] == SATT0) && + (fname.fn_unam[1] == SATT1) && + (fname.fn_unam[2] == SATT2)) { + if (rstsLoadAndScanSATT(&context, fname.fn_uaa, fname.fn_uar, &ret_val) == SCPE_OK) { + const char *fmt = "???"; + + ret_val *= 512; + + switch (level) { + case PK_LVL0: + fmt = "0.0"; + break; + + case PK_LVL11: + fmt = "1.1"; + break; + + case PK_LVL12: + fmt = "1.2"; + break; + } + + sim_messagef(SCPE_OK, "%s%d: '%s' Contains a RSTS File system\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename); + sim_messagef(SCPE_OK, "%s%d: Pack ID: %6.6s ", sim_dname (dptr), (int)(uptr-dptr->units), context.packid); + sim_messagef(SCPE_OK, "Revision Level: %3s ", fmt); + sim_messagef(SCPE_OK, "Pack Clustersize: %d\n", context.pcs); + sim_messagef(SCPE_OK, "%s%d: Last Unallocated Sector In File System: %u\n", sim_dname (dptr), (int)(uptr-dptr->units), (uint32)(ret_val / 512)); + goto cleanup_done; + } + } + } while ((link = fname.fn_ulnk) != 0); + } + } + } + } +cleanup_done: +uptr->capac = saved_capac; +return ret_val; +} + #pragma pack(push,1) typedef struct _RT11_HomeBlock { uint8 hb_b_bbtable[130]; @@ -1484,29 +1949,27 @@ Next_Partition: Return_Cleanup: if (partitions) { - if (!sim_quiet) { - const char *parttype; + const char *parttype; - switch (version) { - case HB_C_SYSVER_V3A: - parttype = "V3A"; - break; + switch (version) { + case HB_C_SYSVER_V3A: + parttype = "V3A"; + break; - case HB_C_SYSVER_V04: - parttype = "V04"; - break; + case HB_C_SYSVER_V04: + parttype = "V04"; + break; - case HB_C_SYSVER_V05: - parttype = "V05"; - break; + case HB_C_SYSVER_V05: + parttype = "V05"; + break; - default: - parttype = "???"; - break; - } - sim_printf ("%s%d: '%s' Contains RT11 partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename); - sim_printf ("%d valid partition%s, Type: %s, Sectors On Disk: %u\n", partitions, partitions == 1 ? "" : "s", parttype, (uint32)(ret_val / 512)); + default: + parttype = "???"; + break; } + sim_messagef (SCPE_OK, "%s%d: '%s' Contains RT11 partitions\n", sim_dname (dptr), (int)(uptr-dptr->units), uptr->filename); + sim_messagef (SCPE_OK, "%d valid partition%s, Type: %s, Sectors On Disk: %u\n", partitions, partitions == 1 ? "" : "s", parttype, (uint32)(ret_val / 512)); } uptr->capac = saved_capac; return ret_val; @@ -1520,6 +1983,7 @@ static FILESYSTEM_CHECK checks[] = { &get_ods2_filesystem_size, &get_ods1_filesystem_size, &get_ultrix_filesystem_size, + &get_rsts_filesystem_size, &get_rt11_filesystem_size, /* This should be the last entry in the table to reduce the possibility of matching an RT-11 @@ -2129,19 +2593,36 @@ fprintf (st, "was created. This metadata is therefore available whenever that V fprintf (st, "attached to an emulated disk device in the future so the device type and\n"); fprintf (st, "size can be automatically be configured.\n\n"); -if (0 == (uptr-dptr->units)) { - if (dptr->numunits > 1) { - uint32 i; +if (dptr->numunits > 1) { + uint32 i, attachable_count = 0, out_count = 0, skip_count; - for (i=0; i < dptr->numunits; ++i) - if (dptr->units[i].flags & UNIT_ATTABLE) - fprintf (st, " sim> ATTACH {switches} %s%d diskfile\n", dptr->name, i); + for (i=0; i < dptr->numunits; ++i) + if ((dptr->units[i].flags & UNIT_ATTABLE) && + !(dptr->units[i].flags & UNIT_DIS)) + ++attachable_count; + for (i=0; (i < dptr->numunits) && (out_count < 2); ++i) + if ((dptr->units[i].flags & UNIT_ATTABLE) && + !(dptr->units[i].flags & UNIT_DIS)) { + fprintf (st, " sim> ATTACH {switches} %s%d diskfile\n", dptr->name, i); + ++out_count; + } + if (attachable_count > 4) { + fprintf (st, " .\n"); + fprintf (st, " .\n"); + fprintf (st, " .\n"); } - else - fprintf (st, " sim> ATTACH {switches} %s diskfile\n", dptr->name); + skip_count = attachable_count - 2; + for (i=0; i < dptr->numunits; ++i) + if ((dptr->units[i].flags & UNIT_ATTABLE) && + !(dptr->units[i].flags & UNIT_DIS)) { + if (skip_count == 0) + fprintf (st, " sim> ATTACH {switches} %s%d diskfile\n", dptr->name, i); + else + --skip_count; + } } else - fprintf (st, " sim> ATTACH {switches} %s diskfile\n\n", dptr->name); + fprintf (st, " sim> ATTACH {switches} %s diskfile\n", dptr->name); fprintf (st, "\n%s attach command switches\n", dptr->name); fprintf (st, " -R Attach Read Only.\n"); fprintf (st, " -E Must Exist (if not specified an attempt to create the indicated\n"); @@ -2183,9 +2664,7 @@ fprintf (st, " sim> att rq2 -f vhd RA92.vhd\n"); fprintf (st, " RQ2: creating new file\n"); fprintf (st, " sim> sho rq2\n"); fprintf (st, " RQ2, 1505MB, attached to RA92.vhd, write enabled, RA92, autosize, VHD format\n"); -fprintf (st, " sim> ! dir RA92.vhd\n"); -fprintf (st, " Volume in drive H is New Volume\n"); -fprintf (st, " Volume Serial Number is F8DE-510C\n\n"); +fprintf (st, " sim> dir RA92.vhd\n"); fprintf (st, " Directory of H:\\Data\n\n"); fprintf (st, " 04/14/2011 12:57 PM 5,120 RA92.vhd\n"); fprintf (st, " 1 File(s) 5,120 bytes\n"); @@ -2196,9 +2675,7 @@ fprintf (st, " RQ3: Copied 1505MB. 99%% complete.\n"); fprintf (st, " RQ3: Copied 1505MB. Done.\n"); fprintf (st, " sim> sh rq3\n"); fprintf (st, " RQ3, 1505MB, attached to RA92-1.vhd, write enabled, RA92, autosize, VHD format\n"); -fprintf (st, " sim> ! dir RA92*\n"); -fprintf (st, " Volume in drive H is New Volume\n"); -fprintf (st, " Volume Serial Number is F8DE-510C\n\n"); +fprintf (st, " sim> dir RA92*\n"); fprintf (st, " Directory of H:\\Data\n\n"); fprintf (st, " 04/14/2011 01:12 PM 5,120 RA92-1.vhd\n"); fprintf (st, " 04/14/2011 12:58 PM 5,120 RA92.vhd\n"); diff --git a/sim_rev.h b/sim_rev.h index 02bc902..fe4a642 100644 --- a/sim_rev.h +++ b/sim_rev.h @@ -48,6 +48,14 @@ #include ".git-commit-id.h" #endif +/* + Simh's git commit id would be undefined when working with an + extracted archive (zip file or tar ball). To address this + problem and record the commit id that the archive was created + from, the archive creation process populates the below + information as a consequence of the "sim_rev.h export-subst" + line in the .gitattributes file. + */ #if !defined(SIM_GIT_COMMIT_ID) #define SIM_GIT_COMMIT_ID $Format:%H$ #define SIM_GIT_COMMIT_TIME $Format:%aI$ diff --git a/sim_video.c b/sim_video.c index fe9d6cb..a4fedf4 100644 --- a/sim_video.c +++ b/sim_video.c @@ -37,6 +37,10 @@ t_bool vid_mouse_b1 = FALSE; t_bool vid_mouse_b2 = FALSE; t_bool vid_mouse_b3 = FALSE; static VID_QUIT_CALLBACK vid_quit_callback = NULL; +static VID_GAMEPAD_CALLBACK motion_callback[10]; +static VID_GAMEPAD_CALLBACK button_callback[10]; +static int vid_gamepad_inited = 0; +static int vid_gamepad_ok = 0; /* Or else just joysticks. */ t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback) { @@ -44,6 +48,41 @@ vid_quit_callback = callback; return SCPE_OK; } +static t_stat register_callback (void **array, int n, void *callback) +{ + int i, j = -1; + + if (!vid_gamepad_inited) { + return SCPE_NOATT; + } + + for (i = 0; i < n; i++) { + if (array[i] == callback) + return SCPE_ALATT; + if (array[i] == NULL) + j = i; + } + + if (j != -1) { + array[j] = callback; + return SCPE_OK; + } + + return SCPE_NXM; +} + +t_stat vid_register_gamepad_motion_callback (VID_GAMEPAD_CALLBACK callback) +{ + int n = sizeof (motion_callback) / sizeof (callback); + return register_callback ((void **)motion_callback, n, (void *)callback); +} + +t_stat vid_register_gamepad_button_callback (VID_GAMEPAD_CALLBACK callback) +{ + int n = sizeof (button_callback) / sizeof (callback); + return register_callback ((void **)button_callback, n, (void *)callback); +} + t_stat vid_show (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc) { return vid_show_video (st, uptr, val, desc); @@ -510,6 +549,64 @@ return SCPE_OK; } #endif +static t_stat vid_init_controllers (void) +{ + SDL_Joystick *y; + SDL_version ver; + int i, n; + + if (vid_gamepad_inited) + return SCPE_OK; + + /* Chech that the SDL_GameControllerFromInstanceID function is + available at run time. */ + SDL_GetVersion(&ver); + vid_gamepad_ok = (ver.major > 2 || + (ver.major == 2 && (ver.minor > 0 || ver.patch >= 4))); + + SDL_InitSubSystem(SDL_INIT_JOYSTICK); + if (vid_gamepad_ok) + SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); + + if (SDL_JoystickEventState (SDL_ENABLE) < 0) { + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + return SCPE_IOERR; + } + + if (vid_gamepad_ok && SDL_GameControllerEventState (SDL_ENABLE) < 0) { + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + return SCPE_IOERR; + } + + n = SDL_NumJoysticks(); + + for (i = 0; i < n; i++) { + if (vid_gamepad_ok && SDL_IsGameController (i)) { + SDL_GameController *x = SDL_GameControllerOpen (i); + if (x != NULL) { + sim_debug (SIM_VID_DBG_VIDEO, vid_dev, + "Game controller: %s\n", SDL_GameControllerNameForIndex(i)); + } + } + else { + y = SDL_JoystickOpen (i); + if (y != NULL) { + sim_debug (SIM_VID_DBG_VIDEO, vid_dev, + "Joystick: %s\n", SDL_JoystickNameForIndex(i)); + sim_debug (SIM_VID_DBG_VIDEO, vid_dev, + "Number of axes: %d, buttons: %d\n", + SDL_JoystickNumAxes(y), + SDL_JoystickNumButtons(y)); + } + } + } + + vid_gamepad_inited = 1; + return SCPE_OK; +} + t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, int flags) { if (!vid_active) { @@ -538,10 +635,18 @@ if (!vid_active) { vid_dev = dptr; + memset (motion_callback, 0, sizeof motion_callback); + memset (button_callback, 0, sizeof button_callback); + stat = vid_create_window (); if (stat != SCPE_OK) return stat; + if (vid_init_controllers () != SCPE_OK) { + sim_debug (SIM_VID_DBG_VIDEO, vid_dev, + "vid_open() - Failed initializing game controllers\n"); + } + sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_open() - Success\n"); } return SCPE_OK; @@ -553,6 +658,12 @@ if (vid_active) { SDL_Event user_event; int status; + vid_gamepad_inited = 0; + memset (motion_callback, 0, sizeof motion_callback); + memset (button_callback, 0, sizeof button_callback); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER); + vid_active = FALSE; if (vid_ready) { sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_close()\n"); @@ -1149,6 +1260,61 @@ switch (key) { } } +void vid_joy_motion (SDL_JoyAxisEvent *event) +{ + int n = sizeof motion_callback / sizeof (VID_GAMEPAD_CALLBACK); + int i; + + for (i = 0; i < n; i++) { + if (motion_callback[i]) { + motion_callback[i](event->which, event->axis, event->value); + } + } +} + +void vid_joy_button (SDL_JoyButtonEvent *event) +{ + int n = sizeof button_callback / sizeof (VID_GAMEPAD_CALLBACK); + int i; + + for (i = 0; i < n; i++) { + if (button_callback[i]) { + button_callback[i](event->which, event->button, event->state); + } + } +} + +void vid_controller_motion (SDL_ControllerAxisEvent *event) +{ + SDL_JoyAxisEvent e; + e.which = event->which; + e.axis = event->axis; + e.value = event->value; + vid_joy_motion (&e); +} + +void vid_controller_button (SDL_ControllerButtonEvent *event) +{ + /* SDL_GameControllerFromInstanceID is only available from SDL + version 2.0.4, so check the version at compile time. The + version is also checked at run time. */ +#if (SDL_MAJOR_VERSION > 2) || (SDL_MAJOR_VERSION == 2 && \ + (SDL_MINOR_VERSION > 0) || (SDL_PATCHLEVEL >= 4)) + + SDL_JoyButtonEvent e; + SDL_GameControllerButtonBind b; + SDL_GameController *c; + SDL_GameControllerButton button = (SDL_GameControllerButton)event->button; + + c = SDL_GameControllerFromInstanceID (event->which); + b = SDL_GameControllerGetBindForButton (c, button); + e.which = event->which; + e.button = b.value.button; + e.state = event->state; + vid_joy_button (&e); +#endif +} + void vid_key (SDL_KeyboardEvent *event) { SIM_KEY_EVENT ev; @@ -1691,17 +1857,36 @@ while (vid_active) { case SDL_KEYDOWN: case SDL_KEYUP: - vid_key ((SDL_KeyboardEvent*)&event); + vid_key (&event.key); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: - vid_mouse_button ((SDL_MouseButtonEvent*)&event); + vid_mouse_button (&event.button); break; case SDL_MOUSEMOTION: - vid_mouse_move ((SDL_MouseMotionEvent*)&event); + vid_mouse_move (&event.motion); break; + + case SDL_JOYAXISMOTION: + vid_joy_motion (&event.jaxis); + break; + + case SDL_JOYBUTTONUP: + case SDL_JOYBUTTONDOWN: + vid_joy_button (&event.jbutton); + break; + + case SDL_CONTROLLERAXISMOTION: + vid_controller_motion (&event.caxis); + break; + + case SDL_CONTROLLERBUTTONUP: + case SDL_CONTROLLERBUTTONDOWN: + vid_controller_button (&event.cbutton); + break; + #if SDL_MAJOR_VERSION != 1 case SDL_WINDOWEVENT: if (event.window.windowID == vid_windowID) { diff --git a/sim_video.h b/sim_video.h index 47bb8bb..d1c0497 100644 --- a/sim_video.h +++ b/sim_video.h @@ -180,6 +180,9 @@ t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, i /* code responsible for cursor display in video) */ typedef void (*VID_QUIT_CALLBACK)(void); t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback); +typedef void (*VID_GAMEPAD_CALLBACK)(int, int, int); +t_stat vid_register_gamepad_motion_callback (VID_GAMEPAD_CALLBACK); +t_stat vid_register_gamepad_button_callback (VID_GAMEPAD_CALLBACK); t_stat vid_close (void); t_stat vid_poll_kb (SIM_KEY_EVENT *ev); t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev); From a5a63ac7b2c98620089905b1b3ef021c8b79db71 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 14 Feb 2020 18:44:14 -0500 Subject: [PATCH 90/98] KA10: Cleanup debugging code. --- PDP10/kx10_cpu.c | 168 ++++++++++------------------------------------- PDP10/kx10_sys.c | 12 ++-- PDP10/kx10_tu.c | 2 +- 3 files changed, 45 insertions(+), 137 deletions(-) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 1df9a8b..b4223e1 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -1179,12 +1179,24 @@ t_stat dev_pi(uint32 dev, uint64 *data) { if (dev & 040) { /* SBDIAG */ AB = (AB + 1) & RMASK; res = 0; - if (((*data >> 31) & 037) == 010) { - switch(*data & 037) { - case 0: res = 06000000000LL; break; - case 1: res = 0500000000LL; break; - case 2: res = 0; break; - default: res = 0; break; + if (((*data >> 31) & 030) == 010) { + int mc = MEMSIZE / 262144; + int c = (*data >> 31) & 07; + int s = 0; + if (c < mc) { + switch(*data & 037) { + case 0: res = 06000000000LL; break; + case 1: res = 00500000000LL; break; + case 2: res = 0; break; + case 012: + res = 0; + s = (int)(0176000 & *data) << 6; + s /= 262144; + if (s != c) + res = 010000000LL; + break; + default: res = 0; break; + } } } MB = res; @@ -1996,7 +2008,6 @@ load_tlb(int uf, int page, int wr) pg = (page & 0377) >> 2; /* 2 1024 word page entries */ sim_interval--; data = M[dbr + pg]; -//fprintf(stderr, "Load page %06o dbr%012llo pg%06o data=%012llo -> ", page, dbr, pg, data); if ((page & 02) == 0) data &= ~0160000000000LL; else @@ -2033,7 +2044,6 @@ load_tlb(int uf, int page, int wr) e_tlb[(page & 0776)|1] = pg|1; data = e_tlb[page]; } -//fprintf(stderr, " %06o %06o\n\r", pg, pg | 1); } else #endif #define PG_PUB 0040000 @@ -2061,7 +2071,6 @@ load_tlb(int uf, int page, int wr) int base = 0540; #endif -//fprintf(stderr, "Lookup Page %o %03o u=%o w=%o %06o\r\n", sect, page, uf, wr, AB); /* Get segment pointer */ /* And save it */ if (QKLB) @@ -2071,7 +2080,6 @@ load_tlb(int uf, int page, int wr) data = M[ub_ptr + base]; else data = M[eb_ptr + base]; -//fprintf(stderr, "Map %06o %03o %012llo %012llo %012llo\n\r", base, sect, data, spt, cst); /* Find correct page table */ sect_loop: switch ((data >> 33) & 07) { @@ -2091,7 +2099,6 @@ sect_loop: sim_interval--; index = data & RMASK; data = M[index + spt]; -//fprintf(stderr, "SMap1 %012llo %o %o\n\r", data, index, index + spt); break; case 3: /* Indirect page */ @@ -2099,7 +2106,6 @@ sect_loop: index = (data >> 18) & PG_IDX; sim_interval--; data = M[(data & RMASK) + spt]; -//fprintf(stderr, "IMap1 %012llo %o %o %o\n\r", data, pg << 9, index, page); if ((data & PG_STG) != 0) { fault_data = 0; page_fault = 1; @@ -2108,7 +2114,6 @@ sect_loop: pg = data & PG_PAG; sim_interval--; data = M[(pg << 9) | index]; -//fprintf(stderr, "JMap1 %012llo %o %o %o\n\r", data, pg << 9, index, page); goto sect_loop; } if ((data & PG_STG) != 0) { @@ -2116,14 +2121,12 @@ sect_loop: page_fault = 1; return 0; } -//fprintf(stderr, "XMap %012llo\n\r", data); pg = data & PG_PAG; /* Update CST entry if needed */ if (cst) { sim_interval--; cst_val = M[cst + pg]; -//fprintf(stderr, "ZMap %08o %012llo %012llo age\n\r", cst+pg, data, cst_val); if ((cst_val & PG_AGE) == 0) { fault_data = 0; page_fault = 1; @@ -2135,7 +2138,6 @@ sect_loop: /* Get address of page */ sim_interval--; data = M[(pg << 9) | page]; -//fprintf(stderr, "YMap %012llo %o %o\n\r", data, pg << 9, page); pg_loop: /* Decode map pointer */ @@ -2156,7 +2158,6 @@ pg_loop: sim_interval--; index = data & RMASK; data = M[index + spt]; -//fprintf(stderr, "SMap2 %012llo %o %o\n\r", data, index, index + spt); break; case 3: /* Indirect page */ @@ -2164,7 +2165,6 @@ pg_loop: index = (data >> 18) & PG_IDX; sim_interval--; data = M[(data & RMASK) + spt]; -//fprintf(stderr, "IMap2 %012llo %o %o %o\n\r", data, pg << 9, index, page); if ((data & PG_STG) != 0) { fault_data = 0; page_fault = 1; @@ -2173,7 +2173,6 @@ pg_loop: pg = data & RMASK; sim_interval--; data = M[(pg << 9) | index]; -//fprintf(stderr, "JMap %012llo %o %o %o\n\r", data, pg << 9, index, page); goto pg_loop; } @@ -2189,7 +2188,6 @@ pg_loop: if (cst) { sim_interval--; cst_val = M[cst + pg]; -//fprintf(stderr, "CMap %08o %012llo %012llo age\n\r", cst + pg, data, cst_val); if ((cst_val & PG_AGE) == 0) { fault_data = 0; page_fault = 1; @@ -2199,7 +2197,6 @@ pg_loop: if (wr) cst_val |= 1; } else if (wr) { /* Trying to write and not writable */ -//fprintf(stderr, "WMap %012llo %012llo age\n\r", data, cst_val); fault_data = 0 /* Write fault */; page_fault = 1; return 0; @@ -2227,13 +2224,12 @@ pg_loop: if (acc_bits & PG_CAC) data |= KL_PAG_C; if (QKLB) - data |= (sect & 037) << 18; + data |= (sect & 037) << 18; /* And save it */ if (uf) u_tlb[page] = data & (SECTM|RMASK); else e_tlb[page] = data & (SECTM|RMASK); -//fprintf(stderr, "Page %03o %08o %o\r\n", page, data, uf); } else { /* Map the page */ @@ -2304,8 +2300,6 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int uf = 0; sect = 0; } else if (xct_flag != 0 && !fetch) { -//fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o w=%o", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg, wr); -//fprintf(stderr, " s%o %o", sect, glb_sect); if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || @@ -2314,14 +2308,10 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int pub = (FLAGS & PRV_PUB) != 0; if ((xct_flag & 014) == 04 && !ptr_flg && glb_sect == 0) -// if (QKLB && (!glb_sect /*|| ((xct_flag & 4) != 0 && prev_sect == 0)*/) && !extend) sect = prev_sect; if ((xct_flag & 03) == 01 && BYF5 && glb_sect == 0) -// if (QKLB && (!glb_sect /*|| ((xct_flag & 4) != 0 && prev_sect == 0)*/) && !extend) sect = prev_sect; -//fprintf(stderr, " ps=%o os%o", prev_sect, sect); } -//fprintf(stderr, " %o %o\n\r", uf, pub); } /* Check if invalid section */ @@ -2329,7 +2319,6 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fault_data = (027LL << 30) | (((uint64)sect) << 18) | (uint64)addr; if (uf) /* U */ fault_data |= SMASK; /* BIT0 */ -//fprintf(stderr, "Invalid section %012llo %06o\n\r", fault_data, PC); page_fault = 1; return 0; } @@ -2347,7 +2336,6 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int else data = e_tlb[page]; -//fprintf(stderr, "Map page %06o -> %06o %06o %o\n\r", page, data, sect, flag); if (QKLB && t20_page && ((data >> 18) & 037) != sect) data = 0; /* If not valid, go refill it */ @@ -2368,7 +2356,6 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int return 0; if (wr) /* T */ fault_data |= BIT5; /* BIT5 */ -//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o d=%012llo\n\r", addr, (data & KL_PAG_A) == 0, wr, (data & KL_PAG_W) == 0, data, fault_data); return 0; } } @@ -2404,7 +2391,6 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fault_data = ((uint64)addr) | 021LL << 30 | BIT8 |((uf)?SMASK:0); if (QKLB && t20_page) fault_data |= (((uint64)sect) << 18); -//fprintf(stderr, "Public fault %012llo %06o %06o %012llo\n\r", fault_data, FLAGS << 5, PC, data); page_fault = 1; return 0; } @@ -2451,7 +2437,6 @@ int page_lookup(t_addr addr, int flag, t_addr *loc, int wr, int cur_context, int fault_data |= BIT3; /* BIT3 */ if (data & KL_PAG_A) /* A */ fault_data |= BIT2; /* BIT2 */ -//fprintf(stderr, "Page fault %06o a=%o wr=%o w=%o %06o %06o %012llo\n\r", addr, (data & KL_PAG_A) == 0, wr, (data & KL_PAG_W) == 0, data, PC, fault_data); page_fault = 1; return 0; } @@ -2479,23 +2464,19 @@ int Mem_read(int flag, int cur_context, int fetch) { if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { if (xct_flag != 0 && !fetch) { -//fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgr ", IR, PC, AB, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || ((xct_flag & 1) != 0 && !cur_context && BYF5 )) { MB = FM[prev_ctx|AB]; -//fprintf(stderr, "prev \n\r"); return 0; } -//fprintf(stderr, "\n\r"); } /* Check if invalid section */ if (QKLB && t20_page && !flag && (sect & 07740) != 0) { fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); if (USER==0) /* U */ fault_data |= SMASK; /* BIT0 */ -//fprintf(stderr, "Invalid section %012llo\n\r", fault_data); page_fault = 1; return 0; } @@ -2504,7 +2485,6 @@ int Mem_read(int flag, int cur_context, int fetch) { if (!page_lookup(AB, flag, &addr, 0, cur_context, fetch)) return 1; if (addr >= (int)MEMSIZE) { -//fprintf(stderr, "NXM error r %08o\n\r", addr); irq_flags |= 02000; return 1; } @@ -2521,23 +2501,19 @@ int Mem_write(int flag, int cur_context) { if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { if (xct_flag != 0) { -//fprintf(stderr, "PXCT ir=%03o pc=%06o ad=%06o x=%02o c=%o b=%o p=%o rgw ", IR, PC, addr, xct_flag, cur_context, BYF5, ptr_flg); if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || ((xct_flag & 2) != 0 && !cur_context && ptr_flg) || ((xct_flag & 1) != 0 && !cur_context && BYF5 )) { -//fprintf(stderr, "prev \n\r"); FM[prev_ctx|AB] = MB; return 0; } -//fprintf(stderr, "\n\r"); } /* Check if invalid section */ if (QKLB && t20_page && !flag && (sect & 07740) != 0) { fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); if (USER==0) /* U */ fault_data |= SMASK; /* BIT0 */ -//fprintf(stderr, "Invalid section %012llo\n\r", fault_data); page_fault = 1; return 0; } @@ -2546,7 +2522,6 @@ int Mem_write(int flag, int cur_context) { if (!page_lookup(AB, flag, &addr, 1, cur_context, 0)) return 1; if (addr >= (int)MEMSIZE) { -//fprintf(stderr, "NXM error w %08o\n\r", addr); irq_flags |= 02000; return 1; } @@ -2586,7 +2561,7 @@ int exec_page_lookup(t_addr addr, int wr, int *loc) data = e_tlb[page]; /* If not valid, go refill it */ - if (data == 0 || (data & LMASK) != 0) { + if (data == 0 || (data & 037) != 0) { sect = 0; data = load_tlb(upmp, page, wr); if (data == 0) { @@ -2610,7 +2585,6 @@ int Mem_examine_word(int n, int wrd, uint64 *data) { addr = (M[addr+1] + wrd) & RMASK; if (exec_page_lookup(addr, 0, &addr)) return 1; -//fprintf(stderr, "Examine: %06o %012llo\n\r", addr, M[addr]); *data = M[addr]; return 0; } @@ -2626,7 +2600,6 @@ int Mem_deposit_word(int n, int wrd, uint64 *data) { addr = (M[addr+1] + wrd) & RMASK; if (exec_page_lookup(addr, 1, &addr)) return 1; -//fprintf(stderr, "Deposit: %06o %012llo -> %012llo\n\r", addr, M[addr], *data); M[addr] = *data; return 0; } @@ -2647,7 +2620,6 @@ int Mem_read_byte(int n, uint16 *data, int byte) { if (addr >= MEMSIZE) return 0; val = M[addr]; -// fprintf(stderr, "Read: %06o %012llo -> ", addr, val); s = (val >> 24) & 077; p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; if (p & 0400) { @@ -2658,7 +2630,6 @@ int Mem_read_byte(int n, uint16 *data, int byte) { np &= 077; val &= PMASK; val |= (uint64)(np) << 30; -// fprintf(stderr, " %012llo %d %d %d\n\r", val, s, p, np); M[addr] = val; addr = val & RMASK; if (exec_page_lookup((int)(val & RMASK), 0, &addr)) @@ -2667,14 +2638,12 @@ int Mem_read_byte(int n, uint16 *data, int byte) { msk = (uint64)(1) << s; msk--; val = M[addr]; -// fprintf(stderr, "Byte: %06o %012llo %012llo %012llo %d %d %d -> ", addr, val, msk, val >> p, s, p, need); val = (val >> p) & msk; if (s > 8) need -= 16; else need -= 8; *data |= val << need; -// fprintf(stderr, " %012llo %06o \n\r", val, *data); } return s; } @@ -2695,7 +2664,6 @@ int Mem_write_byte(int n, uint16 *data) { val = M[addr]; if (val == 0) return 1; -// fprintf(stderr, "Write: %06o %012llo -> ", addr, val); s = (val >> 24) & 077; p = (((val >> 30) & 077) + (0777 ^ s) + 1) & 0777; if (p & 0400) { @@ -2706,7 +2674,6 @@ int Mem_write_byte(int n, uint16 *data) { np &= 077; val &= PMASK; val |= (uint64)(np) << 30; -// fprintf(stderr, "%06o %012llo %d %d %d\n\r", addr, val, s, p, np); M[addr] = val; addr = val & RMASK; if (exec_page_lookup((int)(val & RMASK), 1, &addr)) @@ -2716,11 +2683,9 @@ int Mem_write_byte(int n, uint16 *data) { msk--; msk <<= p; val = M[addr]; -// fprintf(stderr, "Byte: %06o %012llo %012llo %o %o %o -> ", addr, val, msk, s, p, need); val &= CM(msk); val |= msk & (((uint64)(dat >> (need - s))) << p); M[addr] = val; -// fprintf(stderr, " %012llo %06o \n\r", val, dat); need -= s; } return s; @@ -3886,7 +3851,6 @@ int Mem_read_nopage() { MB = get_reg(AB); } else { if (AB >= (int)MEMSIZE) { -//fprintf(stderr, "NXM non-page error r %08o\n\r", AB); #if KL irq_flags |= 02000; #else @@ -3910,7 +3874,6 @@ int Mem_write_nopage() { set_reg(AB, MB); } else { if (AB >= (int)MEMSIZE) { -//fprintf(stderr, "NXM non-page error w %08o\n\r", AB); #if KL irq_flags |= 02000; #else @@ -4198,7 +4161,6 @@ in_loop: if (QKLB && t20_page && (cur_sect != 0 || glb_sect)) { if (MB & SMASK || cur_sect == 0) { /* Instruction format IFIW */ if (MB & BIT1 && cur_sect != 0) { /* Illegal index word */ -//fprintf(stderr, "Illegal fault %06o %012llo\n\r", PC, MB); fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | (AR & RMASK) | ((uint64)cur_sect << 18); page_fault = 1; @@ -4225,14 +4187,12 @@ in_loop: } MB = AR; } else { -// if (((xct_flag & 014) != 014 || (FLAGS & USER) != 0)) - glb_sect = 0; + glb_sect = 0; if ((MB & RMASK) < 020) sect = cur_sect = 1; AR = MB; } AB = AR & RMASK; -//fprintf(stderr, "LFIW %012llo %o %02o %06o %06o %o\n\r", MB, ind, ix, cur_sect, AB, glb_sect); } else { /* Extended index EFIW */ ind = (MB & BIT1) != 0; ix = (MB >> 30) & 017; @@ -4254,7 +4214,6 @@ in_loop: sect = cur_sect = (AR >> 18) & 07777; AB = AR & RMASK; glb_sect = 1; -//fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", AR, ind, ix, cur_sect, AB); } if (ind) goto in_loop; @@ -4423,7 +4382,7 @@ st_pi: /* Process the instruction */ switch (IR) { -#if KL +#if KL case 0052: /* PMOVE */ case 0053: /* PMOVEM */ if (QKLB && t20_page && (FLAGS & USER) == 0) { @@ -5825,7 +5784,6 @@ unasign: f = 1; SC = _byte_adj[(FE - 37)].s; FE = _byte_adj[(FE - 37)].p; -//fprintf(stderr, "ADJBP > 36 %d %d\n\r", SC, FE); } left = (36 - FE) / SC; /* Number bytes left (36 - P)/S */ bpw = left + (FE / SC); /* Bytes per word */ @@ -5907,7 +5865,6 @@ unasign: #if KL if (QKLB && t20_page && pc_sect != 0 && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; -//fprintf(stderr, "ILDB %012llo %d %d -> %d %d\n\r", AR, SCAD, i, _byte_adj[i].p, _byte_adj[i].s); if (SCAD == 077) goto muuo; SC = _byte_adj[i].s; @@ -5938,7 +5895,6 @@ unasign: AB = (AB + 1) & RMASK; if (Mem_read(0, 0, 0)) goto last; -//fprintf(stderr, "ILBP %o %o %06o %012llo\n\r", SC, SCAD, AB, MB); if (MB & SMASK) { if (MB & BIT1) { fault_data = 024LL << 30 | (((FLAGS & USER) != 0)?SMASK:0) | @@ -5991,7 +5947,6 @@ unasign: #if KL if (QKLB && t20_page && pc_sect != 0 && SCAD > 36) { /* Extended pointer */ int i = SCAD - 37; -//fprintf(stderr, "LDB %012llo %d %d -> %d %d\n\r", AR, SCAD, i, _byte_adj[i].p, _byte_adj[i].s); if (SCAD == 077) goto muuo; SC = _byte_adj[i].s; @@ -6018,10 +5973,11 @@ ldb_ptr: BYF5 = 1; #if KL ptr_flg = 1; - if (QKLB && t20_page && (SC < 36) && pc_sect != 0 && (glb_sect || cur_sect != 0) && (AR & BIT12) != 0) { + if (QKLB && t20_page && (SC < 36) && + pc_sect != 0 && (glb_sect || cur_sect != 0) && + (AR & BIT12) != 0) { /* Full pointer */ AB = (AB + 1) & RMASK; -//fprintf(stderr, "LBP %o %o %06o %012llo\n\r", SC, SCAD, AB, MB); } else glb_sect = 0; #endif @@ -7304,7 +7260,6 @@ jrstf: FLAGS |= f; #endif check_apr_irq(); -//fprintf(stderr, "XJRST %06o %06o %06o %06o %012llo\r\n", pc_sect, PC, prev_sect, FLAGS << 5, BR); break; case 017: /* Invalid */ @@ -7318,7 +7273,6 @@ jrstf: goto muuo; case 007: /* XPCW */ -//fprintf(stderr, "XPCW %06o %06o %06o %06o\r\n", pc_sect, AB, PC, FLAGS << 5); MB = (((uint64)FLAGS) << 23) & FMASK; /* Save Previous Public context */ if ((FLAGS & USER) == 0) { @@ -7547,12 +7501,12 @@ jrstf: } /* Check if access to register */ - if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { + if (AB < 020 && ((QKLB && + (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { AR = AB; /* direct map */ if (flag1) /* U */ AR |= SMASK; /* BIT0 */ AR |= BIT2|BIT3|BIT4|BIT8; -//fprintf(stderr, "Map reg %012llo %06o\r\n", AR, AB); set_reg(AC, AR); break; } @@ -7570,7 +7524,6 @@ jrstf: AR |= fault_data; if (flag1) /* U */ AR |= SMASK; -//fprintf(stderr, "Map fault %012llo %06o\r\n", AR, AB); set_reg(AC, AR); break; } @@ -7592,7 +7545,6 @@ jrstf: } else AR = (f & 01740) ? 0 : 0377777LL; AR |= BIT8; -//fprintf(stderr, "Map ok %012llo %03o %06o\r\n", AR, cur_sect, AB); #else /* Check if Paging Enabled */ if (!page_enable || AB < 020) { @@ -7701,7 +7653,6 @@ jrstf: PC = BR & RMASK; PC_CHANGE f_pc_inh = 1; -//fprintf(stderr, "Pushj %06o %06o %012llo %012llo %06o\n\r", pc_sect, cur_sect, AR, MB, PC); break; case 0261: /* PUSH */ @@ -7748,7 +7699,6 @@ jrstf: glb_sect = 1; } } -//fprintf(stderr, "Pop %o %o %06o %06o %06o %012llo %012llo\n\r", f, xct_flag, prev_sect, sect, cur_sect, AR, BR); #endif AB = AR & RMASK; if (Mem_read(0, 0, 0)) @@ -7805,8 +7755,14 @@ jrstf: if (Mem_read(0, 0, 0)) goto last; - if (hst_lnt) + if (hst_lnt) { +#if KL + hst[hst_p].ea = AB | (sect << 18); +#else + hst[hst_p].ea = AB; +#endif hst[hst_p].mb = MB; + } #if ITS | KL_ITS if (QITS && (FLAGS & USER)) { jpc = PC; @@ -7832,7 +7788,6 @@ jrstf: check_apr_irq(); #endif } -//fprintf(stderr, "Popj %06o %06o %012llo %012llo %06o\n\r", pc_sect, cur_sect, AR, MB, PC); break; case 0264: /* JSR */ /* AR Frm PC */ @@ -8643,7 +8598,6 @@ last: /* Handle page fault and traps */ if (page_enable && page_fault) { page_fault = 0; -//fprintf(stderr, "Page fault %06o %012llo %06o\n\r", PC, fault_data, FLAGS << 5); BYF5 = 0; #if KL_ITS if (QITS) { @@ -8703,26 +8657,17 @@ last: f_load_pc = 1; f_pc_inh = 1; if (pi_cycle) { -//fprintf(stderr, "Page fault trap %06o\n\r", PC); pi_cycle = 0; irq_flags |= 01000; FM[(7 << 4) | 2] = fault_data; pi_enable = 0; -// pi_rq = check_irq_level(); - // goto st_pi; } -// if (pi_cycle) { - // pi_cycle = 0; - // set_pi_hold(); /* Hold off all lower interrupts */ - // pi_restore = 1; /* Release the pending IRQ */ - // } } #endif #if KI /* Handle page fault and traps */ if (page_enable && page_fault) { if (pi_cycle) { -//fprintf(stderr, "Page fault trap %06o\n\r", PC); inout_fail = 1; } page_fault = 0; @@ -8855,7 +8800,6 @@ do_byte_setup(int n, int wr, int *pos, int *sz) p = (val1 >> 30) & 077; np = (p + (0777 ^ s) + 1) & 0777; /* Advance pointer */ -//fprintf(stderr, "%s %012llo %012llo %2o %2o %03o\n\r", (wr)?"store":"load", val1, val2, s, p, np); if (QKLB && t20_page && pc_sect != 0) { if (p > 36) { /* Extended pointer */ int i = p - 37; @@ -8873,7 +8817,6 @@ do_byte_setup(int n, int wr, int *pos, int *sz) MB = val2 & (SECTM|RMASK); sect = (MB >> 18) & 07777; glb_sect = 1; -//fprintf(stderr, "Load_bytex %012llo %012llo %06 %2o %2o\n\r", val1, val2, sect, s, p); } else if ((val1 & BIT12) != 0) { /* Full pointer */ if (np & 0400) { np = p = ((0777 ^ s) + 044 + 1) & 0777; @@ -8881,7 +8824,6 @@ do_byte_setup(int n, int wr, int *pos, int *sz) val2 = (val2 & LMASK) | ((val2 + 1) & RMASK); else val2 = (val2 & ~(SECTM|RMASK)) | ((val2 + 1) & (SECTM|RMASK)); -//fprintf(stderr, "Load_byte0 %012llo %012llo %06 %2o %2o\n\r", val1, val2, sect, s, p); } if (val2 & SMASK) { if (val2 & BIT1) { @@ -8894,18 +8836,13 @@ do_byte_setup(int n, int wr, int *pos, int *sz) ix = GET_XR(val2); MB = (val2 & RMASK) | ((val2 & RSIGN)? LMASK:0); sect = cur_sect; -// if ((FLAGS & USER) == 0 && - // (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) - // sect = prev_sect; glb_sect = 0; -//fprintf(stderr, "Load_byte1 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } else { ind = (val2 & BIT1) != 0; ix = (val2 >> 30) & 017; MB = val2 & (SECTM|RMASK); sect = (MB >> 18) & 07777; glb_sect = 1; -//fprintf(stderr, "Load_byte2 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } } else { if (np & 0400) { @@ -8916,11 +8853,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) ind = TST_IND(val1) != 0; MB = (val1 & RMASK) | ((val1 & RSIGN)? LMASK:0); sect = cur_sect; -// if ((FLAGS & USER) == 0 && - // (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) - // sect = prev_sect; glb_sect = 0; -//fprintf(stderr, "Load_byte3 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } } else { if (np & 0400) { @@ -8931,11 +8864,7 @@ do_byte_setup(int n, int wr, int *pos, int *sz) ind = TST_IND(val1) != 0; MB = (val1 & RMASK) | ((val1 & RSIGN)? LMASK:0); sect = cur_sect; - // if ((FLAGS & USER) == 0 && - // (((xct_flag & 2) != 0 && !wr) || ((xct_flag & 1) != 0 && wr))) - // sect = prev_sect; glb_sect = 0; -//fprintf(stderr, "Load_byte4 %012llo %012llo %2o %2o\n\r", val1, val2, s, p); } *pos = np & 077; @@ -8944,24 +8873,19 @@ do_byte_setup(int n, int wr, int *pos, int *sz) temp = get_reg(ix); /* Check if extended indexing */ if (QKLB && t20_page && glb_sect != 0 && (temp & SMASK) == 0 && (temp & SECTM) != 0) { -//fprintf(stderr, "Index %06o %012llo %06o\n\r", AB, temp, sect); temp = (temp + MB) & (SECTM|RMASK); sect = (temp >> 18) & 07777; MB = 0; glb_sect = 1; -//fprintf(stderr, "Index2 %06o %012llo %06o\n\r", AB, temp, sect); } else glb_sect = 0; temp = MB = (MB + temp) & FMASK; AB = MB & RMASK; } while (ind & !check_irq_level()) { - // ptr_flg = 1; if (Mem_read(0, 1, 0)) { - // ptr_flg = 0; return 1; } - // ptr_flg = 0; /* Check if extended indexing */ if (QKLB && sect != 0) { if (MB & SMASK) { /* Instruction format IFIW */ @@ -8989,7 +8913,6 @@ do_byte_setup(int n, int wr, int *pos, int *sz) } else temp = MB; AB = temp & RMASK; -//fprintf(stderr, "IFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, cur_sect, AB); } else { /* Extended index EFIW */ ind = (MB & BIT1) != 0; ix = (MB >> 30) & 017; @@ -9007,7 +8930,6 @@ do_byte_setup(int n, int wr, int *pos, int *sz) sect = cur_sect = (temp >> 18) & 07777; AB = temp & RMASK; glb_sect = 1; -//fprintf(stderr, "EFIW %012llo %o %02o %06o %06o\n\r", MB, ind, ix, sect, AB); } } else { ix = GET_XR(MB); @@ -9017,12 +8939,11 @@ do_byte_setup(int n, int wr, int *pos, int *sz) temp = get_reg(ix); /* Check if extended indexing */ if (QKLB && sect != 0 && (temp & SMASK) == 0 && (temp & SECTM) != 0) { -//fprintf(stderr, "Index %06o %012llo %06o\n\r", AB, temp, sect); - temp = (temp + ((AB & RSIGN) ? SECTM|((uint64)AB): (uint64)AB)) & (SECTM|RMASK); + temp = (temp + ((AB & RSIGN) ? + SECTM|((uint64)AB): (uint64)AB)) & (SECTM|RMASK); sect = (temp >> 18) & 07777; MB = 0; glb_sect = 1; -//fprintf(stderr, "Index2 %06o %012llo %06o\n\r", AB, temp, sect); AB = 0; } else glb_sect = 0; @@ -9048,14 +8969,11 @@ do_byte_setup(int n, int wr, int *pos, int *sz) set_reg(n+2, val2); modify = wr; -// ptr_flg = !wr; - // BYF5 = wr; /* Read final value */ if (Mem_read(0, 0, 0)) { modify = ptr_flg = BYF5 = 0; return 1; } -//fprintf(stderr, "Load %06o %06llo -> %012llo\n\r", sect, AB, MB); modify = 0; return 0; } @@ -9084,7 +9002,6 @@ load_byte(int n, uint64 *data, uint64 fill, int cnt) msk = (uint64)(1) << s; msk--; *data = (MB >> p) & msk; -//fprintf(stderr, "Load_bytes %2o %2o %06o %06o %012llo\n\r", s, p, sect, AB, *data); if (cnt) { /* Decrement count */ val1 = get_reg(n); @@ -9095,7 +9012,6 @@ load_byte(int n, uint64 *data, uint64 fill, int cnt) return 1; back: -//fprintf(stderr, "Load_bytef %2o %2o %06o %06o %012llo\n\r", s, p, sect, AB, *data); ptr_flg = 0; val1 = get_reg(n+1); val1 &= PMASK; @@ -9122,7 +9038,6 @@ store_byte(int n, uint64 data, int cnt) msk <<= p; MB &= CM(msk); MB |= msk & ((uint64)(data) << p); -//fprintf(stderr, "store_bytes %2o %2o %06o %06o %012llo\n\r", s, p, sect, AB, data); if (Mem_write(0, 0)) goto back; @@ -9492,7 +9407,6 @@ do_extend(uint32 ia) reg |= ((uint64)i) << 30; i = 0; a = 0; -//fprintf(stderr, "Edit pat %03o %012llo %012llo\n\r", val1, reg, MB); switch ((val1 >> 6) & 07) { case 0: /* Individual options */ switch (val1 & 077) { @@ -9623,7 +9537,6 @@ do_extend(uint32 ia) return 0; if (Mem_write(0, 0)) return 0; -//fprintf(stderr, "Edit exchange %06o %06o %012llo %012llo\n\r", sect, AB, BR, MB); if (QKLB && pc_sect != 0 && (BR & BIT12) != 0) { AB = (AR + 1) & RMASK; sect = ((AR + 1)>> 18) & 07777; @@ -9631,18 +9544,15 @@ do_extend(uint32 ia) AB = AR & RMASK; /* Restore lower pointer */ sect = (AR >> 18) & 07777; MB = BR; -//fprintf(stderr, "Restore %06o %06o %012llo\n\r", sect, AB, MB); (void)Mem_write(0, 0); return 0; } AD = MB; MB = get_reg(ext_ac+5); -//fprintf(stderr, "Edit exchange2 %06o %06o %012llo %012llo\n\r", sect, AB, AD, MB); if (Mem_write(0, 0)) { AB = AR & RMASK; /* Restore lower pointer */ sect = (AR >> 18) & 07777; MB = BR; -//fprintf(stderr, "Restore %06o %06o %012llo\n\r", sect, AB, MB); (void)Mem_write(0, 0); return 0; } @@ -9718,7 +9628,6 @@ do_extend(uint32 ia) fill2 |= SMASK; set_reg(ext_ac, fill2); } -//fprintf(stderr, "CVD %04llo %012lld %012llo c=%012llo\n\r", val1, ARX, AR, get_reg(ext_ac)); while ((get_reg(ext_ac) & MANT) != 0) { if (!load_byte(ext_ac, &val1, 0, 1)) { set_reg(ext_ac+3, AR); @@ -9755,7 +9664,6 @@ do_extend(uint32 ia) AR = AR + BR + f; ARX &= CMASK; AR &= FMASK; -//fprintf(stderr, "CVD %04llo %012lld %012llo\n\r", val1, ARX, AR); } ARX &= CMASK; if ((get_reg(ext_ac) & MANT) == 0) { @@ -9957,7 +9865,6 @@ do_extend(uint32 ia) reg = get_reg(ext_ac); val1 = get_reg(ext_ac + 1); val2 = get_reg(ext_ac + 2); -//fprintf(stderr, "XBLT: %012llo %012llo %012llo\n\r", reg, val1, val2); while (reg != 0) { if (reg & SMASK) { val1 = (val1 - 1) & (SECTM|RMASK); @@ -9968,7 +9875,6 @@ do_extend(uint32 ia) val1 = (val1 + 1) & (SECTM|RMASK); goto xblt_done; } -//fprintf(stderr, " XBLT: D=%012llo 1-%012llo 2-%012llo\n\r", MB, val1, val2); val2 = (val2 - 1) & (SECTM|RMASK); sect = (val2 >> 18) & 00037; AB = val2 & RMASK; @@ -9987,7 +9893,6 @@ do_extend(uint32 ia) ptr_flg = 1; if (Mem_read(0, 0, 0)) goto xblt_done; -//fprintf(stderr, " XBLT: D=%012llo 1-%012llo 2-%012llo\n\r", MB, val1, val2); sect = (val2 >> 18) & 00037; AB = val2 & RMASK; ptr_flg = 0; @@ -10001,7 +9906,6 @@ do_extend(uint32 ia) } } xblt_done: -//fprintf(stderr, "XBLT done: %012llo %012llo %012llo\n\r", reg, val1, val2); ptr_flg = BYF5 = 0; set_reg(ext_ac, reg); set_reg(ext_ac + 1, val1); diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index d1c83b5..10bf9f3 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -880,10 +880,14 @@ static const char *opcode[] = { "LUUO10", "LUUO11", "LUUO12", "LUUO13", "LUUO14", "LUUO15", "LUUO16", "LUUO17", "LUUO20", "LUUO21", "LUUO22", "LUUO23", "LUUO24", "LUUO25", "LUUO26", "LUUO27", "LUUO30", "LUUO31", "LUUO32", "LUUO33", "LUUO34", "LUUO35", "LUUO36", "LUUO37", -"MUUO40", "MUUO41", "MUUO42", "MUUO43", "MUUO44", "MUUO45", "MUUO46", "MUUO47", -"MUUO50", "MUUO51", "MUUO52", "MUUO53", "MUUO54", "MUUO55", "MUUO56", "MUUO57", -"MUUO60", "MUUO61", "MUUO62", "MUUO63", "MUUO64", "MUUO65", "MUUO66", "MUUO67", -"MUUO70", "MUUO71", "MUUO72", "MUUO73", "MUUO74", "MUUO75", "MUUO76", "MUUO77", +"CALL", "INITI", "MUUO42", "MUUO43", "MUUO44", "MUUO45", "MUUO46", "CALLI", +#if KL +"OPEN", "TTCALL", "PMOVE", "PMOVEM", "MUUO54", "RENAME", "IN", "OUT", +#else +"OPEN", "TTCALL", "MUUO52", "MUUO53", "MUUO54", "RENAME", "IN", "OUT", +#endif +"SETSTS", "STATO", "STATUS", "GETSTS", "INBUF", "OUTBUF", "INPUT", "OUTPUT", +"CLOSE", "RELEAS", "MTAPE", "UGETF", "USETI", "USETO", "LOOKUP", "ENTER", #if KL "UJEN", "GFAD", "GFSB", "JSYS", "ADJSP", "GFMP", "GFDV ", diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index fc948e5..86bd00a 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -785,7 +785,7 @@ t_stat tu_srv(UNIT * uptr) } return SCPE_OK; } - sim_activate(uptr, 50); + sim_activate(uptr, 20); return SCPE_OK; } From 69ffb3956637799fd92d8b72cba6399fc6d75cce Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Fri, 14 Feb 2020 18:44:34 -0500 Subject: [PATCH 91/98] KA10: Fixed KL10 FE printer to work. --- PDP10/kl10_fe.c | 354 +++++++++++++++++++++++++++++------------------- 1 file changed, 211 insertions(+), 143 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index e9e744f..9bd4ba7 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -305,10 +305,11 @@ DEVICE dte_dev = { #define LPST us9 #define LPCNT us10 -#define PTRMSK 00777 /* Current data load pointer */ -#define EOFFLG 01000 /* Tops 20 wants EOF */ -#define HDSFLG 02000 /* Tell Tops 20 The current device status */ -#define ACKFLG 04000 /* Post an acknowwledge message */ +#define EOFFLG 001 /* Tops 20 wants EOF */ +#define HDSFLG 002 /* Tell Tops 20 The current device status */ +#define ACKFLG 004 /* Post an acknowwledge message */ +#define INTFLG 010 /* Send interrupt */ +#define DELFLG 020 /* Previous character was delimiter */ #define MARGIN 6 @@ -329,8 +330,86 @@ t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *lp20_description (DEVICE *dptr); char lp20_buffer[134 * 3]; + +#define LP20_RAM_RAP 010000 /* RAM Parity */ +#define LP20_RAM_INT 04000 /* Interrrupt bit */ +#define LP20_RAM_DEL 02000 /* Delimiter bit */ +#define LP20_RAM_TRN 01000 /* Translation bite */ +#define LP20_RAM_PI 00400 /* Paper Instruction */ +#define LP20_RAM_CHR 00377 /* Character translation */ + uint16 lp20_vfu[256]; uint16 lp20_ram[256]; +uint16 lp20_dvfu[] = { /* Default VFU */ + /* 66 line page with 6 line margin */ + 00377, /* Line 0 8 7 6 5 4 3 2 1 */ + 00220, /* Line 1 8 5 */ + 00224, /* Line 2 8 5 3 */ + 00230, /* Line 3 8 5 4 */ + 00224, /* Line 4 8 5 3 */ + 00220, /* Line 5 8 5 */ + 00234, /* Line 6 8 5 4 3 */ + 00220, /* Line 7 8 5 */ + 00224, /* Line 8 8 5 3 */ + 00230, /* Line 9 8 5 4 */ + 00264, /* Line 10 8 6 5 3 */ + 00220, /* Line 11 8 5 */ + 00234, /* Line 12 8 5 4 3 */ + 00220, /* Line 13 8 5 */ + 00224, /* Line 14 8 5 3 */ + 00230, /* Line 15 8 5 4 */ + 00224, /* Line 16 8 5 3 */ + 00220, /* Line 17 8 5 */ + 00234, /* Line 18 8 5 4 3 */ + 00220, /* Line 19 8 5 */ + 00364, /* Line 20 8 7 6 5 3 */ + 00230, /* Line 21 8 5 4 */ + 00224, /* Line 22 8 5 3 */ + 00220, /* Line 23 8 5 */ + 00234, /* Line 24 8 5 4 3 */ + 00220, /* Line 25 8 5 */ + 00224, /* Line 26 8 5 3 */ + 00230, /* Line 27 8 5 4 */ + 00224, /* Line 28 8 5 3 */ + 00220, /* Line 29 8 5 */ + 00276, /* Line 30 8 6 5 4 3 2 */ + 00220, /* Line 31 8 5 */ + 00224, /* Line 32 8 5 3 */ + 00230, /* Line 33 8 5 4 */ + 00224, /* Line 34 8 5 3 */ + 00220, /* Line 35 8 5 */ + 00234, /* Line 36 8 5 4 3 */ + 00220, /* Line 37 8 5 */ + 00224, /* Line 38 8 5 3 */ + 00230, /* Line 39 8 5 4 */ + 00364, /* Line 40 8 7 6 5 3 */ + 00220, /* Line 41 8 5 */ + 00234, /* Line 42 8 5 4 3 */ + 00220, /* Line 43 8 5 */ + 00224, /* Line 44 8 5 3 */ + 00230, /* Line 45 8 5 4 */ + 00224, /* Line 46 8 5 3 */ + 00220, /* Line 47 8 5 */ + 00234, /* Line 48 8 5 4 3 */ + 00220, /* Line 49 8 5 */ + 00264, /* Line 50 8 6 5 3 */ + 00230, /* Line 51 8 5 4 */ + 00224, /* Line 52 8 5 3 */ + 00220, /* Line 53 8 5 */ + 00234, /* Line 54 8 5 4 3 */ + 00220, /* Line 55 8 5 */ + 00224, /* Line 56 8 5 3 */ + 00230, /* Line 57 8 5 4 */ + 00224, /* Line 58 8 5 3 */ + 00220, /* Line 59 8 5 */ + 00020, /* Line 60 5 */ + 00020, /* Line 61 5 */ + 00020, /* Line 62 5 */ + 00020, /* Line 63 5 */ + 00020, /* Line 64 5 */ + 04020, /* Line 65 12 5 */ + 010000, /* End of form */ +}; struct _buffer lp20_queue; @@ -476,7 +555,7 @@ t_stat dte_devio(uint32 dev, uint64 *data) { if (res & DTE_CO11SR) dte_unit[0].STATUS |= (DTE_11RELD); if (res & DTE_CO11DB) { -sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n"); + sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n"); dte_unit[0].STATUS |= DTE_11DB; sim_activate(&dte_unit[0], 200); } @@ -765,6 +844,7 @@ error: uptr->STATUS |= DTE_10DB; set_interrupt(DTE_DEVNUM, dte_unit[0].STATUS); } + sim_debug(DEBUG_DETAIL, &dte_dev, "DTE: error %012llo\n", word); return; } @@ -786,14 +866,14 @@ error: in->dcnt = (uint16)(iword & 0177777); /* Read in data */ dp = &in->data[0]; - for (cnt = in->dcnt; cnt >= 0; cnt --) { + for (cnt = in->dcnt; cnt > 0; cnt --) { /* Read in data */ s = Mem_read_byte(0, dp, 0); if (s == 0) goto error; in->sz = s; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o %06o\n", - *dp, *dp >> 8, *dp & 0377, ((*dp & 0377) << 8) | ((*dp >> 8) & 0377)); + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o %06o cnt=%o\n", + *dp, *dp >> 8, *dp & 0377, ((*dp & 0377) << 8) | ((*dp >> 8) & 0377), cnt); dp++; if (s <= 8) cnt--; @@ -921,22 +1001,23 @@ dte_function(UNIT *uptr) #if (NUM_DEVS_LP20 > 0) /* Handle printer data */ if (cmd->dev == PRI_EMLPT) { + uptr->LPST &= ~(EOFFLG); if (!sim_is_active(&lp20_unit)) sim_activate(&lp20_unit, 1000); -// lp20_unit.LPST &= ~EOFFLG; while (cmd->dptr < cmd->dcnt) { - if (((lp20_queue.in_ptr + 1) & 0xff) == lp20_queue.out_ptr) - return; ch = (int32)(cmd->data[cmd->dptr >> 1]); if ((cmd->dptr & 1) == 0) ch >>= 8; ch &= 0177; + if (((lp20_queue.in_ptr + 1) & 0xff) == lp20_queue.out_ptr) + return; lp20_queue.buff[lp20_queue.in_ptr] = ch; lp20_queue.in_ptr = (lp20_queue.in_ptr + 1) & 0xff; cmd->dptr++; } if (cmd->dptr != cmd->dcnt) return; + sim_debug(DEBUG_DETAIL, &dte_dev, "LP20 done\n"); break; } #endif @@ -955,16 +1036,16 @@ dte_function(UNIT *uptr) if (cmd->sz > 8) cmd->dcnt += cmd->dcnt; while (cmd->dptr < cmd->dcnt) { - if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) - return; ch = (int32)(cmd->data[cmd->dptr >> 1]); if ((cmd->dptr & 1) == 0) ch >>= 8; ch &= 0177; if (ch != 0) { - sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %o %d\n", ch, ln); + if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) + return; otty->buff[otty->in_ptr] = ch; otty->in_ptr = (otty->in_ptr + 1) & 0xff; + sim_debug(DEBUG_DATA, &dte_dev, "TTY queue %o %d\n", ch, ln); } cmd->dptr++; } @@ -983,17 +1064,17 @@ cty: if (cmd->sz > 8) cmd->dcnt += cmd->dcnt; while (cmd->dptr < cmd->dcnt) { - if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) - return; ch = (int32)(cmd->data[cmd->dptr >> 1]); if ((cmd->dptr & 1) == 0) ch >>= 8; ch &= 0177; if (ch != 0) { - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) + return; cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + sim_debug(DEBUG_DATA, &dte_dev, "CTY queue %o\n", ch); } cmd->dptr++; } @@ -1010,12 +1091,12 @@ cty: ln = (ch >> 8); ch &= 0177; if (ch != 0 && ln == PRI_CTYDV) { - if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) - return; - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %o\n", ch); ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) + return; + sim_debug(DEBUG_DATA, &dte_dev, "CTY queue %o\n", ch); } else if (ch != 0 && ln >= NUM_DLS && ln <= tty_desc.lines) { struct _buffer *otty; @@ -1023,9 +1104,9 @@ cty: otty = &tty_out[ln]; if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) return; - sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %o %d\n", ch, ln); otty->buff[otty->in_ptr] = ch; otty->in_ptr = (otty->in_ptr + 1) & 0xff; + sim_debug(DEBUG_DATA, &dte_dev, "TTY queue %o %d\n", ch, ln); } cmd->dptr+=2; } @@ -1043,23 +1124,15 @@ cty: #if (NUM_DEVS_LP20 > 0) if (cmd->dev == PRI_EMLPT) { if (cmd->data[0] != 0) { - data1[0] = 2; + data1[0] = 2 << 8; data1[1] = 0; data1[2] = 0; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) - return; + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) + return; } else { lp20_unit.LPST |= HDSFLG; if (!sim_is_active(&lp20_unit)) sim_activate(&lp20_unit, 1000); -// data1[0] = 0; - // data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; - // if (lp20_unit.LPST & EOFFLG) - // data1[0] |= 040; - // -// if (lp20_unit.LPST & VFUFLG) - // data1[1] |= 04; - // data1[2] = 0; //0100220; } } #endif @@ -1080,27 +1153,14 @@ cty: case PRI_EMHDS: /* Here is device status */ if (cmd->dev == PRI_EMLPT) { sim_debug(DEBUG_DETAIL, &dte_dev, "LPT HDS %06o %06o %06o\n", cmd->data[0], cmd->data[1], cmd->data[2]); -// data1[0] = 0; - // data1[1] = (lp20_unit.LINE == 0) ? 0x1: 0; if (cmd->data[0] & 040) { - // data1[0] |= 040; lp20_unit.LPST |= EOFFLG; lp20_unit.LPCNT = 0; } lp20_unit.LPST |= HDSFLG; + sim_debug(DEBUG_DETAIL, &dte_dev, "LPT HDS %06o \n", lp20_unit.LPST); if (!sim_is_active(&lp20_unit)) sim_activate(&lp20_unit, 1000); -// if (lp20_unit.LPST & VFUFLG) - // data1[1] |= 04; - // data1[2] = 0100220; -// if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) - // return; -// if (cmd->data[0] & 040) { - // lp20_unit.LPST |= EOFFLG; - // } - // if ((lp20_unit.LPST & EOFFLG) != 0 && dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) - // return; - // lp20_unit.LPST &= ~EOFFLG; } break; #if (NUM_DEVS_LP20 > 0) @@ -1108,11 +1168,16 @@ cty: if (cmd->dev == PRI_EMLPT) { int ln = lp20_unit.LPCNT; while (cmd->dptr < cmd->dcnt) { - lp20_vfu[ln++] = cmd->data[cmd->dptr++]; + uint16 d = cmd->data[cmd->dptr++]; + if (d == (0357 << 8)) + lp20_vfu[ln++] = 010000; /* Signal end of page */ + else + lp20_vfu[ln++] = ((d >> 8) & 077) | ((d <<6) & 07700); } lp20_unit.LPCNT = ln; - // lp20_unit.LPST |= ACKFLG; - data1[0] = 0; + for (ln = 0; ln < 256; ln++) + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP20 VFU %02d => %04o\n", ln, lp20_vfu[ln]); + data1[0] = 0; if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) sim_activate(uptr, 1000); } @@ -1126,7 +1191,6 @@ cty: lp20_ram[ln] = cmd->data[cmd->dptr]; } lp20_unit.LPCNT = ln; - // lp20_unit.LPST |= ACKFLG; for (ln = 0; ln < 256; ln++) sim_debug(DEBUG_DETAIL, &lp20_dev, "LP20 RAM %02x => %04x\n", ln, lp20_ram[ln]); data1[0] = 0; @@ -1143,7 +1207,7 @@ cty: int ln = cmd->data[0] - NUM_DLS; sim_debug(DEBUG_DETAIL, &dte_dev, "Flush out %d %o\n", ln, cmd->data[0]); - if (ln == (NUM_DLS - PRI_CTYDV)) + if (ln == (NUM_DLS - PRI_CTYDV)) cty_out.in_ptr = cty_out.out_ptr = 0; else tty_out[ln].in_ptr = tty_out[ln].out_ptr = 0; @@ -1283,7 +1347,7 @@ void dte_transfer(UNIT *uptr) { cnt -= 2; if (out->func & PRI_IND_FLG) { uint16 dwrd = out->dcnt; -sim_debug(DEBUG_DATA, &dte_dev, "DTE: Indirect %o %o\n", cnt, out->dcnt); + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Indirect %o %o\n", cnt, out->dcnt); dwrd |= (out->sdev << 8); if (!Mem_write_byte(0, &dwrd)) goto error; @@ -1492,7 +1556,6 @@ dte_queue(int func, int dev, int dcnt, uint16 *data) out->func = func; out->dev = dev; out->dcnt = (dcnt-1)*2; -// out->dcnt = dcnt*2; out->spare = 0; sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d queue resp: %o (%o) f=%o %s d=%o\n", dte_out_ptr, dte_out_res, out->cnt, out->dcnt, out->func, @@ -1788,31 +1851,29 @@ lp20_printline(UNIT *uptr, int nl) { int trim = 0; uint16 data1 = 1; /* Trim off trailing blanks */ - while (uptr->COL >= 0 && lp20_buffer[uptr->POS - 1] == ' ') { + while (uptr->COL >= 0 && lp20_buffer[uptr->COL - 1] == ' ') { uptr->COL--; - uptr->POS--; trim = 1; } - lp20_buffer[uptr->POS] = '\0'; + lp20_buffer[uptr->COL] = '\0'; sim_debug(DEBUG_DETAIL, &lp20_dev, "LP output %d %d [%s]\n", uptr->COL, nl, lp20_buffer); /* Stick a carraige return and linefeed as needed */ if (uptr->COL != 0 || trim) - lp20_buffer[uptr->POS++] = '\r'; + lp20_buffer[uptr->COL++] = '\r'; if (nl != 0) { - lp20_buffer[uptr->POS++] = '\n'; + lp20_buffer[uptr->COL++] = '\n'; uptr->LINE++; } - if (nl > 0 && uptr->LINE >= ((int32)uptr->capac - MARGIN)) { - lp20_buffer[uptr->POS++] = '\f'; - uptr->LINE = 0; + if (nl > 0 && lp20_vfu[uptr->LINE] == 010000) { + lp20_buffer[uptr->COL++] = '\f'; + uptr->LINE = 1; } else if (nl < 0 && uptr->LINE >= (int32)uptr->capac) { - uptr->LINE = 0; + uptr->LINE = 1; } - sim_fwrite(&lp20_buffer, 1, uptr->POS, uptr->fileref); - uptr->pos += uptr->POS; + sim_fwrite(&lp20_buffer, 1, uptr->COL, uptr->fileref); + uptr->pos += uptr->COL; uptr->COL = 0; - uptr->POS = 0; return; } @@ -1827,16 +1888,20 @@ lp20_output(UNIT *uptr, char c) { lp20_printline(uptr, 1); if ((uptr->flags & UNIT_UC) && (c & 0140) == 0140) c &= 0137; - else if (c >= 040 && c < 0177) { - lp20_buffer[uptr->POS++] = c; - uptr->COL++; + else if (c >= 040 && c < 0177) { /* If printable */ + lp20_buffer[uptr->COL++] = c; + } if (c == 011) { /* Tab */ + lp20_buffer[uptr->COL++] = ' '; + while ((uptr->COL & 07) != 0) + lp20_buffer[uptr->COL++] = ' '; } return; } t_stat lp20_svc (UNIT *uptr) { - char c; + char ch; + uint16 ram_ch; uint16 data1[5]; int l = uptr->LINE; @@ -1845,93 +1910,78 @@ t_stat lp20_svc (UNIT *uptr) if (dte_dev.flags & TYPE_RSX20 && uptr->LPST & HDSFLG) { data1[0] = 0; - data1[1] = (uptr->LINE == 0) ? 0x1: 0; - if (uptr->LPST & EOFFLG) - data1[0] |= 040; -// if (uptr->LPST & VFUFLG) - // data1[1] |= 04; + data1[1] = (uptr->LINE == 1) ? 01<<8: 0; + sim_debug(DEBUG_DETAIL, &dte_dev, "LPT queue %06o %06o \n", lp20_unit.LPST, uptr->LPST); + if (uptr->LPST & EOFFLG) { + data1[0] |= 040 << 8; + uptr->LPCNT = 0; + } + if (uptr->LPST & INTFLG) { + data1[1] |= 02 << 8; + uptr->LPCNT = 0; + } data1[2] = 0110200; //0100220; if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 4, data1) == 0) sim_activate(uptr, 1000); -// if ((uptr->LPST & (EOFFLG)) == (EOFFLG)) { - // data1[0] = (PRI_EMLPT << 8); - // if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) - // sim_activate(uptr, 1000); -// uptr->LPST &= ~ACKFLG; - // } - uptr->LPST &= ~(HDSFLG|EOFFLG); + uptr->LPST &= ~(HDSFLG); } if (lp20_queue.out_ptr == lp20_queue.in_ptr) return SCPE_OK; while (lp20_queue.out_ptr != lp20_queue.in_ptr) { - c = lp20_queue.buff[lp20_queue.out_ptr]; + ch = lp20_queue.buff[lp20_queue.out_ptr]; lp20_queue.out_ptr = (lp20_queue.out_ptr + 1) & 0xff; - if (c < 040) { /* Control character */ - sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x %04x\n", c, lp20_ram[c] ); - switch(c) { - case 011: /* Horizontal tab, space to 8'th column */ - lp20_output(uptr, ' '); - while ((uptr->COL & 07) != 0) - lp20_output(uptr, ' '); - break; - case 015: /* Carriage return, print line */ - lp20_printline(uptr, 0); - break; - case 012: /* Line feed, print line, space one line */ - lp20_printline(uptr, 1); - break; - case 014: /* Form feed, skip to top of page */ - lp20_printline(uptr, 0); + ram_ch = lp20_ram[ch]; + + /* If previous was delimiter or translation do it */ + if (uptr->LPST & DELFLG || (ram_ch & (LP20_RAM_DEL|LP20_RAM_TRN)) != 0) { + ch = ram_ch & LP20_RAM_CHR; + uptr->LPST &= ~DELFLG; + if (ram_ch & LP20_RAM_DEL) + uptr->LPST |= DELFLG; + } + /* Flag if interrupt set */ + if (ram_ch & LP20_RAM_INT) + uptr->LPST |= HDSFLG|INTFLG; + /* Check if paper motion */ + if (ram_ch & LP20_RAM_PI) { + int lines = 0; /* Number of new lines to output */ + lp20_printline(uptr, (ram_ch & 037) != 020); /* Print any buffered line */ + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x %04x\n", ch, ram_ch); + if ((ram_ch & 020) == 0) { /* Find channel mark in output */ + while ((lp20_vfu[uptr->LINE] & (1 << (ram_ch & 017))) == 0) { + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP skip chan %04x %04x %d\n", lp20_vfu[uptr->LINE], ram_ch, uptr->LINE); + if (lp20_vfu[uptr->LINE] & 010000) { /* Hit bottom of form */ sim_fwrite("\014", 1, 1, uptr->fileref); uptr->pos++; - uptr->LINE = 0; - break; - case 013: /* Vertical tab, Skip mod 20 */ - lp20_printline(uptr, 1); - while((uptr->LINE % 20) != 0) { - sim_fwrite("\r\n", 1, 2, uptr->fileref); - uptr->pos+=2; - uptr->LINE++; - } - break; - case 020: /* Skip half page */ - lp20_printline(uptr, 1); - while((uptr->LINE % 30) != 0) { - sim_fwrite("\r\n", 1, 2, uptr->fileref); - uptr->pos+=2; - uptr->LINE++; - } - break; - case 021: /* Skip even lines */ - lp20_printline(uptr, 1); - while((uptr->LINE % 2) != 0) { - sim_fwrite("\r\n", 1, 2, uptr->fileref); - uptr->pos+=2; - uptr->LINE++; - } - break; - case 022: /* Skip triple lines */ - lp20_printline(uptr, 1); - while((uptr->LINE % 3) != 0) { - sim_fwrite("\r\n", 1, 2, uptr->fileref); - uptr->pos+=2; - uptr->LINE++; - } - break; - case 023: /* Skip one line */ - lp20_printline(uptr, -1); - break; - default: /* Ignore */ + lines = 0; + uptr->LINE = 1; break; + } + lines++; + uptr->LINE++; + } + } else { + while ((ram_ch & 017) != 0) { + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP skip line %04x %04x %d\n", lp20_vfu[uptr->LINE], ram_ch, uptr->LINE); + if (lp20_vfu[uptr->LINE] & 010000) { /* Hit bottom of form */ + sim_fwrite("\014", 1, 1, uptr->fileref); + uptr->pos++; + lines = 0; + uptr->LINE = 1; + } + lines++; + uptr->LINE++; + ram_ch--; + } } - if (uptr->LINE == 0) { - uptr->LPST |= HDSFLG; - sim_activate(uptr, 1000); - } - } else { - sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x '%c' %04x\n", c, c, lp20_ram[c] ); - lp20_output(uptr, c); + for(;lines > 0; lines--) { + sim_fwrite("\r\n", 1, 2, uptr->fileref); + uptr->pos+=2; + } + } else if (ch != 0) { + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x '%c' %04x\n", ch, ch, ram_ch); + lp20_output(uptr, ch); } } if (lp20_queue.out_ptr == lp20_queue.in_ptr) { @@ -1953,9 +2003,27 @@ t_stat lp20_svc (UNIT *uptr) t_stat lp20_reset (DEVICE *dptr) { UNIT *uptr = &lp20_unit; + int i; uptr->POS = 0; uptr->COL = 0; uptr->LINE = 1; + /* Clear RAM & VFU */ + for (i = 0; i < 256; i++) { + lp20_ram[i] = 0; + lp20_vfu[i] = 0; + } + + /* Load default VFU into VFU */ + memcpy(&lp20_vfu, lp20_dvfu, sizeof(lp20_dvfu)); + lp20_ram[012] = LP20_RAM_TRN|LP20_RAM_PI|7; /* Line feed, print line, space one line */ + lp20_ram[013] = LP20_RAM_TRN|LP20_RAM_PI|6; /* Vertical tab, Skip mod 20 */ + lp20_ram[014] = LP20_RAM_TRN|LP20_RAM_PI|0; /* Form feed, skip to top of page */ + lp20_ram[015] = LP20_RAM_TRN|LP20_RAM_PI|020; /* Carrage return */ + lp20_ram[020] = LP20_RAM_TRN|LP20_RAM_PI|1; /* Skip half page */ + lp20_ram[021] = LP20_RAM_TRN|LP20_RAM_PI|2; /* Skip even lines */ + lp20_ram[022] = LP20_RAM_TRN|LP20_RAM_PI|3; /* Skip triple lines */ + lp20_ram[023] = LP20_RAM_TRN|LP20_RAM_PI|4; /* Skip one line */ + lp20_ram[024] = LP20_RAM_TRN|LP20_RAM_PI|5; sim_cancel (&lp20_unit); /* deactivate unit */ return SCPE_OK; } From dc1ab57fde2696e5034600d8e4899d4a93a8f726 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sat, 15 Feb 2020 16:20:58 -0500 Subject: [PATCH 92/98] KA10: Updated documentation. --- README.md | 2 +- Visual Studio Projects/PDP10-KL.vcproj | 10 +++++----- doc/ka10_doc.doc | Bin 215552 -> 220160 bytes doc/ki10_doc.doc | Bin 149504 -> 154112 bytes doc/kl10_doc.doc | Bin 146432 -> 161280 bytes 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index dec5847..c49f0d0 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ The KL10 sim has successfully run Tops 10 6.03-7.03, ITS and Tops 20 V2-V7. * LP20 Line printer on KL10 Front End. * IMP networking support for ITS and TENEX. - * NIA20 networking support for KL10 (in progress). + * NIA20 networking support for KL10. * CH10 networking support for ITS. * 340 Display Station support. diff --git a/Visual Studio Projects/PDP10-KL.vcproj b/Visual Studio Projects/PDP10-KL.vcproj index a1a00af..093a52e 100644 --- a/Visual Studio Projects/PDP10-KL.vcproj +++ b/Visual Studio Projects/PDP10-KL.vcproj @@ -3,7 +3,7 @@ ProjectType="Visual C++" Version="9.00" Name="PDP10-KL" - ProjectGUID="{0BA63EC5-BD4F-44FB-AE89-7DD2C84CB1D9}" + ProjectGUID="{DA2AA7A0-B679-456B-B152-DEF40FAE5A7A}" RootNamespace="PDP10-KL" Keyword="Win32Proj" TargetFrameworkVersion="131072" @@ -41,7 +41,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../PDP10/;../PDP11/;../VAX/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2" - PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KL=1;SIM_BUILD_TOOL=simh-Visual-Studio-Project;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC" + PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KL=1;USE_SHARED;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;PTW32_STATIC_LIB;USE_READER_THREAD;SIM_ASYNCH_IO;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG" KeepComments="false" BasicRuntimeChecks="0" RuntimeLibrary="1" @@ -63,7 +63,7 @@ 5=#F#%-#X6gt$MzMG0Wg2lOJ$D#l6N$b@!Bjo3=_Ezp1M(D-i&Kk@%+%oCY=qrLq4xvq!E z9I8oAVv!M!O%_Sw{Prp1QoEl7If37F7$%rjGNK$VC6I7bpAI zy&QL4hRk4HOr)3+xnHJ85&u)9Q0~JrT_*84Q^rd%w(0VqlvvZ%WL6D5wj^PlW9CNP zu)@$GsDKxs68-=y;g9elTwt?NULw9)k6#&or!hV4?~~09fp#%wL0`Ke%cR@B=_bz3 znPifDG{Ar0bbRSUR6U!9^^gp?HQ3N%;!}uc$OKXg-EcZ#A)T1u+Ve>-4jvV7zIJgs zpI+{X_2uXpT22wE#cr$%ot;9y49S&&k`pJ_5YhTJZb?13Z`?;pD^Iy02XEz2#UkXj~E+$8FlAQSDtADehPypL(oJrDb2tTPES zq<~i3@5Z#v+Jou!tX{F@GepnuX3G?{_9v?*7P@WAphzvy^Sm}8 zG_7(4_i(I}Dy;XmSGtLhXGU>azB|BoyR{V7`|p|uIYUcT_t!i6(vt8;%Z?`5?#eOI zw|Zmx5N#^PgIcS$QO}-$t$=@TmgscWx#Lao&~C1{qA|1`9n`MbEm5R z`BRC_@5YV`-6;~^$afUf&EESXbDd4<$db{H4=QmNiaK~2rF-4h){l4FF~MzvP9`0i zaL3+G-+u0$QSbTYUVYQ;_}(TtO-u0HH;rC}TC2Tdj`&NTOSCQenHF}-B$LqkKCC*0 z)wL`-Z-O7X(OhwLYKD41OVaa-2t)q8S+cMdNqKz?CEmddsB-d{f z+|sm6&$~K&-cr}e7aICYXS=SJU=C~gnfR7rGui(`WulJ}wXgIs?d^cR__v_9i5sYc z9I8iqmlxbvyuGvGwA1m{@Lztf0~e7iG?16( zzK^mR=k_)*H*Y_xxi|v(R5^j-(=xm@K7}J~gf_?Xw&!(r4jq?dTinN7VG6Y;Y1itS zDqwef3-iRnRod5Xp?5MX;)iqMhOk_=4!E!yvP>6eLt-Vk8~HQ;5I-n-*knPacZFo|}-FHDb)mgbC1Xt8)}ECc&Ya)X0#?lz{Str=~S{C(G5ky*bk+`doZTrGVVWvM@lWwyWcqr@vO zE>yjm22;rA`J7J6Z2RsnxTn~Eqe;4_yIV$RX?JG^H0+alxzYZLCFFxV&eopjMNcnv z)A;ww>Jez4XP$6OhJSN@ntgnbY2)tIrMk-W9zidO`R>fkVG*n6x?m5jrEsr$y`Jsf z6%A&N-{a=~IZNvfHx>$qVe!&(xosQHm&#sl`ao_4M!B2BUDE9)D)OeSRyl~>Lno;I zhb~DM2T&KCZVTEmwg!K%t!-^mzDbHzv#xmkoMuZ0u^xsbnj|}Jgo(EExs|lLZZoZH z^|dCNtygcbycrZd&+G7Bx$rYq?a_-(#9ipjQSs=3>&w0BK49ZZ&e zK!aWOX$^+kKWT8rzNx`RdtfTlDe8Wc)bqW4vQPf8?>#sCdoX-G7*++tmx3W*G3?0u z&7UqGq+j~GLN|CEmK2y&XGn@oDKP0yRD0W(ka~VrKy`EMGy-Qtnq8==N$GZ_rXIF` z!#rvY(!s0n7f>1Do3Brv{93-2Bf;=sFsu!RyMy75V7Mh1ZU~02x*-jnG0ha^wf0SY z5H%w@#@rQSoEQ_;a|rr{j{{P6^Zl$oMY6T_^^lUmw|Yp2BA5X)VHV7Ry|54VL#s^N zqL9w)v{x0<)#Y}e2Kn}00w<@Foui3I?6YcJU|%7~>DbxRO3usI=TDwIFX!b*FgzFx zYlGqLV7Ma~ZV84Pg5j%#+R^Ezs2kns(ITunUPrP1=Vf75?YLyynnIIms_mCFCuT0+ zDCfhHBGb;ft&2@6GU=J=*Px_8C+G}aU?G&jGjPTZE22l$c8UgL>=Oi~eY%PCgPR}= z`ojvS02PL`tN-^dql5USj!p>c6vu&h{P3Fx%;AtZ+y9sU_Ok~~hW%xUxgoW|3QR;3sUIr2(^gZrjhbm{Y{kQ-k6rsPZR4XwE0o4T zLlR^>Ot3XGO_`0FMXp5;nJcgSTt1P8Ts-=m6pn1gLuRb4nPpbks5xeP4ExJ5#jc&r z?fd50Z2t8hiHAAkaD#tgcGWz_&FQDJO-FN&-9E>xwNZ1;*7{~9*(V?2OZvNym>w*L zt#eJKjhbh6UM1&F$#MCT|8svqz<%g|BgC2b=FO5 z_^Bt8K(OyP(c`81;r`VS}i{*^c3C=bqEfJExtV zbGJ6~C>)1uzsPN{tDH3lyCLOSCNDe#i=HjTXvqvG;3rExxp*959;}1h=ZHf-Ooak? z15{G3f!(kNYN6XQJO}+@01Ss5C4O<|p^f%04XaTK2_2~vvEo02^T|Y=d?ya1*3M z2IN6bg(sNHxpQ)onW!9Nmb>i#H=n^Q|1KGOJSCiC0qP%Pn#!1_+L}kW!}?dLX;Ug~ z)E1frq>(FhG*X`g zumLVW)HWOixp49=@9|IEb}E7^U>3}QC9o8hLBiXtC`g5}9c(^OTF%E3sCb7k+09?1TN#k!XSY3KI(U2a7%d?MM!{&93I*^uEPySr72byrVK3+-&_3TWXCWJI zgW-?^)vyh=!-DTwCr}Ad=lNm<^I$$a1B=cxcDsnwz91GTUZ_5+Wd#hv%=!a06My1NSk)0gTQT^#kF zp>0sZL-Lva>jSoOd+-S9gtUJ~NP9Oz+ItbwK8TR^QG~RQBcy#2A??!$X`e+%J7BU+^efH( z8u!x<_Tdpus@*)oiL9e>ZJD z)wKC*bJR3*yBg^EjX75z|28asE-ZdNEdE1S+&CA{^@YWog~gkP#V-qsw+xHNhQ(Wl z#V-$w$A`re!{Tkj;>lt0_F?g~uy}{CcxG7q%CPuV&cN=Ml|=nVt9x3%mU>%&&H9wN zcx>6PZw$Pg>l_U;2H2;E8+)RY6Kj9C+nLum`{q&3;YQh;I~Owrs>e9*gr$3R{Bx}H z#-+w_O&Rl=GUhjBoYa(Ya#O~s4VzqD&{Pu(n>w?|S#wFdHy1mvUSh`1((edI&$K{QVmoz$F+UR&$qvPd`j(^wGWLVMEWTkv~+LE4TOV2v7fk8FS zCX=Qw6`ldr$T}_N3mB+QrY{<CtX zQvQ%%suomMYXCe zpc<9xQ$0a-sU^#7`d&)Qsdd(xG*zgUf+|xgO2vQ*QzM`*kha(P++?airQ*~`7zLw2 zMJg4hRFoPS$lOPbnfj8Yic%^_Z3PvgRD>D;Dn6|aWbP+ly6R7BKy{~-6?{X6bjX7d z723Mz?92O{r|kfrFWKJvx${DI)qPa&QLX2S7Z{RC-1G;&=|CMEhA6ZheYcZAEH}x4 z>_g55lct8BKps>;CF}xy0kpx0)ahueH4aoF%7<~tLuVmj6}}6k9mX4J`r7CSD1=q8 z8n%PJO4^{rqfEzCjM2~q7Qtdz5Bkn&gUm;?dbM_f!SFaNfVH4P)1|r9dID5_nuYw- z2Fa-}{0>$G(oX2m={v2}&;|LaD+~dZqsk%r6?f=PG9=fiG&KuUnpz4w*5Oy^8{n%H z-pB=+myhV(@v#HQ|n6D0txF8%%Csm8?=|SIa95(paN9IItb2R`N{_EHt_v1 zka?E&q)jDW08c?J?1k?^-^abA)HJpBhsm%KUIf*?^v&I{-1d&MPKvojUr)C4JNc3V z<=;C6CR1~5*+^TU%O?B;xu7c9GT0x;yr9!t-vL&|OjW4?@Dqrs_S7j=rQUxn(?`?w zHQ^6I#VHl0RFv8WDoRZXq&Yt3&?MrML4~OuuoK$7>1k1m18Gs3M>VK&Pz_49;U-WW zN;Rm{fwXAyr0Z+Qsz0grG&iU_C80O9gOs;z(Hibp`>%2O1PWt(i_Og{N6i40qYgvT zPMQR&MyV3jaTi<5d!7QN>eCTW#Yxqs;KLyU} zY1;?EU8a?9tw~WCYCEV5r4rBkpb}5^N8!0t?70n8=uwepFsR70V^4T4m3wxA$~`Le z3;>mS_J16nOGTf9prVfoK4U=zpZ9CSa`n(RwLgSCuyHSAbO2x0QPvksg~LpXBc3Xx zYEaj&bQeyw8GduMz2glh);woR*E`qS8?$i9uqo!}c3cs+EdMgTHujb;opgJbpEn|I z{meYuFBFRP-W>1sIsK0Qj1gU zT%gL5s!4lK+4ORAjqT2W*hh3|UN2*4=B4-^H7P1H?E_VpR9PAhswnL^9dtpe4vlI{ zJ3%!i)swP7b);2ahviCFMQJsts?_2P4Ls{9O3x53IvYsOpygNT`|T<(sUW0c&=^n= zNClv6pu*32JG7&(bKs7SzSm5;8dL@92de&TfvunlQ0lordM7Pa-eXsc2}tFiELaXI0S$(6Vt6^m2(RAT2i7?4?H&8L)Zf{~_X?Z8 zF%ky}P!3CAIp{0;>>{0fo$aV~4Es;*E&H5g|ED)!WuNcnd&6#C&M?2+&G-8b60Lc6 z!yZU+jHE(G&{zD!$_V6i#rJ7yErc1c5#E4mI1OR@R$x#!-zGCit!LmYjPMzm2}@uH z^ouf51WVynI08GHBWdwOt&*P=tO9;sU^{G~&&=T1!2LaZ&zjcylLO(W2GPJz4{Ylr zX21PcPhTe!V-tG$j<(j{BMgUJ;CBgu*1dfhhQyxN`)XS24;3olMc@Yu4HNYj4BtZ( zzhdB*3=I?YrwxTL2l$CY!$kefLkz?LzkO(s*j0ZFQ4UK$1w9q>4hO}&ilCS`*%k9_ z*DPOZ`zP5w>;LA~$A~;&3$uL5T^YH!OiNKtn`W86<1DYp=w*UYD delta 10165 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 t=k>VqXm4wuolsl&< diff --git a/doc/ki10_doc.doc b/doc/ki10_doc.doc index c6031e9dd49aaae320d615c0bead193f915295d3..c772f57e215d953360eb1ae7760700aa480941c5 100644 GIT binary patch delta 8117 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 Rx6fFm#=2$fO$)8<{{aPa0*3$q diff --git a/doc/kl10_doc.doc b/doc/kl10_doc.doc index 75f435537d42b01d7df356a6ce7efb7d077f52fe..e1184954786c3cb26d7098634dbc1acef5f3cf3a 100644 GIT binary patch delta 21961 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 delta 14753 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:P+Na;K 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 Date: Sat, 15 Feb 2020 16:21:18 -0500 Subject: [PATCH 93/98] KA10: Cleanup NIA device. --- PDP10/kl10_nia.c | 859 +++++++++++++++++++++++++++++++---------------- 1 file changed, 561 insertions(+), 298 deletions(-) diff --git a/PDP10/kl10_nia.c b/PDP10/kl10_nia.c index 9c9ae59..6102a71 100644 --- a/PDP10/kl10_nia.c +++ b/PDP10/kl10_nia.c @@ -91,6 +91,7 @@ #define CHNERR 07762 #define SLFTST 07751 #define INTERR 07750 +#define EBSERR 07752 /* 12 Bit Shift */ #define NIA_CMD_SND 0001 /* Send a datagram */ @@ -348,24 +349,27 @@ struct nia_device { int h4000; /* Heart beat detection */ int rar; uint64 ebuf; + uint64 status; /* Status of device. */ uint32 uver[4]; /* Version information */ int r_pkt; /* Packet pending */ } nia_data; -#define STATUS u3 extern int32 tmxr_poll; static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff}; t_stat nia_devio(uint32 dev, uint64 *data); -void nia_start(UNIT *); -void nia_stop(UNIT *); -void nia_enable(UNIT *); -void nia_disable(UNIT *); -void nia_error(UNIT *, int); -t_stat nia_srv(UNIT *); +void nia_start(); +void nia_stop(); +void nia_enable(); +void nia_disable(); +void nia_load_ptt(); +void nia_load_mcast(); +void nia_error(int); t_stat nia_eth_srv(UNIT *); +t_stat nia_rec_srv(UNIT *); +t_stat nia_cmd_srv(UNIT *); t_stat nia_reset (DEVICE *dptr); t_stat nia_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc); t_stat nia_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc); @@ -377,10 +381,15 @@ const char *nia_description (DEVICE *dptr); struct rh_if nia_rh = { NULL, NULL, NULL}; UNIT nia_unit[] = { - {UDATA(nia_srv, UNIT_IDLE+UNIT_ATTABLE, 0)}, /* 0 */ - {UDATA(nia_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ + {UDATA(nia_eth_srv, UNIT_IDLE+UNIT_ATTABLE, 0)}, /* 0 */ + {UDATA(nia_rec_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 1 */ + {UDATA(nia_cmd_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 2 */ }; +#define nia_cmd_uptr (&nia_unit[2]) /* Unit for processing commands */ +#define nia_recv_uptr (&nia_unit[0]) /* Unit doing receive digestion */ +#define nia_proc_uptr (&nia_unit[1]) /* Unit doing receive dispatching */ + DIB nia_dib = {NIA_DEVNUM | RH20_DEV, 1, &nia_devio, NULL, &nia_rh }; MTAB nia_mod[] = { @@ -416,7 +425,7 @@ DEBTAB nia_debug[] = { DEVICE nia_dev = { "NI", nia_unit, NULL, nia_mod, - 2, 8, 0, 1, 8, 36, + 3, 8, 0, 1, 8, 36, NULL, NULL, &nia_reset, NULL, &nia_attach, &nia_detach, &nia_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, nia_debug, NULL, NULL, &nia_help, NULL, NULL, &nia_description @@ -425,57 +434,58 @@ DEVICE nia_dev = { t_stat nia_devio(uint32 dev, uint64 *data) { DEVICE *dptr = &nia_dev; - UNIT *uptr = nia_unit; + UNIT *uptr = nia_cmd_uptr; switch(dev & 03) { case CONO: if (*data & NIA_CPT) nia_reset(dptr); - uptr->STATUS &= ~(NIA_SEB|NIA_LAR|NIA_SSC|NIA_DIS|NIA_ENB|NIA_PIA); - uptr->STATUS |= *data & (NIA_SEB|NIA_LAR|NIA_SSC|NIA_DIS|NIA_ENB|NIA_PIA); - uptr->STATUS &= ~(*data & (NIA_EPE|NIA_FQE|NIA_DME|NIA_RQA)); + nia_data.status &= ~(NIA_SEB|NIA_LAR|NIA_SSC|NIA_DIS|NIA_ENB|NIA_PIA); + nia_data.status |= *data & (NIA_SEB|NIA_LAR|NIA_SSC|NIA_DIS|NIA_ENB|NIA_PIA); + nia_data.status &= ~(*data & (NIA_EPE|NIA_FQE|NIA_DME|NIA_RQA)); clr_interrupt(NIA_DEVNUM); if (*data & NIA_MRN) { - if ((uptr->STATUS & NIA_MRN) == 0) - nia_start(uptr); + if ((nia_data.status & NIA_MRN) == 0) + nia_start(); } else { - if ((uptr->STATUS & NIA_MRN) != 0) - nia_stop(uptr); + if ((nia_data.status & NIA_MRN) != 0) + nia_stop(); } if (*data & NIA_ENB) { - if ((uptr->STATUS & NIA_MRN) != 0 && (uptr->STATUS & NIA_ECP) == 0) - nia_enable(uptr); + if ((nia_data.status & NIA_MRN) != 0 && + (nia_data.status & NIA_ECP) == 0) + nia_enable(); else - uptr->STATUS |= NIA_ECP; + nia_data.status |= NIA_ECP; } else - uptr->STATUS &= ~NIA_ECP; + nia_data.status &= ~NIA_ECP; if (*data & NIA_DIS) { - if ((uptr->STATUS & NIA_MRN) != 0 && (uptr->STATUS & NIA_DCP) == 0) - nia_disable(uptr); + if ((nia_data.status & NIA_MRN) != 0 && + (nia_data.status & NIA_DCP) == 0) + nia_disable(); else - uptr->STATUS |= NIA_DCP; + nia_data.status |= NIA_DCP; } else - uptr->STATUS &= ~NIA_DCP; + nia_data.status &= ~NIA_DCP; if (*data & NIA_CQA && - (uptr->STATUS & NIA_CQA) == 0 && - (uptr->STATUS & NIA_MRN) != 0) { - uptr->STATUS |= NIA_CQA; + (nia_data.status & NIA_CQA) == 0 && + (nia_data.status & NIA_MRN) != 0) { + nia_data.status |= NIA_CQA; sim_activate(uptr, 200); } - if (uptr->STATUS & (NIA_CPE|NIA_RQA)) - set_interrupt(NIA_DEVNUM, uptr->STATUS & NIA_PIA); - sim_debug(DEBUG_CONO, dptr, "NIA %03o CONO %06o PC=%o %06o\n", dev, - (uint32)*data, PC, uptr->STATUS); + if (nia_data.status & (NIA_CPE|NIA_RQA)) + set_interrupt(NIA_DEVNUM, nia_data.status & NIA_PIA); + sim_debug(DEBUG_CONO, dptr, "NIA %03o CONO %06o PC=%06o %012llo\n", dev, + (uint32)(*data & RMASK), PC, nia_data.status); break; case CONI: - *data = (uint64)uptr->STATUS; - *data |= NIA_PPT|NIA_PID; + *data = nia_data.status|NIA_PPT|NIA_PID; sim_debug(DEBUG_CONI, dptr, "NIA %03o CONI %012llo PC=%o\n", dev, *data, PC); break; case DATAO: - if (uptr->STATUS & NIA_SEB) { + if (nia_data.status & NIA_SEB) { nia_data.ebuf = *data; } else { if (*data & NIA_LRA) { @@ -493,10 +503,10 @@ t_stat nia_devio(uint32 dev, uint64 *data) dev, *data, PC); break; case DATAI: - if (uptr->STATUS & NIA_SEB) { + if (nia_data.status & NIA_SEB) { *data = nia_data.ebuf; } else { - if (uptr->STATUS & NIA_LAR) { + if (nia_data.status & NIA_LAR) { *data = ((uint64)nia_data.rar) << 20; *data &= ~NIA_MSB; *data |= NIA_LRA; @@ -518,29 +528,34 @@ ipv4_inet_ntoa(struct in_addr ip) static char str[20]; if (sim_end) - sprintf (str, "%d.%d.%d.%d", ip.s_addr & 0xFF, (ip.s_addr >> 8) & 0xFF, - (ip.s_addr >> 16) & 0xFF, (ip.s_addr >> 24) & 0xFF); + sprintf (str, "%d.%d.%d.%d", ip.s_addr & 0xFF, + (ip.s_addr >> 8) & 0xFF, + (ip.s_addr >> 16) & 0xFF, + (ip.s_addr >> 24) & 0xFF); else - sprintf (str, "%d.%d.%d.%d", (ip.s_addr >> 24) & 0xFF, (ip.s_addr >> 16) & 0xFF, - (ip.s_addr >> 8) & 0xFF, ip.s_addr & 0xFF); + sprintf (str, "%d.%d.%d.%d", (ip.s_addr >> 24) & 0xFF, + (ip.s_addr >> 16) & 0xFF, + (ip.s_addr >> 8) & 0xFF, + ip.s_addr & 0xFF); return str; } /* * Set error code and stop. */ -void nia_error(UNIT * uptr, int err) +void nia_error(int err) { nia_data.rar = err; sim_debug(DEBUG_DETAIL, &nia_dev, "NIA error %03o\n", err); - uptr->STATUS |= NIA_CPE; - set_interrupt(NIA_DEVNUM, uptr->STATUS & NIA_PIA); + nia_data.status |= NIA_CPE; + set_interrupt(NIA_DEVNUM, nia_data.status & NIA_PIA); + nia_stop(); } /* * Start NIA device, load in 2 words using RH20 mode. */ -void nia_start(UNIT * uptr) +void nia_start() { sim_debug(DEBUG_DETAIL, &nia_dev, "NIA start\n"); /* Set up RH20 to read 2 words */ @@ -549,35 +564,85 @@ void nia_start(UNIT * uptr) rh20_setup(&nia_rh); /* Read PCB address */ if (!rh_read(&nia_rh)) { - nia_error(uptr, CHNERR); + nia_error(CHNERR); return; } - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA PCB %012llo %o\n", nia_rh.buf, nia_rh.wcr); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA PCB %012llo %o\n", nia_rh.buf, + nia_rh.wcr); nia_data.pcb = (t_addr)(nia_rh.buf & AMASK); nia_data.resp_hdr = (t_addr)((nia_rh.buf + 4) & AMASK); nia_data.unk_hdr = (t_addr)((nia_rh.buf + 8) & AMASK); /* Read PIA value */ if (!rh_read(&nia_rh)) { - nia_error(uptr, CHNERR); + nia_error(CHNERR); return; } - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA PIA %012llo %o\n", nia_rh.buf, nia_rh.wcr); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA PIA %012llo %o\n", nia_rh.buf, + nia_rh.wcr); nia_data.pia = (int)(nia_rh.buf & 7); - uptr->STATUS |= NIA_MRN; + nia_data.status |= NIA_MRN; memcpy(&nia_data.macs[0], &nia_data.mac, sizeof (ETH_MAC)); memcpy(&nia_data.macs[1], &broadcast_ethaddr, sizeof(ETH_MAC)); } -void nia_stop(UNIT *uptr) +void nia_stop() { sim_debug(DEBUG_DETAIL, &nia_dev, "NIA stop\n"); - uptr->STATUS &= ~NIA_MRN; + nia_data.status &= ~NIA_MRN; +} + +/* + * Enable NIA 20. + * + * Read in PTT and MACS table. + */ +void nia_enable() +{ + uint64 word; + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA enable\n"); + /* Load pointers to various table */ + if (Mem_read_word(nia_data.unk_hdr + PCB_UPL, &word, 0)) { + nia_error(EBSERR); + return; + } + nia_data.unk_len = (int)(word & AMASK); + /* Load PTT */ + if (Mem_read_word(nia_data.pcb + PCB_PTT, &word, 0)) { + nia_error(EBSERR); + return; + } + nia_data.ptt_addr = (t_addr)(word & AMASK); + nia_load_ptt(); + /* Load MCT */ + if (Mem_read_word(nia_data.pcb + PCB_MCT, &word, 0)) { + nia_error(EBSERR); + return; + } + nia_data.mcast_addr = (t_addr)(word & AMASK); + nia_load_mcast(); + /* Load read count buffer address */ + if (Mem_read_word(nia_data.pcb + PCB_RCB, &word, 0)) { + nia_error(EBSERR); + return; + } + nia_data.rcb = (t_addr)(word & AMASK); + nia_data.status |= NIA_ECP; + nia_data.status &= ~NIA_DCP; +} + +/* + * Disable NIA 20. + */ +void nia_disable() +{ + nia_data.status |= NIA_DCP; + nia_data.status &= ~NIA_ECP; } /* * Copy a MAC address from string to memory word. */ -void nia_cpy_mac(UNIT *uptr, uint64 word1, uint64 word2, ETH_MAC *mac) +void nia_cpy_mac(uint64 word1, uint64 word2, ETH_MAC *mac) { ETH_MAC m; m[0] = (unsigned char)((word1 >> 28) & 0xff); @@ -592,7 +657,7 @@ void nia_cpy_mac(UNIT *uptr, uint64 word1, uint64 word2, ETH_MAC *mac) /* * Copy memory to a packet. */ -uint8 *nia_cpy_to(UNIT *uptr, t_addr addr, uint8 *data, int len) +uint8 *nia_cpy_to(t_addr addr, uint8 *data, int len) { uint64 word; /* Copy full words */ @@ -628,7 +693,7 @@ uint8 *nia_cpy_to(UNIT *uptr, t_addr addr, uint8 *data, int len) /* * Copy a packet to memory. */ -uint8 *nia_cpy_from(UNIT *uptr, t_addr addr, uint8 *data, int len) +uint8 *nia_cpy_from(t_addr addr, uint8 *data, int len) { uint64 word; @@ -662,10 +727,142 @@ uint8 *nia_cpy_from(UNIT *uptr, t_addr addr, uint8 *data, int len) return data; } +/* + * Get next entry off a queue. + * Return entry in *entry and 1 if successfull. + * Returns 0 if fail, queue locked or memory out of bounds. + */ +int nia_getq(t_addr head, t_addr *entry) +{ + uint64 temp; + t_addr flink; + t_addr nlink; + int i; + *entry = 0; /* For safty */ + + /* Try and get lock */ + if (Mem_read_word(head, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + /* Check if entry locked */ + if ((temp & SMASK) == 0) + return 0; + + /* Increment lock here */ + + /* Get head of queue */ + if (Mem_read_word(head + 1, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + flink = (t_addr)(temp & AMASK); + /* Check if queue empty */ + if (flink == (head+1)) { + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA empty %08o\n", head); + /* Decrement lock here */ + return 1; + } + /* Get link to next entry */ + if (Mem_read_word(flink + 1, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + nlink = (t_addr)(temp & AMASK); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA head: q=%08o f=%08o n=%08o\n", + head, flink, nlink); + /* Set Head Flink to point to next */ + temp = (uint64)nlink; + if (Mem_write_word(head+1, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + /* Set Next Blink to head */ + temp = (uint64)(head + 1); + if (Mem_write_word(nlink+1, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + /* Return entry */ + *entry = flink; + + /* Decrement lock here */ + return 1; +} + + +/* + * Put entry on head of queue. + * Return entry in *entry and 1 if successfull. + * Returns 0 if fail, queue locked or memory out of bounds. + */ +int nia_putq(t_addr head, t_addr *entry) +{ + uint64 temp; + t_addr blink; + + /* Try and get lock */ + if (Mem_read_word(head, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + /* Check if entry locked */ + if ((temp & SMASK) == 0) + return 0; + + /* Increment lock here */ + + /* Hook entry into tail of queue */ + if (Mem_read_word(head + 2, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + + blink = (t_addr)(temp & AMASK); /* Get back link */ + /* Get link to previous entry */ + temp = (uint64)*entry; + if (Mem_write_word(blink, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + /* Old forward is new */ + if (Mem_write_word(head+2, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + + /* Flink is head of queue */ + temp = (uint64)(head+1); + if (Mem_write_word(*entry, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + + /* Back link points to previous */ + temp = (uint64)blink; + if (Mem_write_word(*entry+1, &temp, 0)) { + nia_error(EBSERR); + return 0; + } + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put: q=%08o i=%08o b=%08o\n", + head, *entry, blink); + *entry = 0; + /* Decement lock here */ + + /* Check if Queue was empty, and response queue */ + if (blink == (head+1) && head == nia_data.resp_hdr) { + nia_data.status |= NIA_RQA; + set_interrupt(NIA_DEVNUM, nia_data.pia); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA set response\n"); + } + return 1; +} + + /* * Load in the protocol type table */ -void nia_load_ptt(UNIT *uptr) +void nia_load_ptt() { int i; int n = 0; @@ -674,9 +871,17 @@ void nia_load_ptt(UNIT *uptr) for (i = 0; i < 17; i++) { uint64 word1, word2; - word1 = M[addr++]; - word2 = M[addr++]; - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %012llo %012llo\n\r",n, word1, word2); + /* Get entry */ + if (Mem_read_word(addr++, &word1, 0)) { + nia_error(EBSERR); + return; + } + if (Mem_read_word(addr++, &word2, 0)) { + nia_error(EBSERR); + return; + } + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %012llo %012llo\n\r", + n, word1, word2); if (word1 & SMASK) { uint16 type; type = (uint16)(word1 >> 12) & 0xff; @@ -687,21 +892,20 @@ void nia_load_ptt(UNIT *uptr) } addr++; } - for (i = 0; i < n; i++) { - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %04x %010o\n\r",n, nia_data.ptt_proto[i], - nia_data.ptt_head[i]); - } + for (i = 0; i < n; i++) + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %04x %010o\n\r", + n, nia_data.ptt_proto[i], nia_data.ptt_head[i]); nia_data.ptt_n = n; } /* * Load in the multi-cast table */ -void nia_load_mcast(UNIT *uptr) +void nia_load_mcast() { int i; int n = 0; - char buffer[20]; + char buffer[20]; t_addr addr = nia_data.mcast_addr; /* Start with our own address. */ @@ -710,28 +914,36 @@ void nia_load_mcast(UNIT *uptr) memcpy(&nia_data.macs[n], &broadcast_ethaddr, sizeof (ETH_MAC)); n++; for (i = 0; i < 17; i++) { - uint64 word1, word2; + uint64 word1, word2; - word1 = M[addr++]; - word2 = M[addr++]; - if (word2 & 1) { - nia_cpy_mac(uptr, word1, word2, &nia_data.macs[n]); - n++; - } + if (Mem_read_word(addr++, &word1, 0)) { + nia_error(EBSERR); + return; + } + if (Mem_read_word(addr++, &word2, 0)) { + nia_error(EBSERR); + return; + } + if (word2 & 1) { + nia_cpy_mac(word1, word2, &nia_data.macs[n]); + n++; + } } for(i = 0; i< n; i++) { eth_mac_fmt(&nia_data.macs[i], buffer); - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load mcast%d: %s\n\r",i, buffer); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load mcast%d: %s\n\r",i,buffer); } nia_data.macs_n = n - 2; - if (uptr->flags & UNIT_ATT) - eth_filter (&nia_data.etherface, n, nia_data.macs, nia_data.amc, nia_data.prmsc); + if (nia_recv_uptr->flags & UNIT_ATT) + eth_filter (&nia_data.etherface, n, nia_data.macs, nia_data.amc, + nia_data.prmsc); } /* * Pretty print a packet for debugging. */ -void nia_packet_debug(struct nia_device *nia, const char *action, ETH_PACK *packet) { +void nia_packet_debug(struct nia_device *nia, const char *action, + ETH_PACK *packet) { struct nia_eth_hdr *eth = (struct nia_eth_hdr *)&packet->msg[0]; struct arp_hdr *arp = (struct arp_hdr *)eth; struct ip *ip = (struct ip *)&packet->msg[sizeof(struct nia_eth_hdr)]; @@ -887,58 +1099,91 @@ void nia_packet_debug(struct nia_device *nia, const char *action, ETH_PACK *pack /* * Send out a packet. */ -int nia_send_pkt(UNIT *uptr) +int nia_send_pkt(uint64 cmd) { - uint64 word1, word2, cmd; - struct nia_eth_hdr *hdr = (struct nia_eth_hdr *)(&nia_data.snd_buff.msg[0]); + uint64 word1, word2; + struct nia_eth_hdr *hdr = (struct nia_eth_hdr *)(&nia_data.snd_buff.msg[0]); uint8 *data = &nia_data.snd_buff.msg[sizeof(struct nia_eth_hdr)]; ETH_MAC dest; uint16 type; int len; int blen; - len = (int)(M[nia_data.cmd_entry + 4] & 0177777) + sizeof(struct nia_eth_hdr); + /* Read packet length */ + if (Mem_read_word(nia_data.cmd_entry + 4, &word1, 0)) { + nia_error(EBSERR); + return 0; + } + len = (int)(word1 & 0177777); + blen = len + sizeof(struct nia_eth_hdr); /* Check for runt packet */ - if (len < ETH_MIN_PACKET && (cmd & (NIA_FLG_PAD << 20)) == 0) { + if (blen < ETH_MIN_PACKET && (cmd & (NIA_FLG_PAD << 8)) == 0) { return NIA_ERR_RUN; } /* Check for too long of a packet */ - if (len > ETH_MAX_PACKET) { + if (blen > ETH_MAX_PACKET) { nia_data.pcnt[NIA_CNT_XF]++; nia_data.pcnt[NIA_CNT_XFM] |= NIA_XFM_XFL; return NIA_ERR_LNG; } - if ((uptr->flags & UNIT_ATT) == 0) + /* If unit not attached, nothing more we can do */ + if ((nia_recv_uptr->flags & UNIT_ATT) == 0) return 0; - len -= sizeof(struct nia_eth_hdr); - /* Load destination address */ - word1 = M[nia_data.cmd_entry+7]; - word2 = M[nia_data.cmd_entry+8]; - nia_cpy_mac(uptr, word1, word2, &dest); - memcpy(hdr->dest, dest, sizeof(ETH_MAC)); - /* Copy our address over */ - memcpy(hdr->src, nia_data.mac, sizeof(ETH_MAC)); - /* Copy protocol type */ - word1 = M[nia_data.cmd_entry+5]; + /* Read protocol type */ + if (Mem_read_word(nia_data.cmd_entry + 5, &word1, 0)) { + nia_error(EBSERR); + return 0; + } type = (uint16)(word1 >> 12) & 0xff; type |= (uint16)(word1 << 4) & 0xff00; hdr->type = htons(type); + + /* Load destination address */ + if (Mem_read_word(nia_data.cmd_entry + 7, &word1, 0)) { + nia_error(EBSERR); + return 0; + } + if (Mem_read_word(nia_data.cmd_entry + 8, &word2, 0)) { + nia_error(EBSERR); + return 0; + } + nia_cpy_mac(word1, word2, &dest); + memcpy(hdr->dest, dest, sizeof(ETH_MAC)); + /* Copy our address over */ + memcpy(hdr->src, nia_data.mac, sizeof(ETH_MAC)); + /* Set packet length */ nia_data.snd_buff.len = len + sizeof(struct nia_eth_hdr); /* Copy over rest of packet */ - cmd = (M[nia_data.cmd_entry + 3] >> 20); - if (cmd & NIA_FLG_BSD) { - word1 = M[nia_data.cmd_entry + 9] & AMASK; + if (cmd & (NIA_FLG_BSD << 8)) { + if (Mem_read_word(nia_data.cmd_entry + 9, &word1, 0)) { + nia_error(EBSERR); + return 0; + } while (len > 0) { - word2 = M[word1] & AMASK; - blen = (int)(M[word1+2] & 0177777); - data = nia_cpy_to(uptr, word2, data, blen); + uint64 tlen; + /* Read pointer to buffer */ + if (Mem_read_word((t_addr)(word1 & AMASK), &word2, 0)) { + nia_error(EBSERR); + return 0; + } + /* Read length */ + if (Mem_read_word((t_addr)((word1+2) & AMASK), &tlen, 0)) { + nia_error(EBSERR); + return 0; + } + blen = (int)(tlen & 0177777); + data = nia_cpy_to(word2, data, blen); len -= blen; - word1 = M[word1+1] & AMASK; + if (Mem_read_word((t_addr)((word1 + 1) & AMASK), &word1, 0)) { + nia_error(EBSERR); + return 0; + } } } else { - data = nia_cpy_to(uptr, nia_data.cmd_entry + 9, data, len); + data = nia_cpy_to(nia_data.cmd_entry + 9, data, len); } - if (cmd & NIA_FLG_PAD && nia_data.snd_buff.len < ETH_MIN_PACKET) { + if ((cmd & (NIA_FLG_PAD << 8) != 0) && + nia_data.snd_buff.len < ETH_MIN_PACKET) { while (nia_data.snd_buff.len < ETH_MIN_PACKET) { *data = 0; nia_data.snd_buff.len++; @@ -954,110 +1199,10 @@ int nia_send_pkt(UNIT *uptr) return 0; } -/* - * Enable NIA 20. - * - * Read in PTT and MACS table. - */ -void nia_enable(UNIT *uptr) -{ - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA enable\n"); - /* Load pointers to various table */ - nia_data.unk_len = (int)(M[(nia_data.unk_hdr + PCB_UPL) & AMASK] & AMASK); - /* Load PTT */ - nia_data.ptt_addr = (t_addr)(M[(nia_data.pcb + PCB_PTT) & AMASK] & AMASK); - nia_load_ptt(uptr); - /* Load MCT */ - nia_data.mcast_addr = (t_addr)(M[(nia_data.pcb + PCB_MCT) & AMASK] & AMASK); - nia_load_mcast(uptr); - /* Load read count buffer address */ - nia_data.rcb = (t_addr)(M[(nia_data.pcb + PCB_RCB) & AMASK] & AMASK); - uptr->STATUS |= NIA_ECP; - uptr->STATUS &= ~NIA_DCP; - /* Start receiver */ - sim_activate(&nia_unit[1], 200); -} - -/* - * Disable NIA 20. - */ -void nia_disable(UNIT *uptr) -{ - uptr->STATUS |= NIA_DCP; - uptr->STATUS &= ~NIA_ECP; - /* Stop receiver */ - sim_cancel(&nia_unit[1]); -} - -/* Get next entry off a queue. Returns 0 if fail */ -int nia_getq(t_addr head, t_addr *entry) -{ - uint64 temp; - t_addr flink; - t_addr nlink; - int i; - *entry = 0; /* For safty */ - - temp = M[head]; - /* Check if entry locked */ - if ((temp & SMASK) == 0) - return 0; - - /* Increment lock here */ - - flink = (t_addr)(M[head+1] & AMASK); - /* Check if queue empty */ - if (flink == (head+1)) { - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA empty %08o\n", head); - /* Decrement lock here */ - return 1; - } - nlink = (t_addr)(M[flink] & AMASK); - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA head: q=%08o f=%08o n=%08o\n", head, flink, nlink); - M[head+1] = (uint64)nlink; /* Set Head Flink to point to next */ - M[nlink+1] = (uint64)(head + 1); /* Set Next Blink to head */ - *entry = flink; - - /* Decrement lock here */ - return 1; -} - -/* Put entry on head of queue. */ -int nia_putq(UNIT *uptr, t_addr head, t_addr *entry) -{ - uint64 temp; - t_addr blink; - - temp = M[head]; - /* Check if entry locked */ - if ((temp & SMASK) == 0) - return 0; - - /* Increment lock here */ - - /* Set up entry. */ - blink = (t_addr)(M[head+2] & AMASK); /* Get back link */ - M[blink] = (uint64)*entry; /* Old prevous entry */ - M[*entry] = (uint64)(head+1); /* Flink is head of queue */ - M[*entry+1] = (uint64)blink; /* Back link points to previous */ - M[head+2] = (uint64)*entry; /* Old forward is new */ - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put: q=%08o i=%08o b=%08o\n", head, *entry, blink); - *entry = 0; - /* Decement lock here */ - - /* Check if Queue was empty, and response queue */ - if (blink == (head+1) && head == nia_data.resp_hdr) { - uptr->STATUS |= NIA_RQA; - set_interrupt(NIA_DEVNUM, nia_data.pia); - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA set response\n"); - } - return 1; -} - /* * Process commands. */ -t_stat nia_srv(UNIT * uptr) +t_stat nia_cmd_srv(UNIT * uptr) { t_addr free_q = nia_data.unk_hdr; uint64 word1, word2; @@ -1065,10 +1210,10 @@ t_stat nia_srv(UNIT * uptr) int len, i; int err; - /* See if we have command to process */ + /* See if we have command that we could not respond too */ if (nia_data.cmd_entry != 0) { /* Have to put this either on response queue or free queue */ - if (nia_putq(uptr, nia_data.cmd_rply, &nia_data.cmd_entry) == 0) { + if (nia_putq(nia_data.cmd_rply, &nia_data.cmd_entry) == 0){ sim_activate(uptr, 200); /* Reschedule ourselves to deal with it */ return SCPE_OK; } @@ -1076,7 +1221,7 @@ t_stat nia_srv(UNIT * uptr) } /* Check if we are running */ - if ((uptr->STATUS & NIA_MRN) == 0 || (uptr->STATUS & NIA_CQA) == 0) { + if ((nia_data.status & NIA_MRN) == 0 || (nia_data.status & NIA_CQA) == 0) { return SCPE_OK; } @@ -1090,37 +1235,46 @@ t_stat nia_srv(UNIT * uptr) /* Check if we got one */ if (nia_data.cmd_entry == 0) { /* Nothing to do */ - uptr->STATUS &= ~NIA_CQA; + nia_data.status &= ~NIA_CQA; return SCPE_OK; } - /* Preform function of command */ - cmd = (uint32)(M[nia_data.cmd_entry + 3] >> 12); + /* Get command */ + if (Mem_read_word(nia_data.cmd_entry + 3, &word1, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } + cmd = (uint32)(word1 >> 12); /* Save initial status */ nia_data.cmd_status = ((uint8)(cmd >> 16)) & 0xff; sim_debug(DEBUG_DETAIL, &nia_dev, "NIA cmd: %08x\n", cmd); cmd &= 0xffff; len = 5; + /* Preform function of command */ switch(cmd & 0xff) { case NIA_CMD_SND: /* Send a datagram */ - err = nia_send_pkt(uptr); + err = nia_send_pkt(cmd); if (err != 0) cmd |= ((err<<1)|1) << 16; cmd |= NIA_STS_SR << 16; len = 10; break; case NIA_CMD_LPTT: /* Load Protocol Type table */ - nia_load_ptt(uptr); + nia_load_ptt(); break; case NIA_CMD_LMAC: /* Load Multicast table */ - nia_load_mcast(uptr); + nia_load_mcast(); break; case NIA_CMD_RCNT: /* Read counts */ for (i = 0; i < NIA_CNT_LEN; i++) { - M[nia_data.cnt_addr + i] = nia_data.pcnt[i]; + word1 = nia_data.pcnt[i]; + if (Mem_write_word(nia_data.cnt_addr + i, &word1, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } if ((cmd & (NIA_FLG_CLRC << 20)) != 0) nia_data.pcnt[i] = 0; - } + } break; case NIA_CMD_WPLI: /* Write PLI */ break; @@ -1132,25 +1286,53 @@ t_stat nia_srv(UNIT * uptr) word1 |= ((uint64)nia_data.mac[1]) << 20; word1 |= ((uint64)nia_data.mac[2]) << 12; word1 |= ((uint64)nia_data.mac[3]) << 4; - M[nia_data.cmd_entry + 4] = word1; word2 = ((uint64)nia_data.mac[4]) << 28; word2 |= ((uint64)nia_data.mac[5]) << 20; - M[nia_data.cmd_entry + 5] = word2; - M[nia_data.cmd_entry + 6] = (uint64)((nia_data.amc << 2)| - (nia_data.h4000 << 1) |nia_data.prmsc); - M[nia_data.cmd_entry + 7] = (nia_data.uver[3] << 12) | (0xF << 6) | 0xF; + if (Mem_write_word(nia_data.cmd_entry + 4, &word1, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } + if (Mem_write_word(nia_data.cmd_entry + 5, &word2, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } + word1 = (uint64)((nia_data.amc << 2)| (nia_data.h4000 << 1) + | nia_data.prmsc); + /* Micro code version, PTT len MACS len */ + word2 = (nia_data.uver[3] << 12) |(0xF << 6)|0xF; + if (Mem_write_word(nia_data.cmd_entry + 6, &word1, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } + if (Mem_write_word(nia_data.cmd_entry + 7, &word2, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } break; case NIA_CMD_WNSA: /* Write Station Address */ len = 8; - word1 = M[nia_data.cmd_entry+4]; - word2 = M[nia_data.cmd_entry+5]; - nia_cpy_mac(uptr, word1, word2, &nia_data.mac); - word1 = M[nia_data.cmd_entry+6]; + if (Mem_read_word(nia_data.cmd_entry + 4, &word1, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } + if (Mem_read_word(nia_data.cmd_entry + 5, &word2, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } + nia_cpy_mac(word1, word2, &nia_data.mac); + if (Mem_read_word(nia_data.cmd_entry + 6, &word1, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } + if (Mem_read_word(nia_data.cmd_entry + 7, &word2, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } nia_data.prmsc = (int)(word1 & 1); nia_data.h4000 = (int)((word1 & 2) != 0); nia_data.amc = (int)((word1 & 4) != 0); memcpy(&nia_data.macs[0], &nia_data.mac, sizeof (ETH_MAC)); - if (uptr->flags & UNIT_ATT) + if (nia_recv_uptr->flags & UNIT_ATT) eth_filter (&nia_data.etherface, nia_data.macs_n + 2, nia_data.macs, 0, 0); break; @@ -1162,24 +1344,27 @@ t_stat nia_srv(UNIT * uptr) } nia_data.cmd_rply = nia_data.unk_hdr; - M[nia_data.cmd_entry+3] = ((uint64)cmd) << 12; + word1 = ((uint64)cmd) << 12; + if (Mem_write_word(nia_data.cmd_entry + 3, &word1, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } if (((cmd >> 16) & 1) != 0 || (cmd & (NIA_FLG_RESP << 8)) != 0) { nia_data.cmd_rply = nia_data.resp_hdr; } else if ((cmd & 0xff) == NIA_CMD_SND) { nia_data.cmd_rply = M[nia_data.cmd_entry + 5]; } for(i = 0; i < len; i++) - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA rcmd: %d %09llx %012llo\n", i, M[nia_data.cmd_entry + i], - M[nia_data.cmd_entry + i]); - (void)nia_putq(uptr, nia_data.cmd_rply, &nia_data.cmd_entry); + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA rcmd: %d %09llx %012llo\n", + i, M[nia_data.cmd_entry + i], M[nia_data.cmd_entry + i]); + (void)nia_putq(nia_data.cmd_rply, &nia_data.cmd_entry); sim_activate(uptr, 500); return SCPE_OK; } -/* - * Receive ether net packets. - */ -t_stat nia_eth_srv(UNIT * uptr) + +int +nia_rec_pkt() { struct nia_eth_hdr *hdr; uint16 type; @@ -1187,40 +1372,19 @@ t_stat nia_eth_srv(UNIT * uptr) int len; t_addr queue; t_addr bsd; - t_addr word; + uint64 word; uint8 *data; - sim_clock_coschedule(uptr, 100); /* continue poll */ - - /* Check if we are running */ - if ((nia_unit[0].STATUS & NIA_MRN) == 0) - return SCPE_OK; - - /* See if we have command to process */ + /* See if we have received packet to process */ if (nia_data.rec_entry != 0) { /* Have to put this response queue */ - if (nia_putq(&nia_unit[0], nia_data.resp_hdr, &nia_data.rec_entry) == 0) - return SCPE_OK; + if (nia_putq(nia_data.resp_hdr, &nia_data.rec_entry) == 0) + return 0; } -loop: - /* Check if we need to get a packet */ - if (nia_data.r_pkt == 0) { - if (eth_read(&nia_data.etherface, &nia_data.rec_buff, NULL) <= 0) - return SCPE_OK; - nia_packet_debug(&nia_data, "recv", &nia_data.rec_buff); - hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]); - type = ntohs(hdr->type); - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA read packet: %d %04x\n", - nia_data.rec_buff.len, type); - nia_data.r_pkt = 1; - nia_data.pcnt[NIA_CNT_BR] += nia_data.rec_buff.len; - nia_data.pcnt[NIA_CNT_FR] ++; - if (hdr->dest[0] & 1) { - nia_data.pcnt[NIA_CNT_MCB] += nia_data.rec_buff.len; - nia_data.pcnt[NIA_CNT_MCF] ++; - } - } + /* If no pending packet, return success */ + if (nia_data.r_pkt == 0) + return 1; /* Determine which queue to get free packet from */ hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]); @@ -1236,49 +1400,144 @@ loop: /* Try to grab place to save packet */ if (nia_getq(queue, &nia_data.rec_entry) == 0) - return SCPE_OK; /* Could not get lock, try later */ + return 0; /* Indicate packet not processed */ + /* If we queue empty, just drop packet */ if (nia_data.rec_entry == 0) { sim_debug(DEBUG_DETAIL, &nia_dev, "NIA drop packet\n"); nia_data.r_pkt = 0; /* Drop packet it queue empty */ if (queue == nia_data.unk_hdr) nia_data.pcnt[NIA_CNT_DUN]++; - else + else nia_data.pcnt[NIA_CNT_D01 + i]++; nia_data.pcnt[NIA_CNT_UBU] += nia_data.rec_buff.len; - return SCPE_OK; + nia_data.status |= NIA_FQE; + set_interrupt(NIA_DEVNUM, nia_data.status & NIA_PIA); + return 1; /* We did what we could with it. */ } - /* Got one, now fill in data */ - M[nia_data.rec_entry + 3] = (uint64)(NIA_CMD_RCV << 12); - (void)nia_cpy_from(&nia_unit[0], nia_data.rec_entry + 5, (uint8 *)&hdr->dest, sizeof(ETH_MAC)); - (void)nia_cpy_from(&nia_unit[0], nia_data.rec_entry + 7, (uint8 *)&hdr->src, sizeof(ETH_MAC)); - M[nia_data.rec_entry + 9] = (uint64)(((type & 0xff00) >> 4) | ((type & 0xff) << 12)); - data = &nia_data.rec_buff.msg[sizeof(struct nia_eth_hdr)]; + /* Get some information about packet */ len = nia_data.rec_buff.len - sizeof(struct nia_eth_hdr); - M[nia_data.rec_entry + 4] = len + 4; - bsd = (t_addr)(M[nia_data.rec_entry + 10] & AMASK); + data = &nia_data.rec_buff.msg[sizeof(struct nia_eth_hdr)]; + + /* Got one, now fill in data */ + word = (uint64)(NIA_CMD_RCV << 12); + if (Mem_write_word(nia_data.rec_entry + 3, &word, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } + word = (uint64)len; + if (Mem_write_word(nia_data.rec_entry + 4, &word, 0)) { + nia_error(EBSERR); + return 0; + } + (void)nia_cpy_from(nia_data.rec_entry + 5, + (uint8 *)&hdr->dest, sizeof(ETH_MAC)); + (void)nia_cpy_from(nia_data.rec_entry + 7, + (uint8 *)&hdr->src, sizeof(ETH_MAC)); + word = (uint64)(((type & 0xff00) >> 4) | + ((type & 0xff) << 12)); + if (Mem_write_word(nia_data.rec_entry + 9, &word, 0)) { + nia_error(EBSERR); + return 0; + } + if (Mem_read_word(nia_data.rec_entry + 10, &word, 0)) { + nia_error(EBSERR); + return 0; + } + bsd = (t_addr)(word & AMASK); while (len > 0) { int blen; - word = (t_addr)(M[bsd] & AMASK); - blen = (int)(M[bsd+2] & 0177777); + /* Get length of segment */ + if (Mem_read_word(bsd+2, &word, 0)) { + nia_error(EBSERR); + return 0; + } + blen = (int)(word & 0177777); if (blen > len) blen = len; - data = nia_cpy_from(&nia_unit[0], word, data, blen); + /* Get address of where to put data */ + if (Mem_read_word(bsd, &word, 0)) { + nia_error(EBSERR); + return 0; + } + data = nia_cpy_from(word, data, blen); len -= blen; - bsd = M[bsd+1] & AMASK; + /* Get pointer to next segment */ + if (Mem_read_word(bsd+1, &word, 0)) { + nia_error(EBSERR); + return 0; + } + bsd = word & AMASK; } for(i = 0; i < 10; i++) - sim_debug(DEBUG_DETAIL, &nia_dev, "NIA recv: %d %09llx %012llo\n", i, M[nia_data.rec_entry + i], - M[nia_data.rec_entry + i]); - /* Put on response queue */ - if (nia_putq(&nia_unit[0], nia_data.resp_hdr, &nia_data.rec_entry) == 0) - return SCPE_OK; /* Could not get lock, try again */ + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA recv: %d %09llx %012llo\n", + i, M[nia_data.rec_entry + i], M[nia_data.rec_entry + i]); + /* All done with packet */ nia_data.r_pkt = 0; + /* Put on response queue */ + return nia_putq(nia_data.resp_hdr, &nia_data.rec_entry); +} + +/* + * Receive ether net packets. + */ +t_stat nia_eth_srv(UNIT * uptr) +{ + struct nia_eth_hdr *hdr; + uint16 type; + + /* Check if we need to get a packet */ + while (nia_data.r_pkt == 0) { + if (eth_read(&nia_data.etherface, &nia_data.rec_buff, NULL) <= 0) + return SCPE_OK; + + nia_packet_debug(&nia_data, "recv", &nia_data.rec_buff); + hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]); + type = ntohs(hdr->type); + /* Check if we are running */ + if ((nia_data.status & NIA_MRN) == 0) { + sim_debug(DEBUG_DETAIL, &nia_dev, + "NIA read packet - not running: %d %04x\n", + nia_data.rec_buff.len, type); + return SCPE_OK; + } + + sim_debug(DEBUG_DETAIL, &nia_dev, "NIA read packet: %d %04x\n", + nia_data.rec_buff.len, type); + nia_data.r_pkt = 1; /* Mark packet buffer full */ + nia_data.pcnt[NIA_CNT_BR] += nia_data.rec_buff.len; + nia_data.pcnt[NIA_CNT_FR] ++; + if (hdr->dest[0] & 1) { + nia_data.pcnt[NIA_CNT_MCB] += nia_data.rec_buff.len; + nia_data.pcnt[NIA_CNT_MCF] ++; + } + + /* Try to process the packet */ + if (nia_rec_pkt() == 0) { + sim_activate(nia_proc_uptr, 100); + return SCPE_OK; + } + } return SCPE_OK; } +/* + * Handle delayed packets. + */ +t_stat nia_rec_srv(UNIT * uptr) +{ + + /* Process what we have */ + if (nia_rec_pkt() == 0) { + sim_activate(uptr, 100); + return SCPE_OK; + } + /* See if we can pick up any more packets */ + return nia_eth_srv(nia_recv_uptr); +} + t_stat nia_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc) @@ -1313,7 +1572,7 @@ t_stat nia_reset (DEVICE *dptr) break; } if (i == 6) { /* First call to reset? */ - /* Set a default MAC address in a BBN assigned OID range no longer in use */ + /* Set a default MAC address in a BBN assigned OID range no longer in use */ nia_set_mac (dptr->units, 0, "00:00:02:00:00:00/24", NULL); } return SCPE_OK; @@ -1334,38 +1593,43 @@ t_stat nia_attach(UNIT* uptr, CONST char* cptr) memcpy(&nia_data.macs[1], &broadcast_ethaddr, 6); status = eth_open(&nia_data.etherface, cptr, &nia_dev, DEBUG_ETHER); if (status != SCPE_OK) { - free(tptr); - return status; + free(tptr); + return status; } eth_mac_fmt(&nia_data.mac, buf); /* format ethernet mac address */ - if (SCPE_OK != eth_check_address_conflict (&nia_data.etherface, &nia_data.mac)) { - eth_close(&nia_data.etherface); - free(tptr); - return sim_messagef (SCPE_NOATT, "%s: MAC Address Conflict on LAN for address %s\n", + if (SCPE_OK != eth_check_address_conflict (&nia_data.etherface, + &nia_data.mac)) { + eth_close(&nia_data.etherface); + free(tptr); + return sim_messagef (SCPE_NOATT, + "%s: MAC Address Conflict on LAN for address %s\n", nia_dev.name, buf); } if (SCPE_OK != eth_filter(&nia_data.etherface, 2, nia_data.macs, 0, 0)) { - eth_close(&nia_data.etherface); - free(tptr); - return sim_messagef (SCPE_NOATT, "%s: Can't set packet filter for MAC Address %s\n", + eth_close(&nia_data.etherface); + free(tptr); + return sim_messagef (SCPE_NOATT, + "%s: Can't set packet filter for MAC Address %s\n", nia_dev.name, buf); } uptr->filename = tptr; uptr->flags |= UNIT_ATT; - eth_setcrc(&nia_data.etherface, 0); /* Don't need CRC */ + eth_setcrc(&nia_data.etherface, 1); /* Enable CRC */ /* init read queue (first time only) */ status = ethq_init(&nia_data.ReadQ, 8); if (status != SCPE_OK) { - eth_close(&nia_data.etherface); - uptr->filename = NULL; - free(tptr); - return sim_messagef (status, "%s: Can't initialize receive queue\n", nia_dev.name); + eth_close(&nia_data.etherface); + uptr->filename = NULL; + free(tptr); + return sim_messagef (status, "%s: Can't initialize receive queue\n", + nia_dev.name); } - eth_set_async (&nia_data.etherface, 0); /* Allow Asynchronous inbound packets */ + /* Allow Asynchronous inbound packets */ + eth_set_async (&nia_data.etherface, 0); return SCPE_OK; } @@ -1379,7 +1643,6 @@ t_stat nia_detach(UNIT* uptr) free(uptr->filename); uptr->filename = NULL; uptr->flags &= ~UNIT_ATT; - sim_cancel (uptr+1); /* stop the packet receiving services */ } return SCPE_OK; } From b75cdfc3e346d519589c5ef56d7bb31af6663d40 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 16 Feb 2020 00:32:32 -0500 Subject: [PATCH 94/98] KA10: Cleanup compiler warnings. --- PDP10/kl10_nia.c | 17 +++++++++-------- PDP10/kx10_cpu.c | 10 ++++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/PDP10/kl10_nia.c b/PDP10/kl10_nia.c index 6102a71..757d7e1 100644 --- a/PDP10/kl10_nia.c +++ b/PDP10/kl10_nia.c @@ -737,7 +737,6 @@ int nia_getq(t_addr head, t_addr *entry) uint64 temp; t_addr flink; t_addr nlink; - int i; *entry = 0; /* For safty */ /* Try and get lock */ @@ -958,7 +957,6 @@ void nia_packet_debug(struct nia_device *nia, const char *action, char dst_ip[20]; char src_port[8]; char dst_port[8]; - char mac_buf[20]; char flags[64]; static struct tcp_flag_bits { const char *name; @@ -1172,7 +1170,7 @@ int nia_send_pkt(uint64 cmd) return 0; } blen = (int)(tlen & 0177777); - data = nia_cpy_to(word2, data, blen); + data = nia_cpy_to((t_addr)(word2 & AMASK), data, blen); len -= blen; if (Mem_read_word((t_addr)((word1 + 1) & AMASK), &word1, 0)) { nia_error(EBSERR); @@ -1182,7 +1180,7 @@ int nia_send_pkt(uint64 cmd) } else { data = nia_cpy_to(nia_data.cmd_entry + 9, data, len); } - if ((cmd & (NIA_FLG_PAD << 8) != 0) && + if (((cmd & (NIA_FLG_PAD << 8)) != 0) && nia_data.snd_buff.len < ETH_MIN_PACKET) { while (nia_data.snd_buff.len < ETH_MIN_PACKET) { *data = 0; @@ -1352,7 +1350,11 @@ t_stat nia_cmd_srv(UNIT * uptr) if (((cmd >> 16) & 1) != 0 || (cmd & (NIA_FLG_RESP << 8)) != 0) { nia_data.cmd_rply = nia_data.resp_hdr; } else if ((cmd & 0xff) == NIA_CMD_SND) { - nia_data.cmd_rply = M[nia_data.cmd_entry + 5]; + if (Mem_read_word(nia_data.cmd_entry + 5, &word1, 0)) { + nia_error(EBSERR); + return SCPE_OK; + } + nia_data.cmd_rply = (t_addr)(word1 & AMASK); } for(i = 0; i < len; i++) sim_debug(DEBUG_DETAIL, &nia_dev, "NIA rcmd: %d %09llx %012llo\n", @@ -1461,14 +1463,14 @@ nia_rec_pkt() nia_error(EBSERR); return 0; } - data = nia_cpy_from(word, data, blen); + data = nia_cpy_from((t_addr)(word & AMASK), data, blen); len -= blen; /* Get pointer to next segment */ if (Mem_read_word(bsd+1, &word, 0)) { nia_error(EBSERR); return 0; } - bsd = word & AMASK; + bsd = (t_addr)(word & AMASK); } for(i = 0; i < 10; i++) @@ -1565,7 +1567,6 @@ t_stat nia_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc) t_stat nia_reset (DEVICE *dptr) { int i; - struct nia_packet *p; for (i = 0; i < 6; i++) { if (nia_data.mac[i] != 0) diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index b4223e1..690b70b 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -2462,7 +2462,8 @@ void set_reg(int reg, uint64 value) { int Mem_read(int flag, int cur_context, int fetch) { t_addr addr; - if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { + if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || + (glb_sect && sect == 1))) || !QKLB)) { if (xct_flag != 0 && !fetch) { if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || @@ -2474,7 +2475,7 @@ int Mem_read(int flag, int cur_context, int fetch) { } /* Check if invalid section */ if (QKLB && t20_page && !flag && (sect & 07740) != 0) { - fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); + fault_data = (027LL << 30) | (uint64)AB | (((uint64)sect) << 18); if (USER==0) /* U */ fault_data |= SMASK; /* BIT0 */ page_fault = 1; @@ -2499,7 +2500,8 @@ int Mem_read(int flag, int cur_context, int fetch) { int Mem_write(int flag, int cur_context) { t_addr addr; - if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || (glb_sect && sect == 1))) || !QKLB)) { + if (AB < 020 && ((QKLB && (glb_sect == 0 || sect == 0 || + (glb_sect && sect == 1))) || !QKLB)) { if (xct_flag != 0) { if (((xct_flag & 8) != 0 && cur_context && !ptr_flg) || ((xct_flag & 4) != 0 && !cur_context && !BYF5 && !ptr_flg) || @@ -2511,7 +2513,7 @@ int Mem_write(int flag, int cur_context) { } /* Check if invalid section */ if (QKLB && t20_page && !flag && (sect & 07740) != 0) { - fault_data = (027LL << 30) | (uint64)addr | (((uint64)sect) << 18); + fault_data = (027LL << 30) | (uint64)AB | (((uint64)sect) << 18); if (USER==0) /* U */ fault_data |= SMASK; /* BIT0 */ page_fault = 1; From 67d859b359914d3280f9f1791caa465e57c2ad71 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 16 Feb 2020 18:49:42 -0500 Subject: [PATCH 95/98] KA10: Added save of internal state to devices. Also SNA for FE. --- PDP10/kl10_fe.c | 397 ++++++++++++++++++++++++++++++----------------- PDP10/kl10_nia.c | 8 +- PDP10/kx10_cpu.c | 23 ++- PDP10/kx10_imp.c | 7 +- 4 files changed, 290 insertions(+), 145 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 9bd4ba7..348ef00 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -258,6 +258,12 @@ struct _buffer { } cty_in, cty_out; int cty_done; +#define full(q) ((((q)->in_ptr + 1) & 0xff) == (q)->out_ptr) +#define empty(q) ((q)->in_ptr == (q)->out_ptr) +#define not_empty(q) ((q)->in_ptr != (q)->out_ptr) +#define inco(q) (q)->out_ptr = ((q)->out_ptr + 1) & 0xff +#define inci(q) (q)->in_ptr = ((q)->in_ptr + 1) & 0xff + DIB dte_dib[] = { { DTE_DEVNUM|000, 1, dte_devio, dte_devirq}, }; @@ -561,13 +567,16 @@ t_stat dte_devio(uint32 dev, uint64 *data) { } if (dte_unit[0].STATUS & (DTE_10DB|DTE_11DN|DTE_10DN|DTE_11ER|DTE_10ER)) set_interrupt(dev, dte_unit[0].STATUS); - sim_debug(DEBUG_CONO, &dte_dev, "CTY %03o CONO %06o %06o\n", dev, (uint32)*data, PC); + sim_debug(DEBUG_CONO, &dte_dev, "CTY %03o CONO %06o %06o\n", dev, + (uint32)*data, PC); break; case DATAI: - sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAI %06o\n", dev, (uint32)*data); + sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAI %06o\n", dev, + (uint32)*data); break; case DATAO: - sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAO %06o\n", dev, (uint32)*data); + sim_debug(DEBUG_DATAIO, &dte_dev, "CTY %03o DATAO %06o\n", dev, + (uint32)*data); if (*data == 01365) { dte_unit[0].STATUS |= DTE_SEC|DTE_10ER; dte_unit[0].STATUS &= ~(DTE_10DB|DTE_IND|DTE_11DB); @@ -631,19 +640,19 @@ void dte_second(UNIT *uptr) { default: case SEC_MONO: /* Ouput character in monitor mode */ ch = (int32)(word & 0177); - if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) { + if (full(&cty_out)) { sim_activate(uptr, 200); return; } if (ch != 0) { - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - cty_out.buff[cty_out.in_ptr] = (char)(word & 0x7f); - cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + cty_out.buff[cty_out.in_ptr] = ch & 0x7f; + inci(&cty_out); sim_activate(&dte_unit[1], 200); } M[SEC_DTCHR + base] = ch; M[SEC_DTMTD + base] = FMASK; break; + case SEC_SETPRI: enter_pri: if (Mem_examine_word(0, 0, &word)) @@ -659,28 +668,31 @@ enter_pri: dte_in_cmd = dte_out_res = 0; cty_done = 0; /* Start input process */ - M[SEC_DTCMD + base] = 0; - M[SEC_DTFLG + base] = FMASK; - uptr->STATUS &= ~DTE_11DB; -return; - break; + M[SEC_DTCMD + base] = 0; + M[SEC_DTFLG + base] = FMASK; + uptr->STATUS &= ~DTE_11DB; + return; + case SEC_SETDDT: /* Read character from console */ - if (cty_in.in_ptr == cty_in.out_ptr) { + if (empty(&cty_in)) { M[SEC_DTF11 + base] = 0; M[SEC_DTMTI + base] = FMASK; break; } ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + inco(&cty_in); M[SEC_DTF11 + base] = 0177 & ch; M[SEC_DTMTI + base] = FMASK; break; + case SEC_CLRDDT: /* Clear DDT input mode */ uptr->STATUS &= ~DTE_MON; break; + case SEC_MONON: uptr->STATUS |= DTE_MON; break; + case SEC_RDSW: /* Read switch register */ M[SEC_DTSWR + base] = SW; M[SEC_DTF11 + base] = SW; @@ -700,6 +712,7 @@ return; break; } break; + case SEC_CLKCTL: /* Clock control: Used by KLDCP */ switch(word) { case SEC_CLKOFF: @@ -752,28 +765,28 @@ void dte_its(UNIT *uptr) { sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEOUT = %012llo\n", word); while (cnt > 0) { if (ln < 0) { - if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) + if (full(&cty_out)) return; if (!Mem_read_byte(0, &data, 1)) return; ch = data & 0177; sim_debug(DEBUG_DETAIL, &dte_dev, "CTY queue %x\n", ch); cty_out.buff[cty_out.in_ptr] = ch; - cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + inci(&cty_out); cnt--; if (! sim_is_active(&dte_unit[1])) sim_activate(&dte_unit[1], 50); #if (NUM_DEVS_TTY > 0) } else { struct _buffer *otty = &tty_out[ln]; - if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) + if (full(otty)) return; if (!Mem_read_byte(0, &data, 1)) return; ch = data & 0177; sim_debug(DEBUG_DETAIL, &dte_dev, "TTY queue %x %d\n", ch, ln); otty->buff[otty->in_ptr] = ch; - otty->in_ptr = (otty->in_ptr + 1) & 0xff; + inci(otty); cnt--; #endif } @@ -872,8 +885,10 @@ error: if (s == 0) goto error; in->sz = s; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read Idata: %06o %03o %03o %06o cnt=%o\n", - *dp, *dp >> 8, *dp & 0377, ((*dp & 0377) << 8) | ((*dp >> 8) & 0377), cnt); + sim_debug(DEBUG_DATA, &dte_dev, + "DTE: Read Idata: %06o %03o %03o %06o cnt=%o\n", + *dp, *dp >> 8, *dp & 0377, + ((*dp & 0377) << 8) | ((*dp >> 8) & 0377), cnt); dp++; if (s <= 8) cnt--; @@ -903,7 +918,8 @@ error: cnt -= 2; sim_debug(DEBUG_DATA, &dte_dev, "DTE: Read CMD: %o c=%o f=%o %s d=%o\n", dte_in_ptr, in->cnt, in->func, - ((in->func & 0377) > PRI_EMLDV)?"***":pri_name[in->func & 0377], in->dev); + ((in->func & 0377) > PRI_EMLDV)?"***": + pri_name[in->func & 0377], in->dev); dp = &in->data[0]; for (; cnt > 0; cnt -=2) { /* Read in data */ @@ -942,6 +958,7 @@ dte_function(UNIT *uptr) int32 ch; struct _dte_queue *cmd; int func; + int dev; /* Check if queue is empty */ while (dte_in_cmd != dte_in_ptr) { @@ -951,8 +968,10 @@ dte_function(UNIT *uptr) return; } cmd = &dte_in[dte_in_cmd]; + dev = cmd->dev & 0377; func = cmd->func & 0377; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: func %o %02o %s dev %o cnt %d dcnt %d\n", + sim_debug(DEBUG_DATA, &dte_dev, + "DTE: func %o %02o %s dev %o cnt %d dcnt %d\n", dte_in_cmd, func, (func > PRI_EMLDV) ? "***" : pri_name[func], cmd->dev, cmd->dcnt, cmd->dptr ); switch (func) { @@ -974,9 +993,11 @@ dte_function(UNIT *uptr) case PRI_EMLBE: /* Acknowledge line */ /* Should never get these */ break; + case PRI_EMHDR: /* Here is date and time */ /* Ignore this function */ break; + case PRI_EMRDT: /* Request Date/Time */ { time_t t = time(NULL); @@ -1000,7 +1021,7 @@ dte_function(UNIT *uptr) #if (NUM_DEVS_LP20 > 0) /* Handle printer data */ - if (cmd->dev == PRI_EMLPT) { + if (dev == PRI_EMLPT) { uptr->LPST &= ~(EOFFLG); if (!sim_is_active(&lp20_unit)) sim_activate(&lp20_unit, 1000); @@ -1009,10 +1030,10 @@ dte_function(UNIT *uptr) if ((cmd->dptr & 1) == 0) ch >>= 8; ch &= 0177; - if (((lp20_queue.in_ptr + 1) & 0xff) == lp20_queue.out_ptr) + if (full(&lp20_queue)) return; lp20_queue.buff[lp20_queue.in_ptr] = ch; - lp20_queue.in_ptr = (lp20_queue.in_ptr + 1) & 0xff; + inci(&lp20_queue); cmd->dptr++; } if (cmd->dptr != cmd->dcnt) @@ -1022,13 +1043,13 @@ dte_function(UNIT *uptr) } #endif -#if (NUM_DEVS_TTY > 0) /* Handle terminal data */ - if ((cmd->dev & 0377) == PRI_EMDLS) { + if (dev == PRI_EMDLS) { int ln = cmd->sdev; struct _buffer *otty; if (ln == PRI_CTYDV) goto cty; +#if (NUM_DEVS_TTY > 0) ln -= NUM_DLS; if (ln > 0 && ln >= tty_desc.lines) break; @@ -1041,49 +1062,84 @@ dte_function(UNIT *uptr) ch >>= 8; ch &= 0177; if (ch != 0) { - if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) + if (full(otty)) return; otty->buff[otty->in_ptr] = ch; - otty->in_ptr = (otty->in_ptr + 1) & 0xff; - sim_debug(DEBUG_DATA, &dte_dev, "TTY queue %o %d\n", ch, ln); + inci(otty); + sim_debug(DEBUG_DATA, &dte_dev, "TTY queue %o %d\n", + ch, ln); } cmd->dptr++; } if (cmd->dptr != cmd->dcnt) return; +#endif break; } -#endif - /* Fall through */ - case PRI_EMSNA: /* Send all (ttys) */ - if (cmd->dev != PRI_EMCTY) - break; + + if (dev == PRI_EMCTY) { cty: - sim_activate(&dte_unit[1], 100); - data1[0] = 0; - if (cmd->sz > 8) - cmd->dcnt += cmd->dcnt; - while (cmd->dptr < cmd->dcnt) { - ch = (int32)(cmd->data[cmd->dptr >> 1]); - if ((cmd->dptr & 1) == 0) - ch >>= 8; - ch &= 0177; - if (ch != 0) { - ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); - if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) - return; - cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); - cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; - sim_debug(DEBUG_DATA, &dte_dev, "CTY queue %o\n", ch); - } - cmd->dptr++; + sim_activate(&dte_unit[1], 100); + data1[0] = 0; + if (cmd->sz > 8) + cmd->dcnt += cmd->dcnt; + while (cmd->dptr < cmd->dcnt) { + ch = (int32)(cmd->data[cmd->dptr >> 1]); + if ((cmd->dptr & 1) == 0) + ch >>= 8; + ch &= 0177; + if (ch != 0) { + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + if (full(&cty_out)) + return; + cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); + inci(&cty_out); + sim_debug(DEBUG_DATA, &dte_dev,"CTY queue %o\n",ch); + } + cmd->dptr++; + } + if (cmd->dptr != cmd->dcnt) + return; + } + break; + + case PRI_EMSNA: /* Send all (ttys) */ + /* Handle terminal data */ + if (dev == PRI_EMDLS || dev == PRI_EMCTY) { + struct _buffer *otty; + int ln; + while (cmd->dptr < cmd->dcnt) { + ch = (int32)(cmd->data[cmd->dptr >> 1]); + if ((cmd->dptr & 1) == 0) + ch >>= 8; + ch &= 0177; + if (ch != 0) { + sim_debug(DEBUG_DATA, &dte_dev, "SNA queue %o\n", ch); + ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); + if (!(full(&cty_out))) { + cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); + inci(&cty_out); + } +#if (NUM_DEVS_TTY > 0) + for(ln = 0; ln <= tty_desc.lines; ln++) { + otty = &tty_out[ln]; + if (!(full(otty))) { + otty->buff[otty->in_ptr] = ch; + inci(otty); + } + } +#endif + } + cmd->dptr++; + } + if (cmd->dptr != cmd->dcnt) + return; + data1[0] = 0; } - if (cmd->dptr != cmd->dcnt) - return; break; case PRI_EMLNC: /* Line-Char */ - if (cmd->dev == PRI_EMDLS) { + if (dev == PRI_EMDLS) { sim_activate(&dte_unit[1], 100); while (cmd->dptr < cmd->dcnt) { int ln; @@ -1093,7 +1149,7 @@ cty: if (ch != 0 && ln == PRI_CTYDV) { ch = sim_tt_outcvt( ch, TT_GET_MODE(uptr->flags)); cty_out.buff[cty_out.in_ptr] = (char)(ch & 0xff); - cty_out.in_ptr = (cty_out.in_ptr + 1) & 0xff; + inci(&cty_out); if (((cty_out.in_ptr + 1) & 0xff) == cty_out.out_ptr) return; sim_debug(DEBUG_DATA, &dte_dev, "CTY queue %o\n", ch); @@ -1102,10 +1158,10 @@ cty: struct _buffer *otty; ln -= NUM_DLS; otty = &tty_out[ln]; - if (((otty->in_ptr + 1) & 0xff) == otty->out_ptr) + if (full(otty)) return; otty->buff[otty->in_ptr] = ch; - otty->in_ptr = (otty->in_ptr + 1) & 0xff; + inci(otty); sim_debug(DEBUG_DATA, &dte_dev, "TTY queue %o %d\n", ch, ln); } cmd->dptr+=2; @@ -1116,75 +1172,95 @@ cty: break; case PRI_EMOPS: - if (cmd->dev == PRI_EMLPT) { +#if (NUM_DEVS_LP20 > 0) + if (dev == PRI_EMLPT) { lp20_unit.LINE = 0; } +#endif break; + case PRI_EMRDS: /* Request device status */ -#if (NUM_DEVS_LP20 > 0) - if (cmd->dev == PRI_EMLPT) { + if (dev == PRI_EMLPT) { if (cmd->data[0] != 0) { data1[0] = 2 << 8; data1[1] = 0; data1[2] = 0; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, 3, data1) == 0) + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, + 3, data1) == 0) return; } else { +#if (NUM_DEVS_LP20 > 0) lp20_unit.LPST |= HDSFLG; - if (!sim_is_active(&lp20_unit)) - sim_activate(&lp20_unit, 1000); + if (!sim_is_active(&lp20_unit)) + sim_activate(&lp20_unit, 1000); +#else + data1[0] = 2 << 8; + data1[1] = 0; + data1[2] = 0; + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMLPT, + 3, data1) == 0) + return; +#endif } } -#endif - if (cmd->dev == PRI_EMCTY) { + if (dev == PRI_EMCTY) { data1[0] = 0; data1[1] = 0; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMCTY, 3, data1) == 0) + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMCTY, + 3, data1) == 0) return; } - if (cmd->dev == PRI_EMDH1) { + if (dev == PRI_EMDH1) { data1[0] = 0; data1[1] = 0; - if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMDH1, 3, data1) == 0) + if (dte_queue(PRI_EMHDS+PRI_IND_FLG, PRI_EMDH1, + 3, data1) == 0) return; } break; case PRI_EMHDS: /* Here is device status */ - if (cmd->dev == PRI_EMLPT) { - sim_debug(DEBUG_DETAIL, &dte_dev, "LPT HDS %06o %06o %06o\n", cmd->data[0], cmd->data[1], cmd->data[2]); +#if (NUM_DEVS_LP20 > 0) + if (dev == PRI_EMLPT) { + sim_debug(DEBUG_DETAIL, &dte_dev, "LPT HDS %06o %06o %06o\n", + cmd->data[0], cmd->data[1], cmd->data[2]); if (cmd->data[0] & 040) { lp20_unit.LPST |= EOFFLG; lp20_unit.LPCNT = 0; } lp20_unit.LPST |= HDSFLG; - sim_debug(DEBUG_DETAIL, &dte_dev, "LPT HDS %06o \n", lp20_unit.LPST); + sim_debug(DEBUG_DETAIL, &dte_dev, "LPT HDS %06o \n", + lp20_unit.LPST); if (!sim_is_active(&lp20_unit)) sim_activate(&lp20_unit, 1000); } +#endif break; -#if (NUM_DEVS_LP20 > 0) case PRI_EMLDV: /* Load LP VFU */ - if (cmd->dev == PRI_EMLPT) { +#if (NUM_DEVS_LP20 > 0) + if (dev == PRI_EMLPT) { int ln = lp20_unit.LPCNT; while (cmd->dptr < cmd->dcnt) { uint16 d = cmd->data[cmd->dptr++]; if (d == (0357 << 8)) lp20_vfu[ln++] = 010000; /* Signal end of page */ else - lp20_vfu[ln++] = ((d >> 8) & 077) | ((d <<6) & 07700); + lp20_vfu[ln++] = ((d >> 8) & 077)|((d <<6) & 07700); } lp20_unit.LPCNT = ln; for (ln = 0; ln < 256; ln++) - sim_debug(DEBUG_DETAIL, &lp20_dev, "LP20 VFU %02d => %04o\n", ln, lp20_vfu[ln]); - data1[0] = 0; - if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) - sim_activate(uptr, 1000); + sim_debug(DEBUG_DETAIL, &lp20_dev, + "LP20 VFU %02d => %04o\n", ln, lp20_vfu[ln]); + data1[0] = 0; + if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) + sim_activate(uptr, 1000); } +#endif break; case PRI_EMLDR: /* Load LP RAM */ - if (cmd->dev == PRI_EMLPT) { +#if (NUM_DEVS_LP20 > 0) + if (dev == PRI_EMLPT) { int ln = lp20_unit.LPCNT; for (;cmd->dptr < cmd->dcnt; cmd->dptr++, ln++) { if (ln < 256) @@ -1192,21 +1268,23 @@ cty: } lp20_unit.LPCNT = ln; for (ln = 0; ln < 256; ln++) - sim_debug(DEBUG_DETAIL, &lp20_dev, "LP20 RAM %02x => %04x\n", ln, lp20_ram[ln]); - data1[0] = 0; - if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) - sim_activate(uptr, 1000); + sim_debug(DEBUG_DETAIL, &lp20_dev, + "LP20 RAM %02x => %04x\n", ln, lp20_ram[ln]); + data1[0] = 0; + if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) + sim_activate(uptr, 1000); } - break; #endif + break; -#if (NUM_DEVS_TTY > 0) case PRI_EMFLO: /* Flush output */ - if ((cmd->dev & 0377) == PRI_EMDLS) { +#if (NUM_DEVS_TTY > 0) + if (dev == PRI_EMDLS) { int ln = cmd->data[0] - NUM_DLS; - sim_debug(DEBUG_DETAIL, &dte_dev, "Flush out %d %o\n", ln, cmd->data[0]); + sim_debug(DEBUG_DETAIL, &dte_dev, "Flush out %d %o\n", + ln, cmd->data[0]); if (ln == (NUM_DLS - PRI_CTYDV)) cty_out.in_ptr = cty_out.out_ptr = 0; else @@ -1215,16 +1293,22 @@ cty: if (dte_queue(PRI_EMLBE, PRI_EMDLS, 1, data1) == 0) return; } +#endif +#if (NUM_DEVS_LP20 > 0) if ((cmd->dev & 0377) == PRI_EMLPT) { data1[0] = cmd->data[0]; if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) return; } +#endif break; + case PRI_EMDSC: /* Dataset connect */ break; + case PRI_EMHUD: /* Hang up dataset */ - if ((cmd->dev & 0377) == PRI_EMDLS) { +#if (NUM_DEVS_TTY > 0) + if (dev == PRI_EMDLS) { int ln = cmd->sdev - NUM_DLS; if (ln >= 0) { TMLN *lp = &tty_ldsc[ln]; @@ -1234,39 +1318,45 @@ cty: } } break; + case PRI_EMXOF: /* XOFF line */ - if ((cmd->dev & 0377) == PRI_EMDLS) { + if (dev == PRI_EMDLS) { int ln = cmd->sdev - NUM_DLS; if (ln >= 0) { tty_ldsc[ln].rcve = 0; } } break; + case PRI_EMXON: /* XON line */ - if ((cmd->dev & 0377) == PRI_EMDLS) { + if (dev == PRI_EMDLS) { int ln = cmd->sdev - NUM_DLS; if (ln >= 0) { tty_ldsc[ln].rcve = 1; } } break; + case PRI_EMHLS: /* Here is line speeds */ - if ((cmd->dev & 0377) == PRI_EMDLS) { + if (dev == PRI_EMDLS) { int ln = cmd->sdev - NUM_DLS; sim_debug(DEBUG_DETAIL, &tty_dev, "HDL %o o=%d i=%d %o\n", ln, cmd->data[0], cmd->data[1], cmd->data[2]); } break; + case PRI_EMHLA: /* Here is line allocation */ case PRI_EMRBI: /* Reboot information */ case PRI_EMAKA: /* Ack ALL */ case PRI_EMTDO: /* Turn device On/Off */ break; + case PRI_EMEDR: /* Enable/Disable line */ if (cmd->dev == PRI_EMDH1) { /* Zero means enable, no-zero means disable */ tty_enable = !((cmd->data[0] >> 8) & 0xff); - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY enable %x\n", tty_enable); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY enable %x\n", + tty_enable); if (tty_enable) { sim_activate(&tty_unit[0], 1000); sim_activate(&tty_unit[1], 1000); @@ -1323,7 +1413,7 @@ void dte_transfer(UNIT *uptr) { uptr->STATUS &= ~DTE_SIND; } else { sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d send CMD: [%o] %o %o %o\n", - dte_out_ptr, dte_out_res, scnt, out->cnt, out->func, out->dev); + dte_out_ptr, dte_out_res, scnt, out->cnt, out->func, out->dev); /* Get size of packet */ cnt = out->cnt; if ((out->func & PRI_IND_FLG) == 0) @@ -1347,7 +1437,8 @@ void dte_transfer(UNIT *uptr) { cnt -= 2; if (out->func & PRI_IND_FLG) { uint16 dwrd = out->dcnt; - sim_debug(DEBUG_DATA, &dte_dev, "DTE: Indirect %o %o\n", cnt, out->dcnt); + sim_debug(DEBUG_DATA, &dte_dev, "DTE: Indirect %o %o\n", cnt, + out->dcnt); dwrd |= (out->sdev << 8); if (!Mem_write_byte(0, &dwrd)) goto error; @@ -1390,7 +1481,8 @@ dte_input() uint64 word; word = M[ITS_DTEODN]; /* Check if ready for output done */ - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo %d\n", word, cty_done); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo %d\n", word, + cty_done); if ((word & SMASK) != 0) { if (cty_done) { word = 64LL; @@ -1412,24 +1504,25 @@ dte_input() /* Tell 10 something is ready */ uptr->STATUS |= DTE_10DB; set_interrupt(DTE_DEVNUM, uptr->STATUS); - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo\n", word); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEODN = %012llo\n", + word); } } /* Check if ready for any input */ word = M[ITS_DTETYI]; if ((word & SMASK) != 0) { /* CTY first. */ - if (cty_in.in_ptr != cty_in.out_ptr) { + if (not_empty(&cty_in)) { ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + inco(&cty_in); word = (uint64)ch; #if (NUM_DEVS_TTY > 0) } else { ln = uptr->CNT; while ((word & SMASK) != 0) { - if (tty_in[ln].in_ptr != tty_in[ln].out_ptr) { + if (not_empty(&tty_in[ln])) { ch = tty_in[ln].buff[tty_in[ln].out_ptr]; - tty_in[ln].out_ptr = (tty_in[ln].out_ptr + 1) & 0xff; + inco(&tty_in[ln]); word = ((uint64)(ln+1) << 18) | (uint64)ch; } ln++; @@ -1446,7 +1539,8 @@ dte_input() /* Tell 10 something is ready */ uptr->STATUS |= DTE_10DB; set_interrupt(DTE_DEVNUM, uptr->STATUS); - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", word); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTETYI = %012llo\n", + word); } } #if (NUM_DEVS_TTY > 0) @@ -1469,7 +1563,8 @@ dte_input() M[ITS_DTEHNG] = word; uptr->STATUS |= DTE_10DB; set_interrupt(DTE_DEVNUM, uptr->STATUS); - sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEHNG = %012llo\n", word); + sim_debug(DEBUG_DETAIL, &dte_dev, "CTY ITS DTEHNG = %012llo\n", + word); } } #endif @@ -1486,9 +1581,9 @@ dte_input() /* Grab a chunck of input from CTY if any */ n = 0; save_ptr = cty_in.out_ptr; - while (cty_in.in_ptr != cty_in.out_ptr && n < 32) { + while (not_empty(&cty_in) && n < 32) { ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + inco(&cty_in); sim_debug(DEBUG_DETAIL, &dte_dev, "CTY recieve %02x\n", ch); dataq[n++] = (PRI_CTYDV << 8) | ch; } @@ -1499,11 +1594,14 @@ dte_input() } #if (NUM_DEVS_TTY > 0) n = 0; - /* While we have room for one more packet, grab as much input as we can */ - for (ln = 0; ln < tty_desc.lines && ((dte_out_res + 1) & 0x1f) != dte_out_ptr; ln++) { - while (tty_in[ln].in_ptr != tty_in[ln].out_ptr) { - ch = tty_in[ln].buff[tty_in[ln].out_ptr]; - tty_in[ln].out_ptr = (tty_in[ln].out_ptr + 1) & 0xff; + /* While we have room for one more packet, + * grab as much input as we can */ + for (ln = 0; ln < tty_desc.lines && + ((dte_out_res + 1) & 0x1f) != dte_out_ptr; ln++) { + struct _buffer *itty = &tty_in[ln]; + while (not_empty(itty)) { + ch = itty->buff[itty->out_ptr]; + inco(itty); dataq[n++] = ((ln + NUM_DLS) << 8) | ch; if (n == 32) { if (dte_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) @@ -1639,12 +1737,12 @@ t_stat dtei_svc (UNIT *uptr) /* If we have room see if any new lines */ - while (((cty_in.in_ptr + 1) & 0xff) != cty_in.out_ptr) { + while (!full(&cty_in)) { ch = sim_poll_kbd (); if (ch & SCPE_KFLAG) { ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (uptr->flags)); cty_in.buff[cty_in.in_ptr] =ch & 0377; - cty_in.in_ptr = (cty_in.in_ptr + 1) & 0xff; + inci(&cty_in); sim_debug(DEBUG_DETAIL, &dte_dev, "CTY char %o '%c'\n", ch, ((ch > 040 && ch < 0177)? ch: '.')); } else @@ -1653,9 +1751,9 @@ t_stat dtei_svc (UNIT *uptr) /* If Monitor input, place in buffer */ if ((optr->STATUS & (DTE_SEC|DTE_MON)) == (DTE_SEC|DTE_MON) && - cty_in.in_ptr != cty_in.out_ptr && M[SEC_DTMTI + base] == 0) { + not_empty(&cty_in) && M[SEC_DTMTI + base] == 0) { ch = cty_in.buff[cty_in.out_ptr]; - cty_in.out_ptr = (cty_in.out_ptr + 1) & 0xff; + inco(&cty_in); M[SEC_DTF11 + base] = ch; M[SEC_DTMTI + base] = FMASK; if (dte_dev.flags & TYPE_RSX20) { @@ -1679,7 +1777,7 @@ t_stat dteo_svc (UNIT *uptr) base = eb_ptr; #endif /* Flush out any pending CTY output */ - while(cty_out.in_ptr != cty_out.out_ptr) { + while(not_empty(&cty_out)) { char ch = cty_out.buff[cty_out.out_ptr]; if (ch != 0) { if (sim_putchar(ch) != SCPE_OK) { @@ -1687,7 +1785,7 @@ t_stat dteo_svc (UNIT *uptr) return SCPE_OK;; } } - cty_out.out_ptr = (cty_out.out_ptr + 1) & 0xff; + inco(&cty_out); sim_debug(DEBUG_DETAIL, &dte_dev, "CTY outch %o '%c'\n", ch, ((ch > 040 && ch < 0177)? ch: '.')); } @@ -1856,7 +1954,8 @@ lp20_printline(UNIT *uptr, int nl) { trim = 1; } lp20_buffer[uptr->COL] = '\0'; - sim_debug(DEBUG_DETAIL, &lp20_dev, "LP output %d %d [%s]\n", uptr->COL, nl, lp20_buffer); + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP output %d %d [%s]\n", uptr->COL, nl, + lp20_buffer); /* Stick a carraige return and linefeed as needed */ if (uptr->COL != 0 || trim) lp20_buffer[uptr->COL++] = '\r'; @@ -1911,7 +2010,7 @@ t_stat lp20_svc (UNIT *uptr) data1[0] = 0; data1[1] = (uptr->LINE == 1) ? 01<<8: 0; - sim_debug(DEBUG_DETAIL, &dte_dev, "LPT queue %06o %06o \n", lp20_unit.LPST, uptr->LPST); + sim_debug(DEBUG_DETAIL, &dte_dev, "LPT status %06o \n", uptr->LPST); if (uptr->LPST & EOFFLG) { data1[0] |= 040 << 8; uptr->LPCNT = 0; @@ -1926,15 +2025,15 @@ t_stat lp20_svc (UNIT *uptr) uptr->LPST &= ~(HDSFLG); } - if (lp20_queue.out_ptr == lp20_queue.in_ptr) + if (empty(&lp20_queue)) return SCPE_OK; - while (lp20_queue.out_ptr != lp20_queue.in_ptr) { + while (not_empty(&lp20_queue)) { ch = lp20_queue.buff[lp20_queue.out_ptr]; - lp20_queue.out_ptr = (lp20_queue.out_ptr + 1) & 0xff; + inco(&lp20_queue); ram_ch = lp20_ram[ch]; /* If previous was delimiter or translation do it */ - if (uptr->LPST & DELFLG || (ram_ch & (LP20_RAM_DEL|LP20_RAM_TRN)) != 0) { + if (uptr->LPST & DELFLG || (ram_ch &(LP20_RAM_DEL|LP20_RAM_TRN)) != 0) { ch = ram_ch & LP20_RAM_CHR; uptr->LPST &= ~DELFLG; if (ram_ch & LP20_RAM_DEL) @@ -1946,11 +2045,15 @@ t_stat lp20_svc (UNIT *uptr) /* Check if paper motion */ if (ram_ch & LP20_RAM_PI) { int lines = 0; /* Number of new lines to output */ - lp20_printline(uptr, (ram_ch & 037) != 020); /* Print any buffered line */ - sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x %04x\n", ch, ram_ch); + /* Print any buffered line */ + lp20_printline(uptr, (ram_ch & 037) != 020); + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x %04x\n", + ch, ram_ch); if ((ram_ch & 020) == 0) { /* Find channel mark in output */ while ((lp20_vfu[uptr->LINE] & (1 << (ram_ch & 017))) == 0) { - sim_debug(DEBUG_DETAIL, &lp20_dev, "LP skip chan %04x %04x %d\n", lp20_vfu[uptr->LINE], ram_ch, uptr->LINE); + sim_debug(DEBUG_DETAIL, &lp20_dev, + "LP skip chan %04x %04x %d\n", + lp20_vfu[uptr->LINE], ram_ch, uptr->LINE); if (lp20_vfu[uptr->LINE] & 010000) { /* Hit bottom of form */ sim_fwrite("\014", 1, 1, uptr->fileref); uptr->pos++; @@ -1963,7 +2066,9 @@ t_stat lp20_svc (UNIT *uptr) } } else { while ((ram_ch & 017) != 0) { - sim_debug(DEBUG_DETAIL, &lp20_dev, "LP skip line %04x %04x %d\n", lp20_vfu[uptr->LINE], ram_ch, uptr->LINE); + sim_debug(DEBUG_DETAIL, &lp20_dev, + "LP skip line %04x %04x %d\n", + lp20_vfu[uptr->LINE], ram_ch, uptr->LINE); if (lp20_vfu[uptr->LINE] & 010000) { /* Hit bottom of form */ sim_fwrite("\014", 1, 1, uptr->fileref); uptr->pos++; @@ -1980,11 +2085,12 @@ t_stat lp20_svc (UNIT *uptr) uptr->pos+=2; } } else if (ch != 0) { - sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x '%c' %04x\n", ch, ch, ram_ch); + sim_debug(DEBUG_DETAIL, &lp20_dev, "LP deque %02x '%c' %04x\n", + ch, ch, ram_ch); lp20_output(uptr, ch); } } - if (lp20_queue.out_ptr == lp20_queue.in_ptr) { + if (empty(&lp20_queue)) { data1[0] = 0; if (dte_queue(PRI_EMLBE, PRI_EMLPT, 1, data1) == 0) sim_activate(uptr, 1000); @@ -2072,7 +2178,8 @@ lp20_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc) return SCPE_OK; } -t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, + const char *cptr) { fprintf (st, "Line Printer (LPT)\n\n"); fprintf (st, "The line printer (LPT) writes data to a disk file. The POS register specifies\n"); @@ -2127,14 +2234,16 @@ t_stat ttyi_svc (UNIT *uptr) if (lp->conn == 0) continue; flg = 1; - while (flg && ((iptr->in_ptr + 1) & 0xff) != iptr->out_ptr) { + while (flg && !full(iptr)) { /* Spool up as much as we have room for */ int32 ch = tmxr_getc_ln(lp); if ((ch & TMXR_VALID) != 0) { - ch = sim_tt_inpcvt (ch, TT_GET_MODE(tty_unit[0].flags) | TTUF_KSR); + ch = sim_tt_inpcvt (ch, + TT_GET_MODE(tty_unit[0].flags) | TTUF_KSR); iptr->buff[iptr->in_ptr] = ch & 0377; - iptr->in_ptr = (iptr->in_ptr + 1) & 0xff; - sim_debug(DEBUG_DETAIL, &tty_dev, "TTY recieve %d: %o\n", ln, ch); + inci(iptr); + sim_debug(DEBUG_DETAIL, &tty_dev, "TTY recieve %d: %o\n", + ln, ch); } else flg = 0; } @@ -2159,17 +2268,22 @@ t_stat ttyo_svc (UNIT *uptr) for (ln = 0; ln < tty_desc.lines; ln++) { struct _buffer *optr = &tty_out[ln]; lp = &tty_ldsc[ln]; - if (lp->conn == 0) + if (lp->conn == 0) { + if (not_empty(optr)) { + optr->out_ptr = optr->in_ptr = 0; + tty_done[ln] = 1; + } continue; - if (optr->out_ptr == optr->in_ptr) + } + if (empty(optr)) continue; - while (optr->out_ptr != optr->in_ptr) { + while (not_empty(optr)) { int32 ch = optr->buff[optr->out_ptr]; ch = sim_tt_outcvt(ch, TT_GET_MODE (tty_unit[0].flags) | TTUF_KSR); sim_debug(DEBUG_DATA, &tty_dev, "TTY: %d output %o\n", ln, ch); r = tmxr_putc_ln (lp, ch); if (r == SCPE_OK) - optr->out_ptr = (optr->out_ptr + 1) & 0xff; + inco(optr); else if (r == SCPE_LOST) { optr->out_ptr = optr->in_ptr = 0; continue; @@ -2213,13 +2327,14 @@ t_stat tty_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc) tmxr_linemsg (&tty_ldsc[i], "\r\nOperator disconnected line\r\n"); tmxr_send_buffered_data (&tty_ldsc[i]); } - tmxr_detach_ln (&tty_ldsc[i]); /* completely reset line */ + tmxr_detach_ln (&tty_ldsc[i]); /* completely reset line */ } } if (tty_desc.lines < newln) - memset (tty_ldsc + tty_desc.lines, 0, sizeof(*tty_ldsc)*(newln-tty_desc.lines)); + memset (tty_ldsc + tty_desc.lines, 0, + sizeof(*tty_ldsc)*(newln-tty_desc.lines)); tty_desc.lines = newln; - return tty_reset (&tty_dev); /* setup lines and auto config */ + return tty_reset (&tty_dev); /* setup lines and auto config */ } /* SET LOG processor */ diff --git a/PDP10/kl10_nia.c b/PDP10/kl10_nia.c index 757d7e1..8456409 100644 --- a/PDP10/kl10_nia.c +++ b/PDP10/kl10_nia.c @@ -386,6 +386,12 @@ UNIT nia_unit[] = { {UDATA(nia_cmd_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 2 */ }; +REG nia_reg[] = { + {BRDATA(DATA, &nia_data, 16, 8, sizeof(struct nia_device)), REG_HRO}, + {0} +}; + + #define nia_cmd_uptr (&nia_unit[2]) /* Unit for processing commands */ #define nia_recv_uptr (&nia_unit[0]) /* Unit doing receive digestion */ #define nia_proc_uptr (&nia_unit[1]) /* Unit doing receive dispatching */ @@ -424,7 +430,7 @@ DEBTAB nia_debug[] = { }; DEVICE nia_dev = { - "NI", nia_unit, NULL, nia_mod, + "NI", nia_unit, nia_reg, nia_mod, 3, 8, 0, 1, 8, 36, NULL, NULL, &nia_reset, NULL, &nia_attach, &nia_detach, &nia_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, nia_debug, diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index 690b70b..dfa4ad9 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -182,7 +182,6 @@ int mtr_enable; /* Enable Timer */ int mtr_flags; /* Flags for accounting */ int tim_per; /* Timer period */ int tim_val; /* Current timer value */ -int mem_cnt; /* Number of memory cycles */ int rtc_tim; /* Time till next 60hz clock */ uint32 brk_addr; /* Address break */ int brk_flags; /* Break flags */ @@ -465,6 +464,28 @@ REG cpu_reg[] = { { ORDATAD (OPC, opc, 36, "Saved PC and flags")}, { ORDATAD (MAR, mar, 18, "Memory address register")}, { ORDATAD (QUA_TIME, qua_time, 36, "Quantum timer"), REG_RO}, +#endif +#if KL + { ORDATAD (EXT_AC, ext_ac, 4, "Extended Instruction AC"), REG_HRO}, + { ORDATAD (PREV_CTX, prev_ctx, 5, "Previous context"), REG_HRO}, + { ORDATAD (ITQ_EN, irq_enable, 16, "Interrupt enable"), REG_HRO}, + { ORDATAD (ITQ_FLGS, irq_flags, 16, "Interrupt Flags"), REG_HRO}, + { ORDATAD (MTR_IRQ, mtr_irq, 1, "Timer IRQ"), REG_HRO}, + { ORDATAD (MTR_EN, mtr_enable, 1, "Timer Enable"), REG_HRO}, + { ORDATAD (MTR_FLGS, mtr_flags, 3, "Timer Flags"), REG_HRO}, + { ORDATAD (TIM_PER, tim_per, 12, "Timer period"), REG_HRO}, + { ORDATAD (TIM_VAl, tim_val, 12, "Timer period"), REG_HRO}, + { ORDATAD (RTC_TIM, rtc_tim, 12, "RTC timer"), REG_HRO}, + { ORDATAD (BRK_ADDR, brk_addr, 18, "Break address"), REG_HRO}, + { ORDATAD (BRK_FLGS, brk_flags, 18, "Break address"), REG_HRO}, + { ORDATAD (T20_PAGE, t20_page, 1, "TOPS20 paging"), REG_HRO}, + { ORDATAD (PTR_FLG, ptr_flg, 1, "Accessing pointer"), REG_HRO}, + { ORDATAD (EXTEND, extend, 1, "Execute Extend"), REG_HRO}, + { ORDATAD (SECT, sect, 12, "access section"), REG_HRO}, + { ORDATAD (CUR_SECT, cur_sect, 12, "Current section"), REG_HRO}, + { ORDATAD (PREV_SECT, prev_sect, 12, "Previous section"), REG_HRO}, + { ORDATAD (PC_SECT, pc_sect, 12, "PC section"), REG_HRO}, + { ORDATAD (GLB_SECT, glb_sect, 1, "Global section"), REG_HRO}, #endif { NULL } }; diff --git a/PDP10/kx10_imp.c b/PDP10/kx10_imp.c index 19249fe..bdfbadb 100644 --- a/PDP10/kx10_imp.c +++ b/PDP10/kx10_imp.c @@ -569,10 +569,13 @@ DEBTAB imp_debug[] = { {0, 0} }; - +REG imp_reg[] = { + {BRDATA(DATA, &imp_data, 16, 8, sizeof(struct imp_device)), REG_HRO}, + {0} +}; DEVICE imp_dev = { - "IMP", imp_unit, NULL, imp_mod, + "IMP", imp_unit, imp_reg, imp_mod, 3, 8, 0, 1, 8, 36, NULL, NULL, &imp_reset, NULL, &imp_attach, &imp_detach, &imp_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, imp_debug, From 3a7584f29fd4cf62ef8886b17fe6a61735e6f096 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 16 Feb 2020 20:28:21 -0500 Subject: [PATCH 96/98] SCP: Updated to current. --- Visual Studio Projects/Pre-Build-Event.cmd | 2 +- makefile | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Visual Studio Projects/Pre-Build-Event.cmd b/Visual Studio Projects/Pre-Build-Event.cmd index 1261014..3efafb4 100644 --- a/Visual Studio Projects/Pre-Build-Event.cmd +++ b/Visual Studio Projects/Pre-Build-Event.cmd @@ -29,7 +29,7 @@ rem rem Everything implicitly requires BUILD to also be set to have rem any meaning, it always gets set. set _X_BUILD=BUILD -set _X_REQUIRED_WINDOWS_BUILD=20191213 +set _X_REQUIRED_WINDOWS_BUILD=20191221 call :FindVCVersion _VC_VER set _PDB=%~dpn1.pdb diff --git a/makefile b/makefile index d3e7f16..dabd170 100644 --- a/makefile +++ b/makefile @@ -32,8 +32,8 @@ # installed, gmake should be invoked with LPATH=/usr/lib:/usr/local/lib # defined (adjusted as needed depending on where they may be installed). # -# In the unlikely event that someone wants to build network capable -# simulators without networking support, invoking GNU make with +# In the unlikely event that someone wants to build network capable +# simulators without networking support, invoking GNU make with # NONETWORK=1 will do the trick. # # The default build will build compiler optimized binaries. @@ -255,7 +255,7 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin) LTO_EXCLUDE_VERSIONS = PCAPLIB = pcap ifeq (agcc,$(findstring agcc,${GCC})) # Android target build? - OS_CCDEFS = -D_GNU_SOURCE -DSIM_ASYNCH_IO + OS_CCDEFS = -D_GNU_SOURCE -DSIM_ASYNCH_IO OS_LDFLAGS = -lm else # Non-Android (or Native Android) Builds ifeq (,$(INCLUDES)$(LIBRARIES)) @@ -464,19 +464,19 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin) endif ifneq (,$(call find_include,pthread)) ifneq (,$(call find_lib,pthread)) - OS_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO + OS_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO OS_LDFLAGS += -lpthread $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) else LIBEXTSAVE := ${LIBEXT} LIBEXT = a ifneq (,$(call find_lib,pthread)) - OS_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO + OS_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO OS_LDFLAGS += -lpthread $(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread)) else ifneq (,$(findstring Haiku,$(OSTYPE))) - OS_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO + OS_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO $(info using libpthread: $(call find_include,pthread)) endif endif @@ -1166,9 +1166,6 @@ else ifneq (,$(findstring -fstrict-overflow,$(GCC_OPTIMIZERS))) CFLAGS_O += -fno-strict-overflow endif - ifneq (,$(findstring -fcommon,$(GCC_OPTIMIZERS))$(findstring -fno-common,$(GCC_OPTIMIZERS))) - CFLAGS_O += -fcommon - endif ifeq (,$(NO_LTO)) ifneq (,$(findstring -flto,$(GCC_OPTIMIZERS))) CFLAGS_O += -flto -fwhole-program @@ -2823,7 +2820,7 @@ besm6 : ${BIN}besm6${EXE} ${BIN}besm6${EXE} : ${BESM6} ${SIM} ifneq (1,${CPP_BUILD}${CPP_FORCE}) ${MKDIRBIN} - ${CC} ${BESM6} ${SIM} ${BESM6_OPT} ${CC_OUTSPEC} ${LDFLAGS} + ${CC} ${BESM6} ${SIM} ${BESM6_OPT} ${BESM6_PANEL_OPT} ${CC_OUTSPEC} ${LDFLAGS} ifneq (,$(call find_test,${BESM6D},besm6)) $@ $(call find_test,${BESM6D},besm6) ${TEST_ARG} endif From 2b1c0bc566baf7a42bb3fa74e2943cfee438c5e7 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 16 Feb 2020 20:28:43 -0500 Subject: [PATCH 97/98] KA10: Cleanup some compiler warnings. --- PDP10/kl10_fe.c | 2 +- PDP10/kx10_cpu.c | 32 ++++++++++++++++---------------- PDP10/kx10_tu.c | 3 +-- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/PDP10/kl10_fe.c b/PDP10/kl10_fe.c index 348ef00..9a3c2b4 100644 --- a/PDP10/kl10_fe.c +++ b/PDP10/kl10_fe.c @@ -209,7 +209,7 @@ t_stat dte_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cpt const char *dte_description (DEVICE *dptr); extern uint64 SW; /* Switch register */ -char *pri_name[] = { "(0)", "EM2EI", "EM2TI", "EMSTR", "EMLNC", "EMRDS", "(6)", +CONST char *pri_name[] = { "(0)", "EM2EI", "EM2TI", "EMSTR", "EMLNC", "EMRDS", "(6)", "EMHDS", "(10)", "EMRDT", "EMHDR", "EMFLO", "EMSNA", "EMDSC", "EMHUD", "EMLBE", "EMXOF", "EMXON", "EMHLS", "EMHLA", "EMRBI", "EMAKA", "EMTDO", "EMEDR", "EMLDR", "EMLDV" }; diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index dfa4ad9..4a2f0c6 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -909,7 +909,7 @@ int opflags[] = { #endif #if KL -struct { +struct _byte { int p; int s; } _byte_adj[] = { @@ -2557,7 +2557,7 @@ int Mem_write(int flag, int cur_context) { } /* executive page table lookup */ -int exec_page_lookup(t_addr addr, int wr, int *loc) +int exec_page_lookup(t_addr addr, int wr, t_addr *loc) { int data; int page = (RMASK & addr) >> 9; @@ -5854,9 +5854,9 @@ unasign: page_fault = 1; goto last; } - BR = (MB + adjw) & RMASK | (MB & LMASK); + BR = ((MB + adjw) & RMASK) | (MB & LMASK); } else - BR = (MB + adjw) & (SECTM|RMASK) | (MB & ~(SECTM|RMASK)); + BR = ((MB + adjw) & (SECTM|RMASK)) | (MB & ~(SECTM|RMASK)); set_reg(AC, AR); set_reg(AC+1, BR); break; @@ -5887,22 +5887,22 @@ unasign: SCAD = (AR >> 30) & 077; #if KL if (QKLB && t20_page && pc_sect != 0 && SCAD > 36) { /* Extended pointer */ - int i = SCAD - 37; + f = SCAD - 37; if (SCAD == 077) goto muuo; - SC = _byte_adj[i].s; - SCAD = (_byte_adj[i].p + (0777 ^ SC) + 1) & 0777; - i++; + SC = _byte_adj[f].s; + SCAD = (_byte_adj[f].p + (0777 ^ SC) + 1) & 0777; + f++; if (SCAD & 0400) { SCAD = ((0777 ^ SC) + 044 + 1) & 0777; AR++; - for(i = 0; i < 28; i++) { - if (_byte_adj[i].s == SC && _byte_adj[i].p == SCAD) + for(f = 0; f < 28; f++) { + if (_byte_adj[f].s == SC && _byte_adj[f].p == SCAD) break; } } AR &= (SECTM|RMASK); - AR |= ((uint64)(i + 37)) << 30; + AR |= ((uint64)(f + 37)) << 30; MB = AR; if (Mem_write(0, 0)) goto last; @@ -5925,9 +5925,9 @@ unasign: page_fault = 1; goto last; } - MB = (MB + 1) & RMASK | (MB & LMASK); + MB = ((MB + 1) & RMASK) | (MB & LMASK); } else - MB = (MB + 1) & (SECTM|RMASK) | (MB & ~(SECTM|RMASK)); + MB = ((MB + 1) & (SECTM|RMASK)) | (MB & ~(SECTM|RMASK)); if (Mem_write(0,0)) goto last; AB = (AB - 1) & RMASK; @@ -5969,11 +5969,11 @@ unasign: SCAD = (AR >> 30) & 077; #if KL if (QKLB && t20_page && pc_sect != 0 && SCAD > 36) { /* Extended pointer */ - int i = SCAD - 37; + f = SCAD - 37; if (SCAD == 077) goto muuo; - SC = _byte_adj[i].s; - SCAD = _byte_adj[i].p; + SC = _byte_adj[f].s; + SCAD = _byte_adj[f].p; ld_ptr: glb_sect = 1; sect = (AR >> 18) & 07777; diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index 86bd00a..87cc20e 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -156,7 +156,6 @@ #define CPOS u4 #define DATAPTR u6 -struct rh_if tu_rh[NUM_DEVS_TU]; uint8 tu_buf[NUM_DEVS_TU][TU_NUMFR]; uint16 tu_frame[NUM_DEVS_TU]; uint16 tu_tcr[NUM_DEVS_TU]; @@ -188,7 +187,7 @@ UNIT tu_unit[] = { { UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) }, }; -struct rh_if tu_rh[] = { +struct rh_if tu_rh[NUM_DEVS_TU] = { { &tu_write, &tu_read} }; From 5b1cf1b9218f57608b304ee79e92c0d92d476965 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Mon, 17 Feb 2020 12:33:45 -0500 Subject: [PATCH 98/98] SCP: Updated to current. --- scp.c | 5 ++++- scp.h | 1 + sim_defs.h | 12 ++++++++++-- sim_ether.c | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/scp.c b/scp.c index 39e82af..b31169a 100644 --- a/scp.c +++ b/scp.c @@ -451,7 +451,8 @@ t_addr (*sim_vm_parse_addr) (DEVICE *dptr, CONST char *cptr, CONST char **tptr) t_value (*sim_vm_pc_value) (void) = NULL; t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs) = NULL; t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason) = NULL; -const char *sim_vm_release = NULL; +const char *sim_vm_release; +const char *sim_vm_release_message; const char **sim_clock_precalibrate_commands = NULL; @@ -6072,6 +6073,8 @@ fprintf (st, "%sBuild: %s", flag ? "\n " : " ", S_xstr(SIM_BUILD)) #undef S_xstr #endif fprintf (st, "\n"); +if (sim_vm_release_message != NULL) /* if a release message string is defined */ + fprintf (st, "\n%s", sim_vm_release_message); /* then display it */ return SCPE_OK; } diff --git a/scp.h b/scp.h index 409c3a1..120145d 100644 --- a/scp.h +++ b/scp.h @@ -403,6 +403,7 @@ void sim_aio_activate (ACTIVATE_API caller, UNIT *uptr, int32 event_time); extern char sim_name[64]; extern const char *sim_vm_release; +extern const char *sim_vm_release_message; extern DEVICE *sim_devices[]; extern REG *sim_PC; extern const char *sim_stop_messages[SCPE_BASE]; diff --git a/sim_defs.h b/sim_defs.h index a60fad3..17b90ff 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -1090,7 +1090,11 @@ extern int32 sim_asynch_latency; extern int32 sim_asynch_inst_latency; /* Thread local storage */ -#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__hpux) && !defined(__OpenBSD__) && !defined(_AIX) +#if defined(thread_local) +#define AIO_TLS thread_local +#elif (__STDC_VERSION__ >= 201112) && !(defined(__STDC_NO_THREADS__)) +#define AIO_TLS _Thread_local +#elif defined(__GNUC__) && !defined(__APPLE__) && !defined(__hpux) && !defined(__OpenBSD__) && !defined(_AIX) #define AIO_TLS __thread #elif defined(_MSC_VER) #define AIO_TLS __declspec(thread) @@ -1255,7 +1259,11 @@ extern int32 sim_asynch_inst_latency; sim_asynch_queue = uptr; \ } \ if (sim_idle_wait) { \ - sim_debug (TIMER_DBG_IDLE, &sim_timer_dev, "waking due to event on %s after %d instructions\n", sim_uname(uptr), event_time);\ + if (sim_deb) { /* only while debug do lock/unlock overhead */ \ + AIO_UNLOCK; \ + sim_debug (TIMER_DBG_IDLE, &sim_timer_dev, "waking due to event on %s after %d instructions\n", sim_uname(uptr), event_time);\ + AIO_LOCK; \ + } \ pthread_cond_signal (&sim_asynch_wake); \ } \ AIO_UNLOCK; \ diff --git a/sim_ether.c b/sim_ether.c index e339d6d..e5a5bc8 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -1389,7 +1389,7 @@ struct _PACKET_OID_DATA { }; typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA; typedef void **LPADAPTER; -#define OID_802_3_CURRENT_ADDRESS 0x01010102 /* Extracted from ntddmdis.h */ +#define OID_802_3_CURRENT_ADDRESS 0x01010102 /* Extracted from ntddndis.h */ static int pcap_mac_if_win32(const char *AdapterName, unsigned char MACAddress[6]) {