From 1cb2f3b96c5e3d0b83c5750540e58b427e7bbbd1 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 19 May 2024 14:18:37 -0400 Subject: [PATCH] KA10: Fix divide error on KS10, add in some devices. Fix divide of 0 on KS10 processor. Fix write access for auxiliary processor memory. Updated support new PIDP10 panel. Allow eight Unibux ports on the TEN device. Added GE DATANET-760 device to PDP6 Removed USER mode restriction for idle detection. Added Data Disc 6600 Television Display System. --- PDP10/CMakeLists.txt | 5 + PDP10/ka10_dd.c | 756 ++++++++++ PDP10/ka10_dd_font.c | 1858 ++++++++++++++++++++++++ PDP10/ka10_dd_font.h | 134 ++ PDP10/ka10_pipanel.c | 763 ++++++++++ PDP10/ka10_ten11.c | 63 +- PDP10/kl10_dn.c | 1188 +++++++++++++++ PDP10/ks10_dz.c | 1 - PDP10/ks10_tcu.c | 1 - PDP10/ks10_uba.c | 3 - PDP10/kx10_cpu.c | 56 +- PDP10/kx10_ddc.c | 402 +++++ PDP10/kx10_defs.h | 12 +- PDP10/kx10_dpy.c | 2 + PDP10/kx10_dt.c | 2 - PDP10/kx10_rp.c | 11 +- PDP10/kx10_sys.c | 17 +- PDP10/kx10_tu.c | 1 - PDP10/kx10_tym.c | 684 +++++++++ PDP10/pdp11_ddcmp.h | 493 +++++++ PDP10/pdp6_dsk.c | 5 +- PDP10/pdp6_dtc.c | 2 - PDP10/pdp6_ge.c | 424 ++++++ Visual Studio Projects/PDP10-KA.vcproj | 8 + Visual Studio Projects/PDP10-KI.vcproj | 8 + Visual Studio Projects/PDP6.vcproj | 4 + cmake/simh-packaging.cmake | 206 +-- cmake/simh-simulators.cmake | 246 ++-- makefile | 9 +- 29 files changed, 7063 insertions(+), 301 deletions(-) create mode 100644 PDP10/ka10_dd.c create mode 100644 PDP10/ka10_dd_font.c create mode 100644 PDP10/ka10_dd_font.h create mode 100644 PDP10/ka10_pipanel.c create mode 100644 PDP10/kl10_dn.c create mode 100644 PDP10/kx10_ddc.c create mode 100644 PDP10/kx10_tym.c create mode 100644 PDP10/pdp11_ddcmp.h create mode 100644 PDP10/pdp6_ge.c diff --git a/PDP10/CMakeLists.txt b/PDP10/CMakeLists.txt index 20d60dde9..9e7648a7f 100644 --- a/PDP10/CMakeLists.txt +++ b/PDP10/CMakeLists.txt @@ -103,6 +103,8 @@ add_simulator(pdp10-ka ${KA10D}/kx10_disk.c ${KA10D}/ka10_pclk.c ${KA10D}/ka10_tv.c + ${KA10D}/ka10_dd.c + ${KA10D}/kx10_ddc.c ${DISPLAY340} ${DISPLAYIII} INCLUDES @@ -149,6 +151,8 @@ add_simulator(pdp10-ki ${KI10D}/kx10_imp.c ${KI10D}/kx10_dpy.c ${KI10D}/kx10_disk.c + ${KI10D}/kx10_ddc.c + ${KI10D}/kx10_tym.c ${DISPLAY340} INCLUDES ${KI10D} @@ -236,6 +240,7 @@ add_simulator(pdp6 ${PDP6D}/pdp6_dcs.c ${PDP6D}/kx10_dpy.c ${PDP6D}/pdp6_slave.c + ${PDP6D}/pdp6_ge.c ${DISPLAY340} INCLUDES ${PDP6D} diff --git a/PDP10/ka10_dd.c b/PDP10/ka10_dd.c new file mode 100644 index 000000000..026f841d0 --- /dev/null +++ b/PDP10/ka10_dd.c @@ -0,0 +1,756 @@ +/* ka10_dd.c: Data Disc 6600 Television Display System, with + PDP-10 interface and video switch made at Stanford AI lab. + + Copyright (c) 2022-2023, Lars Brinkhoff + + 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 + LARS BRINKHOFF 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 Lars Brinkhoff shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Lars Brinkhoff. +*/ + +#include "kx10_defs.h" +#ifndef NUM_DEVS_DD +#define NUM_DEVS_DD 0 +#endif + +#if NUM_DEVS_DD > 0 +#include "sim_video.h" + +#define DD_DEVNUM 0510 +#define VDS_DEVNUM 0340 + +#define DD_WIDTH 512 /* Display width. */ +#define DD_HEIGHT 480 /* Display height. */ +#define DD_PIXELS (DD_WIDTH * DD_HEIGHT) /* Total number of pixels. */ +#define DD_CHANNELS 32 /* Data Disc channels. */ +#define DD_COLUMNS 85 +#define FONT_WIDTH 6 +#define FONT_HEIGHT 12 +#define MARGIN 2 +#define VDS_OUTPUTS 64 /* Video switch outputs. */ +#define III_DISPLAYS 6 + +#define STATUS u3 +#define MA u4 /* Current memory address. */ +#define PIA u5 +#define COLUMN u6 +#define LINE us9 +#define CHANNEL us10 + +/* CONI/O Bits */ +#define DD_HALT 000000010 /* CONI: Halted. */ +#define DD_RESET 000000010 /* CONO: Reset. */ +#define DD_INT 000000020 /* CONI: Interrupting. */ +#define DD_FORCE 000000020 /* CONO: Force field. */ +#define DD_FIELD 000000040 /* CONI: Field. */ +#define DD_HALT_ENA 000000100 /* CONI: Halt interrupt enabled. */ +#define DD_DDGO 000000100 /* CONO: Go. */ +#define DD_LATE 000000200 /* CONI: Late. */ +#define DD_SPGO 000000200 /* CONO */ +#define DD_LATE_ENA 000000400 /* Late interrupt enabled. */ +#define DD_USER 000001000 /* User mode. */ +#define DD_NXM 000002000 /* CONI: Accessed non existing memory. */ + +/* Function codes. */ +#define FC_GRAPHICS 001 /* Graphics mode. */ +#define FC_WRITE 002 /* Write to disc. */ +#define FC_DARK 004 /* Dark background. */ +#define FC_DOUBLE_W 010 /* Double width. */ +#define FC_ERASE 010 /* Erase graphics. */ +#define FC_ADDITIVE 020 /* Additive graphics. */ +#define FC_SINGLE_H 040 /* Single height. */ + +/* There are 64 displays, fed from the video switch. */ +static uint32 vds_surface[VDS_OUTPUTS][DD_PIXELS]; +static uint32 vds_palette[VDS_OUTPUTS][2]; +static VID_DISPLAY *vds_vptr[VDS_OUTPUTS]; + +/* There are 32 channels on the Data Disc. */ +static uint8 dd_channel[DD_CHANNELS][DD_PIXELS]; +static uint8 dd_changed[DD_CHANNELS]; +static int dd_windows = 1; + +static uint8 dd_function_code = 0; +static uint16 dd_line_buffer[DD_COLUMNS + 1]; +static int dd_line_buffer_address = 0; +static int dd_line_buffer_written = 0; +#define WRITTEN 0400 + +uint32 vds_channel; /* Currently selected video outputs. */ +uint8 vds_changed[VDS_OUTPUTS]; +uint32 vds_selection[VDS_OUTPUTS]; /* Data Disc channels. */ +uint32 vds_sync_inhibit[VDS_OUTPUTS]; +uint32 vds_analog[VDS_OUTPUTS]; /* Analog channel. */ + +#include "ka10_dd_font.h" + +static t_stat dd_set_windows (UNIT *uptr, int32 val, CONST char *cptr, void *desc) ; +static t_stat dd_show_windows (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +static void dd_chargen (char c, int column); +static void dd_graphics (uint8 data, int column); +static t_stat dd_devio(uint32 dev, uint64 *data); +static t_stat vds_devio(uint32 dev, uint64 *data); +static t_stat dd_svc(UNIT *uptr); +static t_stat vds_svc(UNIT *uptr); +static t_stat dd_reset(DEVICE *dptr); +static t_stat vds_reset(DEVICE *dptr); +static t_stat dd_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +static t_stat vds_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +static const char *dd_description (DEVICE *dptr); +static const char *vds_description (DEVICE *dptr); + +DIB dd_dib = { DD_DEVNUM, 1, dd_devio, NULL}; + +UNIT dd_unit = { + UDATA (&dd_svc, UNIT_IDLE, 0) +}; + +MTAB dd_mod[] = { + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "WINDOWS", "WINDOWS", + &dd_set_windows, &dd_show_windows, NULL}, + { 0 } + }; + +DEVICE dd_dev = { + "DD", &dd_unit, NULL, dd_mod, + 1, 10, 31, 1, 8, 8, + NULL, NULL, dd_reset, + NULL, NULL, NULL, &dd_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_DISPLAY, 0, dev_debug, + NULL, NULL, &dd_help, NULL, NULL, &dd_description + }; + +UNIT vds_unit = { + UDATA (&vds_svc, UNIT_IDLE, 0) +}; + +DIB vds_dib = { VDS_DEVNUM, 1, vds_devio, NULL}; + +DEVICE vds_dev = { + "VDS", &vds_unit, NULL, NULL, + 1, 10, 31, 1, 8, 8, + NULL, NULL, vds_reset, + NULL, NULL, NULL, &vds_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_DISPLAY, 0, dev_debug, + NULL, NULL, &vds_help, NULL, NULL, &vds_description + }; + +static void unimplemented (const char *text) +{ + fprintf (stderr, "\r\n[UNIMPLEMENTED: %s]\r\n", text); +} + +static void +dd_hang (const char *msg) +{ + sim_debug(DEBUG_CMD, &dd_dev, "HANG: %s\n", msg); + dd_unit.STATUS |= DD_HALT; +} + +static void +dd_halt (const char *msg) +{ + sim_debug(DEBUG_CMD, &dd_dev, "HALT: %s\n", msg); + dd_unit.STATUS |= DD_HALT; +} + +static void +dd_execute (const char *msg) +{ + int i; + sim_debug(DEBUG_CMD, &dd_dev, "%s; %s mode\n", + msg, (dd_function_code & FC_GRAPHICS) ? "graphics" : "text"); + if (dd_unit.LINE >= DD_HEIGHT) + return; + + if (dd_function_code & FC_GRAPHICS) { + for (i = 1; i <= 64; i++) { + if (dd_line_buffer[i] & WRITTEN) + dd_graphics (dd_line_buffer[i] & 0377, i - 1); + } + } else { + for (i = 1; i <= DD_COLUMNS; i++) { + if (dd_line_buffer[i] & WRITTEN) + dd_chargen (dd_line_buffer[i] & 0177, i - 1); + } + } + + memset (dd_line_buffer, 0, sizeof dd_line_buffer); + dd_line_buffer_address = 1; + dd_line_buffer_written = 0; +} + +static t_stat +dd_devio(uint32 dev, uint64 *data) { + UNIT *uptr = &dd_unit; + switch(dev & 3) { + case CONI: + *data = uptr->PIA | uptr->STATUS; + sim_debug (DEBUG_CONI, &dd_dev, "%06llo (%6o)\n", *data, PC); + break; + case CONO: + sim_debug (DEBUG_CONO, &dd_dev, "%06llo (%6o)\n", *data, PC); + uptr->STATUS &= ~DD_HALT; + clr_interrupt (DD_DEVNUM); + uptr->PIA = (uint32)(*data & 7); + if (*data & DD_RESET) { + sim_debug(DEBUG_DETAIL, &dd_dev, "Reset.\n"); + uptr->PIA = 0; + uptr->STATUS = 0; + uptr->COLUMN = dd_line_buffer_address = 1; + uptr->LINE = 0; + dd_function_code = 0; + sim_cancel (uptr); + } + if (*data & DD_FORCE) { + sim_debug(DEBUG_DETAIL, &dd_dev, "Force field.\n"); + } + if (*data & 040) { + sim_debug(DEBUG_DETAIL, &dd_dev, "Halt interrupt enabled.\n"); + uptr->STATUS |= DD_HALT_ENA; + } + if (*data & DD_DDGO) { + sim_debug(DEBUG_DETAIL, &dd_dev, "Go.\n"); + } + if (*data & DD_SPGO) { + sim_debug(DEBUG_DETAIL, &dd_dev, "SPGO\n"); + } + if (*data & DD_LATE_ENA) { + sim_debug(DEBUG_DETAIL, &dd_dev, "Late interrupt enabled.\n"); + uptr->STATUS |= DD_LATE_ENA; + } + if (*data & DD_USER) { + sim_debug(DEBUG_DETAIL, &dd_dev, "User mode.\n"); + uptr->STATUS |= DD_USER; + } + break; + case DATAI: + *data = 0; + sim_debug(DEBUG_DATAIO, &dd_dev, "DATAI (%6o)\n", PC); + break; + case DATAO: + uptr->MA = *data & 0777777; + sim_debug(DEBUG_DATAIO, &dd_dev, "DATAO %06o (%6o)\n", uptr->MA, PC); + if (uptr->STATUS & DD_DDGO) + sim_activate (uptr, 1); + break; + } + return SCPE_OK; +} + +static void +dd_pixel (int x, int y, uint8 pixel) +{ + if (x >= DD_WIDTH) + return; + if (y >= DD_HEIGHT) + return; + pixel &= 1; + if (!(dd_function_code & FC_DARK)) + pixel ^= 1; + if (dd_function_code & FC_ADDITIVE) + dd_channel[dd_unit.CHANNEL][DD_WIDTH * y + x] |= pixel; + else + dd_channel[dd_unit.CHANNEL][DD_WIDTH * y + x] = pixel; + dd_changed[dd_unit.CHANNEL] = 1; +} + +static void +dd_chargen (char c, int column) +{ + int i, j; + uint8 pixels; + int line = dd_unit.LINE; + int field = line & 1; + + if (line >= DD_HEIGHT || column >= DD_COLUMNS) + return; + + sim_debug (DEBUG_DETAIL, &dd_dev, "CHARGEN %03o %d@(%d,%d)\n", + c, dd_unit.CHANNEL, column, dd_unit.LINE); + + for (i = 0; i < FONT_HEIGHT-1; i += 2, line += 2) { + pixels = font[c][i + field]; + for (j = 0; j < FONT_WIDTH-1; j++) { + dd_pixel (6 * column + j, line, pixels >> 4); + pixels <<= 1; + } + } +} + +static void +dd_byte (uint8 data) +{ + int max = (dd_function_code & FC_GRAPHICS) ? 64 : DD_COLUMNS; + if (dd_line_buffer_address <= max) { + sim_debug(DEBUG_DETAIL, &dd_dev, "Buffer[%d] %03o\n", + dd_line_buffer_address, data); + dd_line_buffer[dd_line_buffer_address] = data | WRITTEN; + } + dd_line_buffer_address++; + dd_line_buffer_address &= 0177; +} + +static void +dd_text (uint64 insn) +{ + int rubout = 0; + char text[6]; + int i; + + text[0] = (insn >> 29) & 0177; + text[1] = (insn >> 22) & 0177; + text[2] = (insn >> 15) & 0177; + text[3] = (insn >> 8) & 0177; + text[4] = (insn >> 1) & 0177; + text[5] = 0; + + sim_debug(DEBUG_CMD, &dd_dev, "TEXT \"%s\" to %d@(%d,%d)\n", + text, dd_unit.CHANNEL, dd_unit.COLUMN, dd_unit.LINE); + + for (i = 0; i < 5; i++) { + switch (text[i]) { + case 000: + case 0177: + sim_debug (DEBUG_DETAIL, &dd_dev, "CHAR %03o ignored\n", text[i]); + break; + case 012: + if (rubout) + goto print; + if (dd_line_buffer_written) { + sim_debug (DEBUG_DETAIL, &dd_dev, "LF clear rest of line\n"); + while (dd_line_buffer_address <= DD_COLUMNS) + dd_byte (040); + dd_execute ("LF execute"); + } + dd_unit.LINE += FONT_HEIGHT; + if (!(dd_function_code & FC_SINGLE_H)) + dd_unit.LINE += FONT_HEIGHT; + dd_unit.LINE &= 0777; + sim_debug (DEBUG_DETAIL, &dd_dev, "CHAR 012 LF -> (%d,%d)\n", + dd_unit.COLUMN, dd_unit.LINE); + break; + case 015: + if (rubout) + goto print; + if (dd_line_buffer_written) { + sim_debug (DEBUG_DETAIL, &dd_dev, "CR clear rest of line\n"); + while (dd_line_buffer_address <= DD_COLUMNS) + dd_byte (040); + dd_execute ("CR execute"); + } + dd_unit.COLUMN = dd_line_buffer_address = MARGIN; + sim_debug (DEBUG_DETAIL, &dd_dev, "CHAR 015 CR -> (%d,%d)\n", + dd_unit.COLUMN, dd_unit.LINE); + break; + case 010: + case 011: + if (!rubout) + break; + /* Fall through. */ + default: + print: + { + char ch[2]; + memset (ch, 0, 2); + if (text[i] > 040 && text[i] < 0177) + ch[0] = text[i]; + sim_debug (DEBUG_DETAIL, &dd_dev, "CHAR %03o %s (%d,%d)\n", + text[i], ch, dd_line_buffer_address, dd_unit.LINE); + } + dd_byte (text[i]); + dd_line_buffer_written = 1; + dd_unit.COLUMN++; + dd_unit.COLUMN &= 0177; + break; + } + rubout = (text[i] == 0177); + } +} + +static void +dd_graphics (uint8 data, int column) +{ + int i, j; + + sim_debug (DEBUG_CMD, &dd_dev, "GRAPHICS %03o %d@(%d,%d)\n", + data, dd_unit.CHANNEL, column, dd_unit.LINE); + + column = 8 * column + 4; + for (i = 0; i < 8; i++) { + dd_pixel (column, dd_unit.LINE, data >> 7); + column++; + data <<= 1; + } +} + +static void +dd_function (uint8 data) +{ + dd_function_code = data; + sim_debug(DEBUG_CMD, &dd_dev, "COMMAND: function code %03o\n", data); + if (data & FC_GRAPHICS) + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: graphics mode\n"); + else + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: text mode\n"); + if (data & FC_WRITE) + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: write to disc\n"); + else + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: write to display\n"); + if (data & FC_DARK) + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: dark background\n"); + else + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: light background\n"); + switch (data & (FC_GRAPHICS|FC_DOUBLE_W)) { + case 000: + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: single width\n"); + break; + case FC_DOUBLE_W: + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: double width\n"); + break; + case FC_GRAPHICS|FC_ERASE: + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: erase\n"); + break; + } + if (data & FC_ADDITIVE) + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: additive\n"); + else + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: replace\n"); + if (data & FC_SINGLE_H) + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: single height\n"); + else + sim_debug(DEBUG_DETAIL, &dd_dev, "Function: double height\n"); +} + +static void +dd_command (uint32 command, uint8 data) +{ + int i; + switch (command) { + case 0: + dd_execute ("COMMAND: execute"); + break; + case 1: + dd_function (data); + break; + case 2: + dd_unit.CHANNEL = data & 077; + sim_debug(DEBUG_CMD, &dd_dev, "COMMAND: channel select %d\n", + dd_unit.CHANNEL); + if ((dd_function_code & (FC_GRAPHICS|FC_ERASE)) == (FC_GRAPHICS|FC_ERASE)) { + sim_debug(DEBUG_CMD, &dd_dev, "COMMAND: erase channel %d\n", + dd_unit.CHANNEL); + dd_changed[dd_unit.CHANNEL] = 1; + for (i = 0; i < DD_PIXELS; i++) + dd_channel[dd_unit.CHANNEL][i] = 0; + } + break; + case 3: + dd_unit.COLUMN = dd_line_buffer_address = data & 0177; + if (dd_unit.COLUMN == 0 || dd_unit.COLUMN > DD_COLUMNS) + dd_hang ("Text column outside bounds"); + sim_debug(DEBUG_CMD, &dd_dev, "COMMAND: column select %d\n", + dd_unit.COLUMN); + break; + case 4: + dd_unit.LINE = ((data & 037) << 4) | (dd_unit.LINE & 017); + sim_debug(DEBUG_CMD, &dd_dev, "COMMAND: high order line address -> %d\n", + dd_unit.LINE); + break; + case 5: + dd_unit.LINE = (data & 017) | (dd_unit.LINE & 0760); + sim_debug(DEBUG_CMD, &dd_dev, "COMMAND: low order line address -> %d\n", + dd_unit.LINE); + break; + case 6: + sim_debug(DEBUG_CMD, &dd_dev, "COMMAND: write directly %03o (%d,%d)\n", + data, dd_unit.COLUMN, dd_unit.LINE); + dd_unit.COLUMN++; + dd_unit.COLUMN &= 0177; + break; + case 7: + dd_line_buffer_address = data & 0177; + sim_debug(DEBUG_CMD, &dd_dev, "COMMAND: line buffer address %03o\n", + dd_line_buffer_address); + break; + } +} + +static void +dd_decode (uint64 insn) +{ + switch (insn & 077) { + case 001: case 003: case 005: case 007: + case 011: case 013: case 015: case 017: + case 021: case 023: case 025: case 027: + case 031: case 033: case 035: case 037: + case 041: case 043: case 045: case 047: + case 051: case 053: case 055: case 057: + case 061: case 063: case 065: case 067: + case 071: case 073: case 075: case 077: + dd_text (insn); + break; + case 002: case 022: case 042: case 062: + sim_debug(DEBUG_CMD, &dd_dev, "COMMAND: graphics %012llo\n", insn >> 4); + dd_byte ((insn >> 28) & 0377); + dd_byte ((insn >> 20) & 0377); + dd_byte ((insn >> 12) & 0377); + dd_byte ((insn >> 4) & 0377); + break; + case 000: case 040: case 060: + dd_halt ("halt instruction"); + break; + case 020: + dd_unit.MA = insn >> 18; + sim_debug(DEBUG_CMD, &dd_dev, "JUMP %06o\n", dd_unit.MA); + break; + case 006: case 016: case 026: case 036: + case 046: case 056: case 066: case 076: + case 012: case 032: case 052: case 072: + sim_debug(DEBUG_CMD, &dd_dev, "NOP\n"); + break; + case 010: case 030: case 050: case 070: + sim_debug(DEBUG_CMD, &dd_dev, "(weird command)\n"); + case 004: case 014: case 024: case 034: + case 044: case 054: case 064: case 074: + dd_command ((insn >> 9) & 7, (insn >> 28) & 0377); + dd_command ((insn >> 6) & 7, (insn >> 20) & 0377); + dd_command ((insn >> 3) & 7, (insn >> 12) & 0377); + break; + default: + sim_debug(DEBUG_CMD, &dd_dev, "(UNDOCUMENTED %012llo)\n", insn); + break; + } +} + +static t_stat +dd_svc (UNIT *uptr) +{ + if (uptr->MA >= MEMSIZE) { + uptr->STATUS |= DD_NXM; + dd_halt ("NXM"); + } else { + dd_decode (M[uptr->MA++]); + } + + if (uptr->STATUS & DD_HALT) { + uptr->STATUS |= DD_INT; + if (uptr->STATUS & DD_HALT_ENA) { + sim_debug(DEBUG_IRQ, &dd_dev, "Interrupt: halt\n"); + set_interrupt (DD_DEVNUM, uptr->PIA); + } + } else + sim_activate_after (uptr, 100); + + return SCPE_OK; +} + +static void +dd_display (int n) +{ + uint32 selection = vds_selection[n]; + int i, j; + + if (selection == 0) { + sim_debug(DEBUG_DETAIL, &vds_dev, "Output %d displays no channels\n", n); + return; + } + +#if 1 + if (!(selection & (selection - 1))) { + for (i = 0; (selection & 020000000000) == 0; i++) + selection <<= 1; + if (!dd_changed[i] && !vds_changed[n]) + return; + sim_debug(DEBUG_DETAIL, &vds_dev, "Output %d from channel %d\n", n, i); + for (j = 0; j < DD_PIXELS; j++) + vds_surface[n][j] = vds_palette[n][dd_channel[i][j]]; + } else { +#endif + +#if 0 + for (j = 0; j < DD_PIXELS; j++) { + uint8 pixel = 0; + for (i = 0; i < DD_CHANNELS; i++, selection <<= 1) { + if (selection & 020000000000) + pixel |= dd_channel[i][j]; + vds_surface[n][j] = vds_palette[n][pixel]; + } + } +#else + } +#endif + + vid_draw_window (vds_vptr[n], 0, 0, DD_WIDTH, DD_HEIGHT, vds_surface[n]); + vid_refresh_window (vds_vptr[n]); + sim_debug (DEBUG_DETAIL, &vds_dev, "Refresh window %p\n", vds_vptr[n]); +} + +static t_stat +vds_svc (UNIT *uptr) +{ + int i; + for (i = III_DISPLAYS; i < dd_windows + III_DISPLAYS; i++) + dd_display (i); + for (i = 0; i < DD_CHANNELS; i++) + dd_changed[i] = 0; + for (i = 0; i < VDS_OUTPUTS; i++) + vds_changed[i] = 0; + + sim_activate_after (uptr, 33333); + return SCPE_OK; +} + +uint32 dd_keyboard_line (void *p) +{ + int i; + VID_DISPLAY *vptr = (VID_DISPLAY *)p; + sim_debug(DEBUG_DETAIL, &vds_dev, "Key event on window %p\n", vptr); + for (i = 0; i < VDS_OUTPUTS; i++) { + if (vptr == vds_vptr[i]) + return i; + } + return ~0U; +} + +static t_stat +dd_reset (DEVICE *dptr) +{ + if (dptr->flags & DEV_DIS || sim_switches & SWMASK('P')) { + sim_cancel (&dd_unit); + memset (dd_channel, 0, sizeof dd_channel); + memset (dd_changed, 0, sizeof dd_changed); + return SCPE_OK; + } + if (dptr->flags & DEV_DIS) + set_cmd (0, "VDS DISABLED"); + else + set_cmd (0, "VDS ENABLED"); + + return SCPE_OK; +} + +static t_stat dd_set_windows (UNIT *uptr, int32 val, CONST char *cptr, void *desc) +{ + t_value x; + t_stat r; + if (cptr == NULL) + return SCPE_ARG; + x = get_uint (cptr, 10, 32, &r); + if (r != SCPE_OK) + return r; + dd_windows = x; + return SCPE_OK; +} + +static t_stat dd_show_windows (FILE *st, UNIT *uptr, int32 val, CONST void *desc) +{ + if (uptr == NULL) + return SCPE_IERR; + fprintf (st, "WINDOWS=%d", dd_windows); + return SCPE_OK; +} + +static t_stat +dd_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ + return SCPE_OK; +} + +static const char * +dd_description (DEVICE *dptr) +{ + return "Data Disc Television Display System"; +} + +static t_stat +vds_reset (DEVICE *dptr) +{ + t_stat r; + int i; + if (dptr->flags & DEV_DIS || sim_switches & SWMASK('P')) { + for (i = 0; i < VDS_OUTPUTS; i++) { + if (vds_vptr[i] != NULL) + vid_close_window (vds_vptr[i]); + } + vds_channel = 0; + memset (vds_vptr, 0, sizeof vds_vptr); + memset (vds_palette, 0, sizeof vds_palette); + memset (vds_selection, 0, sizeof vds_selection); + memset (vds_sync_inhibit, 0, sizeof vds_sync_inhibit); + memset (vds_analog, 0, sizeof vds_analog); + sim_cancel (&vds_unit); + return SCPE_OK; + } + + for (i = III_DISPLAYS; i < dd_windows + III_DISPLAYS; i++) { + if (vds_vptr[i] == NULL) { + char title[40]; + snprintf (title, sizeof title, "Data Disc display %d", i); + r = vid_open_window (&vds_vptr[i], &dd_dev, title, DD_WIDTH, DD_HEIGHT, 0); + if (r != SCPE_OK) + return r; + fprintf(stderr, "Window %d is %p\r\n", i, vds_vptr[i]); + vds_palette[i][0] = vid_map_rgb_window (vds_vptr[i], 0x00, 0x00, 0x00); + vds_palette[i][1] = vid_map_rgb_window (vds_vptr[i], 0x00, 0xFF, 0x30); + } + } + + sim_activate (&vds_unit, 1); + return SCPE_OK; +} + +static t_stat +vds_devio(uint32 dev, uint64 *data) +{ + switch(dev & 3) { + case CONO: + sim_debug(DEBUG_CONO, &vds_dev, "%012llo (%6o)\n", *data, PC); + vds_channel = *data & 077; + break; + case DATAO: + sim_debug(DEBUG_DATAIO, &vds_dev, "%012llo (%6o)\n", *data, PC); + vds_changed[vds_channel] = 1; + vds_selection[vds_channel] = *data >> 4; + vds_sync_inhibit[vds_channel] = (*data >> 3) & 1; + vds_analog[vds_channel] = *data & 7; + sim_debug(DEBUG_DETAIL, &vds_dev, "Output %d selection %011o\n", + vds_channel, vds_selection[vds_channel]); +#if 0 + sim_debug(DEBUG_DETAIL, &vds_dev, "Sync inhibit %d\n", + vds_sync_inhibit[vds_channel]); + sim_debug(DEBUG_DETAIL, &vds_dev, "Analog %d\n", + vds_analog[vds_channel]); +#endif + break; + } + return SCPE_OK; +} + +static t_stat +vds_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ + return SCPE_OK; +} + +static const char * +vds_description (DEVICE *dptr) +{ + return "Video Switch"; +} +#endif diff --git a/PDP10/ka10_dd_font.c b/PDP10/ka10_dd_font.c new file mode 100644 index 000000000..c056d4c55 --- /dev/null +++ b/PDP10/ka10_dd_font.c @@ -0,0 +1,1858 @@ +#include + +/* ka10_dd_font.c: Font data for Data Disc 6600 Television Display System. + + Copyright (c) 2022-2023, Lars Brinkhoff + + Process this with a C compiler supporting the binary 0b prefix + to generate the ka10_dd_font.h file included in the emulator. + + 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 + LARS BRINKHOFF 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 Lars Brinkhoff shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Lars Brinkhoff. +*/ + +/* Font from http://www.bitsavers.org/pdf/dataDisc/Television_Display_System_Reference_Manual_Jul69.pdf */ +static unsigned int tds_font[128][12] = { + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 000 + { 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b10101, + 0b01110, + 0b00100, + 0b00000, + 0b00000 }, // 001 down arrow + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 002 alpha + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 003 beta + { 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b01010, + 0b01010, + 0b10001, + 0b10001, + 0b10001, + 0b10001, + 0b00000, + 0b00000 }, // 004 AND + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 005 NOT + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01111, + 0b10001, + 0b01110, + 0b10000, + 0b01111, + 0b00000, + 0b00000 }, // 006 epsilon + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b01010, + 0b01010, + 0b01010, + 0b01010, + 0b00000, + 0b00000 }, // 007 pi + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 010 lambda + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 011 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 012 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 013 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 014 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 015 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01010, + 0b10101, + 0b10101, + 0b01010, + 0b00000, + 0b00000, + 0b00000 }, // 016 infinity + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 017 partial differential + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b11110, + 0b00001, + 0b00001, + 0b11110, + 0b00000, + 0b00000, + 0b00000 }, // 020 subset + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01111, + 0b10000, + 0b10000, + 0b01111, + 0b00000, + 0b00000, + 0b00000 }, // 021 superset + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 022 intersection + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 023 union + { 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b10001, + 0b11111, + 0b10001, + 0b01010, + 0b01010, + 0b00100, + 0b00000, + 0b00000 }, // 024 for all + { 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b00001, + 0b00001, + 0b01111, + 0b00001, + 0b00001, + 0b11111, + 0b00000, + 0b00000 }, // 025 there exists + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b11011, + 0b10101, + 0b11011, + 0b01110, + 0b00000, + 0b00000, + 0b00000 }, // 026 circled times + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01010, + 0b11111, + 0b01010, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 027 double arrow + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b00000, + 0b00000 }, // 030 underscore + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b00010, + 0b11111, + 0b00010, + 0b00100, + 0b00000, + 0b00000, + 0b00000 }, // 031 right arrow + { 0b00000, + 0b00000, + 0b00000, + 0b01010, + 0b10100, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 032 tilde + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00010, + 0b11111, + 0b00100, + 0b11111, + 0b01000, + 0b00000, + 0b00000 }, // 033 not equal + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 034 less than or equal + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 035 greater than or equal + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b00000, + 0b11111, + 0b00000, + 0b11111, + 0b00000, + 0b00000, + 0b00000 }, // 036 equivalence + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 037 OR + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 040 SPC + { 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b00000, + 0b00100, + 0b00000, + 0b00000 }, // 041 ! + { 0b00000, + 0b00000, + 0b00000, + 0b01010, + 0b01010, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 042 " + { 0b00000, + 0b00000, + 0b00000, + 0b01010, + 0b01010, + 0b11111, + 0b01010, + 0b11111, + 0b01010, + 0b01010, + 0b00000, + 0b00000 }, // 043 # + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10101, + 0b10100, + 0b01110, + 0b00101, + 0b10101, + 0b01110, + 0b00000, + 0b00000 }, // 044 $ + { 0b00000, + 0b00000, + 0b00000, + 0b11001, + 0b11001, + 0b00010, + 0b00100, + 0b01000, + 0b10011, + 0b10011, + 0b00000, + 0b00000 }, // 045 % + { 0b00000, + 0b00000, + 0b00000, + 0b01000, + 0b10100, + 0b10100, + 0b01000, + 0b10101, + 0b10010, + 0b01101, + 0b00000, + 0b00000 }, // 046 & + { 0b00000, + 0b00000, + 0b00000, + 0b01000, + 0b00100, + 0b00100, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 047 ' + { 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b01000, + 0b10000, + 0b10000, + 0b10000, + 0b01000, + 0b00100, + 0b00000, + 0b00000 }, // 050 ( + { 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b00010, + 0b00001, + 0b00001, + 0b00001, + 0b00010, + 0b00100, + 0b00000, + 0b00000 }, // 051 ) + { 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b10101, + 0b01110, + 0b11111, + 0b01110, + 0b10101, + 0b00100, + 0b00000, + 0b00000 }, // 052 * + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b00100, + 0b11111, + 0b00100, + 0b00100, + 0b00000, + 0b00000, + 0b00000 }, // 053 + + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01000, + 0b00100, + 0b00100, + 0b00000 }, // 054 , + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 055 - + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01100, + 0b01100, + 0b00000, + 0b00000 }, // 056 . + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00001, + 0b00010, + 0b00100, + 0b01000, + 0b10000, + 0b00000, + 0b00000, + 0b00000 }, // 057 / + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b10001, + 0b10101, + 0b10001, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 060 0 + { 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b01100, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b01110, + 0b00000, + 0b00000 }, // 061 1 + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b00001, + 0b00010, + 0b00100, + 0b01000, + 0b11111, + 0b00000, + 0b00000 }, // 062 + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b00001, + 0b00001, + 0b00110, + 0b00001, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 063 + { 0b00000, + 0b00000, + 0b00000, + 0b00010, + 0b00110, + 0b01010, + 0b10010, + 0b11111, + 0b00010, + 0b00010, + 0b00000, + 0b00000 }, // 064 + { 0b00000, + 0b00000, + 0b00000, + 0b01111, + 0b01000, + 0b01000, + 0b01110, + 0b00001, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 065 + { 0b00000, + 0b00000, + 0b00000, + 0b00110, + 0b01000, + 0b10000, + 0b11110, + 0b10001, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 066 + { 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b00001, + 0b00010, + 0b00100, + 0b00100, + 0b01000, + 0b01000, + 0b00000, + 0b00000 }, // 067 + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b10001, + 0b01110, + 0b10001, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 070 + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b10001, + 0b01111, + 0b00001, + 0b00001, + 0b00001, + 0b00000, + 0b00000 }, // 071 9 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b00000, + 0b00100, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 072 : + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b00000, + 0b00100, + 0b00100, + 0b01000, + 0b00000 }, // 073 ; + { 0b00000, + 0b00000, + 0b00000, + 0b00010, + 0b00100, + 0b01000, + 0b10000, + 0b01000, + 0b00100, + 0b00010, + 0b00000, + 0b00000 }, // 074 < + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b00000, + 0b11111, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 075 = + { 0b00000, + 0b00000, + 0b00000, + 0b01000, + 0b00100, + 0b00010, + 0b00001, + 0b00010, + 0b00100, + 0b01000, + 0b00000, + 0b00000 }, // 076 > + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b00001, + 0b00010, + 0b00100, + 0b00100, + 0b00000, + 0b00100, + 0b00000 }, // 077 ? + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b10111, + 0b10101, + 0b10111, + 0b10000, + 0b10000, + 0b01110, + 0b00000 }, // 100 @ + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b10001, + 0b11111, + 0b10001, + 0b10001, + 0b10001, + 0b00000, + 0b00000 }, // 101 A + { 0b00000, + 0b00000, + 0b00000, + 0b11110, + 0b10001, + 0b10001, + 0b11110, + 0b10001, + 0b10001, + 0b11110, + 0b00000, + 0b00000 }, // 102 B + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b10000, + 0b10000, + 0b10000, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 103 C + { 0b00000, + 0b00000, + 0b00000, + 0b11110, + 0b01001, + 0b01001, + 0b01001, + 0b01001, + 0b01001, + 0b11110, + 0b00000, + 0b00000 }, // 104 D + { 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b10000, + 0b10000, + 0b11110, + 0b10000, + 0b10000, + 0b11111, + 0b00000, + 0b00000 }, // 105 E + { 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b10000, + 0b10000, + 0b11110, + 0b10000, + 0b10000, + 0b10000, + 0b00000, + 0b00000 }, // 106 F + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b10000, + 0b10000, + 0b10111, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 107 G + { 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b10001, + 0b10001, + 0b11111, + 0b10001, + 0b10001, + 0b10001, + 0b00000, + 0b00000 }, // 110 H + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b01110, + 0b00000, + 0b00000 }, // 111 I + { 0b00000, + 0b00000, + 0b00000, + 0b00001, + 0b00001, + 0b00001, + 0b00001, + 0b00001, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 112 J + { 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b10010, + 0b10100, + 0b11000, + 0b10100, + 0b10010, + 0b10001, + 0b00000, + 0b00000 }, // 113 K + { 0b00000, + 0b00000, + 0b00000, + 0b10000, + 0b10000, + 0b10000, + 0b10000, + 0b10000, + 0b10000, + 0b11111, + 0b00000, + 0b00000 }, // 114 L + { 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b11011, + 0b10101, + 0b10001, + 0b10001, + 0b10001, + 0b10001, + 0b00000, + 0b00000 }, // 115 M + { 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b11001, + 0b11101, + 0b10111, + 0b10011, + 0b10001, + 0b10001, + 0b00000, + 0b00000 }, // 116 N + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b10001, + 0b10001, + 0b10001, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 117 O + { 0b00000, + 0b00000, + 0b00000, + 0b11110, + 0b10001, + 0b10001, + 0b11110, + 0b10000, + 0b10000, + 0b10000, + 0b00000, + 0b00000 }, // 120 P + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b10001, + 0b10001, + 0b10101, + 0b10010, + 0b01101, + 0b00000, + 0b00000 }, // 121 Q + { 0b00000, + 0b00000, + 0b00000, + 0b11110, + 0b10001, + 0b10001, + 0b11110, + 0b10100, + 0b10010, + 0b10001, + 0b00000, + 0b00000 }, // 122 R + { 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10000, + 0b10000, + 0b01110, + 0b00001, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 123 S + { 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b00000, + 0b00000 }, // 124 T + { 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b10001, + 0b10001, + 0b10001, + 0b10001, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 125 U + { 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b10001, + 0b10001, + 0b10001, + 0b01010, + 0b01010, + 0b00100, + 0b00000, + 0b00000 }, // 126 V + { 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b10001, + 0b10001, + 0b10001, + 0b10101, + 0b11011, + 0b10001, + 0b00000, + 0b00000 }, // 127 W + { 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b10001, + 0b01010, + 0b00100, + 0b01010, + 0b10001, + 0b10001, + 0b00000, + 0b00000 }, // 130 X + { 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b10001, + 0b01010, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b00000, + 0b00000 }, // 131 Y + { 0b00000, + 0b00000, + 0b00000, + 0b11111, + 0b00001, + 0b00010, + 0b00100, + 0b01000, + 0b10000, + 0b11111, + 0b00000, + 0b00000 }, // 132 Z + { 0b00000, + 0b00000, + 0b00000, + 0b11110, + 0b10000, + 0b10000, + 0b10000, + 0b10000, + 0b10000, + 0b11110, + 0b00000, + 0b00000 }, // 133 [ + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b10000, + 0b01000, + 0b00100, + 0b00010, + 0b00001, + 0b00000, + 0b00000, + 0b00000 }, // 134 backslash + { 0b00000, + 0b00000, + 0b00000, + 0b01111, + 0b00001, + 0b00001, + 0b00001, + 0b00001, + 0b00001, + 0b01111, + 0b00000, + 0b00000 }, // 135 ] + { 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b01110, + 0b10101, + 0b00100, + 0b00100, + 0b00100, + 0b00100, + 0b00000, + 0b00000 }, // 136 up arrow + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00100, + 0b01000, + 0b11111, + 0b01000, + 0b00100, + 0b00000, + 0b00000, + 0b00000 }, // 137 left arrow + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 140 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b00001, + 0b01111, + 0b10001, + 0b01111, + 0b00000, + 0b00000 }, // 141 a + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 142 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 143 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 144 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b11111, + 0b10000, + 0b01111, + 0b00000, + 0b00000 }, // 145 e + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 146 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 147 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 150 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 151 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 152 + { 0b00000, + 0b00000, + 0b00000, + 0b10000, + 0b10000, + 0b10010, + 0b10100, + 0b11000, + 0b10100, + 0b10010, + 0b00000, + 0b00000 }, // 153 k + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 154 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b11010, + 0b10101, + 0b10101, + 0b10101, + 0b10101, + 0b00000, + 0b00000 }, // 155 m + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 156 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01110, + 0b10001, + 0b10001, + 0b10001, + 0b01110, + 0b00000, + 0b00000 }, // 157 o + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 160 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 161 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b10110, + 0b11001, + 0b10000, + 0b10000, + 0b10000, + 0b00000, + 0b00000 }, // 162 r + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b01111, + 0b10000, + 0b01110, + 0b00001, + 0b11110, + 0b00000, + 0b00000 }, // 163 s + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 164 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b10001, + 0b10001, + 0b10001, + 0b10011, + 0b01101, + 0b00000, + 0b00000 }, // 165 u + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 166 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 167 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 170 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 171 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 172 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 173 { + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 174 | + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 175 + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 176 } + { 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000, + 0b00000 }, // 177 +}; + +/* Font from Knight TV. */ +static unsigned int knight_font[128][12] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +/* SAIL7 font. */ +static unsigned int sail7_font[128][12] = { + { 0, 0x00, 0x1F, 0x11, 0x15, 0x11, 0x1F, 0x00, 0x00, 0, 0, 0 }, // 000 + { 0, 0x04, 0x04, 0x04, 0x15, 0x0E, 0x04, 0x00, 0x00, 0, 0, 0 }, // 001 down arrow + { 0, 0x00, 0x00, 0x0D, 0x12, 0x12, 0x0D, 0x00, 0x00, 0, 0, 0 }, // 002 alpha + { 0, 0x06, 0x09, 0x0E, 0x09, 0x09, 0x0E, 0x08, 0x00, 0, 0, 0 }, // 003 beta + { 0, 0x00, 0x04, 0x0A, 0x11, 0x00, 0x00, 0x00, 0x00, 0, 0, 0 }, // 004 AND + { 0, 0x00, 0x00, 0x1F, 0x01, 0x01, 0x00, 0x00, 0x00, 0, 0, 0 }, // 005 NOT + { 0, 0x00, 0x07, 0x08, 0x0E, 0x08, 0x07, 0x00, 0x00, 0, 0, 0 }, // 006 epsilon + { 0, 0x00, 0x1F, 0x0A, 0x0A, 0x0A, 0x09, 0x00, 0x00, 0, 0, 0 }, // 007 pi + { 0, 0x10, 0x08, 0x04, 0x0A, 0x11, 0x11, 0x00, 0x00, 0, 0, 0 }, // 010 lambda + { 0, 0x1C, 0x08, 0x0E, 0x0D, 0x06, 0x05, 0x06, 0x00, 0, 0, 0 }, // 011 TB + { 0, 0x10, 0x10, 0x17, 0x1C, 0x07, 0x04, 0x04, 0x00, 0, 0, 0 }, // 012 LF + { 0, 0x0A, 0x0A, 0x04, 0x07, 0x02, 0x02, 0x02, 0x00, 0, 0, 0 }, // 013 VT + { 0, 0x1C, 0x10, 0x1F, 0x14, 0x16, 0x04, 0x04, 0x00, 0, 0, 0 }, // 014 FF + { 0, 0x0E, 0x10, 0x16, 0x15, 0x0E, 0x05, 0x05, 0x00, 0, 0, 0 }, // 015 CR + { 0, 0x00, 0x0A, 0x15, 0x15, 0x15, 0x0A, 0x00, 0x00, 0, 0, 0 }, // 016 infinity + { 0, 0x0C, 0x02, 0x07, 0x09, 0x09, 0x06, 0x00, 0x00, 0, 0, 0 }, // 017 partial differential + { 0, 0x00, 0x0F, 0x10, 0x10, 0x0F, 0x00, 0x00, 0x00, 0, 0, 0 }, // 020 subset + { 0, 0x00, 0x1E, 0x01, 0x01, 0x1E, 0x00, 0x00, 0x00, 0, 0, 0 }, // 021 superset + { 0, 0x06, 0x09, 0x09, 0x09, 0x09, 0x09, 0x00, 0x00, 0, 0, 0 }, // 022 intersection + { 0, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x00, 0, 0, 0 }, // 023 union + { 0, 0x11, 0x11, 0x1F, 0x11, 0x0A, 0x04, 0x00, 0x00, 0, 0, 0 }, // 024 for all + { 0, 0x1F, 0x01, 0x07, 0x01, 0x01, 0x1F, 0x00, 0x00, 0, 0, 0 }, // 025 there exists + { 0, 0x00, 0x0E, 0x15, 0x1B, 0x15, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 026 circled times + { 0, 0x00, 0x00, 0x0A, 0x1F, 0x0A, 0x00, 0x00, 0x00, 0, 0, 0 }, // 027 double arrow + { 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0, 0, 0 }, // 030 underscore + { 0, 0x00, 0x04, 0x02, 0x1F, 0x02, 0x04, 0x00, 0x00, 0, 0, 0 }, // 031 right arrow + { 0, 0x00, 0x08, 0x15, 0x02, 0x00, 0x00, 0x00, 0x00, 0, 0, 0 }, // 032 tilde + { 0, 0x01, 0x02, 0x1F, 0x04, 0x1F, 0x08, 0x10, 0x00, 0, 0, 0 }, // 033 not equal + { 0, 0x00, 0x02, 0x04, 0x08, 0x04, 0x02, 0x0F, 0x00, 0, 0, 0 }, // 034 less than or equal + { 0, 0x00, 0x08, 0x04, 0x02, 0x04, 0x08, 0x1E, 0x00, 0, 0, 0 }, // 035 greater than or equal + { 0, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0, 0, 0 }, // 036 equivalence + { 0, 0x00, 0x11, 0x0A, 0x04, 0x00, 0x00, 0x00, 0x00, 0, 0, 0 }, // 037 OR + { 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0, 0 }, // 040 SPC + { 0, 0x06, 0x06, 0x06, 0x06, 0x00, 0x06, 0x00, 0x00, 0, 0, 0 }, // 041 ! + { 0, 0x0A, 0x0A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0, 0 }, // 042 " + { 0, 0x0A, 0x1F, 0x0A, 0x0A, 0x1F, 0x0A, 0x00, 0x00, 0, 0, 0 }, // 043 # + { 0, 0x04, 0x0F, 0x14, 0x0E, 0x05, 0x1E, 0x04, 0x00, 0, 0, 0 }, // 044 $ + { 0, 0x1F, 0x19, 0x02, 0x04, 0x0B, 0x13, 0x00, 0x00, 0, 0, 0 }, // 045 % + { 0, 0x0C, 0x14, 0x08, 0x15, 0x12, 0x1D, 0x00, 0x00, 0, 0, 0 }, // 046 & + { 0, 0x06, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0, 0 }, // 047 ' + { 0, 0x02, 0x04, 0x08, 0x08, 0x08, 0x04, 0x02, 0x00, 0, 0, 0 }, // 050 ( + { 0, 0x08, 0x04, 0x02, 0x02, 0x02, 0x04, 0x08, 0x00, 0, 0, 0 }, // 051 ) + { 0, 0x00, 0x15, 0x0E, 0x1B, 0x0E, 0x15, 0x00, 0x00, 0, 0, 0 }, // 052 * + { 0, 0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00, 0x00, 0, 0, 0 }, // 053 + + { 0, 0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x04, 0x00, 0, 0, 0 }, // 054 , + { 0, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0, 0, 0 }, // 055 - + { 0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0, 0, 0 }, // 056 . + { 0, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x00, 0x00, 0, 0, 0 }, // 057 / + { 0, 0x06, 0x09, 0x0B, 0x0D, 0x09, 0x06, 0x00, 0x00, 0, 0, 0 }, // 060 0 + { 0, 0x02, 0x06, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, 0, 0, 0 }, // 061 1 + { 0, 0x0E, 0x11, 0x01, 0x0E, 0x10, 0x1F, 0x00, 0x00, 0, 0, 0 }, // 062 2 + { 0, 0x0E, 0x11, 0x06, 0x01, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 063 3 + { 0, 0x02, 0x06, 0x0A, 0x1F, 0x02, 0x02, 0x00, 0x00, 0, 0, 0 }, // 064 4 + { 0, 0x1F, 0x10, 0x1E, 0x01, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 065 5 + { 0, 0x0E, 0x10, 0x1E, 0x11, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 066 6 + { 0, 0x1F, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0, 0, 0 }, // 067 7 + { 0, 0x0E, 0x11, 0x0E, 0x11, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 070 8 + { 0, 0x0E, 0x11, 0x11, 0x0F, 0x01, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 071 9 + { 0, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04, 0x00, 0x00, 0, 0, 0 }, // 072 : + { 0, 0x00, 0x04, 0x04, 0x00, 0x06, 0x02, 0x04, 0x00, 0, 0, 0 }, // 073 ; + { 0, 0x00, 0x02, 0x04, 0x08, 0x04, 0x02, 0x00, 0x00, 0, 0, 0 }, // 074 < + { 0, 0x00, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x00, 0x00, 0, 0, 0 }, // 075 = + { 0, 0x00, 0x08, 0x04, 0x02, 0x04, 0x08, 0x00, 0x00, 0, 0, 0 }, // 076 > + { 0, 0x0E, 0x11, 0x01, 0x06, 0x00, 0x04, 0x00, 0x00, 0, 0, 0 }, // 077 ? + { 0, 0x0E, 0x11, 0x17, 0x17, 0x10, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 100 @ + { 0, 0x0E, 0x11, 0x1F, 0x11, 0x11, 0x11, 0x00, 0x00, 0, 0, 0 }, // 101 A + { 0, 0x1E, 0x11, 0x1E, 0x11, 0x11, 0x1E, 0x00, 0x00, 0, 0, 0 }, // 102 B + { 0, 0x0E, 0x11, 0x10, 0x10, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 103 C + { 0, 0x1E, 0x11, 0x11, 0x11, 0x11, 0x1E, 0x00, 0x00, 0, 0, 0 }, // 104 D + { 0, 0x1F, 0x10, 0x1E, 0x10, 0x10, 0x1F, 0x00, 0x00, 0, 0, 0 }, // 105 E + { 0, 0x1F, 0x10, 0x1E, 0x10, 0x10, 0x10, 0x00, 0x00, 0, 0, 0 }, // 106 F + { 0, 0x0E, 0x11, 0x10, 0x13, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 107 G + { 0, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11, 0x00, 0x00, 0, 0, 0 }, // 110 H + { 0, 0x0E, 0x04, 0x04, 0x04, 0x04, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 111 I + { 0, 0x01, 0x01, 0x01, 0x01, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 112 J + { 0, 0x11, 0x12, 0x14, 0x1C, 0x12, 0x11, 0x00, 0x00, 0, 0, 0 }, // 113 K + { 0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0, 0, 0 }, // 114 L + { 0, 0x11, 0x1B, 0x15, 0x15, 0x11, 0x11, 0x00, 0x00, 0, 0, 0 }, // 115 M + { 0, 0x11, 0x19, 0x15, 0x13, 0x11, 0x11, 0x00, 0x00, 0, 0, 0 }, // 116 N + { 0, 0x0E, 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 117 O + { 0, 0x1E, 0x11, 0x1E, 0x10, 0x10, 0x10, 0x00, 0x00, 0, 0, 0 }, // 120 P + { 0, 0x0E, 0x11, 0x11, 0x15, 0x13, 0x0E, 0x01, 0x00, 0, 0, 0 }, // 121 Q + { 0, 0x1E, 0x11, 0x1E, 0x14, 0x12, 0x11, 0x00, 0x00, 0, 0, 0 }, // 122 R + { 0, 0x0E, 0x11, 0x0C, 0x02, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 123 S + { 0, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0, 0, 0 }, // 124 T + { 0, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 125 U + { 0, 0x11, 0x11, 0x11, 0x0A, 0x0A, 0x04, 0x00, 0x00, 0, 0, 0 }, // 126 V + { 0, 0x11, 0x11, 0x15, 0x15, 0x1B, 0x11, 0x00, 0x00, 0, 0, 0 }, // 127 W + { 0, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x11, 0x00, 0x00, 0, 0, 0 }, // 130 X + { 0, 0x11, 0x11, 0x0E, 0x04, 0x04, 0x04, 0x00, 0x00, 0, 0, 0 }, // 131 Y + { 0, 0x1F, 0x01, 0x02, 0x08, 0x10, 0x1F, 0x00, 0x00, 0, 0, 0 }, // 132 Z + { 0, 0x0E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0E, 0x00, 0, 0, 0 }, // 133 [ + { 0, 0x10, 0x08, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0, 0, 0 }, // 134 backslash + { 0, 0x0E, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0E, 0x00, 0, 0, 0 }, // 135 ] + { 0, 0x04, 0x0E, 0x15, 0x04, 0x04, 0x04, 0x00, 0x00, 0, 0, 0 }, // 136 ^ + { 0, 0x00, 0x04, 0x08, 0x1F, 0x08, 0x04, 0x00, 0x00, 0, 0, 0 }, // 137 _ + { 0, 0x06, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0, 0, 0 }, // 140 ` + { 0, 0x00, 0x0E, 0x01, 0x0F, 0x11, 0x0D, 0x00, 0x00, 0, 0, 0 }, // 141 a + { 0, 0x10, 0x16, 0x19, 0x11, 0x11, 0x16, 0x00, 0x00, 0, 0, 0 }, // 142 b + { 0, 0x00, 0x0E, 0x10, 0x10, 0x10, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 143 c + { 0, 0x01, 0x0D, 0x13, 0x11, 0x11, 0x0D, 0x00, 0x00, 0, 0, 0 }, // 144 d + { 0, 0x00, 0x0E, 0x11, 0x1F, 0x10, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 145 e + { 0, 0x07, 0x08, 0x1E, 0x08, 0x08, 0x08, 0x00, 0x00, 0, 0, 0 }, // 146 f + { 0, 0x00, 0x0F, 0x11, 0x11, 0x0E, 0x01, 0x1E, 0x00, 0, 0, 0 }, // 147 g + { 0, 0x10, 0x16, 0x19, 0x11, 0x11, 0x11, 0x00, 0x00, 0, 0, 0 }, // 150 h + { 0, 0x04, 0x00, 0x0C, 0x04, 0x04, 0x04, 0x00, 0x00, 0, 0, 0 }, // 151 i + { 0, 0x02, 0x00, 0x06, 0x02, 0x02, 0x02, 0x0C, 0x00, 0, 0, 0 }, // 152 j + { 0, 0x08, 0x09, 0x0A, 0x0C, 0x0A, 0x09, 0x00, 0x00, 0, 0, 0 }, // 153 k + { 0, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0, 0, 0 }, // 154 l + { 0, 0x00, 0x1A, 0x15, 0x15, 0x15, 0x15, 0x00, 0x00, 0, 0, 0 }, // 155 m + { 0, 0x00, 0x16, 0x19, 0x11, 0x11, 0x11, 0x00, 0x00, 0, 0, 0 }, // 156 n + { 0, 0x00, 0x0E, 0x11, 0x11, 0x11, 0x0E, 0x00, 0x00, 0, 0, 0 }, // 157 o + { 0, 0x00, 0x16, 0x19, 0x11, 0x11, 0x16, 0x10, 0x00, 0, 0, 0 }, // 160 p + { 0, 0x00, 0x0D, 0x13, 0x11, 0x11, 0x0D, 0x01, 0x00, 0, 0, 0 }, // 161 q + { 0, 0x00, 0x16, 0x19, 0x10, 0x10, 0x10, 0x00, 0x00, 0, 0, 0 }, // 162 r + { 0, 0x00, 0x0F, 0x10, 0x0E, 0x01, 0x1E, 0x00, 0x00, 0, 0, 0 }, // 163 s + { 0, 0x08, 0x1F, 0x08, 0x08, 0x08, 0x06, 0x00, 0x00, 0, 0, 0 }, // 164 t + { 0, 0x00, 0x11, 0x11, 0x11, 0x11, 0x0D, 0x00, 0x00, 0, 0, 0 }, // 165 u + { 0, 0x00, 0x11, 0x11, 0x0A, 0x0A, 0x04, 0x00, 0x00, 0, 0, 0 }, // 166 v + { 0, 0x00, 0x11, 0x11, 0x15, 0x15, 0x0A, 0x00, 0x00, 0, 0, 0 }, // 167 w + { 0, 0x00, 0x11, 0x0A, 0x04, 0x0A, 0x11, 0x00, 0x00, 0, 0, 0 }, // 170 x + { 0, 0x00, 0x11, 0x11, 0x11, 0x0F, 0x01, 0x0E, 0x00, 0, 0, 0 }, // 171 y + { 0, 0x00, 0x1F, 0x02, 0x04, 0x08, 0x1F, 0x00, 0x00, 0, 0, 0 }, // 172 z + { 0, 0x03, 0x04, 0x04, 0x08, 0x04, 0x04, 0x03, 0x00, 0, 0, 0 }, // 173 { + { 0, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0, 0, 0 }, // 174 | + { 0, 0x00, 0x04, 0x0A, 0x11, 0x0A, 0x04, 0x00, 0x00, 0, 0, 0 }, // 175 altmode + { 0, 0x18, 0x04, 0x04, 0x02, 0x04, 0x04, 0x18, 0x00, 0, 0, 0 }, // 176 } + { 0, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0, 0, 0 }, // 177 +}; + +int main (void) +{ + unsigned int *font; + unsigned int i; + + FILE *f = fopen ("ka10_dd_font.h", "w"); + if (f == NULL) + return 1; + + fprintf (f, "static uint8 font[128][12] = {\n"); + + for (i = 0; i < 128; i++) { + font = sail7_font[i]; + fprintf (f, " { %03o, %03o, %03o, %03o, %03o, %03o, ", + font[0], font[1], font[2], font[3], font[4], font[5]); + fprintf (f, "%03o, %03o, %03o, %03o, %03o, %03o }, // %03o\n", + font[6], font[7], font[8], font[9], font[10], font[11], i); + } + + fprintf (f, "};\n"); + fclose (f); + return 0; +} diff --git a/PDP10/ka10_dd_font.h b/PDP10/ka10_dd_font.h new file mode 100644 index 000000000..7b7573ce2 --- /dev/null +++ b/PDP10/ka10_dd_font.h @@ -0,0 +1,134 @@ +/* ka10_dd_font.h: Font data for Data Disc 6600 Television Display System. + + Copyright (c) 2022-2023, Lars Brinkhoff */ + +static uint8 font[128][12] = { + { 000, 000, 037, 021, 025, 021, 037, 000, 000, 000, 000, 000 }, // 000 + { 000, 004, 004, 004, 025, 016, 004, 000, 000, 000, 000, 000 }, // 001 + { 000, 000, 000, 015, 022, 022, 015, 000, 000, 000, 000, 000 }, // 002 + { 000, 006, 011, 016, 011, 011, 016, 010, 000, 000, 000, 000 }, // 003 + { 000, 000, 004, 012, 021, 000, 000, 000, 000, 000, 000, 000 }, // 004 + { 000, 000, 000, 037, 001, 001, 000, 000, 000, 000, 000, 000 }, // 005 + { 000, 000, 007, 010, 016, 010, 007, 000, 000, 000, 000, 000 }, // 006 + { 000, 000, 037, 012, 012, 012, 011, 000, 000, 000, 000, 000 }, // 007 + { 000, 020, 010, 004, 012, 021, 021, 000, 000, 000, 000, 000 }, // 010 + { 000, 034, 010, 016, 015, 006, 005, 006, 000, 000, 000, 000 }, // 011 + { 000, 020, 020, 027, 034, 007, 004, 004, 000, 000, 000, 000 }, // 012 + { 000, 012, 012, 004, 007, 002, 002, 002, 000, 000, 000, 000 }, // 013 + { 000, 034, 020, 037, 024, 026, 004, 004, 000, 000, 000, 000 }, // 014 + { 000, 016, 020, 026, 025, 016, 005, 005, 000, 000, 000, 000 }, // 015 + { 000, 000, 012, 025, 025, 025, 012, 000, 000, 000, 000, 000 }, // 016 + { 000, 014, 002, 007, 011, 011, 006, 000, 000, 000, 000, 000 }, // 017 + { 000, 000, 017, 020, 020, 017, 000, 000, 000, 000, 000, 000 }, // 020 + { 000, 000, 036, 001, 001, 036, 000, 000, 000, 000, 000, 000 }, // 021 + { 000, 006, 011, 011, 011, 011, 011, 000, 000, 000, 000, 000 }, // 022 + { 000, 011, 011, 011, 011, 011, 006, 000, 000, 000, 000, 000 }, // 023 + { 000, 021, 021, 037, 021, 012, 004, 000, 000, 000, 000, 000 }, // 024 + { 000, 037, 001, 007, 001, 001, 037, 000, 000, 000, 000, 000 }, // 025 + { 000, 000, 016, 025, 033, 025, 016, 000, 000, 000, 000, 000 }, // 026 + { 000, 000, 000, 012, 037, 012, 000, 000, 000, 000, 000, 000 }, // 027 + { 000, 000, 000, 000, 000, 000, 000, 000, 077, 000, 000, 000 }, // 030 + { 000, 000, 004, 002, 037, 002, 004, 000, 000, 000, 000, 000 }, // 031 + { 000, 000, 010, 025, 002, 000, 000, 000, 000, 000, 000, 000 }, // 032 + { 000, 001, 002, 037, 004, 037, 010, 020, 000, 000, 000, 000 }, // 033 + { 000, 000, 002, 004, 010, 004, 002, 017, 000, 000, 000, 000 }, // 034 + { 000, 000, 010, 004, 002, 004, 010, 036, 000, 000, 000, 000 }, // 035 + { 000, 000, 037, 000, 037, 000, 037, 000, 000, 000, 000, 000 }, // 036 + { 000, 000, 021, 012, 004, 000, 000, 000, 000, 000, 000, 000 }, // 037 + { 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000, 000 }, // 040 + { 000, 006, 006, 006, 006, 000, 006, 000, 000, 000, 000, 000 }, // 041 + { 000, 012, 012, 012, 000, 000, 000, 000, 000, 000, 000, 000 }, // 042 + { 000, 012, 037, 012, 012, 037, 012, 000, 000, 000, 000, 000 }, // 043 + { 000, 004, 017, 024, 016, 005, 036, 004, 000, 000, 000, 000 }, // 044 + { 000, 037, 031, 002, 004, 013, 023, 000, 000, 000, 000, 000 }, // 045 + { 000, 014, 024, 010, 025, 022, 035, 000, 000, 000, 000, 000 }, // 046 + { 000, 006, 002, 004, 000, 000, 000, 000, 000, 000, 000, 000 }, // 047 + { 000, 002, 004, 010, 010, 010, 004, 002, 000, 000, 000, 000 }, // 050 + { 000, 010, 004, 002, 002, 002, 004, 010, 000, 000, 000, 000 }, // 051 + { 000, 000, 025, 016, 033, 016, 025, 000, 000, 000, 000, 000 }, // 052 + { 000, 000, 004, 004, 037, 004, 004, 000, 000, 000, 000, 000 }, // 053 + { 000, 000, 000, 000, 000, 006, 002, 004, 000, 000, 000, 000 }, // 054 + { 000, 000, 000, 000, 077, 000, 000, 000, 000, 000, 000, 000 }, // 055 + { 000, 000, 000, 000, 000, 004, 004, 000, 000, 000, 000, 000 }, // 056 + { 000, 001, 002, 002, 004, 004, 010, 000, 000, 000, 000, 000 }, // 057 + { 000, 006, 011, 013, 015, 011, 006, 000, 000, 000, 000, 000 }, // 060 + { 000, 002, 006, 002, 002, 002, 007, 000, 000, 000, 000, 000 }, // 061 + { 000, 016, 021, 001, 016, 020, 037, 000, 000, 000, 000, 000 }, // 062 + { 000, 016, 021, 006, 001, 021, 016, 000, 000, 000, 000, 000 }, // 063 + { 000, 002, 006, 012, 037, 002, 002, 000, 000, 000, 000, 000 }, // 064 + { 000, 037, 020, 036, 001, 021, 016, 000, 000, 000, 000, 000 }, // 065 + { 000, 016, 020, 036, 021, 021, 016, 000, 000, 000, 000, 000 }, // 066 + { 000, 037, 001, 002, 002, 004, 004, 000, 000, 000, 000, 000 }, // 067 + { 000, 016, 021, 016, 021, 021, 016, 000, 000, 000, 000, 000 }, // 070 + { 000, 016, 021, 021, 017, 001, 016, 000, 000, 000, 000, 000 }, // 071 + { 000, 000, 004, 004, 000, 004, 004, 000, 000, 000, 000, 000 }, // 072 + { 000, 000, 004, 004, 000, 006, 002, 004, 000, 000, 000, 000 }, // 073 + { 000, 000, 002, 004, 010, 004, 002, 000, 000, 000, 000, 000 }, // 074 + { 000, 000, 000, 037, 000, 037, 000, 000, 000, 000, 000, 000 }, // 075 + { 000, 000, 010, 004, 002, 004, 010, 000, 000, 000, 000, 000 }, // 076 + { 000, 016, 021, 001, 006, 000, 004, 000, 000, 000, 000, 000 }, // 077 + { 000, 016, 021, 027, 027, 020, 016, 000, 000, 000, 000, 000 }, // 100 + { 000, 016, 021, 037, 021, 021, 021, 000, 000, 000, 000, 000 }, // 101 + { 000, 036, 021, 036, 021, 021, 036, 000, 000, 000, 000, 000 }, // 102 + { 000, 016, 021, 020, 020, 021, 016, 000, 000, 000, 000, 000 }, // 103 + { 000, 036, 021, 021, 021, 021, 036, 000, 000, 000, 000, 000 }, // 104 + { 000, 037, 020, 036, 020, 020, 037, 000, 000, 000, 000, 000 }, // 105 + { 000, 037, 020, 036, 020, 020, 020, 000, 000, 000, 000, 000 }, // 106 + { 000, 016, 021, 020, 023, 021, 016, 000, 000, 000, 000, 000 }, // 107 + { 000, 021, 021, 037, 021, 021, 021, 000, 000, 000, 000, 000 }, // 110 + { 000, 016, 004, 004, 004, 004, 016, 000, 000, 000, 000, 000 }, // 111 + { 000, 001, 001, 001, 001, 021, 016, 000, 000, 000, 000, 000 }, // 112 + { 000, 021, 022, 024, 034, 022, 021, 000, 000, 000, 000, 000 }, // 113 + { 000, 020, 020, 020, 020, 020, 037, 000, 000, 000, 000, 000 }, // 114 + { 000, 021, 033, 025, 025, 021, 021, 000, 000, 000, 000, 000 }, // 115 + { 000, 021, 031, 025, 023, 021, 021, 000, 000, 000, 000, 000 }, // 116 + { 000, 016, 021, 021, 021, 021, 016, 000, 000, 000, 000, 000 }, // 117 + { 000, 036, 021, 036, 020, 020, 020, 000, 000, 000, 000, 000 }, // 120 + { 000, 016, 021, 021, 025, 023, 016, 001, 000, 000, 000, 000 }, // 121 + { 000, 036, 021, 036, 024, 022, 021, 000, 000, 000, 000, 000 }, // 122 + { 000, 016, 021, 014, 002, 021, 016, 000, 000, 000, 000, 000 }, // 123 + { 000, 037, 004, 004, 004, 004, 004, 000, 000, 000, 000, 000 }, // 124 + { 000, 021, 021, 021, 021, 021, 016, 000, 000, 000, 000, 000 }, // 125 + { 000, 021, 021, 021, 012, 012, 004, 000, 000, 000, 000, 000 }, // 126 + { 000, 021, 021, 025, 025, 033, 021, 000, 000, 000, 000, 000 }, // 127 + { 000, 021, 012, 004, 012, 021, 021, 000, 000, 000, 000, 000 }, // 130 + { 000, 021, 021, 016, 004, 004, 004, 000, 000, 000, 000, 000 }, // 131 + { 000, 037, 001, 002, 010, 020, 037, 000, 000, 000, 000, 000 }, // 132 + { 000, 016, 010, 010, 010, 010, 010, 016, 000, 000, 000, 000 }, // 133 + { 000, 020, 010, 004, 004, 002, 001, 000, 000, 000, 000, 000 }, // 134 + { 000, 016, 002, 002, 002, 002, 002, 016, 000, 000, 000, 000 }, // 135 + { 000, 004, 016, 025, 004, 004, 004, 000, 000, 000, 000, 000 }, // 136 + { 000, 000, 004, 010, 037, 010, 004, 000, 000, 000, 000, 000 }, // 137 + { 000, 006, 004, 002, 000, 000, 000, 000, 000, 000, 000, 000 }, // 140 + { 000, 000, 016, 001, 017, 021, 015, 000, 000, 000, 000, 000 }, // 141 + { 000, 020, 026, 031, 021, 021, 026, 000, 000, 000, 000, 000 }, // 142 + { 000, 000, 016, 020, 020, 020, 016, 000, 000, 000, 000, 000 }, // 143 + { 000, 001, 015, 023, 021, 021, 015, 000, 000, 000, 000, 000 }, // 144 + { 000, 000, 016, 021, 037, 020, 016, 000, 000, 000, 000, 000 }, // 145 + { 000, 007, 010, 036, 010, 010, 010, 000, 000, 000, 000, 000 }, // 146 + { 000, 000, 017, 021, 021, 016, 001, 036, 000, 000, 000, 000 }, // 147 + { 000, 020, 026, 031, 021, 021, 021, 000, 000, 000, 000, 000 }, // 150 + { 000, 004, 000, 014, 004, 004, 004, 000, 000, 000, 000, 000 }, // 151 + { 000, 002, 000, 006, 002, 002, 002, 014, 000, 000, 000, 000 }, // 152 + { 000, 010, 011, 012, 014, 012, 011, 000, 000, 000, 000, 000 }, // 153 + { 000, 014, 004, 004, 004, 004, 004, 000, 000, 000, 000, 000 }, // 154 + { 000, 000, 032, 025, 025, 025, 025, 000, 000, 000, 000, 000 }, // 155 + { 000, 000, 026, 031, 021, 021, 021, 000, 000, 000, 000, 000 }, // 156 + { 000, 000, 016, 021, 021, 021, 016, 000, 000, 000, 000, 000 }, // 157 + { 000, 000, 026, 031, 021, 021, 026, 020, 000, 000, 000, 000 }, // 160 + { 000, 000, 015, 023, 021, 021, 015, 001, 000, 000, 000, 000 }, // 161 + { 000, 000, 026, 031, 020, 020, 020, 000, 000, 000, 000, 000 }, // 162 + { 000, 000, 017, 020, 016, 001, 036, 000, 000, 000, 000, 000 }, // 163 + { 000, 010, 037, 010, 010, 010, 006, 000, 000, 000, 000, 000 }, // 164 + { 000, 000, 021, 021, 021, 021, 015, 000, 000, 000, 000, 000 }, // 165 + { 000, 000, 021, 021, 012, 012, 004, 000, 000, 000, 000, 000 }, // 166 + { 000, 000, 021, 021, 025, 025, 012, 000, 000, 000, 000, 000 }, // 167 + { 000, 000, 021, 012, 004, 012, 021, 000, 000, 000, 000, 000 }, // 170 + { 000, 000, 021, 021, 021, 017, 001, 016, 000, 000, 000, 000 }, // 171 + { 000, 000, 037, 002, 004, 010, 037, 000, 000, 000, 000, 000 }, // 172 + { 000, 003, 004, 004, 010, 004, 004, 003, 000, 000, 000, 000 }, // 173 + { 000, 004, 004, 004, 004, 004, 004, 004, 000, 000, 000, 000 }, // 174 + { 000, 000, 004, 012, 021, 012, 004, 000, 000, 000, 000, 000 }, // 175 + { 000, 030, 004, 004, 002, 004, 004, 030, 000, 000, 000, 000 }, // 176 + { 000, 077, 077, 077, 077, 077, 077, 077, 077, 000, 000, 000 }, // 177 +}; diff --git a/PDP10/ka10_pipanel.c b/PDP10/ka10_pipanel.c new file mode 100644 index 000000000..4fe878c40 --- /dev/null +++ b/PDP10/ka10_pipanel.c @@ -0,0 +1,763 @@ +/* kx10_pipanel.c: PDP-10 PiDP10 front panel. + + Copyright (c) 2022, Richard Cornwell + Based on code by Oscar Vermeulen + + 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 + +*/ + +#if PIDP10 + +/* The following includes are ok since this code can only be run on a + * Rasberry PI under Linux. + * + * To Build this: + * make PIDP10=1 pdp10-ka + */ +#include /* Needed for pthread */ +#include /* Needed for sleep/geteuid */ +#include +#include +#include "pinctrl/gpiolib.h" +#include "kx10_defs.h" + +extern uint64 SW; /* Switch register */ +extern t_addr AS; /* Address switches */ +extern uint64 MB; /* Memory Bus register */ +extern uint64 MI; /* Memory indicator register */ +extern uint8 MI_flag; /* Memory indicator mode */ +extern uint32 FLAGS; /* Flags register */ +extern uint8 RUN; /* Run flag */ +extern uint32 IR; /* Instruction register */ +extern uint32 AC; /* Accumulator */ +extern uint8 IX; /* Index register */ +extern uint8 IND; /* Indirect flag */ +extern t_addr AB; /* Memory address register */ +extern t_addr PC; /* Program counter register */ +#if KA | KI +extern int nxm_stop; /* Stop if non-existent memory access */ +extern int adr_cond; /* Address stop condition */ +#endif +extern uint8 IOB_PI; /* Pending Interrupt requests */ +extern uint8 PIR; /* Current Interrupt requests */ +extern uint8 PIH; /* Currently held interrupts */ +extern uint8 PIE; /* Currently enabled interrupts */ +extern int pi_enable; /* Interrupt system enabled */ +extern uint8 prog_stop; /* Program stop */ +extern uint8 examine_sw; /* Examine memory */ +extern uint8 deposit_sw; /* Deposit memory */ +extern uint8 sing_inst_sw;/* Execute single instruction */ +extern uint8 xct_sw; /* Execute an instruction */ +extern uint8 stop_sw; /* Stop the simulator */ +extern uint8 MI_disable; /* Disable MI display */ +extern int watch_stop; /* Memory Stop */ +extern uint32 rdrin_dev; /* Read in device. */ +extern uint8 MI_disable; /* Disable MI */ +int repeat_sw; /* Repeat switch state */ +int par_stop; /* Parity stop */ +int pwr_off; /* Power off system */ +int rep_rate; /* Rate of repeat function */ +int rep_count; /* Count down to repeat trigger */ + +/* led row 0 */ +#define MB_MASK0 RMASK /* 18-35 */ +#define MB_V_0 0 /* right */ + +/* led row 1 */ +#define MB_MASK1 LMASK /* 0-17 */ +#define MB_V_1 18 /* right */ + +/* led row 2 */ +#define AB_MASK2 RMASK /* 18-35 */ +#define AB_V_2 0 /* right */ + +/* led row 3 */ +#define IX_MASK3 017 +#define IX_V_3 0 /* left */ +#define IND_LAMP 020 +#define AC_MASK3 017 +#define AC_V_3 5 /* left */ +#define IR_MASK3 0777 /* 0-9 */ +#define IR_V_3 9 /* left */ + +/* led row 4 */ +#define PC_MASK4 RMASK /* 18-35 */ +#define PC_V_4 0 /* right */ + +/* led row 5 */ +#define PI_IOB_MASK5 0177 +#define PI_IOB_V_5 7 /* left */ +#define PI_ENB_MASK5 0177 +#define PI_ENB_V_5 0 /* left */ +#define PROG_STOP_LAMP 0040000 +#define USER_LAMP 0100000 +#define MEM_STOP_LAMP 0200000 +#define PWR_LAMP 0400000 + +/* led row 6 */ +#define PI_REQ_MASK6 0177 +#define PI_REQ_V_6 0 /* left */ +#define PI_PRO_MASK6 0177 +#define PI_PRO_V_6 7 /* left */ +#define RUN_LAMP 0040000 +#define PION_LAMP 0100000 +#define PI_LAMP 0200000 +#define MI_LAMP 0400000 + +/* switch row 0 */ +#define SR_MASK0 RMASK +#define SR_V_0 0 /* Left */ + +/* switch row 1 */ +#define SR_MASK1 LMASK +#define SR_V_1 18 /* Left */ + +/* Switch row 2 */ +#define MA_SW_MASK3 RMASK +#define MA_SW_V_3 0 /* Left */ + +/* Switch row 3 */ +#define EXAM_NEXT 000001 /* SW=0 */ +#define EXAM_THIS 000002 /* SW=1 */ +#define XCT_SW 000004 /* SW=2 Set xct_inst */ +#define RESET_SW 000010 /* SW=3 Call reset */ +#define STOP_SW 000020 /* SW=4 Set RUN = 0 */ +#define CONT_SW 000040 /* SW=5 call sim_instr */ +#define START_SW 000100 /* SW=6 Call reset then sim_instr */ +#define READ_SW 000200 /* SW=7 Boot function */ +#define DEP_NEXT 000400 /* SW=8 */ +#define DEP_THIS 001000 /* SW=9 */ + +/* Switch row 4 */ +#define ADR_BRK_SW 000001 /* Address Break */ +#define ADR_STOP_SW 000002 /* Address stop */ +#define WRITE_SW 000004 /* Write stop */ +#define DATA_FETCH 000010 /* Data fetch stop */ +#define INST_FETCH 000020 /* Instruct fetch stop */ +#define REP_SW 000040 /* Repeat switch */ +#define NXM_STOP 000100 /* set nxm_stop */ +#define PAR_STOP 000200 /* Nop */ +#define SING_CYCL 000400 /* Nop */ +#define SING_INST 001000 /* set sing_inst */ + +int xrows[3] = { 4, 17, 27 }; +int xIO = 22; /* GPIO 22: */ +int cols[18] = { 21,20,16,12,7,8,25,24,23,18,10,9,11,5,6,13,19,26 }; + +long intervl = 50000; + +struct { + int last_state; /* last state */ + int state; /* Stable state */ + int debounce; /* Debounce timer */ + int changed; /* Switch changed state */ +} switch_state[16]; + + + +void *blink(void *ptr); /* the real-time GPIO multiplexing process to start up */ +pthread_t blink_thread; +int blink_thread_terminate = 0; + +t_stat gpio_mux_thread_start() +{ + int res; + res = pthread_create(&blink_thread, NULL, blink, &blink_thread_terminate); + if (res) { + return sim_messagef(SCPE_IERR, + "Error creating gpio_mux thread, return code %d\n", res); + } + sim_messagef(SCPE_OK, "Created blink_thread\n"); + sleep(2); /* allow 2 sec for multiplex to start */ + return SCPE_OK; +} + + +/* + * Debounce a momentary switch. + */ +static void debounce_sw(int state, int sw) +{ + if (switch_state[sw].state == state) { + if (switch_state[sw].debounce != 0) { + switch_state[sw].debounce--; + } else { + if (switch_state[sw].last_state != switch_state[sw].state) { + switch_state[sw].changed = 1; + } + switch_state[sw].last_state = switch_state[sw].state; + } + } else { + switch_state[sw].debounce = 8; + switch_state[sw].changed = 0; + switch_state[sw].state = state; + } +} + +static t_addr +read_sw() +{ + int col, row, i; + t_uint64 sw; + t_addr new_as; + struct timespec spec; + + gpio_set_drive(xIO, DRIVE_HIGH); + for (i = 0; i < 18; i++) { + gpio_set_dir(cols[i], DIR_INPUT); + } + + spec.tv_sec = 0; + new_as = 0; + for (row=0; row<5; row++) { + /* Select row address */ + for (i = 0; i < 3; i++) { + if ((row & (1 << i)) == 0) { + gpio_set_drive(xrows[i], DRIVE_LOW); + } else { + gpio_set_drive(xrows[i], DRIVE_HIGH); + } + } + spec.tv_nsec = intervl/10; + nanosleep(&spec, NULL); + sw = 0; + for (i = 0; i < 18; i++) { + if (gpio_get_level(cols[i])) { + sw |= 1 << i; + } + } + /* Map row to values */ + switch (row) { + default: + case 0: + SW = (SW & SR_MASK1) | ((~sw << SR_V_0) & SR_MASK0); + break; + + case 1: + SW = (SW & SR_MASK0) | ((~sw << SR_V_1) & SR_MASK1); + break; + + case 2: + new_as = (t_addr)(~sw << MA_SW_V_3) & MA_SW_MASK3; + break; + + case 3: /* Momentary switches */ + for (col = 0; col < 10; col++) { + int state = (sw & (1 << col)) == 0; + debounce_sw(state, col); + } + break; + + case 4: +#if KA | KI + adr_cond = 0; + adr_cond |= ((sw & INST_FETCH) == 0) ? ADR_IFETCH : 0; + adr_cond |= ((sw & DATA_FETCH) == 0) ? ADR_DFETCH : 0; + adr_cond |= ((sw & WRITE_SW) == 0) ? ADR_WRITE : 0; + adr_cond |= ((sw & ADR_STOP_SW) == 0) ? ADR_STOP : 0; + adr_cond |= ((sw & ADR_BRK_SW) == 0) ? ADR_BREAK : 0; + nxm_stop = (sw & NXM_STOP) == 0; +#endif + sing_inst_sw = ((sw & SING_INST) == 0) || + ((sw & SING_CYCL) == 0); + /* PAR_STOP handle special features */ + par_stop = (sw & PAR_STOP) == 0; + /* SING_CYCL no function yet */ + repeat_sw = (sw & REP_SW) == 0; + break; + } + } + return new_as; +} + +void *blink(void *ptr) +{ + int *terminate = (int *)ptr; + int col, row, i; + int num_gpios, ret; + uint32 leds; + t_addr new_as; + struct timespec spec; + struct sched_param sp; + + spec.tv_sec = 0; + sp.sched_priority = 98; // maybe 99, 32, 31? + if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) + fprintf(stderr, "warning: failed to set RT priority\n"); + + ret = gpiolib_init(); + if (ret < 0) { + sim_messagef(SCPE_IERR, "Unable to initialize gpiolib- %d\n", ret); + return (void *)-1; + } + + num_gpios = ret; + + if (num_gpios == 0) { + sim_messagef(SCPE_IERR, "No GPIO chips found\n"); + return (void *)-1; + } + + ret = gpiolib_mmap(); + if (ret) { + if (ret == EACCES && geteuid()) { + sim_messagef(SCPE_IERR, "Must be root\n"); + } else { + sim_perror("Failed to mmap gpiolib"); + } + return (void *)-1; + } + + /* Initialize GPIO pins */ + gpio_set_fsel(xIO, GPIO_FSEL_OUTPUT); + gpio_set_dir(xIO, DIR_OUTPUT); + gpio_set_drive(xIO, DRIVE_HIGH); + + /* Row address pins */ + for (row = 0; row < 3; row++) { + gpio_set_fsel(xrows[row], GPIO_FSEL_OUTPUT); + gpio_set_dir(xrows[row], DIR_OUTPUT); + gpio_set_drive(xrows[row], DRIVE_HIGH); + } + + /* Columns */ + for (col = 0; col < 10; col++) { + gpio_set_fsel(cols[col], GPIO_FSEL_INPUT); + gpio_set_pull(cols[col], PULL_UP); + } + + /* Read initial value of switches */ + new_as = read_sw(); + sim_messagef(SCPE_OK, "PiDP-10 FP on\n"); + + + /* start the actual multiplexing */ + + while (*terminate == 0) + { + /* Set to point to switchs while updating digits */ + gpio_set_drive(xIO, DRIVE_HIGH); + /* Set direction of columns to output */ + for (i = 0; i < 18; i++) { + gpio_set_dir(cols[i], DIR_OUTPUT); + } + + /* Display each row */ + for (row=0; row<7; row++) { /* 7 rows of LEDS get lit */ + switch (row) { + default: + case 0: + leds = (((MI_flag)? MI : MB) & MB_MASK0) >> MB_V_0; + break; + case 1: + leds = (((MI_flag)? MI : MB) & MB_MASK1) >> MB_V_1; + break; + case 2: + if (par_stop) { + leds = rdrin_dev & 0777; + leds |= rep_rate << 12; + leds |= MI_disable << 10; + } else { + leds = (AB & AB_MASK2) >> AB_V_2; + } + break; + + case 3: + leds = (IR & IR_MASK3) << IR_V_3; + leds |= (AC & AC_MASK3) << AC_V_3; + leds |= (IND) ? IND_LAMP : 0; + leds |= (IX & IX_MASK3) << IX_V_3; + break; + + case 4: + leds = (PC & PC_MASK4) >> PC_V_4; + break; + + case 5: + leds = PWR_LAMP; + leds |= (IOB_PI & PI_IOB_MASK5) << PI_IOB_V_5; + leds |= (PIE & PI_ENB_MASK5) << PI_ENB_V_5; + leds |= (FLAGS & USER) ? USER_LAMP : 0; + leds |= (prog_stop) ? PROG_STOP_LAMP: 0; + leds |= (watch_stop) ? MEM_STOP_LAMP: 0; + break; + + case 6: + leds = (RUN) ? RUN_LAMP : 0; + leds |= (pi_enable) ? PION_LAMP : 0; + leds |= (PIR & PI_REQ_MASK6) << PI_REQ_V_6; + leds |= (PIH & PI_PRO_MASK6) << PI_PRO_V_6; + leds |= (MI_flag) ? PI_LAMP : MI_LAMP; + break; + } + + /* Select correct row to display */ + for (i = 0; i < 3; i++) { + if ((row & (1 << i)) == 0) { + gpio_set_drive(xrows[i], DRIVE_LOW); + } else { + gpio_set_drive(xrows[i], DRIVE_HIGH); + } + } + + /* Update the leds for output */ + for (i = 0; i < 18; i++) { + if ((leds & (1 << i)) == 0) { + gpio_set_drive(cols[i], DRIVE_HIGH); + } else { + gpio_set_drive(cols[i], DRIVE_LOW); + } + } + + /* Select output */ + gpio_set_drive(xIO, DRIVE_LOW); + spec.tv_nsec = intervl; + nanosleep(&spec, NULL); + /* Deselect output */ + gpio_set_drive(xIO, DRIVE_HIGH); + spec.tv_nsec = intervl/10; + nanosleep(&spec, NULL); + } + + /* Read in switches */ + new_as = read_sw(); + + /* If running, check for switch changes */ + if (par_stop) { + /* Process all momentary switches */ + for (col = 0; col < 10; col++) { + if (switch_state[col].changed && switch_state[col].state) { + switch_state[col].changed = 0; + switch (col) { + case 1: /* Examine this */ + rep_rate = (new_as >> 14) & 0xf; + break; + + case 4: /* Stop function */ + stop_sw = 1; + pwr_off = 1; + break; + + case 5: /* Continue */ + MI_disable = !MI_disable; + if (MI_disable) + MI_flag = 0; + break; + +#if KA | KI + case 7: /* ReadIN */ + rdrin_dev = 0774 & new_as; + break; +#endif + + case 0: /* Examine next */ + case 2: /* Execute function */ + case 3: /* Reset function */ + case 6: /* Start */ + case 8: /* Deposit next */ + case 9: /* Deposit this */ + default: + break; + } + } + } + } else { + AS = new_as; + } + + /* Check repeat count */ + if (rep_count > 0 && --rep_count == 0) { + for (col = 0; col < 10; col++) { + switch_state[col].changed = switch_state[col].state; + } + } + + /* Process switch changes if running */ + if (RUN) { + for (col = 0; col < 10; col++) { + if (switch_state[col].changed && switch_state[col].state) { + /* If repeat switch set, trigger timer */ + if (repeat_sw) { + rep_count = (rep_rate + 1) * 16; + } + switch (col) { + case 1: /* Examine this */ + examine_sw = 1; + MI_flag = 0; + switch_state[col].changed = 0; + break; + + case 0: /* Examine next */ + case 5: /* Continue */ + case 6: /* Start */ + case 7: /* ReadIN */ + case 8: /* Deposit next */ + default: + switch_state[col].changed = 0; + break; + + case 2: /* Execute function */ + xct_sw = 1; + switch_state[col].changed = 0; + break; + + case 3: /* Reset function */ + stop_sw = 1; + break; + + case 4: /* Stop function */ + stop_sw = 1; + switch_state[col].changed = 0; + break; + + case 9: /* Deposit this */ + deposit_sw = 1; + MI_flag = 0; + switch_state[col].changed = 0; + break; + } + } + } + } + + /* done with reading the switches, + * so start the next cycle of lighting up LEDs + */ + } + + /* received terminate signal, close down */ + gpio_set_drive(xIO, DRIVE_HIGH); + for (i = 0; i < 18; i++) { + gpio_set_dir(cols[i], DIR_INPUT); + } + + for (row = 0; row < 3; row++) { + gpio_set_drive(xrows[row], DRIVE_HIGH); + } + +} + +volatile int input_wait; +static char *input_buffer = NULL; + +/* + * Handler for EditLine package when line is complete. + */ +static void +read_line_handler(char *line) +{ + if (line != NULL) { + input_buffer = line; + input_wait = 0; + add_history(line); + } +} + +/* + * Process input from stdin or switches. + */ +static char * +vm_read(char *cptr, int32 sz, FILE *file) +{ + struct timeval tv = {0,10000}; /* Wait for 10ms */ + fd_set read_set; + int fd = fileno(file); /* What to wait on */ + int col; + + if (input_buffer != NULL) + free(input_buffer); + rl_callback_handler_install(sim_prompt, (rl_vcpfunc_t*) &read_line_handler); + input_wait = 1; + input_buffer = NULL; + while (input_wait) { + FD_ZERO(&read_set); + FD_SET(fd, &read_set); + tv.tv_sec = 0; + tv.tv_usec = 10000; + (void)select(fd+1, &read_set, NULL, NULL, &tv); + if (FD_ISSET(fd, &read_set)) { + rl_callback_read_char(); + } else { + if (pwr_off) { + if ((input_buffer = (char *)malloc(20)) != 0) { + strcpy(input_buffer, "quit\r"); + stop_sw = 1; + pwr_off = 0; + input_wait = 0; + } + break; + } + + /* Process switches */ + for (col = 0; col < 10; col++) { + if (switch_state[col].changed && switch_state[col].state) { + /* If repeat switch set, trigger timer */ + if (repeat_sw) { + rep_count = (rep_rate + 1) * 16; + } + switch (col) { + case 0: /* Examine next */ + AB++; + MB = (AB < 020) ? FM[AB] : M[AB]; + MI_flag = 0; + break; + + case 1: /* Examine this */ + AB = AS; + MB = (AS < 020) ? FM[AS] : M[AS]; + MI_flag = 0; + break; + + case 2: /* Execute function */ + if ((input_buffer = (char *)malloc(20)) != 0) { + strcpy(input_buffer, "step\r"); + xct_sw = 1; + input_wait = 0; + } + break; + + case 3: /* Reset function */ + if ((input_buffer = (char *)malloc(20)) != 0) { + strcpy(input_buffer, "reset all\r"); + input_wait = 0; + } + break; + + case 4: /* Stop function */ + break; + + case 5: /* Continue */ + if ((input_buffer = (char *)malloc(10)) != 0) { + strcpy(input_buffer, + (sing_inst_sw) ? "step\r" : "cont\r"); + input_wait = 0; + } + break; + + case 6: /* Start */ + if ((input_buffer = (char *)malloc(20)) != 0) { + sprintf(input_buffer, "run %06o\r", AS); + input_wait = 0; + } + break; + +#if KA | KI + case 7: /* ReadIN */ + if ((input_buffer = (char *)malloc(20)) != 0) { + DEVICE *dptr; + int i; + + /* Scan all devices to find match */ + for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { + DIB *dibp = (DIB *) dptr->ctxt; + if (dibp && !(dptr->flags & DEV_DIS) && + (dibp->dev_num == (rdrin_dev & 0774))) { + if (dptr->numunits > 1) + sprintf(input_buffer, "boot %s0\r", + dptr->name); + else + sprintf(input_buffer, "boot %s\r", + dptr->name); + input_wait = 0; + break; + } + } + } + /* If we did not find a boot device, free command */ + if (input_wait) { + free(input_buffer); + input_buffer = NULL; + sim_messagef(SCPE_OK, "Device %03o not found\n", + rdrin_dev); + } + break; +#endif + + case 8: /* Deposit next */ + AB++; + if (AB < 020) { + FM[AB] = SW; + MB = FM[AB]; + } else { + M[AB] = SW; + MB = M[AB]; + } + MI_flag = 0; + break; + + case 9: /* Deposit this */ + AB = AS; + if (AS < 020) { + FM[AS] = SW; + MB = FM[AS]; + } else { + M[AS] = SW; + MB = M[AS]; + } + MI_flag = 0; + break; + } + switch_state[col].changed = 0; + } + } + } + } + rl_callback_handler_remove(); + return input_buffer; +} + +static void +vm_post(t_bool from_scp) +{ +} + +/* + * Start panel thread, and install console read functions. + */ +t_stat pi_panel_start(void) +{ + int terminate = 1; + int i,j; + t_stat r; + + /* start up multiplexing thread */ + r = gpio_mux_thread_start(); + sim_vm_read = &vm_read; + sim_vm_post = &vm_post; + return r; +} + +/* + * Stop display thread. + */ +void pi_panel_stop(void) +{ + if (blink_thread_terminate == 0) { + blink_thread_terminate=1; + sim_vm_read = NULL; + + sleep (2); /* allow threads to close down */ + } +} + +#endif diff --git a/PDP10/ka10_ten11.c b/PDP10/ka10_ten11.c index 89e231fb9..fd6dfeabe 100644 --- a/PDP10/ka10_ten11.c +++ b/PDP10/ka10_ten11.c @@ -39,6 +39,9 @@ static uint64 ten11_pager[256]; t_addr ten11_base = 03000000; t_addr ten11_end = 04000000; +/* Number of Unibuses. */ +#define UNIBUSES 8 + /* Physical address of 10-11 control page. */ #define T11CPA 0776000 //Offset inside TEN11 moby. @@ -116,8 +119,8 @@ DEVICE ten11_dev = { &ten11_description, /* description */ }; -static TMLN ten11_ldsc; /* line descriptor */ -static TMXR ten11_desc = { 1, 0, 0, &ten11_ldsc }; /* mux descriptor */ +static TMLN ten11_ldsc[UNIBUSES]; /* line descriptor */ +static TMXR ten11_desc = { 8, 0, 0, ten11_ldsc }; /* mux descriptor */ static t_stat ten11_reset (DEVICE *dptr) { @@ -175,14 +178,20 @@ static void build (unsigned char *request, unsigned char octet) static t_stat ten11_svc (UNIT *uptr) { + int i; tmxr_poll_rx (&ten11_desc); - if (ten11_ldsc.rcve && !ten11_ldsc.conn) { - ten11_ldsc.rcve = 0; - tmxr_reset_ln (&ten11_ldsc); + + for (i = 0; i < UNIBUSES; i++) { + if (ten11_ldsc[i].rcve && !ten11_ldsc[i].conn) { + ten11_ldsc[i].rcve = 0; + tmxr_reset_ln (&ten11_ldsc[i]); + } } - if (tmxr_poll_conn(&ten11_desc) >= 0) { + + i = tmxr_poll_conn(&ten11_desc); + if (i >= 0) { sim_debug(DBG_CMD, &ten11_dev, "got connection\n"); - ten11_ldsc.rcve = 1; + ten11_ldsc[i].rcve = 1; uptr->wait = TEN11_POLL; } sim_clock_coschedule (uptr, uptr->wait); @@ -214,38 +223,40 @@ static const char *ten11_description (DEVICE *dptr) return "Rubin PDP-10 to PDP-11 interface"; } -static int error (const char *message) +static int error (int unibus, const char *message) { - sim_debug (DBG_TRC, &ten11_dev, "%s\r\n", message); + sim_debug (DBG_TRC, &ten11_dev, "Port %d: %s\r\n", unibus, message); sim_debug (DBG_TRC, &ten11_dev, "CLOSE\r\n"); - ten11_ldsc.rcve = 0; - tmxr_reset_ln (&ten11_ldsc); + ten11_ldsc[unibus].rcve = 0; + tmxr_reset_ln (&ten11_ldsc[unibus]); return -1; } -static int transaction (unsigned char *request, unsigned char *response) +static int transaction (int unibus, unsigned char *request, unsigned char *response) { const uint8 *ten11_request; size_t size; t_stat stat; - stat = tmxr_put_packet_ln (&ten11_ldsc, request + 1, (size_t)request[0]); + stat = tmxr_put_packet_ln (&ten11_ldsc[unibus], request + 1, (size_t)request[0]); if (stat != SCPE_OK) - return error ("Write error in transaction"); + return error (unibus, "Write error in transaction"); do { tmxr_poll_rx (&ten11_desc); - stat = tmxr_get_packet_ln (&ten11_ldsc, &ten11_request, &size); + stat = tmxr_get_packet_ln (&ten11_ldsc[unibus], &ten11_request, &size); + if (!ten11_ldsc[unibus].conn) + return error (unibus, "Connection lost"); } while (stat != SCPE_OK || size == 0); if (size > 7) - return error ("Malformed transaction"); + return error (unibus, "Malformed transaction"); memcpy (response, ten11_request, size); return 0; } -static int read_word (t_addr addr, int *data) +static int read_word (int unibus, t_addr addr, int *data) { unsigned char request[8]; unsigned char response[8]; @@ -263,7 +274,7 @@ static int read_word (t_addr addr, int *data) build (request, (addr >> 8) & 0377); build (request, (addr) & 0377); - if (transaction (request, response) == -1) { + if (transaction (unibus, request, response) == -1) { /* Network error. */ *data = 0; return 0; @@ -285,7 +296,7 @@ static int read_word (t_addr addr, int *data) *data = 0; break; default: - return error ("Protocol error"); + return error (unibus, "Protocol error"); } return 0; @@ -325,8 +336,8 @@ int ten11_read (t_addr addr, uint64 *data) uaddr = ((mapping & T11ADDR) >> 10) + offset; uaddr <<= 2; - read_word (uaddr, &word1); - read_word (uaddr + 2, &word2); + read_word (unibus, uaddr, &word1); + read_word (unibus, uaddr + 2, &word2); *data = ((uint64)word1 << 20) | (word2 << 4); sim_debug (DBG_TRC, &ten11_dev, @@ -336,7 +347,7 @@ int ten11_read (t_addr addr, uint64 *data) return 0; } -static int write_word (t_addr addr, uint16 data) +static int write_word (int unibus, t_addr addr, uint16 data) { unsigned char request[8]; unsigned char response[8]; @@ -355,7 +366,7 @@ static int write_word (t_addr addr, uint16 data) build (request, (data >> 8) & 0377); build (request, (data) & 0377); - transaction (request, response); + transaction (unibus, request, response); switch (response[0]) { @@ -368,7 +379,7 @@ static int write_word (t_addr addr, uint16 data) fprintf (stderr, "TEN11: Write timeout %06o\r\n", addr); break; default: - return error ("Protocol error"); + return error (unibus, "Protocol error"); } return 0; @@ -417,9 +428,9 @@ int ten11_write (t_addr addr, uint64 data) unibus, uaddr, data); if ((data & 010) == 0) - write_word (uaddr, (data >> 20) & 0177777); + write_word (unibus, uaddr, (data >> 20) & 0177777); if ((data & 004) == 0) - write_word (uaddr + 2, (data >> 4) & 0177777); + write_word (unibus, uaddr + 2, (data >> 4) & 0177777); } return 0; } diff --git a/PDP10/kl10_dn.c b/PDP10/kl10_dn.c new file mode 100644 index 000000000..bb42ddadf --- /dev/null +++ b/PDP10/kl10_dn.c @@ -0,0 +1,1188 @@ +/* kl10_dn.c: KL-10 DN network interface. + + Copyright (c) 2019-2021, 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 + +#ifndef NUM_DEVS_DN +#define NUM_DEVS_DN 0 +#endif + +#if KL +#if (NUM_DEVS_DN > 0) +#define UNIT_DUMMY (1 << UNIT_V_UF) + +#define DTE_DEVNUM 0204 +#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 */ +#define DTE_INIT 040000000 /* Recieved an INIT signal last time */ + +/* 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 */ + +/* 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_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 */ +#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_EMLBE 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_NCL 011 /* NCL device */ +#define PRI_DN60 012 /* DN60 */ +#define PRI_CTYDV 000 /* Line number for CTY */ +#define NUM_DLS 5 /* Number of first DH Line */ + + +extern int32 tmxr_poll; +t_stat dn_devio(uint32 dev, uint64 *data); +t_addr dn_devirq(uint32 dev, t_addr addr); +void dn_second(UNIT *uptr); +void dn_primary(UNIT *uptr); +void dn_transfer(UNIT *uptr); +void dn_function(UNIT *uptr); +void dn_input(); +int dn_start(UNIT *uptr); +int dn_queue(int func, int dev, int dcnt, uint16 *data); +t_stat dni_svc (UNIT *uptr); +t_stat dn_svc (UNIT *uptr); +t_stat dno_svc (UNIT *uptr); +t_stat dnrtc_srv(UNIT * uptr); +t_stat dn_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc); +t_stat dn_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc); +t_stat dn_reset (DEVICE *dptr); +t_stat dn_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +const char *dn_description (DEVICE *dptr); +extern uint64 SW; /* Switch register */ + +extern CONST char *pri_name[]; + +#define STATUS u3 +#define CNT u4 + +extern uint32 eb_ptr; + +struct _dn_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[258]; /* Data packet */ + uint16 sdev; /* Secondary device code */ + uint16 sz; /* Byte size */ +} dn_in[32], dn_out[32]; + +int32 dn_in_ptr; +int32 dn_in_cmd; +int32 dn_out_ptr; +int32 dn_out_res; +int32 dn_base; /* Base */ +int32 dn_off; /* Our offset */ +int32 dn_dt10_off; /* Offset to 10 deposit region */ +int32 dn_et10_off; /* Offset to 10 examine region */ +int32 dn_et11_off; /* Offset to 11 examine region */ +int32 dn_proc_num; /* Our processor number */ + +struct _buffer { + int in_ptr; /* Insert pointer */ + int out_ptr; /* Remove pointer */ + char buff[256]; /* Buffer */ +}; + +#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 dn_dib[] = { + { DTE_DEVNUM|000, 1, dn_devio, dn_devirq}, +}; + +MTAB dn_mod[] = { + {MTAB_XTD|MTAB_VDV, TYPE_RSX10, NULL, "RSX10", &dn_set_type, NULL, + NULL, "Sets DTE to RSX10 mode"}, + {MTAB_XTD|MTAB_VDV, TYPE_RSX20, "RSX20", "RSX20", &dn_set_type, &dn_show_type, + NULL, "Sets DTE to RSX20 mode"}, + { 0 } + }; + +UNIT dn_unit[] = { + { UDATA (&dn_svc, TT_MODE_7B, 0), 100}, + { UDATA (&dno_svc, TT_MODE_7B, 0), 100}, + { UDATA (&dni_svc, TT_MODE_7B|UNIT_DIS, 0), 1000 }, + }; + +REG dn_reg[] = { + {SAVEDATA(IN, dn_in) }, + {SAVEDATA(OUT, dn_out) }, + {HRDATA(IN_PTR, dn_in_ptr, 32), REG_HRO}, + {HRDATA(IN_CMD, dn_in_cmd, 32), REG_HRO}, + {HRDATA(OUT_PTR, dn_out_ptr, 32), REG_HRO}, + {HRDATA(OUT_RES, dn_out_res, 32), REG_HRO}, + {HRDATA(BASE, dn_base, 32), REG_HRO}, + {HRDATA(OFF, dn_off, 32), REG_HRO}, + {HRDATA(DTOFF, dn_dt10_off, 32), REG_HRO}, + {HRDATA(ETOFF, dn_et10_off, 32), REG_HRO}, + {HRDATA(E1OFF, dn_et11_off, 32), REG_HRO}, + {HRDATA(PROC, dn_proc_num, 32), REG_HRO}, + {HRDATAD(WRU, sim_int_char, 8, "interrupt character") }, + { 0 }, + }; + + +DEVICE dn_dev = { + "DN", dn_unit, dn_reg, dn_mod, + 3, 10, 31, 1, 8, 8, + NULL, NULL, &dn_reset, + NULL, NULL, NULL, &dn_dib, DEV_DIS | DEV_DISABLE | DEV_DEBUG, 0, dev_debug, + NULL, NULL, &dn_help, NULL, NULL, &dn_description + }; + + +t_stat dn_devio(uint32 dev, uint64 *data) { + uint32 res; + switch(dev & 3) { + case CONI: + *data = (uint64)(dn_unit[0].STATUS) & RMASK; + *data |= DTE_RM; /* Restricted mode */ + sim_debug(DEBUG_CONI, &dn_dev, "DN %03o CONI %06o\n", dev, (uint32)*data); + break; + case CONO: + res = (uint32)(*data & RMASK); + clr_interrupt(dev); + if (res & DTE_PIENB) { + dn_unit[0].STATUS &= ~(DTE_PIA|DTE_PIE); + dn_unit[0].STATUS |= res & (DTE_PIA|DTE_PIE); + } + if (res & DTE_CO11CL) + dn_unit[0].STATUS &= ~(DTE_11DN|DTE_11ER); + if (res & DTE_CO10CL) { + dn_unit[0].STATUS &= ~(DTE_10DN|DTE_10ER); + dn_start(&dn_unit[0]); + } + if (res & DTE_CO10DB) + dn_unit[0].STATUS &= ~(DTE_10DB); + if (res & DTE_CO11CR) + dn_unit[0].STATUS &= ~(DTE_11RELD); + if (res & DTE_CO11SR) + dn_unit[0].STATUS |= (DTE_11RELD); + if (res & DTE_CO11DB) { + sim_debug(DEBUG_CONO, &dn_dev, "DN Ring 11 DB\n"); + dn_unit[0].STATUS |= DTE_11DB; + dn_unit[0].STATUS &= ~(DTE_10DB); + sim_activate(&dn_unit[0], 200); + } + if (dn_unit[0].STATUS & (DTE_10DB|DTE_11DN|DTE_10DN|DTE_11ER|DTE_10ER)) + set_interrupt(dev, dn_unit[0].STATUS); + sim_debug(DEBUG_CONO, &dn_dev, "DN %03o CONO %06o %06o\n", dev, + (uint32)*data, PC); + break; + case DATAI: + sim_debug(DEBUG_DATAIO, &dn_dev, "DN %03o DATAI %06o\n", dev, + (uint32)*data); + break; + case DATAO: + sim_debug(DEBUG_DATAIO, &dn_dev, "DN %03o DATAO %06o\n", dev, + (uint32)*data); + if (*data == 01365) { + dn_unit[0].STATUS |= DTE_10ER; + dn_unit[0].STATUS &= ~(DTE_10DB|DTE_IND|DTE_11DB); + break; + } + dn_unit[0].CNT = (*data & (DTE_TO10IB|DTE_TO10BC)); + dn_unit[0].STATUS |= DTE_TO11; + sim_activate(&dn_unit[0], 10); + break; + } + return SCPE_OK; +} + +/* Handle KL style interrupt vectors */ +t_addr +dn_devirq(uint32 dev, t_addr addr) { + return 0152; +} + +/* Handle TO11 interrupts */ +t_stat dn_svc (UNIT *uptr) +{ + /* Did the 10 knock? */ + if (uptr->STATUS & DTE_11DB) { + /* If in secondary mode, do that protocol */ + if (uptr->STATUS & DTE_SEC) + dn_second(uptr); + dn_primary(uptr); /* Retrieve data */ + } else if (uptr->STATUS & DTE_TO11) { + /* Does 10 want us to send it what we have? */ + dn_transfer(uptr); + } + return SCPE_OK; +} + +/* Handle secondary protocol */ +void dn_second(UNIT *uptr) { + uint64 word; + int32 ch; + uint32 base = 0; +int i; + +#if KI_22BIT + base = eb_ptr; +#endif + /* read command */ + word = M[SEC_DTCMD + base]; + /* Do it */ + sim_debug(DEBUG_DETAIL, &dn_dev, "DN secondary %012llo\n", word); +for (i = 0; i < 8; i++) + sim_debug(DEBUG_DETAIL, &dn_dev, "EB word %o %012llo\n", i, M[eb_ptr + 0150+i]); +for (i = 0; i <100; i++) { + if (Mem_examine_word(1, i, &word)) + break; + sim_debug(DEBUG_DETAIL, &dn_dev, "DN1 word %3o %012llo\n", i, word); +} + switch(word & SEC_CMDMSK) { + default: +#if 0 + case SEC_MONO: /* Ouput character in monitor mode */ + ch = (int32)(word & 0177); + if (full(&cty_out)) { + sim_activate(uptr, 200); + return; + } + if (ch != 0) { + cty_out.buff[cty_out.in_ptr] = ch & 0x7f; + inci(&cty_out); + sim_activate(&dn_unit[1], 200); + } + M[SEC_DTCHR + base] = ch; + M[SEC_DTMTD + base] = FMASK; + break; +#endif + + case SEC_SETPRI: +enter_pri: + if (Mem_examine_word(1, 0, &word)) + return; + sim_debug(DEBUG_DETAIL, &dn_dev, "DN word 0 %012llo\n", word); + dn_proc_num = (word >> 24) & 037; + dn_base = dn_proc_num + 1; + dn_off = dn_base + (word & 0177777); + dn_dt10_off = 16; + dn_et10_off = dn_dt10_off + 16; + dn_et11_off = dn_base + 16; + uptr->STATUS &= ~DTE_SEC; + dn_in_ptr = dn_out_ptr = 0; + dn_in_cmd = dn_out_res = 0; + + /* Start input process */ + M[SEC_DTCMD + base] = 0; + M[SEC_DTFLG + base] = FMASK; + uptr->STATUS &= ~DTE_11DB; + return; +#if 0 + case SEC_SETDDT: /* Read character from console */ + if (empty(&cty_in)) { + M[SEC_DTF11 + base] = 0; + M[SEC_DTMTI + base] = FMASK; + break; + } + ch = cty_in.buff[cty_in.out_ptr]; + 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; + 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 */ + break; +#endif + } + /* Acknowledge command */ + M[SEC_DTCMD + base] = 0; + M[SEC_DTFLG + base] = FMASK; + uptr->STATUS &= ~DTE_11DB; + if (dn_dev.flags & TYPE_RSX20) { + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, dn_unit[0].STATUS); + } +} + + +/* Handle primary protocol */ +void dn_primary(UNIT *uptr) { + uint64 word, iword; + int s; + int cnt; + struct _dn_queue *in; + uint16 data1, *dp; +int i; + + if ((uptr->STATUS & DTE_11DB) == 0) + return; + + /* Check if there is room for another packet */ + if (((dn_in_ptr + 1) & 0x1f) == dn_in_cmd) { + /* If not reschedule ourselves */ + sim_activate(uptr, 100); + return; + } + uptr->STATUS &= ~(DTE_11DB); + clr_interrupt(DTE_DEVNUM); + Mem_examine_word(1, 0, &word); + dn_proc_num = (word >> 24) & 037; + sim_debug(DEBUG_DETAIL, &dn_dev, "DN1 procnum %0o\n", dn_proc_num); + dn_base = dn_proc_num + 1; + sim_debug(DEBUG_DETAIL, &dn_dev, "DN1 base %0o\n", dn_base); + dn_off = dn_base + (word & 0177777); + sim_debug(DEBUG_DETAIL, &dn_dev, "DN1 dn_off %0o\n", dn_off); + dn_dt10_off = 020; + sim_debug(DEBUG_DETAIL, &dn_dev, "DN1 dn_dt_off %0o\n", dn_dt10_off); + dn_et10_off = dn_dt10_off + 16; + sim_debug(DEBUG_DETAIL, &dn_dev, "DN1 dn_et_off %0o\n", dn_et10_off); + dn_et11_off = dn_base + (8 * dn_base); + sim_debug(DEBUG_DETAIL, &dn_dev, "DN1 dn_et11_off %0o\n", dn_et11_off); + +for (i = 0; i < 8; i++) + sim_debug(DEBUG_DETAIL, &dn_dev, "EB word %o %012llo\n", i, M[eb_ptr + 0150+i]); +for (i = 0; i <200; i++) { + if (Mem_examine_word(1, i, &word)) + break; + sim_debug(DEBUG_DETAIL, &dn_dev, "DN1 word %3o %012llo\n", i, word); +} + /* Check status word to see if valid */ + if (Mem_examine_word(1, dn_et11_off + PRI_CMTW_STS, &word)) { + uint32 base; +error: + base = 0; +#if KI_22BIT + 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 (dn_dev.flags & TYPE_RSX20) { + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, dn_unit[0].STATUS); + } + sim_debug(DEBUG_DETAIL, &dn_dev, "DTE: error %012llo\n", word); + return; + } + + sim_debug(DEBUG_DETAIL, &dn_dev, "DTE: status %06llo %012llo\n", dn_et11_off + PRI_CMTW_STS + M[0155 + eb_ptr], word); + if ((word & PRI_CMT_INI) != 0) { + word &= ~PRI_CMT_TOT; + sim_debug(DEBUG_DETAIL, &dn_dev, "DTE: istatus %06llo %012llo\n", dn_dt10_off + PRI_CMTW_STS + M[0157 + eb_ptr], word); + if (Mem_deposit_word(1, dn_dt10_off + PRI_CMTW_STS, &word)) + goto error; + uptr->STATUS |= DTE_11DN|DTE_10DB|DTE_INIT; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + return; + } + if ((uptr->STATUS & DTE_INIT) != 0) { + sim_debug(DEBUG_DETAIL, &dn_dev, "DTE: dstatus %06llo %012llo\n", dn_dt10_off + PRI_CMTW_STS + M[0157 + eb_ptr], word); + if (Mem_deposit_word(1, dn_dt10_off + PRI_CMTW_STS, &word)) + goto error; + uptr->STATUS |= DTE_11DN|DTE_10DB; + uptr->STATUS &= ~DTE_INIT; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + return; + } +// if ((word & PRI_CMT_QP) == 0) { + // goto error; + // } + + in = &dn_in[dn_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\r\n"); + return; + } + /* Get size of transfer */ + if (Mem_examine_word(1, dn_et11_off + PRI_CMTW_CNT, &iword)) + goto error; + sim_debug(DEBUG_EXP, &dn_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(1, dp, 0); + if (s == 0) + goto error; + in->sz = s; + sim_debug(DEBUG_DATA, &dn_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--; + } + uptr->STATUS &= ~DTE_IND; + dn_in_ptr = (dn_in_ptr + 1) & 0x1f; + } else { + /* Transfer from 10 */ + in->dptr = 0; + in->dcnt = 0; + /* Read in count */ + if (!Mem_read_byte(1, &data1, 0)) + goto error; + in->cnt = data1; + cnt = in->cnt-2; + if (!Mem_read_byte(1, &data1, 0)) + goto error; + in->func = data1; + cnt -= 2; + if (!Mem_read_byte(1, &data1, 0)) + goto error; + in->dev = data1; + cnt -= 2; + if (!Mem_read_byte(1, &data1, 0)) + goto error; + in->spare = data1; + cnt -= 2; + sim_debug(DEBUG_DATA, &dn_dev, "DTE: Read CMD: %o c=%o f=%o %s s=%o d=%o\n", + dn_in_ptr, in->cnt, in->func, + ((in->func & 0377) > PRI_EMLDV)?"***": + pri_name[in->func & 0377], in->spare, in->dev); + dp = &in->data[0]; + for (; cnt > 0; cnt -=2) { + /* Read in data */ + if (!Mem_read_byte(1, dp, 0)) + goto error; + sim_debug(DEBUG_DATA, &dn_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->dcnt = in->data[0]; + in->sdev = (in->dcnt >> 8) & 0377; + in->dcnt &= 0377; + word |= PRI_CMT_TOT; + if (Mem_deposit_word(1, dn_dt10_off + PRI_CMTW_STS, &word)) + goto error; + } else { + dn_in_ptr = (dn_in_ptr + 1) & 0x1f; + } + } + word &= ~PRI_CMT_TOT; + if (Mem_deposit_word(1, dn_dt10_off + PRI_CMTW_STS, &word)) + goto error; + uptr->STATUS |= DTE_11DN; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + dn_function(uptr); +} + +/* Process primary protocol packets */ +void +dn_function(UNIT *uptr) +{ + uint16 data1[32]; + int32 ch; + struct _dn_queue *cmd; + int func; + int dev; + + /* Check if queue is empty */ + while (dn_in_cmd != dn_in_ptr) { + if (((dn_out_res + 1) & 0x1f) == dn_out_ptr) { + sim_debug(DEBUG_DATA, &dn_dev, "DTE: func out full %d %d\n", + dn_out_res, dn_out_ptr); + return; + } + cmd = &dn_in[dn_in_cmd]; + dev = cmd->dev & 0377; + func = cmd->func & 0377; + sim_debug(DEBUG_DATA, &dn_dev, + "DTE: func %o %02o %s dev %o cnt %d dcnt %d\n", + dn_in_cmd, func, (func > PRI_EMLDV) ? "***" : pri_name[func], + cmd->dev, cmd->dcnt, cmd->dptr ); + switch (func) { + case PRI_EM2EI: /* Initial message to 11 */ + break; + + case PRI_EM2TI: /* Replay to initial message. */ + data1[0] = (6 << 8) | 5; + data1[1] = (0 << 8) | 0xc0; + data1[2] = (1 << 8) | 0; + if (dn_queue(01, PRI_DN60, 3, data1) == 0) + return; + break; + 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 = sim_get_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 (dn_queue(PRI_EMHDR | PRI_IND_FLG, PRI_EMCLK, 6, data1) == 0) + return; + } + break; + + case PRI_EMSTR: /* String data */ + + + /* Handle terminal data */ + if (dev == PRI_EMDLS) { + int ln = cmd->sdev; + struct _buffer *otty; + if (ln == PRI_CTYDV) + goto cty; + break; + } + + if (dev == PRI_EMCTY) { +cty: +#if 0 + sim_activate(&dn_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, &dn_dev,"DN queue %o\n",ch); + } + cmd->dptr++; + } +#endif + if (cmd->dptr != cmd->dcnt) + return; + } + break; + + case PRI_EMSNA: /* Send all (ttys) */ + break; + + case PRI_EMLNC: /* Line-Char */ + break; + + case PRI_EMOPS: + break; + + case PRI_EMRDS: /* Request device status */ + break; + + case PRI_EMHDS: /* Here is device status */ + break; + case PRI_EMLDV: /* Load LP VFU */ + break; + + case PRI_EMLDR: /* Load LP RAM */ + break; + + + case PRI_EMFLO: /* Flush output */ + break; + + case PRI_EMDSC: /* Dataset connect */ + break; + + case PRI_EMHUD: /* Hang up dataset */ + + case PRI_EMXOF: /* XOFF line */ + break; + + case PRI_EMXON: /* XON line */ + break; + + case PRI_EMHLS: /* Here is line speeds */ + 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 */ + break; + default: + break; + } + /* Mark command as finished */ + cmd->cnt = 0; + dn_in_cmd = (dn_in_cmd + 1) & 0x1F; + } +} + +/* + * Handle primary protocol, + * Send to 10 when requested. + */ +void dn_transfer(UNIT *uptr) { + uint16 cnt; + uint16 scnt; + struct _dn_queue *out; + uint16 *dp; +int i; + + + /* Check if Queue empty */ + if (dn_out_res == dn_out_ptr) + return; + + out = &dn_out[dn_out_ptr]; + uptr->STATUS &= ~DTE_TO11; + clr_interrupt(DTE_DEVNUM); +for (i = 0; i < 8; i++) + sim_debug(DEBUG_DETAIL, &dn_dev, "EB Sword %o %012llo\n", i, M[eb_ptr + 0150+i]); +for (i = 0; i <200; i++) { +uint64 word; + if (Mem_examine_word(1, i, &word)) + break; + sim_debug(DEBUG_DETAIL, &dn_dev, "DN1 Sword %3o %012llo\n", i, word); +} + + /* 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, &dn_dev, "DTE: Send Idata: %06o %03o %03o\n", + *dp, *dp >> 8, *dp & 0377); + if (Mem_write_byte(1, dp) == 0) + goto error; + dp++; + } + uptr->STATUS &= ~DTE_SIND; + } else { + sim_debug(DEBUG_DATA, &dn_dev, "DTE: %d %d send CMD: [%o] %o %o %o\n", + dn_out_ptr, dn_out_res, scnt, 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(1, &cnt)) + goto error; + if (!Mem_write_byte(1, &out->func)) + goto error; + cnt -= 2; + if (!Mem_write_byte(1, &out->dev)) + goto error; + cnt -= 2; + if (!Mem_write_byte(1, &out->spare)) + goto error; + cnt -= 2; + if (out->func & PRI_IND_FLG) { + uint16 dwrd = out->dcnt; + sim_debug(DEBUG_DATA, &dn_dev, "DTE: Indirect %o %o\n", cnt, + out->dcnt); + dwrd |= (out->sdev << 8); + if (!Mem_write_byte(1, &dwrd)) + goto error; + uptr->STATUS |= DTE_SIND; + goto done; + } + cnt -= 2; + dp = &out->data[0]; + for (; cnt > 0; cnt -= 2) { + sim_debug(DEBUG_DATA, &dn_dev, "DTE: Send data: %06o %03o %03o\n", + *dp, *dp >> 8, *dp & 0377); + if (!Mem_write_byte(1, dp)) + goto error; + dp++; + } + } + out->cnt = 0; + dn_out_ptr = (dn_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 +dn_input() +{ + uint16 data1; + uint16 dataq[32]; + int n; + int ln; + int save_ptr; + char ch; + UNIT *uptr = &dn_unit[0]; + +#if 0 + if ((uptr->STATUS & DTE_SEC) == 0) { + /* Check if CTY done with input */ + if (cty_done) { + data1 = PRI_CTYDV; + if (dn_queue(PRI_EMLBE, 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 (not_empty(&cty_in) && n < 32) { + ch = cty_in.buff[cty_in.out_ptr]; + inco(&cty_in); + sim_debug(DEBUG_DETAIL, &dn_dev, "DN recieve %02x\n", ch); + dataq[n++] = (PRI_CTYDV << 8) | ch; + } + if (n > 0 && dn_queue(PRI_EMLNC, PRI_EMDLS, n, dataq) == 0) { + /* Restore the input pointer */ + cty_in.out_ptr = save_ptr; + return; + } + } +#endif +} + +/* + * Queue up a packet to send to 10. + */ +int +dn_queue(int func, int dev, int dcnt, uint16 *data) +{ + uint16 *dp; + struct _dn_queue *out; + + /* Check if room in queue for this packet. */ + if (((dn_out_res + 1) & 0x1f) == dn_out_ptr) { + sim_debug(DEBUG_DATA, &dn_dev, "DTE: %d %d out full\n", dn_out_res, dn_out_ptr); + return 0; + } + out = &dn_out[dn_out_res]; + out->cnt = 10; + out->func = func; + out->dev = dev; + out->dcnt = (dcnt-1)*2; + out->spare = 0; + sim_debug(DEBUG_DATA, &dn_dev, "DTE: %d %d queue resp: %o (%o) f=%o %s d=%o\n", + dn_out_ptr, dn_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++; + } + /* Advance pointer to next function */ + dn_out_res = (dn_out_res + 1) & 0x1f; + return 1; +} + + +/* + * If anything in queue, start a transfer, if one is not already + * pending. + */ +int +dn_start(UNIT *uptr) +{ + uint64 word; + int dcnt; +int i; + + /* Check if queue empty */ + if (dn_out_ptr == dn_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(1, dn_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); + word &= ~PRI_CMT_FWD; + if ((uptr->STATUS & DTE_SIND) != 0) + word |= PRI_CMT_IP; + if (Mem_deposit_word(1, dn_dt10_off + PRI_CMTW_STS, &word)) + goto error; + dcnt = dn_out[dn_out_ptr].cnt; + if ((dn_out[dn_out_ptr].func & PRI_IND_FLG) == 0) + dcnt += dn_out[dn_out_ptr].dcnt; + /* Tell 10 something is ready */ + if ((uptr->STATUS & DTE_SIND) != 0) { + dcnt = dn_out[dn_out_ptr].dcnt; + } + sim_debug(DEBUG_DATA, &dn_dev, "DTE: start: %012llo %o\n", word, dcnt); + word = (uint64)dcnt; + word |= (word << 18); + if (Mem_deposit_word(1, dn_dt10_off + PRI_CMTW_CNT, &word)) + goto error; +for (i = 0; i < 8; i++) + sim_debug(DEBUG_DETAIL, &dn_dev, "EB word %o %012llo\n", i, M[eb_ptr + 0150+i]); +for (i = 0; i <200; i++) { + if (Mem_examine_word(1, i, &word)) + break; + sim_debug(DEBUG_DETAIL, &dn_dev, "DN1 word %3o %012llo\n", i, word); +} + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, uptr->STATUS); + return 1; +} + + +/* Check for input from CTY and put on queue. */ +t_stat dni_svc (UNIT *uptr) +{ + int32 ch; + uint32 base = 0; + UNIT *optr = &dn_unit[0]; + +#if KI_22BIT + base = eb_ptr; +#endif + sim_clock_coschedule (uptr, tmxr_poll); + dn_input(); + if ((optr->STATUS & (DTE_SEC)) == 0) { + dn_function(uptr); /* Process queue */ + dn_start(optr); + } + + +#if 0 + /* If we have room see if any new lines */ + 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; + inci(&cty_in); + sim_debug(DEBUG_DETAIL, &dn_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) && + not_empty(&cty_in) && M[SEC_DTMTI + base] == 0) { + ch = cty_in.buff[cty_in.out_ptr]; + inco(&cty_in); + M[SEC_DTF11 + base] = ch; + M[SEC_DTMTI + base] = FMASK; + if (dn_dev.flags & TYPE_RSX20) { + uptr->STATUS |= DTE_10DB; + set_interrupt(DTE_DEVNUM, dn_unit[0].STATUS); + } + } +#endif + return SCPE_OK; +} + +/* Handle output of characters to CTY. Started whenever there is output pending */ +t_stat dno_svc (UNIT *uptr) +{ +#if 0 + /* Flush out any pending CTY output */ + while(not_empty(&cty_out)) { + char ch = cty_out.buff[cty_out.out_ptr]; + if (ch != 0) { + if (sim_putchar_s(ch) != SCPE_OK) { + sim_activate(uptr, 1000); + return SCPE_OK;; + } + } + inco(&cty_out); + sim_debug(DEBUG_DETAIL, &dn_dev, "DN outch %o '%c'\n", ch, + ((ch > 040 && ch < 0177)? ch: '.')); + } + cty_done++; +#endif + return SCPE_OK; +} + + +/* Handle FE timer interrupts. And keepalive counts */ +t_stat +dnrtc_srv(UNIT * uptr) +{ + UNIT *optr = &dn_unit[0]; + + sim_activate_after(uptr, 1000000/60); + + /* Update out keep alive timer if in secondary protocol */ + if ((optr->STATUS & DTE_SEC) == 0) { + int addr = 0154 + eb_ptr; + uint64 word; + + (void)Mem_examine_word(1, dn_et11_off + PRI_CMTW_STS, &word); + addr = (M[addr+1] + dn_off + PRI_CMTW_KAC) & RMASK; + word = M[addr]; + word = (word + 1) & FMASK; + M[addr] = word; + sim_debug(DEBUG_EXP, &dn_dev, "DN keepalive %06o %012llo %06o\n", + addr, word, optr->STATUS); + } + + return SCPE_OK; +} + + +t_stat dn_reset (DEVICE *dptr) +{ + dn_unit[0].STATUS = 0; //DTE_SEC; + dn_unit[1].STATUS = 0; + dn_unit[2].STATUS = 0; + dn_proc_num = 0; + dn_base = dn_proc_num + 1; + dn_off = 0; + dn_dt10_off = 16; + dn_et10_off = 050; + dn_et11_off = 033; + sim_activate(&dn_unit[2], 1000); + return SCPE_OK; +} + + +t_stat +dn_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 +dn_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; +} + + +t_stat dn_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprint_reg_help (st, &dn_dev); +return SCPE_OK; +} + +const char *dn_description (DEVICE *dptr) +{ + return "DN Network interface"; +} + + +#endif +#endif diff --git a/PDP10/ks10_dz.c b/PDP10/ks10_dz.c index 6945e0555..27055344a 100644 --- a/PDP10/ks10_dz.c +++ b/PDP10/ks10_dz.c @@ -447,7 +447,6 @@ dz_checkirq(struct pdp_dib *dibp) int ln; int stop; TMLN *lp; - int irq = 0; for (i = 0; i < NUM_DEVS_DZ; i++) { if ((dz_csr[i] & MSE) == 0) diff --git a/PDP10/ks10_tcu.c b/PDP10/ks10_tcu.c index c7a785352..3ceac502c 100644 --- a/PDP10/ks10_tcu.c +++ b/PDP10/ks10_tcu.c @@ -81,7 +81,6 @@ tcu_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access) int tcu_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access) { - struct pdp_dib *dibp = (DIB *)dptr->ctxt; time_t curtim; struct tm *tptr; diff --git a/PDP10/ks10_uba.c b/PDP10/ks10_uba.c index 40dde721a..064117181 100644 --- a/PDP10/ks10_uba.c +++ b/PDP10/ks10_uba.c @@ -79,11 +79,8 @@ uba_read(t_addr addr, int ctl, uint64 *data, int access) *data = (uint64)uba_map[ubm][addr & 077]; return 0; } else if ((addr & 077) == 0) { - int pih, pil; int irqf = 0; *data = (uint64)uba_status[ubm]; - pih = 0200 >> ((uba_status[ubm] >> 3) & 07); - pil = 0200 >> (uba_status[ubm] & 07); for (i = 0; i < 128; i++) { if ((uba_irq_ctlr[i] & VECT_CTR) == ctl) irqf |= uba_irq_ctlr[i]; diff --git a/PDP10/kx10_cpu.c b/PDP10/kx10_cpu.c index db86c6e63..1d36e013f 100644 --- a/PDP10/kx10_cpu.c +++ b/PDP10/kx10_cpu.c @@ -140,9 +140,7 @@ uint32 rdrin_dev; /* Read in device */ uint8 IX; /* Index register */ uint8 IND; /* Indirect flag */ #endif -#if PDP6 | KA | KI t_addr AS; /* Address switches */ -#endif int BYF5; /* Flag for second half of LDB/DPB instruction */ int uuo_cycle; /* Uuo cycle in progress */ int SC; /* Shift count */ @@ -1356,7 +1354,6 @@ t_stat dev_apr(uint32 dev, uint64 *data) { * MTR device for KL10. */ t_stat dev_mtr(uint32 dev, uint64 *data) { - uint64 res = 0; switch(dev & 03) { case CONI: @@ -3525,6 +3522,7 @@ int Mem_read_its(int flag, int cur_context, int fetch, int mod) { check_apr_irq(); return 1; } + return 0; } #endif #if NUM_DEVS_TEN11 > 0 @@ -3579,9 +3577,9 @@ int Mem_write_its(int flag, int cur_context) { } if (!page_lookup_its(AB, flag, &addr, 1, cur_context, 0, 0)) return 1; -#if NUM_DEVS_TEN11 > 0 - if (T11RANGE(addr) && QTEN11) { - if (ten11_write (addr, MB)) { +#if NUM_DEVS_AUXCPU > 0 + if (AUXCPURANGE(addr) && QAUXCPU) { + if (auxcpu_write (addr, MB)) { nxm_flag = 1; check_apr_irq(); return 1; @@ -3589,13 +3587,14 @@ int Mem_write_its(int flag, int cur_context) { return 0; } #endif -#if NUM_DEVS_AUXCPU > 0 - if (AUXCPURANGE(addr) && QAUXCPU) { - if (auxcpu_write (addr, MB)) { +#if NUM_DEVS_TEN11 > 0 + if (T11RANGE(addr) && QTEN11) { + if (ten11_write (addr, MB)) { nxm_flag = 1; check_apr_irq(); return 1; } + return 0; } #endif if (addr >= MEMSIZE) { @@ -4486,13 +4485,13 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ #if PIDP10 if (examine_sw) { /* Examine memory switch */ AB = AS; - (void)Mem_read(1, 0, 0, 0); + (void)Mem_read_nopage(); examine_sw = 0; } if (deposit_sw) { /* Deposit memory switch */ AB = AS; MB = SW; - (void)Mem_write(1, 0); + (void)Mem_write_nopage(); deposit_sw = 0; } if (xct_sw) { /* Handle Front panel xct switch */ @@ -4500,13 +4499,14 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ xct_flag = 0; uuo_cycle = 1; f_pc_inh = 1; + f_load_pc = 0; MB = SW; - xct_sw = 0; goto no_fetch; } if (stop_sw) { /* Stop switch set */ RUN = 0; stop_sw = 0; + reason = STOP_HALT; } if (sing_inst_sw) { /* Handle Front panel single instruction */ instr_count = 1; @@ -4854,7 +4854,7 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ /* Check if possible idle loop */ if (sim_idle_enab && - (((FLAGS & USER) != 0 && PC < 020 && AB < 020 && (IR & 0740) == 0340) || + ((PC < 020 && AB < 020 && (IR & 0740) == 0340) || (uuo_cycle && (IR & 0740) == 0 && IA == 041))) { sim_idle (TMR_RTC, FALSE); } @@ -4906,6 +4906,11 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ nrf = 0; fxu_hold_set = 0; modify = 0; +#if PIDP10 + if (xct_sw) { /* Handle Front panel xct switch */ + xct_sw = 0; + } else +#endif f_pc_inh = 0; #if KL | KS if (extend) { @@ -7182,9 +7187,6 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ SC--; } else { AR = BR; -#if KS - FLAGS |= NODIV|TRP1; -#endif break; } } @@ -7243,10 +7245,8 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ SC--; } AR &= FMASK; -#if KL | KS if ((SC & 01600) != 01600) fxu_hold_set = 1; -#endif if (AR == (SMASK|EXPO)) { AR = (AR >> 1) | (AR & SMASK); SC ++; @@ -11775,7 +11775,7 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ MB = BR; if (Mem_write(pi_cycle, 0)) goto last; - MB = AR; + MB = AR; break; } break; @@ -12263,6 +12263,7 @@ if ((reason = build_dev_tab ()) != SCPE_OK) /* build, chk dib_tab */ if (QITS) load_quantum(); #endif + RUN = 0; return SCPE_STEP; } } @@ -13499,7 +13500,11 @@ rtc_srv(UNIT * uptr) tmxr_poll = t/2; #if PDP6 | KA | KI clk_flg = 1; +#if PIDP10 + if (clk_en && !sing_inst_sw) { +#else if (clk_en) { +#endif sim_debug(DEBUG_CONO, &cpu_dev, "CONO timmer\n"); set_interrupt(4, clk_irq); } @@ -13575,13 +13580,17 @@ static const char *pdp10_clock_precalibrate_commands[] = { t_stat cpu_reset (DEVICE *dptr) { - int i; - static int initialized = 0; + int i; + t_stat r = SCPE_OK; + static int initialized = 0; if (!initialized) { initialized = 1; #if PIDP10 - pi_panel_start(); + r = pi_panel_start(); + if (r != SCPE_OK) { + return r; + } #endif } sim_debug(DEBUG_CONO, dptr, "CPU reset\n"); @@ -13656,7 +13665,7 @@ t_stat cpu_reset (DEVICE *dptr) #endif sim_vm_interval_units = "cycles"; sim_vm_step_unit = "instruction"; - return SCPE_OK; + return r; } /* Memory examine */ @@ -13859,6 +13868,7 @@ t_bool build_dev_tab (void) if ((nia_dev.flags & DEV_DIS) == 0 && dptr != &nia_dev && rh20 == (((DIB *)nia_dev.ctxt)->dev_num & 0777)) rh20 += 4; + else /* 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; diff --git a/PDP10/kx10_ddc.c b/PDP10/kx10_ddc.c new file mode 100644 index 000000000..1e01aac1b --- /dev/null +++ b/PDP10/kx10_ddc.c @@ -0,0 +1,402 @@ +/* kx10_ddc.c: Drum RES-10 Disk Controller. + + Copyright (c) 2013-2022, 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 MEDDCHANTABILITY, + 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" + +#ifndef NUM_DEVS_DDC +#define NUM_DEVS_DDC 0 +#endif + +#if (NUM_DEVS_DDC > 0) + +#define DDC_DEVNUM 0440 /* 0174 */ +#define NUM_UNITS_DDC 4 + +/* Flags in the unit flags word */ + +#define UNIT_V_DTYPE (UNIT_V_UF + 0) /* disk type */ +#define UNIT_M_DTYPE 1 +#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) +#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) + +/* Parameters in the unit descriptor */ + +#define STATUS u3 /* Current status */ +#define POS u4 /* Position in sector buffer */ +#define UFLAGS u5 /* Function */ +#define SEC us9 /* Sector counter */ + + +/* CONI bits */ +#define QUEUE_PAR 0400000000000LL +#define DDC_BSY 0000001000000LL +#define DDC_DON 0000000400000LL +#define DDC_CSE 0000000001000LL +#define DDC_QF 0000000000400LL +#define DDC_RDY 0000000000200LL /* Drum Ready */ +#define DDC_SPA 0000000000100LL /* Drum Silo Parity Error */ +#define DDC_NXM 0000000000040LL /* NXM */ +#define DDC_EXC 0000000000020LL /* Exceed Capacity */ +#define DDC_HUD 0000000000010LL /* Drum Hung */ +#define DDC_MPE 0000000000004LL /* MPE */ +#define DDC_OVR 0000000000002LL /* Data overrun */ +#define DDC_CKR 0000000000001LL /* Checksum error */ + +/* CONO bits */ +#define DDC_RST 0000000600000LL /* Drum Reset */ +#define DDC_CLR 0000000400000LL /* Clear Int */ +#define DDC_ERR 0000000200000LL /* Clear Errors */ +#define DDC_EXF 0000000100000LL /* Execute FR */ +#define DDC_EXQ 0000000040000LL /* Execute Queue */ + +/* Command words */ +#define DDC_CMD 0700000000000LL /* Drum command */ +#define DDC_SEQ 0003700000000LL /* Sequence number */ +#define DDC_PIA 0000070000000LL /* PIA */ +#define DDC_FUNC 0000006000000LL /* Function */ +#define DDC_READ 0000002000000LL +#define DDC_WRITE 0000004000000LL +#define DDC_DISK 0000001400000LL /* Logical Disc */ +#define DDC_TRK 0000000377600LL /* Track */ +#define DDC_SEC 0000000000177LL /* Sector */ + +/* DataI bits */ + /* DDC_SEC 0000000000177LL Sector */ +#define DDC_DONE 0400000000000LL /* Done flag */ + +/* Drum Status */ +#define DDC_PWB 0700000000000LL +#define DDC_SECCNT 0017700000000LL /* Sequence counter */ +#define DDC_ADDR 0000000777777LL + +/* DataI */ +/* 177 Sector number */ + +/* Number of sectors = 13 */ +/* Sector size = 0200 words */ + + + +#define DDC10_WDS 0200 + +#define DDC_SIZE (7000 * DDC10_WDS) + +uint64 ddc_buf[DDC10_WDS]; +uint64 ddc_cmd[16]; +int ddc_cmdptr; +int ddc_putptr; + +t_stat ddc_devio(uint32 dev, uint64 *data); +t_stat ddc_svc(UNIT *); +void ddc_ini(UNIT *, t_bool); +t_stat ddc_reset(DEVICE *); +t_stat ddc_attach(UNIT *, CONST char *); +t_stat ddc_detach(UNIT *); +t_stat ddc_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, + const char *cptr); +const char *ddc_description (DEVICE *dptr); + + +UNIT ddc_unit[] = { +/* Controller 1 */ + { UDATA (&ddc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, DDC_SIZE) }, + { UDATA (&ddc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, DDC_SIZE) }, + { UDATA (&ddc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, DDC_SIZE) }, + { UDATA (&ddc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ + UNIT_ROABLE, DDC_SIZE) }, + +}; + +DIB ddc_dib = {DDC_DEVNUM, 1, &ddc_devio, NULL}; + +MTAB ddc_mod[] = { + { MTAB_XTD|MTAB_VUN, 0, "write enabled", "WRITEENABLED", + &set_writelock, &show_writelock, NULL, "Write enable drive" }, + { MTAB_XTD|MTAB_VUN, 1, NULL, "LOCKED", + &set_writelock, NULL, NULL, "Write lock drive" }, + {0} +}; + +REG ddc_reg[] = { + {0} +}; + +DEVICE ddc_dev = { + "DDC", ddc_unit, ddc_reg, ddc_mod, + NUM_UNITS_DDC, 8, 18, 1, 8, 36, + NULL, NULL, &ddc_reset, NULL, &ddc_attach, &ddc_detach, + &ddc_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, dev_debug, + NULL, NULL, &ddc_help, NULL, NULL, &ddc_description +}; + + +t_stat ddc_devio(uint32 dev, uint64 *data) { + UNIT *uptr; + DEVICE *dptr; + + dptr = &ddc_dev; + uptr = &dptr->units[0]; + switch(dev & 3) { + case CONI: + sim_debug(DEBUG_CONI, dptr, "DDC %03o CONI %06o PC=%o\n", dev, + (uint32)*data, PC); + *data = uptr->STATUS; + if (ddc_cmdptr != ((ddc_putptr + 2) & 0xf)) { + *data |= DDC_RDY; + } + if (ddc_cmdptr == ddc_putptr) { + *data |= DDC_BSY; + } + *data |= ((t_uint64)uptr->UFLAGS) << 25; + break; + case CONO: + if (*data & DDC_CLR) { /* Clear irq */ + uptr->STATUS &= ~(DDC_DON); + clr_interrupt(ddc_dib.dev_num); + } + if (*data & DDC_ERR) { /* Clear error */ + uptr->STATUS &= ~(DDC_SPA|DDC_NXM|DDC_EXC|DDC_HUD|DDC_MPE| + DDC_OVR|DDC_CKR|DDC_QF); + } + if (*data & DDC_EXF) { /* Execute FR */ + } + if (*data & DDC_EXQ) { /* Execute Queue */ + if (!sim_is_active(uptr)) { + sim_activate(uptr, 100); + uptr->POS = 0; + } + } + + sim_debug(DEBUG_CONO, dptr, "DDC %03o CONO %06o PC=%o\n", dev, + (uint32)*data, PC); + break; + case DATAI: + *data = (t_uint64)(uptr->SEC++); + uptr->SEC &= 0177; + if (uptr->SEC > (13 << 2)) + uptr->SEC = 0; + if ((uptr->STATUS & DDC_DON) != 0) + *data |= DDC_DONE; + sim_debug(DEBUG_DATAIO, dptr, "DDC %03o DATI %012llo PC=%o\n", + dev, *data, PC); + break; + case DATAO: + sim_debug(DEBUG_DATAIO, dptr, "DDC %03o DATO %012llo, PC=%o\n", + dev, *data, PC); + /* Insert the command into the queue */ + if (((ddc_putptr + 1) & 0xf) != ddc_cmdptr) { + int func; + int pia; + int dsk; + int trk; + int sec; + int seq; + ddc_cmd[ddc_putptr] = *data; + sec = ddc_cmd[ddc_putptr] & DDC_SEC; + trk = (ddc_cmd[ddc_putptr] & DDC_TRK) >> 7; + dsk = (ddc_cmd[ddc_putptr] & DDC_DISK) >> 17; + func = (ddc_cmd[ddc_putptr] & DDC_FUNC) >> 19; + pia = (ddc_cmd[ddc_putptr] & DDC_PIA) >> 21; + seq = (ddc_cmd[ddc_putptr] & DDC_SEQ) >> 24; + sim_debug(DEBUG_DETAIL, dptr, "DDC %d cmd %d %d %d %d %o\n", + dsk, trk, sec, func, pia, seq); + + ddc_putptr = (ddc_putptr + 1) & 0xf; + } else { + uptr->STATUS |= DDC_QF; + } + break; + } + return SCPE_OK; +} + +t_stat ddc_svc (UNIT *uptr) +{ + int wc; + int func; + int pia; + int dsk; + int trk; + int sec; + int seq; + t_addr adr; + uint64 word; + DEVICE *dptr; + UNIT *duptr; + + dptr = &ddc_dev; + sec = (ddc_cmd[ddc_cmdptr] & DDC_SEC) >> 2; + trk = (ddc_cmd[ddc_cmdptr] & DDC_TRK) >> 7; + dsk = (ddc_cmd[ddc_cmdptr] & DDC_DISK) >> 17; + func = (ddc_cmd[ddc_cmdptr] & DDC_FUNC) >> 19; + pia = (ddc_cmd[ddc_cmdptr] & DDC_PIA) >> 21; + seq = (ddc_cmd[ddc_cmdptr] & DDC_SEQ) >> 24; + word = ddc_cmd[ddc_cmdptr+1]; + adr = word & RMASK; + duptr = &ddc_dev.units[dsk]; + + if ((duptr->flags & UNIT_ATT) == 0) { + uptr->STATUS |= DDC_DON|DDC_HUD; + uptr->UFLAGS = seq; + sim_debug(DEBUG_DETAIL, dptr, "DDC %d Set done %d %d\n", dsk, pia, seq); + + set_interrupt(ddc_dib.dev_num, pia); + uptr->POS = 0; + + ddc_cmdptr += 2; + ddc_cmdptr &= 0xf; + if (ddc_cmdptr != ddc_putptr) + sim_activate(uptr, 100); + } + + if (uptr->POS == 0) { + int da; + da = ((trk * 13) + sec) * DDC10_WDS; + (void)sim_fseek(duptr->fileref, da * sizeof(uint64), SEEK_SET); + wc = sim_fread (&ddc_buf[0], sizeof(uint64), + DDC10_WDS, duptr->fileref); + sim_debug(DEBUG_DETAIL, dptr, "DDC %d Read %d %d %d %d %d %o\n", + dsk, da, trk, sec, func, pia, seq); + for (; wc < DDC10_WDS; wc++) + ddc_buf[wc] = 0; + } + + if (func == 2) { + if (Mem_write_word(adr, &ddc_buf[uptr->POS], 0)) { + uptr->STATUS |= DDC_NXM; + goto done; + } + } else if (func == 1) { + if (Mem_read_word(adr, &ddc_buf[uptr->POS], 0)) { + uptr->STATUS |= DDC_NXM; + goto done; + } + } + sim_debug(DEBUG_DATA, dptr, "DDC %d xfer %06o %012llo\n", + dsk, adr, ddc_buf[uptr->POS]); + uptr->POS++; + word = (word & LMASK) | ((adr + 1) & RMASK); + + if (uptr->POS == DDC10_WDS) { +done: + if (func == 2) { + int da; + da = ((trk * 13) + sec) * DDC10_WDS; + (void)sim_fseek(duptr->fileref, da * sizeof(uint64), SEEK_SET); + wc = sim_fwrite (&ddc_buf[0], sizeof(uint64), + DDC10_WDS, duptr->fileref); + sim_debug(DEBUG_DETAIL, dptr, "DDC %d Write %d %d %d %d %d %o\n", + dsk, da, trk, sec, func, pia, seq); + } + sec ++; + ddc_cmd[ddc_cmdptr] &= ~DDC_SEC; + ddc_cmd[ddc_cmdptr] |= (DDC_SEC & (sec << 2)); + word += 0000100000000LL; + sim_debug(DEBUG_DETAIL, dptr, "DDC %d next sect %012llo %012llo\n", dsk, word, ddc_cmd[ddc_cmdptr]); + if ((word & DDC_SECCNT) == 0) { + ddc_cmd[ddc_cmdptr+1] = (word & (DDC_SECCNT|DDC_PWB)) | (adr & RMASK); + uptr->STATUS |= DDC_DON; + uptr->UFLAGS = seq; + uptr->SEC = sec << 2; + sim_debug(DEBUG_DETAIL, dptr, "DDC %d Set done %d %d\n", dsk, pia, seq); + + set_interrupt(ddc_dib.dev_num, pia); + uptr->POS = 0; + + ddc_cmdptr += 2; + ddc_cmdptr &= 0xf; + if (ddc_cmdptr != ddc_putptr) + sim_activate(uptr, 100); + return SCPE_OK; + } + uptr->POS = 0; + } + ddc_cmd[ddc_cmdptr+1] = word; + sim_activate(uptr, 100); + return SCPE_OK; +} + + + + +t_stat +ddc_reset(DEVICE * dptr) +{ + UNIT *uptr; + int i; + ddc_cmdptr = ddc_putptr = 0; + for (i = 0; i < NUM_UNITS_DDC; i++) { + uptr = &dptr->units[i]; + uptr->SEC = 0; + uptr->UFLAGS = 0; + uptr->STATUS = 0; + } + return SCPE_OK; +} + +/* Device attach */ + +t_stat ddc_attach (UNIT *uptr, CONST char *cptr) +{ + t_stat r; + + r = attach_unit (uptr, cptr); + if (r != SCPE_OK || (sim_switches & SIM_SW_REST) != 0) + return r; + return SCPE_OK; +} + +/* Device detach */ + +t_stat ddc_detach (UNIT *uptr) +{ + if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; + if (sim_is_active (uptr)) /* unit active? */ + sim_cancel (uptr); /* cancel operation */ + return detach_unit (uptr); +} + +t_stat ddc_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +fprintf (st, "DDC-10 Drum Drives (DDC)\n\n"); +fprintf (st, "The DDC controller implements the RES-10 disk controller that talked\n"); +fprintf (st, "to drum drives.\n"); +fprintf (st, "Options include the ability to set units write enabled or write locked, to\n"); +fprintf (st, "set the drive type to one of two disk types\n\n"); +fprint_set_help (st, dptr); +fprint_show_help (st, dptr); +fprintf (st, "\nThe type options can be used only when a unit is not attached to a file.\n"); +fprint_reg_help (st, dptr); +return SCPE_OK; +} + +const char *ddc_description (DEVICE *dptr) +{ +return "DDC-10 disk controller"; +} + +#endif diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index f653197fe..8c63fef64 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -513,6 +513,8 @@ extern DEVICE pd_dev; extern DEVICE pclk_dev; extern DEVICE dpy_dev; extern DEVICE iii_dev; +extern DEVICE dd_dev; +extern DEVICE vds_dev; extern DEVICE imx_dev; extern DEVICE imp_dev; extern DEVICE ch10_dev; @@ -528,7 +530,6 @@ extern DEVICE tv_dev; extern DEVICE wcnsls_dev; /* MIT Spacewar Consoles */ extern DEVICE ocnsls_dev; /* Old MIT Spacewar Consoles */ extern DEVICE ai_dev; -extern DEVICE dn_dev; extern DEVICE dct_dev; /* PDP6 devices. */ extern DEVICE dtc_dev; extern DEVICE mtc_dev; @@ -540,6 +541,8 @@ extern DEVICE dup_dev; extern DEVICE tcu_dev; extern DEVICE ddc_dev; extern DEVICE tym_dev; +extern DEVICE ge_dev; +extern DEVICE gtyo_dev; #if KS @@ -729,6 +732,8 @@ extern void ka10_lights_set_aux (int); extern void ka10_lights_clear_aux (int); #endif +#define IBM_DEV 04000 + /* I/O system parameters */ #if !(PDP6 | KS) #define NUM_DEVS_LP 1 @@ -748,6 +753,7 @@ extern void ka10_lights_clear_aux (int); #define NUM_DEVS_DSK 1 #define NUM_DEVS_DCS 1 #define NUM_DEVS_SLAVE PDP6 +#define NUM_DEVS_GE PDP6 #endif #if !(PDP6 | KS) #define NUM_DEVS_DC 1 @@ -758,7 +764,6 @@ extern void ka10_lights_clear_aux (int); #define NUM_DEVS_TTY 1 #define NUM_LINES_TTY 64 #define NUM_DEVS_NIA 1 -#define NUM_DEVS_DN 0 #elif KS #define NUM_DEVS_LP20 1 #define NUM_DEVS_DZ 4 @@ -791,6 +796,7 @@ extern void ka10_lights_clear_aux (int); #define NUM_DEVS_DKB (WAITS * USE_DISPLAY) #define NUM_DEVS_III (WAITS * USE_DISPLAY) #define NUM_DEVS_TV (WAITS * USE_DISPLAY) +#define NUM_DEVS_DD (WAITS * USE_DISPLAY) #define NUM_DEVS_PD ITS #define NUM_DEVS_PCLK WAITS #define NUM_DEVS_IMX ITS @@ -851,7 +857,7 @@ extern uint32 dd_keyboard_line (void *); #endif #if PIDP10 -void pi_panel_start(); +t_stat pi_panel_start(); void pi_panel_stop(); #endif diff --git a/PDP10/kx10_dpy.c b/PDP10/kx10_dpy.c index 45cab60e9..df06a92fb 100644 --- a/PDP10/kx10_dpy.c +++ b/PDP10/kx10_dpy.c @@ -363,6 +363,7 @@ static void dpy_joy_button(int which, int button, int state) } } +#if ITS static int dpy_keyboard (SIM_KEY_EVENT *ev) { sim_debug(DEBUG_DATA, &dpy_dev, "Key %d %s\n", @@ -373,6 +374,7 @@ static int dpy_keyboard (SIM_KEY_EVENT *ev) } return 0; } +#endif /* Reset routine */ diff --git a/PDP10/kx10_dt.c b/PDP10/kx10_dt.c index 26941f30f..29874c4ce 100644 --- a/PDP10/kx10_dt.c +++ b/PDP10/kx10_dt.c @@ -545,7 +545,6 @@ t_stat dt_devio(uint32 dev, uint64 *data) { } void dt_getword(uint64 *data, int req) { - int dev = dt_dib.dev_num; clr_interrupt(DT_DEVNUM|4); if (dtsb & DTB_DATREQ) { dtsb |= DTB_MIS; @@ -559,7 +558,6 @@ void dt_getword(uint64 *data, int req) { } void dt_putword(uint64 *data) { - int dev = dt_dib.dev_num; clr_interrupt(DT_DEVNUM|4); if (dtsb & DTB_DATREQ) { dtsb |= DTB_MIS; diff --git a/PDP10/kx10_rp.c b/PDP10/kx10_rp.c index ceee8752c..60ebd5e2e 100644 --- a/PDP10/kx10_rp.c +++ b/PDP10/kx10_rp.c @@ -1094,18 +1094,17 @@ rp_boot(int32 unit_num, DEVICE * rptr) { UNIT *uptr = &rptr->units[unit_num]; int ctlr = GET_CNTRL_RH(uptr->flags); - int dtype = GET_DTYPE(uptr->flags); uint16 *regs = (uint16 *)(uptr->up7); struct rh_if *rhc = &rp_rh[ctlr]; DEVICE *dptr = uptr->dptr; uint32 addr; - uint32 ptr = 0; uint64 word; #if !KS int wc; #endif #if KS + int dtype = GET_DTYPE(uptr->flags); int da; t_stat r; uint64 len; @@ -1147,8 +1146,8 @@ rp_boot(int32 unit_num, DEVICE * rptr) regs[RPDC] = (int32)((rp_buf[0][04] >> 24) << DC_V_CY); len = (int)(((rp_buf[0][05] & 077) * 4) & RMASK); } -if (len == 0) - len = 4; + if (len == 0) + len = 4; /* Read len sectors into address 1000 */ addr = 01000; for (; len > 0; len--) { @@ -1176,6 +1175,8 @@ if (len == 0) rh_boot_unit = unit_num; #elif KL int sect; + uint32 ptr = 0; + /* KL does not support readin, so fake it by reading in sectors 4 to 7 */ /* Possible in future find boot loader in FE file system */ addr = (MEMSIZE - 512) & RMASK; @@ -1189,6 +1190,8 @@ if (len == 0) } word = (MEMSIZE - 512) & RMASK; #else + uint32 ptr = 0; + disk_read(uptr, &rp_buf[0][0], 0, RP_NUMWD); addr = rp_buf[0][ptr] & RMASK; wc = (rp_buf[0][ptr++] >> 18) & RMASK; diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index 4fc797925..607ef155e 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -177,6 +177,10 @@ DEVICE *sim_devices[] = { #if (NUM_DEVS_TV > 0) &tv_dev, #endif +#if (NUM_DEVS_DD > 0) + &dd_dev, + &vds_dev, +#endif #if NUM_DEVS_IMP > 0 &imp_dev, #endif @@ -233,8 +237,15 @@ DEVICE *sim_devices[] = { #if NUM_DEVS_DUP > 0 &dup_dev, #endif -#if NUM_DEVS_DN > 0 - &dn_dev, +#if NUM_DEVS_DDC > 0 + &ddc_dev, +#endif +#if NUM_DEVS_TYM > 0 + &tym_dev, +#endif +#if NUM_DEVS_GE > 0 + &ge_dev, + >yo_dev, #endif NULL }; @@ -720,6 +731,8 @@ t_stat load_exe (FILE *fileref, int ftype) } if ((sim_switches & SWMASK ('M')) == 0) { /* -m? */ ma = mpage << PAG_V_PN; /* mem addr */ + } else { + ma = mpage; } for (k = 0; k < PAG_SIZE; k++, ma++) { /* copy buf to mem */ if (ma > MEMSIZE) diff --git a/PDP10/kx10_tu.c b/PDP10/kx10_tu.c index a49e0bcfc..35167278b 100644 --- a/PDP10/kx10_tu.c +++ b/PDP10/kx10_tu.c @@ -416,7 +416,6 @@ tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) { int tu_read(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 *data) { - int ctlr = GET_CNTRL_RH(dptr->units[0].flags); uint16 *regs = &rhc->regs[0]; int unit = regs[TUTC] & 07; UNIT *uptr = &dptr->units[unit]; diff --git a/PDP10/kx10_tym.c b/PDP10/kx10_tym.c new file mode 100644 index 000000000..31f3830b1 --- /dev/null +++ b/PDP10/kx10_tym.c @@ -0,0 +1,684 @@ +/* kx10_tym.c: TYM, interface to Tymbase and Tymnet. + + Copyright (c) 2022, Lars Brinkhoff + + 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 + LARS BRINKHOFF 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" +#include "sim_tmxr.h" + +#ifndef NUM_DEVS_TYM +#define NUM_DEVS_TYM 0 +#endif + +#if NUM_DEVS_TYM > 0 + +#define TYM_NAME "TYM" +#define MAX_LINES 32 /* Maximum found in the wild. */ + +#define KEY 0633751506262LL /* Base key. */ +#define BASE 02000 /* Default base address. */ +#define SIZE 01000 /* Default size. */ + +#define LOCK 000 /* Key. */ +#define DUMP 002 /* Base dump loc * 16. */ +#define IRNG 003 /* Input ring loc * 16. */ +#define ISIZ 004 /* Input ring size * 16. */ +#define IHP 005 /* Host set input pointer. */ +#define IBP 006 /* Base set input pointer. */ +#define ORNG 007 /* Output ring loc * 16. */ +#define OSIZ 010 /* Output ring size * 16. */ +#define OHP 011 /* Host set output pointer. */ +#define OBP 012 /* Base set output pointer. */ +#define BCRSH 013 /* Base set crash indicator + reason. */ +#define HCRSH 014 /* Host set crash reason. */ + +#define TYMBAS_ANS 001 +#define TYMBAS_SHT 002 +#define TYMBAS_CRS 003 +#define TYMBAS_DIE 004 +#define TYMBAS_NSP 005 +#define TYMBAS_LOG 006 +#define TYMBAS_AUX 007 +#define TYMBAS_NOP 010 +#define TYMBAS_OUP 011 +#define TYMBAS_GOB 012 +#define TYMBAS_ZAP 013 +#define TYMBAS_EDC 014 +#define TYMBAS_LDC 015 +#define TYMBAS_GRN 016 +#define TYMBAS_RED 017 +#define TYMBAS_YEL 020 +#define TYMBAS_ORG 021 +#define TYMBAS_HNG 022 +#define TYMBAS_ETM 023 +#define TYMBAS_LTM 024 +#define TYMBAS_LOS 025 +#define TYMBAS_SUP 026 +#define TYMBAS_SUR 027 +#define TYMBAS_AXC 030 +#define TYMBAS_TSP 031 +#define TYMBAS_TSR 032 +#define TYMBAS_SAD 033 +#define TYMBAS_ECN 034 +#define TYMBAS_ECF 035 +#define TYMBAS_TCS 036 +#define TYMBAS_TCP 037 +#define TYMBAS_TCR 040 +#define TYMBAS_HSI 041 +#define TYMBAS_DATA 0200 + +static t_stat tym_reset(DEVICE *dptr); +static t_stat tym_attach(UNIT * uptr, CONST char * cptr); +static t_stat tym_detach(UNIT * uptr); +static t_stat tym_interface_srv(UNIT *); +static t_stat tym_alive_srv(UNIT *); +static t_stat tym_input_srv(UNIT *); +static t_stat tym_output_srv(UNIT *); +static const char *tym_description(DEVICE *dptr); + +static TMLN tym_ldsc[MAX_LINES] = { 0 }; +static TMXR tym_desc = { MAX_LINES, 0, 0, tym_ldsc }; + +static UNIT tym_unit[] = { + { UDATA(tym_input_srv, TT_MODE_8B|UNIT_IDLE|UNIT_ATTABLE, 0) }, + { UDATA(tym_output_srv, UNIT_IDLE, 0) }, + { UDATA(tym_interface_srv, UNIT_IDLE, 0) }, + { UDATA(tym_alive_srv, UNIT_IDLE, 0) } +}; + +static MTAB tym_mod[] = { + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 1, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &tym_desc, "Disconnect a specific line" }, + { UNIT_ATT, UNIT_ATT, "SUMMARY", NULL, + NULL, &tmxr_show_summ, (void *) &tym_desc, "Display a summary of line states" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 1, "CONNECTIONS", NULL, + NULL, &tmxr_show_cstat, (void *) &tym_desc, "Display current connections" }, + { MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "STATISTICS", NULL, + NULL, &tmxr_show_cstat, (void *) &tym_desc, "Display multiplexer statistics" }, + { 0 } +}; + +/* Simulator debug controls */ +static DEBTAB tym_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"}, + {"IRQ", DEBUG_IRQ, "Show IRQ requests"}, + {0, 0} +}; + +static int tym_host = 0; +static int tym_base = BASE; +static int tym_size = SIZE; +static uint64 tym_key = KEY; +static int output_port; +static int output_count; + +static REG tym_reg[] = { + { ORDATA(HOST, tym_host, 16) }, + { ORDATA(BASE, tym_base, 22) }, + { ORDATA(SIZE, tym_size, 18) }, + { ORDATA(KEY, tym_key, 36) }, + { ORDATA(PORTS, tym_desc.lines, 8) }, + { 0 } +}; + +DEVICE tym_dev = { + "TYM", tym_unit, tym_reg, tym_mod, + 4, 8, 0, 1, 8, 36, + NULL, NULL, &tym_reset, NULL, &tym_attach, &tym_detach, + NULL, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, tym_debug, + NULL, NULL, NULL, NULL, NULL, &tym_description +}; + +static t_stat tym_reset(DEVICE *dptr) +{ + if (tym_unit[0].flags & UNIT_ATT) { + sim_activate(&tym_unit[2], 1000); + sim_activate(&tym_unit[3], 1000); + } else { + sim_cancel(&tym_unit[0]); + sim_cancel(&tym_unit[1]); + sim_cancel(&tym_unit[2]); + sim_cancel(&tym_unit[3]); + } + return SCPE_OK; +} + +static void block(void) +{ + int i; + for (i = 0; i < MAX_LINES; i++) { + tym_ldsc[i].rcve = 0; + tym_ldsc[i].xmte = 0; + } +} + +static t_stat tym_attach(UNIT *uptr, CONST char *cptr) +{ + t_stat stat = tmxr_attach(&tym_desc, uptr, cptr); + block(); + tym_reset(&tym_dev); + return stat; +} + +static t_stat tym_detach(UNIT *uptr) +{ + t_stat stat = tmxr_detach(&tym_desc, uptr); + block(); + tym_reset(&tym_dev); + return stat; +} + +static uint64 word(int pointer, int base) +{ + t_addr address = (M[tym_base + base] >> 4) & RMASK; + address += M[tym_base + pointer] & RMASK; + return M[address]; +} + +static void next(int pointer, int size) +{ + uint64 modulo = M[tym_base + size] >> 4; + M[tym_base + pointer] = (M[tym_base + pointer] + 1) % modulo; +} + +static void tym_input(uint64 data) +{ + t_addr address = (M[tym_base + IRNG] >> 4) & RMASK; + address += M[tym_base + IBP] & RMASK; + M[address] = data; +} + +static uint64 room (int h, int t, int s) +{ + uint64 head = M[tym_base + h]; + uint64 tail = M[tym_base + t]; + uint64 size = M[tym_base + s] >> 4; + return size - (head - tail) % size; +} + +static void send_word(int type, int port, int data1, int data2) +{ + uint64 data; + sim_debug(DEBUG_DETAIL, &tym_dev, + "Input from base: %03o %03o %03o %03o\n", + type, port, data1, data2); + /* The input ring buffer must have at least one word free. */ + if (room (IBP, IHP, ISIZ) <= 1) + return; + data = (uint64)type << 28; + data |= (uint64)port << 20; + data |= (uint64)data1 << 12; + data |= (uint64)data2 << 4; + tym_input(data); + next(IBP, ISIZ); +} + +static void send_character(int port, int c) +{ + sim_debug(DEBUG_DATA, &tym_dev, "Base: send port %d %03o '%c'.\n", + port, c, c); + send_word(TYMBAS_DATA | 1, port, c, 0); +} + +static void send_string(int port, const char *string) +{ + int n = strlen(string); + int m; + + for (;;) { + if (n <= 0) + return; + else if (n == 1) { + send_character(port, string[0]); + return; + } + + m = n > 0177 ? 0177 : n; + n -= m; + send_word(TYMBAS_DATA | m, port, string[0], string[1]); + string += 2; + m -= 2; + while (m > 0) { + send_word(string[0], string[1], string[2], string[3]); + string += 4; + m -= 4; + } + } +} + +static void send_login(int port) +{ + sim_debug(DEBUG_CMD, &tym_dev, "Base: send login %d.\n", port); + send_word(TYMBAS_LOG, port, 0, 0); + /* This isn't right, but good enough for now. */ + send_string(port, ".....USER\r"); +} + +static void send_zap(int port) +{ + sim_debug(DEBUG_CMD, &tym_dev, "Base: send zap %d.\n", port); + send_word(TYMBAS_ZAP, port, 0, 0); +} + +static void send_orange (int port) +{ + sim_debug(DEBUG_CMD, &tym_dev, "Base: send orange ball %d.\n", port); + send_word(TYMBAS_ORG, port, 0, 0); +} + +static void recv_ans(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, "system is answering\n"); + sim_activate(&tym_unit[0], 1000); +} + +static void recv_sht(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, "system is up but shut\n"); +} + +static void recv_crs(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, "sender is crashed\n"); +} + +static void recv_die(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, "recipient should crash\n"); +} + +static void recv_nsp(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, "base taken over by new supervisor\n"); +} + +static void recv_log(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, "login\n"); + //next 4 data chrs are the info about terminal type, and port or + //origin, then name, etc. +} + +static void recv_aux(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, "supervisor response to establishing auxillary circuit\n"); +} + +static void recv_nop(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " backpressure on\n"); +} + +static void recv_oup(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " backpressure off\n"); +} + +static void recv_gob(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " character gobbler\n"); +} + +static void recv_zap(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, "Zap circuit, port %d\n", port); + tmxr_reset_ln (&tym_ldsc[port]); + tym_ldsc[port].rcve = 0; + tym_ldsc[port].xmte = 0; +} + +static void recv_edc(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " enter defered echo mode\n"); +} + +static void recv_ldc(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " leave deferred echo mode\n"); +} + +static void recv_grn(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " green ball\n"); +} + +static void recv_red(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " red ball\n"); +} + +static void recv_yel(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " yellow ball\n"); + send_orange (port); +} + +static void recv_org(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " orange ball\n"); +} + +static void recv_hng(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " hang character - not used\n"); +} + +static void recv_etm(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " enter 2741 transparent mode\n"); +} + +static void recv_ltm(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " leave 2741 transparent mode\n"); +} + +static void recv_los(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " lost ball\n"); + //data has been lost from buffers. the data filed may tell how + //many were lost +} + +static void recv_sup(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " supervisor request(aux circuits)\n"); +} + +static void recv_sur(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " supervisor response(aux circuits)\n"); +} + +static void recv_axc(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " supervisor string character\n"); +} + +static void recv_tsp(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " test pattern probe\n"); +} + +static void recv_tsr(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " test pattern response\n"); +} + +static void recv_sad(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " host sad\n"); +} + +static void recv_ecn(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " echo on\n"); +} + +static void recv_ecf(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " echo off\n"); +} + +static void recv_tcs(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " term characteristics\n"); + //first data byte indicates which characteristics second data byte + //indicates value to set to +} + +static void recv_tcp(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " term characteristcs probe\n"); + //data byte indicates which terminal characteristic were requested +} + +static void recv_tcr(int port, int subtype, int data) +{ + sim_debug(DEBUG_CMD, &tym_dev, " term characteristcs response\n"); + //data is just like tcs, comes in response to a probe; also is + //reflected by remote when terminal characteristics are sent +} + +static void recv_hsi(int port, int subtype, int data) +{ + tym_host = (subtype << 8) | data; + sim_debug(DEBUG_CMD, &tym_dev, "Host number %06o, %d ports\n", + tym_host, port); + /* Close ports above the host-annonuced maximum. */ + tym_desc.lines = port; + if (tym_desc.lines > MAX_LINES) + tym_desc.lines = MAX_LINES; + for (port = tym_desc.lines; port < MAX_LINES; port++) + tmxr_reset_ln (&tym_ldsc[port]); + sim_activate(&tym_unit[0], 1000); +} + +typedef void (*msgfn) (int, int, int); +static msgfn output[] = { + NULL, + recv_ans, + recv_sht, + recv_crs, + recv_die, + recv_nsp, + recv_log, + recv_aux, + recv_nop, + recv_oup, + recv_gob, + recv_zap, + recv_edc, + recv_ldc, + recv_grn, + recv_red, + recv_yel, + recv_org, + recv_hng, + recv_etm, + recv_ltm, + recv_los, + recv_sup, + recv_sur, + recv_axc, + recv_tsp, + recv_tsr, + recv_sad, + recv_ecn, + recv_ecf, + recv_tcs, + recv_tcp, + recv_tcr, + recv_hsi +}; + +static void output_data(int port, int n) +{ + uint64 data; + int i = 2, c; + + sim_debug(DEBUG_DATA, &tym_dev, + "Output from host: %d characters to port %d\n", n, port); + + data = word(OBP, ORNG) << 16; /* Discard header. */ + goto start; + + while (n > 0) { + data = word(OBP, ORNG); + start: + for (; i < 4 && n > 0; i++, n--) { + c = (data >> 28) & 0177; + data <<= 8; + sim_debug(DEBUG_DATA, &tym_dev, + "Host: send port %d %03o '%c'.\n", port, c, c); + tmxr_putc_ln(&tym_ldsc[port], c); + tmxr_poll_tx(&tym_desc); + } + i = 0; + next(OBP, OSIZ); + } +} + +static void tym_output(void) +{ + int type, port, subtype, data; + while (M[tym_base + OBP] != M[tym_base + OHP]) { + sim_debug(DEBUG_DETAIL, &tym_dev, "Output from host: %llu %012llo\n", + M[tym_base + OBP], word(OBP, ORNG)); + type = word(OBP, ORNG) >> 28; + port = (word(OBP, ORNG) >> 20) & 0377; + subtype = (word(OBP, ORNG) >> 12) & 0377; + data = (word(OBP, ORNG) >> 4) & 0377; + sim_debug(DEBUG_DETAIL, &tym_dev, + "Type %03o, port %03o, subtype %03o, data %03o\n", + type, port, subtype, data); + if (type >= 1 && type <= 41) { + output[type] (port, subtype, data); + next(OBP, OSIZ); + } else if (type & 0200) + output_data(port, type & 0177); + } +} + +static uint64 lock = ~0ULL; +static uint64 dump = ~0ULL; +static uint64 irng = ~0ULL; +static uint64 isiz = ~0ULL; +static uint64 ihp = ~0ULL; +static uint64 ibp = ~0ULL; +static uint64 orng = ~0ULL; +static uint64 osiz = ~0ULL; +static uint64 ohp = ~0ULL; +static uint64 obp = ~0ULL; +static uint64 bcrsh = ~0ULL; +static uint64 hcrsh = ~0ULL; + +static void check(const char *name, int offset, uint64 *value) +{ + uint64 x = M[tym_base + offset]; + if (x != *value) { + sim_debug(DEBUG_DETAIL, &tym_dev, "%s: %012llo\n", name, x); + *value = x; + } +} + +static t_stat tym_interface_srv(UNIT *uptr) +{ + check("Dump location", DUMP, &dump); + check("Input ring location", IRNG, &irng); + check("Input ring size", ISIZ, &isiz); + check("Host input pointer", IHP, &ihp); + check("Base input pointer", IBP, &ibp); + check("Output ring location", ORNG, &orng); + check("Output ring size", OSIZ, &osiz); + check("Host output pointer", OHP, &ohp); + check("Base output pointer", OBP, &obp); + check("Base crash reason", BCRSH, &bcrsh); + check("Host crash reason", HCRSH, &hcrsh); + + if (ohp != obp) + tym_output(); + + sim_activate_after(&tym_unit[2], 1000); + return SCPE_OK; +} + +static t_stat tym_alive_srv(UNIT *uptr) +{ + if (M[tym_base + LOCK] == tym_key) { + M[tym_base + LOCK] = 1; + } + + sim_activate_after(&tym_unit[3], 500000); + return SCPE_OK; +} + +static t_stat tym_input_srv(UNIT *uptr) +{ + int32 ch; + int i; + + if (room (IBP, IHP, ISIZ) > 1) { + i = tmxr_poll_conn(&tym_desc); + if (i >= 0) { + tym_ldsc[i].rcve = 1; + tym_ldsc[i].xmte = 1; + send_login(i); + } + } + + tmxr_poll_rx(&tym_desc); + + for (i = 0; i < tym_desc.lines; i++) { + if (tym_ldsc[i].xmte && tym_ldsc[i].conn == 0) { + tmxr_reset_ln (&tym_ldsc[i]); + tym_ldsc[i].rcve = 0; + tym_ldsc[i].xmte = 0; + send_zap(i); + continue; + } + + /* The input ring buffer must have at least one word free. */ + if (room (IBP, IHP, ISIZ) <= 1) + continue; + + ch = tmxr_getc_ln(&tym_ldsc[i]); + if (ch & TMXR_VALID) + send_character(i, ch & 0377); + } + + sim_activate(&tym_unit[0], 1000); + return SCPE_OK; +} + +static t_stat tym_output_srv(UNIT *uptr) +{ + uint64 data; + int c; + + if (!tmxr_txdone_ln(&tym_ldsc[output_port])) { + sim_activate(&tym_unit[1], 1000); + return SCPE_OK; + } + + data = word(OBP, ORNG); + + c = (data >> 28) & 0177; + data <<= 8; + sim_debug(DEBUG_DATA, &tym_dev, + "Host: send port %d %03o '%c'.\n", output_port, c, c); + if (tmxr_putc_ln(&tym_ldsc[output_port], c) == SCPE_STALL) + return SCPE_OK; + + next(OBP, OSIZ); + if (output_count > 0) + sim_activate(&tym_unit[1], 1000); + return SCPE_OK; +} + +static const char *tym_description(DEVICE *dptr) +{ + return "Tymnet interface"; +} +#endif diff --git a/PDP10/pdp11_ddcmp.h b/PDP10/pdp11_ddcmp.h new file mode 100644 index 000000000..86b65614a --- /dev/null +++ b/PDP10/pdp11_ddcmp.h @@ -0,0 +1,493 @@ +/* pdp11_ddcmp.h: Digital Data Communications Message Protocol support + + Copyright (c) 2013, Mark Pizzolato + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + Digital Data Communications Message Protocol - DDCMP support routines + + 29-May-13 MP Initial implementation +*/ + +#ifndef PDP11_DDCMP_H_ +#define PDP11_DDCMP_H_ 0 + +#include "sim_tmxr.h" + +/* DDCMP packet types */ + +#define DDCMP_SYN 0226u /* Sync character on synchronous links */ +#define DDCMP_DEL 0377u /* Sync character on asynchronous links */ +#define DDCMP_SOH 0201u /* Numbered Data Message Identifier */ +#define DDCMP_ENQ 0005u /* Control Message Identifier */ +#define DDCMP_DLE 0220u /* Maintenance Message Identifier */ + +#define DDCMP_CTL_ACK 1 /* Control Message ACK Type */ +#define DDCMP_CTL_NAK 2 /* Control Message NAK Type */ +#define DDCMP_CTL_REP 3 /* Control Message REP Type */ +#define DDCMP_CTL_STRT 6 /* Control Message STRT Type */ +#define DDCMP_CTL_STACK 7 /* Control Message STACK Type */ + +#define DDCMP_FLAG_SELECT 0x2 /* Link Select */ +#define DDCMP_FLAG_QSYNC 0x1 /* Quick Sync (next message won't abut this message) */ + +#define DDCMP_CRC_SIZE 2 /* Bytes in DDCMP CRC fields */ +#define DDCMP_HEADER_SIZE 8 /* Bytes in DDCMP Control and Data Message headers (including header CRC) */ + +#define DDCMP_RESP_OFFSET 3 /* Byte offset of response (ack) number field */ +#define DDCMP_NUM_OFFSET 4 /* Byte offset of packet number field */ + +#define DDCMP_PACKET_TIMEOUT 4 /* Seconds before sending REP command for unacknowledged packets */ + +#define DDCMP_DBG_PXMT TMXR_DBG_PXMT /* Debug Transmitted Packet Header Contents */ +#define DDCMP_DBG_PRCV TMXR_DBG_PRCV /* Debug Received Packet Header Contents */ +#define DDCMP_DBG_PDAT 0x00004000 /* Debug Packet Data */ + +/* Support routines */ + +/* crc16 polynomial x^16 + x^15 + x^2 + 1 (0xA001) CCITT LSB */ +static uint16 crc16_nibble[16] = { + 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, + 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400, + }; + +static uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len) +{ +const unsigned char* buf = (const unsigned char*)vbuf; + +while(0 != len--) { + crc = (crc>>4) ^ crc16_nibble[(*buf ^ crc) & 0xF]; + crc = (crc>>4) ^ crc16_nibble[((*buf++)>>4 ^ crc) & 0xF]; + }; +return(crc); +} + +/* Debug routines */ + +#include + +static void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len) +{ +if (sim_deb && dptr && (reason & dptr->dctrl)) { + int i, same, group, sidx, oidx; + char outbuf[80], strbuf[18]; + static const char hex[] = "0123456789ABCDEF"; + static const char *const flags [4] = { "..", ".Q", "S.", "SQ" }; + static const char *const nak[18] = { "", " (HCRC)", " (DCRC)", " (REPREPLY)", /* 0-3 */ + "", "", "", "", /* 4-7 */ + " (NOBUF)", " (RXOVR)", "", "", /* 8-11 */ + "", "", "", "", /* 12-15 */ + " (TOOLONG)", " (HDRFMT)" }; /* 16-17 */ + const char *flag = flags[msg[2]>>6]; + int msg2 = msg[2] & 0x3F; + + sim_debug(reason, dptr, "%s len: %d\n", txt, len); + switch (msg[0]) { + case DDCMP_SOH: /* Data Message */ + sim_debug (reason, dptr, "Data Message, Count: %d, Num: %d, Flags: %s, Resp: %d, HDRCRC: %s, DATACRC: %s\n", (msg2 << 8)|msg[1], msg[4], flag, msg[3], + (0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+((msg2 << 8)|msg[1]))) ? "OK" : "BAD"); + break; + case DDCMP_ENQ: /* Control Message */ + sim_debug (reason, dptr, "Control: Type: %d ", msg[1]); + switch (msg[1]) { + case DDCMP_CTL_ACK: /* ACK */ + sim_debug (reason, dptr, "(ACK) ACKSUB: %d, Flags: %s, Resp: %d\n", msg2, flag, msg[3]); + break; + case DDCMP_CTL_NAK: /* NAK */ + sim_debug (reason, dptr, "(NAK) Reason: %d%s, Flags: %s, Resp: %d\n", msg2, ((msg2 > 17)? "": nak[msg2]), flag, msg[3]); + break; + case DDCMP_CTL_REP: /* REP */ + sim_debug (reason, dptr, "(REP) REPSUB: %d, Num: %d, Flags: %s\n", msg2, msg[4], flag); + break; + case DDCMP_CTL_STRT: /* STRT */ + sim_debug (reason, dptr, "(STRT) STRTSUB: %d, Flags: %s\n", msg2, flag); + break; + case DDCMP_CTL_STACK: /* STACK */ + sim_debug (reason, dptr, "(STACK) STCKSUB: %d, Flags: %s\n", msg2, flag); + break; + default: /* Unknown */ + sim_debug (reason, dptr, "(Unknown=0%o)\n", msg[1]); + break; + } + if (len != DDCMP_HEADER_SIZE) { + sim_debug (reason, dptr, "Unexpected Control Message Length: %d expected %d\n", len, DDCMP_HEADER_SIZE); + } + if (0 != ddcmp_crc16 (0, msg, len)) { + sim_debug (reason, dptr, "Unexpected Message CRC\n"); + } + break; + case DDCMP_DLE: /* Maintenance Message */ + sim_debug (reason, dptr, "Maintenance Message, Count: %d, Flags: %s, Addr: %d, HDRCRC: %s, DATACRC: %s\n", (msg2 << 8)|msg[1], flag, msg[5], + (0 == ddcmp_crc16 (0, msg, DDCMP_HEADER_SIZE)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+DDCMP_HEADER_SIZE, 2+((msg2 << 8)|msg[1]))) ? "OK" : "BAD"); + break; + } + if (DDCMP_DBG_PDAT & dptr->dctrl) { + for (i=same=0; i 0) && (0 == memcmp(&msg[i], &msg[i-16], 16))) { + ++same; + continue; + } + if (same > 0) { + sim_debug(reason, dptr, "%04X thru %04X same as above\n", i-(16*same), i-1); + same = 0; + } + group = (((len - i) > 16) ? 16 : (len - i)); + for (sidx=oidx=0; sidx>4)&0xf]; + outbuf[oidx++] = hex[msg[i+sidx]&0xf]; + if (isprint(msg[i+sidx])) + strbuf[sidx] = msg[i+sidx]; + else + strbuf[sidx] = '.'; + } + outbuf[oidx] = '\0'; + strbuf[sidx] = '\0'; + sim_debug(reason, dptr, "%04X%-48s %s\n", i, outbuf, strbuf); + } + if (same > 0) { + sim_debug(reason, dptr, "%04X thru %04X same as above\n", i-(16*same), len-1); + } + } + } +} + +uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len); + +/* Data corruption troll, which simulates imperfect links. + */ + +/* Evaluate the corruption troll's appetite. + * + * A message can be eaten (dropped), nibbled (corrupted) or spared. + * + * The probability of a message not being spared is trollHungerLevel, + * expressed in milli-gulps - 0.1%. The troll selects which action + * to taken on selected messages with equal probability. + * + * Nibbled messages' CRCs are changed when possible to simplify + * identifying them when debugging. When it's too much work to + * find the CRC, the first byte of data is changed. The change + * is an XOR to make it possible to reconstruct the original data. + * + * A particularly unfortunate message can be nibbled by both + * the transmitter and receiver; thus the troll applies a direction- + * dependent pattern. + * + * Return TRUE if the troll ate the message. + * Return FALSE if the message was nibbled or spared. + */ +static t_bool ddcmp_feedCorruptionTroll (TMLN *lp, uint8 *msg, t_bool rx, int32 trollHungerLevel) +{ +double r, rmax; +char msgbuf[80]; + +if (trollHungerLevel == 0) + return FALSE; +r = rand(); +rmax = (double)RAND_MAX; +if (msg[0] == DDCMP_ENQ) { + int eat = 0 + (int) (2000.0 * (r / (rmax + 1.0))); + + if (eat <= (trollHungerLevel * 2)) { /* Hungry? */ + if (eat <= trollHungerLevel) { /* Eat the packet */ + sprintf (msgbuf, "troll ate a %s control message\n", rx ? "RCV" : "XMT"); + tmxr_debug_msg (rx ? DDCMP_DBG_PRCV : DDCMP_DBG_PXMT, lp, msgbuf); + return TRUE; + } + sprintf (msgbuf, "troll bit a %s control message\n", rx ? "RCV" : "XMT"); + tmxr_debug_msg (rx ? DDCMP_DBG_PRCV : DDCMP_DBG_PXMT, lp, msgbuf); + msg[6] ^= rx? 0114: 0154; /* Eat the CRC */ + } + } +else { + int eat = 0 + (int) (3000.0 * (r / (rmax + 1.0))); + + if (eat <= (trollHungerLevel * 3)) { /* Hungry? */ + if (eat <= trollHungerLevel) { /* Eat the packet */ + sprintf (msgbuf, "troll ate a %s %s message\n", rx ? "RCV" : "XMT", (msg[0] == DDCMP_SOH)? "data" : "maintenance"); + tmxr_debug_msg (rx ? DDCMP_DBG_PRCV : DDCMP_DBG_PXMT, lp, msgbuf); + return TRUE; + } + if (eat <= (trollHungerLevel * 2)) { /* HCRC */ + sprintf (msgbuf, "troll bit a %s %s message\n", rx ? "RCV" : "XMT", (msg[0] == DDCMP_SOH)? "data" : "maintenance"); + tmxr_debug_msg (rx ? DDCMP_DBG_PRCV : DDCMP_DBG_PXMT, lp, msgbuf); + msg[6] ^= rx? 0124: 0164; + } + else { /* DCRC */ + sprintf (msgbuf, "troll bit %s %s DCRC\n", (rx? "RCV" : "XMT"), ((msg[0] == DDCMP_SOH)? "data" : "maintenance")); + tmxr_debug_msg (rx ? DDCMP_DBG_PRCV : DDCMP_DBG_PXMT, lp, msgbuf); + msg[8] ^= rx? 0114: 0154; /* Rather than find the CRC, the first data byte will do */ + } + } + } +return FALSE; +} + +/* Get packet from specific line + + Inputs: + *lp = pointer to terminal line descriptor + **pbuf = pointer to pointer of packet contents + *psize = pointer to packet size + + Output: + SCPE_LOST link state lost + SCPE_OK Packet returned OR no packet available + + Implementation notes: + + 1. If a packet is not yet available, then the pbuf address returned is + NULL, but success (SCPE_OK) is returned +*/ + +static t_stat ddcmp_tmxr_get_packet_ln (TMLN *lp, const uint8 **pbuf, uint16 *psize, int32 corruptrate) +{ +int32 c; +size_t payloadsize; +char msg[32]; + +while (TMXR_VALID & (c = tmxr_getc_ln (lp))) { + c &= ~TMXR_VALID; + if (lp->rxpboffset + 1 > lp->rxpbsize) { + lp->rxpbsize += 512; + lp->rxpb = (uint8 *)realloc (lp->rxpb, lp->rxpbsize); + } + lp->rxpb[lp->rxpboffset] = (uint8)c; + if ((lp->rxpboffset == 0) && ((c == DDCMP_SYN) || (c == DDCMP_DEL))) { + tmxr_debug (DDCMP_DBG_PRCV, lp, "Ignoring Interframe Sync Character", (char *)&lp->rxpb[0], 1); + continue; + } + lp->rxpboffset += 1; + if (lp->rxpboffset == 1) { + switch (c) { + default: + tmxr_debug (DDCMP_DBG_PRCV, lp, "Ignoring unexpected byte in DDCMP mode", (char *)&lp->rxpb[0], 1); + lp->rxpboffset = 0; + case DDCMP_SOH: + case DDCMP_ENQ: + case DDCMP_DLE: + continue; + } + } + if (lp->rxpboffset >= DDCMP_HEADER_SIZE) { + if (lp->rxpb[0] == DDCMP_ENQ) { /* Control Message? */ + ++lp->rxpcnt; + *pbuf = lp->rxpb; + *psize = DDCMP_HEADER_SIZE; + lp->rxpboffset = 0; + if (lp->mp->lines > 1) + sprintf (msg, "Line%d: <<< RCV Packet", (int)(lp-lp->mp->ldsc)); + else + strcpy (msg, "<<< RCV Packet"); + ddcmp_packet_trace (DDCMP_DBG_PRCV, lp->mp->dptr, msg, lp->rxpb, *psize); + if (ddcmp_feedCorruptionTroll (lp, lp->rxpb, TRUE, corruptrate)) + break; + return SCPE_OK; + } + payloadsize = ((lp->rxpb[2] & 0x3F) << 8)| lp->rxpb[1]; + if (lp->rxpboffset >= 10 + payloadsize) { + ++lp->rxpcnt; + *pbuf = lp->rxpb; + *psize = (uint16)(10 + payloadsize); + if (lp->mp->lines > 1) + sprintf (msg, "Line%d: <<< RCV Packet", (int)(lp-lp->mp->ldsc)); + else + strcpy (msg, "<<< RCV Packet"); + ddcmp_packet_trace (DDCMP_DBG_PRCV, lp->mp->dptr, msg, lp->rxpb, *psize); + lp->rxpboffset = 0; + if (ddcmp_feedCorruptionTroll (lp, lp->rxpb, TRUE, corruptrate)) + break; + return SCPE_OK; + } + } + } +*pbuf = NULL; +*psize = 0; +if (lp->conn) + return SCPE_OK; +return SCPE_LOST; +} + +/* Store packet in line buffer (or store packet in line buffer and add needed CRCs) + + Inputs: + *lp = pointer to line descriptor + *buf = pointer to packet data + size = size of packet + + Outputs: + status = ok, connection lost, or stall + + Implementation notea: + + 1. If the line is not connected, SCPE_LOST is returned. + 2. If prior packet transmission still in progress, SCPE_STALL is + returned and no packet data is stored. The caller must retry later. +*/ +static t_stat ddcmp_tmxr_put_packet_ln (TMLN *lp, const uint8 *buf, size_t size, int32 corruptrate) +{ +t_stat r; +char msg[32]; + +if (!lp->conn) + return SCPE_LOST; +if (lp->txppoffset < lp->txppsize) { + tmxr_debug (DDCMP_DBG_PXMT, lp, "Skipped Sending Packet - Transmit Busy", (char *)&lp->txpb[3], size); + return SCPE_STALL; + } +if (lp->txpbsize < size) { + lp->txpbsize = size; + lp->txpb = (uint8 *)realloc (lp->txpb, lp->txpbsize); + } +memcpy (lp->txpb, buf, size); +lp->txppsize = size; +lp->txppoffset = 0; +if (lp->mp->lines > 1) + sprintf (msg, "Line%d: >>> XMT Packet", (int)(lp-lp->mp->ldsc)); +else + strcpy (msg, ">>> XMT Packet"); +ddcmp_packet_trace (DDCMP_DBG_PXMT, lp->mp->dptr, msg, lp->txpb, lp->txppsize); +if (!ddcmp_feedCorruptionTroll (lp, lp->txpb, FALSE, corruptrate)) { + ++lp->txpcnt; + while ((lp->txppoffset < lp->txppsize) && + (SCPE_OK == (r = tmxr_putc_ln (lp, lp->txpb[lp->txppoffset])))) + ++lp->txppoffset; + tmxr_send_buffered_data (lp); + } +else {/* Packet eaten, so discard it */ + lp->txppoffset = lp->txppsize; /* Act like all data was sent */ + } +return lp->conn ? SCPE_OK : SCPE_LOST; +} + +static t_stat ddcmp_tmxr_put_packet_crc_ln (TMLN *lp, uint8 *buf, size_t size, int32 corruptrate) +{ +uint16 hdr_crc16 = ddcmp_crc16(0, buf, DDCMP_HEADER_SIZE-DDCMP_CRC_SIZE); + +buf[DDCMP_HEADER_SIZE-DDCMP_CRC_SIZE] = hdr_crc16 & 0xFF; +buf[DDCMP_HEADER_SIZE-DDCMP_CRC_SIZE+1] = (hdr_crc16>>8) & 0xFF; +if (size > DDCMP_HEADER_SIZE) { + uint16 data_crc16 = ddcmp_crc16(0, buf+DDCMP_HEADER_SIZE, size-(DDCMP_HEADER_SIZE+DDCMP_CRC_SIZE)); + buf[size-DDCMP_CRC_SIZE] = data_crc16 & 0xFF; + buf[size-DDCMP_CRC_SIZE+1] = (data_crc16>>8) & 0xFF; + } +return ddcmp_tmxr_put_packet_ln (lp, buf, size, corruptrate); +} + +static void ddcmp_build_data_packet (uint8 *buf, size_t size, uint8 flags, uint8 sequence, uint8 ack) +{ +buf[0] = DDCMP_SOH; +buf[1] = size & 0xFF; +buf[2] = ((size >> 8) & 0x3F) | (flags << 6); +buf[3] = ack; +buf[4] = sequence; +buf[5] = 1; +} + +static void ddcmp_build_maintenance_packet (uint8 *buf, size_t size) +{ +buf[0] = DDCMP_DLE; +buf[1] = size & 0xFF; +buf[2] = ((size >> 8) & 0x3F) | ((DDCMP_FLAG_SELECT|DDCMP_FLAG_QSYNC) << 6); +buf[3] = 0; +buf[4] = 0; +buf[5] = 1; +} + +static t_stat ddcmp_tmxr_put_data_packet_ln (TMLN *lp, uint8 *buf, size_t size, uint8 flags, uint8 sequence, uint8 ack) +{ +ddcmp_build_data_packet (buf, size, flags, sequence, ack); +return ddcmp_tmxr_put_packet_crc_ln (lp, buf, size, 0); +} + +static void ddcmp_build_control_packet (uint8 *buf, uint8 type, uint8 subtype, uint8 flags, uint8 sndr, uint8 rcvr) +{ +buf[0] = DDCMP_ENQ; /* Control Message */ +buf[1] = type; /* STACK type */ +buf[2] = (subtype & 0x3f) | (flags << 6); + /* STACKSUB type and flags */ +buf[3] = rcvr; /* RCVR */ +buf[4] = sndr; /* SNDR */ +buf[5] = 1; /* ADDR */ +} + +static t_stat ddcmp_tmxr_put_control_packet_ln (TMLN *lp, uint8 *buf, uint8 type, uint8 subtype, uint8 flags, uint8 sndr, uint8 rcvr) +{ +ddcmp_build_control_packet (buf, type, subtype, flags, sndr, rcvr); +return ddcmp_tmxr_put_packet_crc_ln (lp, buf, DDCMP_HEADER_SIZE, 0); +} + +static void ddcmp_build_ack_packet (uint8 *buf, uint8 ack, uint8 flags) +{ +ddcmp_build_control_packet (buf, DDCMP_CTL_ACK, 0, flags, 0, ack); +} + +static t_stat ddcmp_tmxr_put_ack_packet_ln (TMLN *lp, uint8 *buf, uint8 ack, uint8 flags) +{ +ddcmp_build_ack_packet (buf, ack, flags); +return ddcmp_tmxr_put_packet_crc_ln (lp, buf, DDCMP_HEADER_SIZE, 0); +} + +static void ddcmp_build_nak_packet (uint8 *buf, uint8 reason, uint8 nack, uint8 flags) +{ +ddcmp_build_control_packet (buf, DDCMP_CTL_NAK, reason, flags, 0, nack); +} + +static t_stat ddcmp_tmxr_put_nak_packet_ln (TMLN *lp, uint8 *buf, uint8 reason, uint8 nack, uint8 flags) +{ +return ddcmp_tmxr_put_control_packet_ln (lp, buf, DDCMP_CTL_NAK, reason, flags, 0, nack); +} + +static void ddcmp_build_rep_packet (uint8 *buf, uint8 ack, uint8 flags) +{ +ddcmp_build_control_packet (buf, DDCMP_CTL_REP, 0, flags, ack, 0); +} + +static t_stat ddcmp_tmxr_put_rep_packet_ln (TMLN *lp, uint8 *buf, uint8 ack, uint8 flags) +{ +return ddcmp_tmxr_put_control_packet_ln (lp, buf, DDCMP_CTL_REP, 0, flags, ack, 0); +} + +static void ddcmp_build_start_packet (uint8 *buf) +{ +ddcmp_build_control_packet (buf, DDCMP_CTL_STRT, 0, DDCMP_FLAG_SELECT|DDCMP_FLAG_QSYNC, 0, 0); +} + +static t_stat ddcmp_tmxr_put_start_packet_ln (TMLN *lp, uint8 *buf) +{ +ddcmp_build_start_packet (buf); +return ddcmp_tmxr_put_packet_crc_ln (lp, buf, DDCMP_HEADER_SIZE, 0); +} + +static void ddcmp_build_start_ack_packet (uint8 *buf) +{ +ddcmp_build_control_packet (buf, DDCMP_CTL_STACK, 0, DDCMP_FLAG_SELECT|DDCMP_FLAG_QSYNC, 0, 0); +} + +static t_stat ddcmp_tmxr_put_start_ack_packet_ln (TMLN *lp, uint8 *buf) +{ +ddcmp_build_start_ack_packet (buf); +return ddcmp_tmxr_put_packet_crc_ln (lp, buf, DDCMP_HEADER_SIZE, 0); +} + +#endif /* PDP11_DDCMP_H_ */ diff --git a/PDP10/pdp6_dsk.c b/PDP10/pdp6_dsk.c index b4fa8b87a..58160fe4a 100644 --- a/PDP10/pdp6_dsk.c +++ b/PDP10/pdp6_dsk.c @@ -263,7 +263,6 @@ dsk_svc (UNIT *uptr) int wc; uint64 data; DEVICE *dptr; - t_stat err; dptr = &dsk_dev; @@ -279,7 +278,7 @@ dsk_svc (UNIT *uptr) if (sec > DSK_SECS) sec -= DSK_SECS; da = (sec + (cyl * DSK_SECS)) * DSK_WDS; - err = sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); + (void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); (void)sim_fwrite (&dsk_buf[0], sizeof(uint64), DSK_WDS, uptr->fileref); sim_debug(DEBUG_DETAIL, dptr, "DSK %d Write %d %d\n", ctlr, da, cyl); @@ -337,7 +336,7 @@ dsk_svc (UNIT *uptr) if (sec > DSK_SECS) sec -= DSK_SECS; da = (sec + (cyl * DSK_SECS)) * DSK_WDS; - err = sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); + (void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); wc = sim_fread (&dsk_buf[0], sizeof(uint64), DSK_WDS, uptr->fileref); sim_debug(DEBUG_DETAIL, dptr, "DSK %d Read %d %d\n", ctlr, da, cyl); diff --git a/PDP10/pdp6_dtc.c b/PDP10/pdp6_dtc.c index 93c1bb449..0f6f7dc3d 100644 --- a/PDP10/pdp6_dtc.c +++ b/PDP10/pdp6_dtc.c @@ -1281,8 +1281,6 @@ dtc_flush (UNIT* uptr) t_stat dtc_detach (UNIT* uptr) { - int32 u = uptr - dtc_dev.units; - if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; if (sim_is_active (uptr)) { diff --git a/PDP10/pdp6_ge.c b/PDP10/pdp6_ge.c new file mode 100644 index 000000000..21aac5078 --- /dev/null +++ b/PDP10/pdp6_ge.c @@ -0,0 +1,424 @@ +/* pdp6_ge.c: GE DATANET-760 with four consoles. + + Copyright (c) 2023, Lars Brinkhoff + + 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 LARS BRINKHOFF 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 implements the MIT AI lab interface to a GE DATANET-760 with + four consoles. It consists of two somewhat independent IO bus + devices: 070 GTYI for keyboard input, and 750 GTYO for display + output. This file presents the two as a single GE device to SIMH + users. +*/ + +#include "kx10_defs.h" +#include "sim_tmxr.h" + +#ifndef NUM_DEVS_GE +#define NUM_DEVS_GE 0 +#endif + +#if NUM_DEVS_GE > 0 + +#define GTYI_DEVNUM 0070 /* GE console input. */ +#define GTYO_DEVNUM 0750 /* GE console output. */ + +#define GE_CONSOLES 4 + +#define GTYI_PIA 00007 /* PI assignment. */ +#define GTYI_DONE 00010 /* Input data ready. */ +#define GTYI_STATUS (GTYI_PIA | GTYI_DONE) + +#define GTYO_PIA 00007 /* PI assignment. */ +#define GTYO_DONE 00100 /* Output data ready. */ +#define GTYO_FROB 00200 /* Set done? */ +#define GTYO_STATUS (GTYO_PIA | GTYO_DONE) + +#define STATUS u3 +#define DATA u4 +#define PORT u5 +#define LP u6 + +#define GE_SOH 001 /* Start of header/message. */ +#define GE_STX 002 /* Start of text. */ +#define GE_ETX 003 /* End of text. */ + + +static t_stat gtyi_svc(UNIT *uptr); +static t_stat gtyo_svc(UNIT *uptr); +static t_stat gtyi_devio(uint32 dev, uint64 *data); +static t_stat gtyo_devio(uint32 dev, uint64 *data); +static t_stat ge_reset(DEVICE *dptr); +static t_stat ge_attach(UNIT *uptr, CONST char *ptr); +static t_stat ge_detach(UNIT *uptr); +static t_stat ge_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); +static const char *ge_description(DEVICE *dptr); + +static void gtyo_done(void); +static void gtyo_soh(char data); +static void gtyo_adr(char data); +static void gtyo_status(char data); +static void gtyo_stx(char data); +static void gtyo_text(char data); +static void gtyo_lp(char data); +static void (*gtyo_process)(char data) = gtyo_soh; + +DIB gtyi_dib = { GTYI_DEVNUM, 1, >yi_devio, NULL }; +DIB gtyo_dib = { GTYO_DEVNUM, 1, >yo_devio, NULL }; + +UNIT ge_unit[2] = { + { UDATA(>yi_svc, UNIT_IDLE|UNIT_ATTABLE, 0), 1000 }, + { UDATA(>yo_svc, UNIT_IDLE|UNIT_ATTABLE, 0), 1000 }, +}; +#define gtyi_unit (&ge_unit[0]) +#define gtyo_unit (&ge_unit[1]) + +static REG ge_reg[] = { + { NULL } +}; + +static MTAB ge_mod[] = { + { 0 } +}; + +#define DEBUG_TRC 0x0000400 + +static DEBTAB ge_debug[] = { + {"TRACE", DEBUG_TRC, "Routine trace"}, + {"CMD", DEBUG_CMD, "Command Processing"}, + {"CONO", DEBUG_CONO, "CONO instructions"}, + {"CONI", DEBUG_CONI, "CONI instructions"}, + {"DATAIO", DEBUG_DATAIO, "DATAI/O instructions"}, + {"IRQ", DEBUG_IRQ, "Debug IRQ requests"}, + {0}, +}; + +DEVICE ge_dev = { + "GE", ge_unit, ge_reg, ge_mod, + 2, 8, 18, 1, 8, 36, + NULL, NULL, &ge_reset, + NULL, &ge_attach, &ge_detach, + >yi_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_MUX, + 0, ge_debug, + NULL, NULL, NULL, + &ge_attach_help, NULL, &ge_description +}; + +DEVICE gtyo_dev = { + "GTYO", NULL, NULL, NULL, + 0, 8, 18, 1, 8, 36, + NULL, NULL, NULL, + NULL, NULL, NULL, + >yo_dib, DEV_DIS | DEV_MUX, + 0, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL +}; + +static TMLN ge_ldsc[GE_CONSOLES]; +static TMXR ge_desc = { GE_CONSOLES, 0, 0, ge_ldsc }; + +static t_stat ge_reset(DEVICE *dptr) +{ + sim_debug(DEBUG_TRC, dptr, "ge_reset()\n"); + + if (ge_dev.flags & DEV_DIS) + gtyo_dev.flags |= DEV_DIS; + else + gtyo_dev.flags &= ~DEV_DIS; + + if (gtyi_unit->flags & UNIT_ATT) { + sim_activate(gtyi_unit, 10); + } else { + sim_cancel(gtyi_unit); + sim_cancel(gtyo_unit); + } + + return SCPE_OK; +} + +static t_stat ge_attach(UNIT *uptr, CONST char *cptr) +{ + t_stat r; + + if (!cptr || !*cptr) + return SCPE_ARG; + ge_desc.buffered = 1000; + r = tmxr_attach(&ge_desc, uptr, cptr); + if (r != SCPE_OK) + return r; + sim_debug(DEBUG_TRC, &ge_dev, "activate connection\n"); + gtyi_unit->STATUS = 0; + gtyo_unit->STATUS = 0; + gtyo_process = gtyo_soh; + sim_activate(gtyi_unit, 10); + + return SCPE_OK; +} + +static t_stat ge_detach(UNIT *uptr) +{ + t_stat r; + + if (!(uptr->flags & UNIT_ATT)) + return SCPE_OK; + sim_cancel(gtyi_unit); + sim_cancel(gtyo_unit); + r = tmxr_detach(&ge_desc, uptr); + uptr->filename = NULL; + return r; +} + +static void gtyi_poll(UNIT *uptr) +{ + int32 ch; + int i; + + tmxr_poll_rx(&ge_desc); + for (i = 0; i < GE_CONSOLES; i++) { + if (!ge_ldsc[i].rcve) + continue; + + if (!ge_ldsc[i].conn) { + ge_ldsc[i].rcve = 0; + tmxr_reset_ln(&ge_ldsc[i]); + sim_debug(DEBUG_CMD, &ge_dev, "Port %d connection lost\n", i); + continue; + } + + ch = tmxr_getc_ln(&ge_ldsc[i]); + if (ch & TMXR_VALID) { + ch &= 0177; + sim_debug(DEBUG_CMD, &ge_dev, "Port %d got %03o\n", i, ch); + if (ch >= 0141 && ch <= 0172) + ch -= 0100; + else if (ch == 0140 || (ch >= 0173 && ch <= 0174)) { + sim_debug(DEBUG_CMD, &ge_dev, "Discard invalid character\n"); + continue; + } + + uptr->DATA = ch; + uptr->PORT = i; + uptr->STATUS |= GTYI_DONE; + if (uptr->STATUS & 7) + sim_debug(DEBUG_CMD, &ge_dev, "GTYI interrupt on channel %d\n", uptr->STATUS & 7); + set_interrupt(GTYI_DEVNUM, uptr->STATUS); + ge_ldsc[i].rcve = 0; + break; + } + } +} + +static t_stat gtyi_svc(UNIT *uptr) +{ + int32 n; + + n = tmxr_poll_conn(&ge_desc); + if (n >= 0) { + sim_debug(DEBUG_CMD, &ge_dev, "got connection\n"); + ge_ldsc[n].rcve = 1; + } + + if ((uptr->STATUS & GTYI_DONE) == 0) + gtyi_poll(uptr); + + sim_activate_after(uptr, 10000); + return SCPE_OK; +} + +static t_stat gtyo_svc(UNIT *uptr) +{ + switch (tmxr_putc_ln(&ge_ldsc[uptr->PORT], uptr->DATA)) { + case SCPE_OK: + sim_debug(DEBUG_CMD, &ge_dev, "Sent %03o to console %d\n", + uptr->DATA, uptr->PORT); + gtyo_done(); + break; + case SCPE_LOST: + ge_ldsc[uptr->PORT].rcve = 0; + tmxr_reset_ln(&ge_ldsc[uptr->PORT]); + sim_debug(DEBUG_CMD, &ge_dev, "lost\n"); + break; + case SCPE_STALL: + sim_debug(DEBUG_CMD, &ge_dev, "stall\n"); + sim_clock_coschedule(uptr, 1000); + break; + default: + break; + } + + tmxr_poll_tx(&ge_desc); + return SCPE_OK; +} + +static t_stat ge_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) +{ +const char helpString[] = + /* The '*'s in the next line represent the standard text width of a help line */ + /****************************************************************************/ + " The %D device connects a secondary processor that is sharing memory with the.\n" + " primary.\n\n" + " The device must be attached to a receive port, this is done by using the\n" + " ATTACH command to specify the receive port number.\n" + "\n" + "+sim> ATTACH %U port\n" + "\n" + ; + + return scp_help(st, dptr, uptr, flag, helpString, cptr); +} + +static const char *ge_description(DEVICE *dptr) +{ + return "GE DATANET-760"; +} + +static void gtyo_done(void) +{ + gtyo_unit->STATUS |= GTYO_DONE; + set_interrupt(GTYO_DEVNUM, gtyo_unit->STATUS); + if (gtyo_unit->STATUS & 7) + sim_debug(DEBUG_CMD, &ge_dev, "GTYO interrupt on channel %d\n", gtyo_unit->STATUS & 7); +} + +static void gtyo_soh(char data) { + if (data == GE_SOH) { + gtyo_process = gtyo_adr; + gtyo_unit->LP = 0; + } + gtyo_done(); +} + +static void gtyo_adr(char data) { + switch(data) { + case 0140: + case 0150: + case 0160: + case 0170: + gtyo_unit->PORT = (data >> 3) & 3; + gtyo_process = gtyo_status; + break; + default: + gtyo_process = gtyo_soh; + break; + } + gtyo_done(); +} + +static void gtyo_status(char data) { + if (data == 0) + gtyo_process = gtyo_stx; + else + gtyo_process = gtyo_soh; + gtyo_done(); +} + +static void gtyo_stx(char data) { + if (data == GE_STX) + gtyo_process = gtyo_text; + gtyo_done(); +} + +static void gtyo_text(char data) { + if (data == GE_ETX) { + gtyo_process = gtyo_lp; + gtyo_done(); + } else { + gtyo_unit->DATA = data; + sim_activate_after(gtyo_unit, 10000); + } +} + +static void gtyo_lp(char data) { + if (gtyo_unit->LP != 0) + sim_debug(DEBUG_CMD, &ge_dev, "Checksum mismatch\n"); + gtyo_process = gtyo_soh; + gtyo_done(); +} + +t_stat gtyi_devio(uint32 dev, uint64 *data) +{ + UNIT *uptr = gtyi_unit; + + switch(dev & 03) { + case CONO: + sim_debug(DEBUG_CONO, &ge_dev, "GTYI %012llo\n", *data); + uptr->STATUS &= ~GTYI_PIA; + uptr->STATUS |= *data & GTYI_PIA; + break; + case CONI: + *data = uptr->STATUS & GTYI_STATUS; + sim_debug(DEBUG_CONI, &ge_dev, "GTYI %012llo\n", *data); + break; + case DATAI: + *data = uptr->DATA | (uptr->PORT << 18); + sim_debug(DEBUG_DATAIO, &ge_dev, "GTYI %012llo\n", *data); + uptr->STATUS &= ~GTYI_DONE; + sim_debug(DEBUG_IRQ, &ge_dev, "Clear GTYI interrupt\n"); + clr_interrupt(GTYI_DEVNUM); + ge_ldsc[uptr->PORT].rcve = 1; + sim_activate(gtyi_unit, 10); + break; + } + + return SCPE_OK; +} + +t_stat gtyo_devio(uint32 dev, uint64 *data) +{ + UNIT *uptr = gtyo_unit; + int ch; + + switch(dev & 03) { + case CONO: + sim_debug(DEBUG_CONO, &ge_dev, "GTYO %012llo\n", *data); + sim_debug(DEBUG_IRQ, &ge_dev, "Clear GTYO interrupt\n"); + clr_interrupt(GTYO_DEVNUM); + uptr->STATUS &= ~GTYO_PIA; + uptr->STATUS |= *data & GTYO_PIA; + if (*data & GTYO_FROB) + gtyo_done(); + break; + case CONI: + *data = uptr->STATUS & GTYO_STATUS; + sim_debug(DEBUG_CONI, &ge_dev, "GTYO %012llo\n", *data); + break; + case DATAO: + sim_debug(DEBUG_DATAIO, &ge_dev, "GTYO %012llo\n", *data); + if (uptr->STATUS & GTYO_DONE) { + sim_debug(DEBUG_IRQ, &ge_dev, "Clear GTYO interrupt\n"); + clr_interrupt(GTYO_DEVNUM); + uptr->STATUS &= ~GTYO_DONE; + ch = *data & 0177; + ch ^= 0177; + ch = ((ch << 1) | (ch >> 6)) & 0177; + if (ch >= 040 && ch <= 0137) + sim_debug(DEBUG_DATAIO, &ge_dev, "Character %03o %c\n", ch, ch); + else + sim_debug(DEBUG_DATAIO, &ge_dev, "Character %03o\n", ch); + uptr->LP ^= ch; + sim_debug(DEBUG_DATAIO, &ge_dev, "LP %03o\n", uptr->LP); + gtyo_process(ch); + } + break; + } + + return SCPE_OK; +} +#endif diff --git a/Visual Studio Projects/PDP10-KA.vcproj b/Visual Studio Projects/PDP10-KA.vcproj index fddbf3398..6df3c2285 100644 --- a/Visual Studio Projects/PDP10-KA.vcproj +++ b/Visual Studio Projects/PDP10-KA.vcproj @@ -211,6 +211,10 @@ RelativePath="..\PDP10\ka10_dkb.c" > + + @@ -275,6 +279,10 @@ RelativePath="..\PDP10\kx10_dc.c" > + + diff --git a/Visual Studio Projects/PDP10-KI.vcproj b/Visual Studio Projects/PDP10-KI.vcproj index ed610ebe4..2d4d1d1d2 100644 --- a/Visual Studio Projects/PDP10-KI.vcproj +++ b/Visual Studio Projects/PDP10-KI.vcproj @@ -215,6 +215,10 @@ RelativePath="..\PDP10\kx10_dc.c" > + + @@ -279,6 +283,10 @@ RelativePath="..\PDP10\kx10_tu.c" > + + diff --git a/Visual Studio Projects/PDP6.vcproj b/Visual Studio Projects/PDP6.vcproj index adf187363..05a38e155 100644 --- a/Visual Studio Projects/PDP6.vcproj +++ b/Visual Studio Projects/PDP6.vcproj @@ -215,6 +215,10 @@ RelativePath="..\PDP10\kx10_dpy.c" > + + diff --git a/cmake/simh-packaging.cmake b/cmake/simh-packaging.cmake index fdcc14481..6a3ac3978 100644 --- a/cmake/simh-packaging.cmake +++ b/cmake/simh-packaging.cmake @@ -1,103 +1,103 @@ -## The default runtime support component/family: -cpack_add_component(runtime_support - DISPLAY_NAME "Runtime support" - DESCRIPTION "Required SIMH runtime support (documentation, shared libraries)" - REQUIRED -) - -## Basic documentation for SIMH -install(FILES doc/simh.doc TYPE DOC COMPONENT runtime_support) - -cpack_add_component(altairz80_family - DISPLAY_NAME "Altair Z80 simulator." - DESCRIPTION "The Altair Z80 simulator with M68000 support. Simulators: altairz80" -) -cpack_add_component(att3b2_family - DISPLAY_NAME "ATT&T 3b2 collection" - DESCRIPTION "The AT&T 3b2 simulator family. Simulators: 3b2, 3b2-700" -) -cpack_add_component(b5500_family - DISPLAY_NAME "Burroughs 5500" - DESCRIPTION "The Burroughs 5500 system simulator. Simulators: b5500" -) -cpack_add_component(cdc1700_family - DISPLAY_NAME "CDC 1700" - DESCRIPTION "The Control Data Corporation's systems. Simulators: cdc1700" -) -cpack_add_component(decpdp_family - DISPLAY_NAME "DEC PDP family" - DESCRIPTION "Digital Equipment Corporation PDP systems. Simulators: pdp1, pdp15, pdp4, pdp6, pdp7, pdp8, pdp9" -) -cpack_add_component(default_family - DISPLAY_NAME "Default SIMH simulator family." - DESCRIPTION "The SIMH simulator collection of historical processors and computing systems that do not belong to -any other simulated system family. Simulators: altair, besm6, ssem, tt2500, tx-0" -) -cpack_add_component(dgnova_family - DISPLAY_NAME "DG Nova and Eclipse" - DESCRIPTION "Data General NOVA and Eclipse system simulators. Simulators: eclipse, nova" -) -cpack_add_component(experimental - DISPLAY_NAME "Experimental (work-in-progress) simulators" - DESCRIPTION "Experimental or work-in-progress simulators not in the SIMH mainline simulator suite. Simulators: alpha, pdq3, sage" -) -cpack_add_component(gould_family - DISPLAY_NAME "Gould simulators" - DESCRIPTION "Gould Systems simulators. Simulators: sel32" -) -cpack_add_component(grisys_family - DISPLAY_NAME "GRI Systems GRI-909" - DESCRIPTION "GRI Systems GRI-909 system simulator. Simulators: gri" -) -cpack_add_component(honeywell_family - DISPLAY_NAME "Honeywell H316" - DESCRIPTION "Honeywell H-316 system simulator. Simulators: h316" -) -cpack_add_component(hp_family - DISPLAY_NAME "HP 2100, 3000" - DESCRIPTION "Hewlett-Packard H2100 and H3000 simulators. Simulators: hp2100, hp3000" -) -cpack_add_component(ibm_family - DISPLAY_NAME "IBM" - DESCRIPTION "IBM system simulators: i650. Simulators: i1401, i1620, i650, i701, i7010, i704, i7070, i7080, i7090, i7094, ibm1130, s3" -) -cpack_add_component(imlac_family - DISPLAY_NAME "IMLAC" - DESCRIPTION "IMLAC system simulators. Simulators: imlac" -) -cpack_add_component(intel_family - DISPLAY_NAME "Intel" - DESCRIPTION "Intel system simulators. Simulators: intel-mds, scelbi" -) -cpack_add_component(interdata_family - DISPLAY_NAME "Interdata" - DESCRIPTION "Interdata systems simulators. Simulators: id16, id32" -) -cpack_add_component(lgp_family - DISPLAY_NAME "LGP" - DESCRIPTION "Librascope systems. Simulators: lgp" -) -cpack_add_component(norsk_family - DISPLAY_NAME "ND simulators" - DESCRIPTION "Norsk Data systems simulator family. Simulators: nd100" -) -cpack_add_component(pdp10_family - DISPLAY_NAME "DEC PDP-10 collection" - DESCRIPTION "DEC PDP-10 architecture simulators and variants. Simulators: pdp10, pdp10-ka, pdp10-ki, pdp10-kl, pdp10-ks" -) -cpack_add_component(pdp11_family - DISPLAY_NAME "DEC PDP-11 collection." - DESCRIPTION "DEC PDP-11 and PDP-11-derived architecture simulators. Simulators: pdp11, uc15" -) -cpack_add_component(sds_family - DISPLAY_NAME "SDS simulators" - DESCRIPTION "Scientific Data Systems (SDS) systems. Simulators: sds, sigma" -) -cpack_add_component(swtp_family - DISPLAY_NAME "SWTP simulators" - DESCRIPTION "Southwest Technical Products (SWTP) system simulators. Simulators: swtp6800mp-a, swtp6800mp-a2" -) -cpack_add_component(vax_family - DISPLAY_NAME "DEC VAX simulator collection" - DESCRIPTION "The Digital Equipment Corporation VAX (plural: VAXen) simulator family. Simulators: infoserver100, infoserver1000, infoserver150vxt, microvax1, microvax2, microvax2000, microvax3100, microvax3100e, microvax3100m80, rtvax1000, vax, vax730, vax750, vax780, vax8200, vax8600, vaxstation3100m30, vaxstation3100m38, vaxstation3100m76, vaxstation4000m60, vaxstation4000vlc" -) +## The default runtime support component/family: +cpack_add_component(runtime_support + DISPLAY_NAME "Runtime support" + DESCRIPTION "Required SIMH runtime support (documentation, shared libraries)" + REQUIRED +) + +## Basic documentation for SIMH +install(FILES doc/simh.doc TYPE DOC COMPONENT runtime_support) + +cpack_add_component(altairz80_family + DISPLAY_NAME "Altair Z80 simulator." + DESCRIPTION "The Altair Z80 simulator with M68000 support. Simulators: altairz80" +) +cpack_add_component(att3b2_family + DISPLAY_NAME "ATT&T 3b2 collection" + DESCRIPTION "The AT&T 3b2 simulator family. Simulators: 3b2, 3b2-700" +) +cpack_add_component(b5500_family + DISPLAY_NAME "Burroughs 5500" + DESCRIPTION "The Burroughs 5500 system simulator. Simulators: b5500" +) +cpack_add_component(cdc1700_family + DISPLAY_NAME "CDC 1700" + DESCRIPTION "The Control Data Corporation's systems. Simulators: cdc1700" +) +cpack_add_component(decpdp_family + DISPLAY_NAME "DEC PDP family" + DESCRIPTION "Digital Equipment Corporation PDP systems. Simulators: pdp1, pdp15, pdp4, pdp6, pdp7, pdp8, pdp9" +) +cpack_add_component(default_family + DISPLAY_NAME "Default SIMH simulator family." + DESCRIPTION "The SIMH simulator collection of historical processors and computing systems that do not belong to +any other simulated system family. Simulators: altair, besm6, ssem, tt2500, tx-0" +) +cpack_add_component(dgnova_family + DISPLAY_NAME "DG Nova and Eclipse" + DESCRIPTION "Data General NOVA and Eclipse system simulators. Simulators: eclipse, nova" +) +cpack_add_component(experimental + DISPLAY_NAME "Experimental (work-in-progress) simulators" + DESCRIPTION "Experimental or work-in-progress simulators not in the SIMH mainline simulator suite. Simulators: alpha, pdq3, sage" +) +cpack_add_component(gould_family + DISPLAY_NAME "Gould simulators" + DESCRIPTION "Gould Systems simulators. Simulators: sel32" +) +cpack_add_component(grisys_family + DISPLAY_NAME "GRI Systems GRI-909" + DESCRIPTION "GRI Systems GRI-909 system simulator. Simulators: gri" +) +cpack_add_component(honeywell_family + DISPLAY_NAME "Honeywell H316" + DESCRIPTION "Honeywell H-316 system simulator. Simulators: h316" +) +cpack_add_component(hp_family + DISPLAY_NAME "HP 2100, 3000" + DESCRIPTION "Hewlett-Packard H2100 and H3000 simulators. Simulators: hp2100, hp3000" +) +cpack_add_component(ibm_family + DISPLAY_NAME "IBM" + DESCRIPTION "IBM system simulators: i650. Simulators: i1401, i1620, i650, i701, i7010, i704, i7070, i7080, i7090, i7094, ibm1130, s3" +) +cpack_add_component(imlac_family + DISPLAY_NAME "IMLAC" + DESCRIPTION "IMLAC system simulators. Simulators: imlac" +) +cpack_add_component(intel_family + DISPLAY_NAME "Intel" + DESCRIPTION "Intel system simulators. Simulators: intel-mds, scelbi" +) +cpack_add_component(interdata_family + DISPLAY_NAME "Interdata" + DESCRIPTION "Interdata systems simulators. Simulators: id16, id32" +) +cpack_add_component(lgp_family + DISPLAY_NAME "LGP" + DESCRIPTION "Librascope systems. Simulators: lgp" +) +cpack_add_component(norsk_family + DISPLAY_NAME "ND simulators" + DESCRIPTION "Norsk Data systems simulator family. Simulators: nd100" +) +cpack_add_component(pdp10_family + DISPLAY_NAME "DEC PDP-10 collection" + DESCRIPTION "DEC PDP-10 architecture simulators and variants. Simulators: pdp10, pdp10-ka, pdp10-ki, pdp10-kl, pdp10-ks" +) +cpack_add_component(pdp11_family + DISPLAY_NAME "DEC PDP-11 collection." + DESCRIPTION "DEC PDP-11 and PDP-11-derived architecture simulators. Simulators: pdp11, uc15" +) +cpack_add_component(sds_family + DISPLAY_NAME "SDS simulators" + DESCRIPTION "Scientific Data Systems (SDS) systems. Simulators: sds, sigma" +) +cpack_add_component(swtp_family + DISPLAY_NAME "SWTP simulators" + DESCRIPTION "Southwest Technical Products (SWTP) system simulators. Simulators: swtp6800mp-a, swtp6800mp-a2" +) +cpack_add_component(vax_family + DISPLAY_NAME "DEC VAX simulator collection" + DESCRIPTION "The Digital Equipment Corporation VAX (plural: VAXen) simulator family. Simulators: infoserver100, infoserver1000, infoserver150vxt, microvax1, microvax2, microvax2000, microvax3100, microvax3100e, microvax3100m80, rtvax1000, vax, vax730, vax750, vax780, vax8200, vax8600, vaxstation3100m30, vaxstation3100m38, vaxstation3100m76, vaxstation4000m60, vaxstation4000vlc" +) diff --git a/cmake/simh-simulators.cmake b/cmake/simh-simulators.cmake index bd456fa5e..15d58c3b8 100644 --- a/cmake/simh-simulators.cmake +++ b/cmake/simh-simulators.cmake @@ -1,123 +1,123 @@ -## -## This is an automagically generated file. Do NOT EDIT. -## Any changes you make will be overwritten!! -## -## Make changes to the SIMH top-level makefile and then run the -## "cmake/generate.py" script to regenerate these files. -## -## cd cmake; python -m generate --help -## -## ------------------------------------------------------------ -set(ALPHAD "${CMAKE_SOURCE_DIR}/alpha") -set(ALTAIRD "${CMAKE_SOURCE_DIR}/ALTAIR") -set(ALTAIRZ80D "${CMAKE_SOURCE_DIR}/AltairZ80") -set(ATT3B2D "${CMAKE_SOURCE_DIR}/3B2") -set(B5500D "${CMAKE_SOURCE_DIR}/B5500") -set(BESM6D "${CMAKE_SOURCE_DIR}/BESM6") -set(CDC1700D "${CMAKE_SOURCE_DIR}/CDC1700") -set(GRID "${CMAKE_SOURCE_DIR}/GRI") -set(H316D "${CMAKE_SOURCE_DIR}/H316") -set(HP2100D "${CMAKE_SOURCE_DIR}/HP2100") -set(HP3000D "${CMAKE_SOURCE_DIR}/HP3000") -set(I1401D "${CMAKE_SOURCE_DIR}/I1401") -set(I1620D "${CMAKE_SOURCE_DIR}/I1620") -set(I650D "${CMAKE_SOURCE_DIR}/I650") -set(I7000D "${CMAKE_SOURCE_DIR}/I7000") -set(I7010D "${CMAKE_SOURCE_DIR}/I7000") -set(I7094D "${CMAKE_SOURCE_DIR}/I7094") -set(IBM1130D "${CMAKE_SOURCE_DIR}/Ibm1130") -set(ID16D "${CMAKE_SOURCE_DIR}/Interdata") -set(ID32D "${CMAKE_SOURCE_DIR}/Interdata") -set(IMLACD "${CMAKE_SOURCE_DIR}/imlac") -set(INTELSYSC "${CMAKE_SOURCE_DIR}/Intel-Systems/common") -set(KA10D "${CMAKE_SOURCE_DIR}/PDP10") -set(KI10D "${CMAKE_SOURCE_DIR}/PDP10") -set(KL10D "${CMAKE_SOURCE_DIR}/PDP10") -set(KS10D "${CMAKE_SOURCE_DIR}/PDP10") -set(LGPD "${CMAKE_SOURCE_DIR}/LGP") -set(ND100D "${CMAKE_SOURCE_DIR}/ND100") -set(NOVAD "${CMAKE_SOURCE_DIR}/NOVA") -set(PDP10D "${CMAKE_SOURCE_DIR}/PDP10") -set(PDP11D "${CMAKE_SOURCE_DIR}/PDP11") -set(PDP18BD "${CMAKE_SOURCE_DIR}/PDP18B") -set(PDP1D "${CMAKE_SOURCE_DIR}/PDP1") -set(PDP6D "${CMAKE_SOURCE_DIR}/PDP10") -set(PDP8D "${CMAKE_SOURCE_DIR}/PDP8") -set(PDQ3D "${CMAKE_SOURCE_DIR}/PDQ-3") -set(S3D "${CMAKE_SOURCE_DIR}/S3") -set(SAGED "${CMAKE_SOURCE_DIR}/SAGE") -set(SDSD "${CMAKE_SOURCE_DIR}/SDS") -set(SEL32D "${CMAKE_SOURCE_DIR}/SEL32") -set(SIGMAD "${CMAKE_SOURCE_DIR}/sigma") -set(SSEMD "${CMAKE_SOURCE_DIR}/SSEM") -set(SWTP6800C "${CMAKE_SOURCE_DIR}/swtp6800/common") -set(SWTP6800D "${CMAKE_SOURCE_DIR}/swtp6800/swtp6800") -set(TT2500D "${CMAKE_SOURCE_DIR}/tt2500") -set(TX0D "${CMAKE_SOURCE_DIR}/TX-0") -set(UC15D "${CMAKE_SOURCE_DIR}/PDP11") -set(VAXD "${CMAKE_SOURCE_DIR}/VAX") - -set(DISPLAYD "${CMAKE_SOURCE_DIR}/display") -set(DISPLAY340 "${DISPLAYD}/type340.c") -set(DISPLAYIII "${DISPLAYD}/iii.c") -set(DISPLAYNG "${DISPLAYD}/ng.c") -set(DISPLAYVT "${DISPLAYD}/vt11.c") - -set(INTELSYSD "${CMAKE_SOURCE_DIR}/Intel-Systems") -set(INTEL_MDSD "${INTELSYSD}/Intel-MDS") -set(SCELBIC "${INTELSYSD}/common") -set(SCELBID "${INTELSYSD}/scelbi") - -## ---------------------------------------- - -if (NOT WITH_VIDEO) - ### Hack: Unset these variables so that they don't expand if - ### not building with video: - set(DISPLAY340 "") - set(DISPLAYIII "") - set(DISPLAYNG "") - set(DISPLAYVT "") -endif () - -## ---------------------------------------- - -add_subdirectory(3B2) -add_subdirectory(ALTAIR) -add_subdirectory(AltairZ80) -add_subdirectory(B5500) -add_subdirectory(BESM6) -add_subdirectory(CDC1700) -add_subdirectory(GRI) -add_subdirectory(H316) -add_subdirectory(HP2100) -add_subdirectory(HP3000) -add_subdirectory(I1401) -add_subdirectory(I1620) -add_subdirectory(I650) -add_subdirectory(I7000) -add_subdirectory(I7094) -add_subdirectory(Ibm1130) -add_subdirectory(Intel-Systems/Intel-MDS) -add_subdirectory(Intel-Systems/scelbi) -add_subdirectory(Interdata) -add_subdirectory(LGP) -add_subdirectory(ND100) -add_subdirectory(NOVA) -add_subdirectory(PDP1) -add_subdirectory(PDP10) -add_subdirectory(PDP11) -add_subdirectory(PDP18B) -add_subdirectory(PDP8) -add_subdirectory(PDQ-3) -add_subdirectory(S3) -add_subdirectory(SAGE) -add_subdirectory(SDS) -add_subdirectory(SEL32) -add_subdirectory(SSEM) -add_subdirectory(TX-0) -add_subdirectory(VAX) -add_subdirectory(alpha) -add_subdirectory(imlac) -add_subdirectory(sigma) -add_subdirectory(swtp6800/swtp6800) -add_subdirectory(tt2500) +## +## This is an automagically generated file. Do NOT EDIT. +## Any changes you make will be overwritten!! +## +## Make changes to the SIMH top-level makefile and then run the +## "cmake/generate.py" script to regenerate these files. +## +## cd cmake; python -m generate --help +## +## ------------------------------------------------------------ +set(ALPHAD "${CMAKE_SOURCE_DIR}/alpha") +set(ALTAIRD "${CMAKE_SOURCE_DIR}/ALTAIR") +set(ALTAIRZ80D "${CMAKE_SOURCE_DIR}/AltairZ80") +set(ATT3B2D "${CMAKE_SOURCE_DIR}/3B2") +set(B5500D "${CMAKE_SOURCE_DIR}/B5500") +set(BESM6D "${CMAKE_SOURCE_DIR}/BESM6") +set(CDC1700D "${CMAKE_SOURCE_DIR}/CDC1700") +set(GRID "${CMAKE_SOURCE_DIR}/GRI") +set(H316D "${CMAKE_SOURCE_DIR}/H316") +set(HP2100D "${CMAKE_SOURCE_DIR}/HP2100") +set(HP3000D "${CMAKE_SOURCE_DIR}/HP3000") +set(I1401D "${CMAKE_SOURCE_DIR}/I1401") +set(I1620D "${CMAKE_SOURCE_DIR}/I1620") +set(I650D "${CMAKE_SOURCE_DIR}/I650") +set(I7000D "${CMAKE_SOURCE_DIR}/I7000") +set(I7010D "${CMAKE_SOURCE_DIR}/I7000") +set(I7094D "${CMAKE_SOURCE_DIR}/I7094") +set(IBM1130D "${CMAKE_SOURCE_DIR}/Ibm1130") +set(ID16D "${CMAKE_SOURCE_DIR}/Interdata") +set(ID32D "${CMAKE_SOURCE_DIR}/Interdata") +set(IMLACD "${CMAKE_SOURCE_DIR}/imlac") +set(INTELSYSC "${CMAKE_SOURCE_DIR}/Intel-Systems/common") +set(KA10D "${CMAKE_SOURCE_DIR}/PDP10") +set(KI10D "${CMAKE_SOURCE_DIR}/PDP10") +set(KL10D "${CMAKE_SOURCE_DIR}/PDP10") +set(KS10D "${CMAKE_SOURCE_DIR}/PDP10") +set(LGPD "${CMAKE_SOURCE_DIR}/LGP") +set(ND100D "${CMAKE_SOURCE_DIR}/ND100") +set(NOVAD "${CMAKE_SOURCE_DIR}/NOVA") +set(PDP10D "${CMAKE_SOURCE_DIR}/PDP10") +set(PDP11D "${CMAKE_SOURCE_DIR}/PDP11") +set(PDP18BD "${CMAKE_SOURCE_DIR}/PDP18B") +set(PDP1D "${CMAKE_SOURCE_DIR}/PDP1") +set(PDP6D "${CMAKE_SOURCE_DIR}/PDP10") +set(PDP8D "${CMAKE_SOURCE_DIR}/PDP8") +set(PDQ3D "${CMAKE_SOURCE_DIR}/PDQ-3") +set(S3D "${CMAKE_SOURCE_DIR}/S3") +set(SAGED "${CMAKE_SOURCE_DIR}/SAGE") +set(SDSD "${CMAKE_SOURCE_DIR}/SDS") +set(SEL32D "${CMAKE_SOURCE_DIR}/SEL32") +set(SIGMAD "${CMAKE_SOURCE_DIR}/sigma") +set(SSEMD "${CMAKE_SOURCE_DIR}/SSEM") +set(SWTP6800C "${CMAKE_SOURCE_DIR}/swtp6800/common") +set(SWTP6800D "${CMAKE_SOURCE_DIR}/swtp6800/swtp6800") +set(TT2500D "${CMAKE_SOURCE_DIR}/tt2500") +set(TX0D "${CMAKE_SOURCE_DIR}/TX-0") +set(UC15D "${CMAKE_SOURCE_DIR}/PDP11") +set(VAXD "${CMAKE_SOURCE_DIR}/VAX") + +set(DISPLAYD "${CMAKE_SOURCE_DIR}/display") +set(DISPLAY340 "${DISPLAYD}/type340.c") +set(DISPLAYIII "${DISPLAYD}/iii.c") +set(DISPLAYNG "${DISPLAYD}/ng.c") +set(DISPLAYVT "${DISPLAYD}/vt11.c") + +set(INTELSYSD "${CMAKE_SOURCE_DIR}/Intel-Systems") +set(INTEL_MDSD "${INTELSYSD}/Intel-MDS") +set(SCELBIC "${INTELSYSD}/common") +set(SCELBID "${INTELSYSD}/scelbi") + +## ---------------------------------------- + +if (NOT WITH_VIDEO) + ### Hack: Unset these variables so that they don't expand if + ### not building with video: + set(DISPLAY340 "") + set(DISPLAYIII "") + set(DISPLAYNG "") + set(DISPLAYVT "") +endif () + +## ---------------------------------------- + +add_subdirectory(3B2) +add_subdirectory(ALTAIR) +add_subdirectory(AltairZ80) +add_subdirectory(B5500) +add_subdirectory(BESM6) +add_subdirectory(CDC1700) +add_subdirectory(GRI) +add_subdirectory(H316) +add_subdirectory(HP2100) +add_subdirectory(HP3000) +add_subdirectory(I1401) +add_subdirectory(I1620) +add_subdirectory(I650) +add_subdirectory(I7000) +add_subdirectory(I7094) +add_subdirectory(Ibm1130) +add_subdirectory(Intel-Systems/Intel-MDS) +add_subdirectory(Intel-Systems/scelbi) +add_subdirectory(Interdata) +add_subdirectory(LGP) +add_subdirectory(ND100) +add_subdirectory(NOVA) +add_subdirectory(PDP1) +add_subdirectory(PDP10) +add_subdirectory(PDP11) +add_subdirectory(PDP18B) +add_subdirectory(PDP8) +add_subdirectory(PDQ-3) +add_subdirectory(S3) +add_subdirectory(SAGE) +add_subdirectory(SDS) +add_subdirectory(SEL32) +add_subdirectory(SSEM) +add_subdirectory(TX-0) +add_subdirectory(VAX) +add_subdirectory(alpha) +add_subdirectory(imlac) +add_subdirectory(sigma) +add_subdirectory(swtp6800/swtp6800) +add_subdirectory(tt2500) diff --git a/makefile b/makefile index 1167f83aa..631d3747a 100644 --- a/makefile +++ b/makefile @@ -2048,7 +2048,8 @@ 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 ${PDP6D}/pdp6_slave.c ${DISPLAYL} ${DISPLAY340} + ${PDP6D}/kx10_dpy.c ${PDP6D}/pdp6_slave.c ${PDP6D}/pdp6_ge.c \ + ${DISPLAYL} ${DISPLAY340} PDP6_OPT = -DPDP6=1 -DUSE_INT64 -I ${PDP6D} -DUSE_SIM_CARD ${DISPLAY_OPT} ${PDP6_DISPLAY_OPT} \ ${AIO_CCDEFS} @@ -2069,8 +2070,8 @@ KA10 = ${KA10D}/kx10_cpu.c ${KA10D}/kx10_sys.c ${KA10D}/kx10_df.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 \ ${KA10D}/ka10_ai.c ${KA10D}/ka10_iii.c ${KA10D}/kx10_disk.c \ - ${KA10D}/ka10_pclk.c ${KA10D}/ka10_tv.c \ - ${DISPLAYL} ${DISPLAY340} ${DISPLAYIII} + ${KA10D}/ka10_pclk.c ${KA10D}/ka10_tv.c ${KA10D}/ka10_dd.c \ + ${KA10D}/kx10_ddc.c ${DISPLAYL} ${DISPLAY340} ${DISPLAYIII} 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. @@ -2090,7 +2091,7 @@ KI10 = ${KI10D}/kx10_cpu.c ${KI10D}/kx10_sys.c ${KI10D}/kx10_df.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 ${KI10D}/kx10_disk.c \ - ${DISPLAYL} ${DISPLAY340} + ${KI10D}/kx10_ddc.c ${KI10D}/kx10_tym.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.