From 6bdba9bd61df0c67c6654ae1f973ee9b71e8905a Mon Sep 17 00:00:00 2001 From: Lars Brinkhoff Date: Tue, 19 Dec 2023 12:06:53 +0100 Subject: [PATCH 1/7] PDP6: Add GE DATANET-760 device. This is a terminal multiplexor to emulate the GE DATANET-760 controller. https://gunkies.org/wiki/MIT_AI_lab_IO_bus_interface_for_GE_Datanet_760 --- PDP10/kx10_defs.h | 3 + PDP10/kx10_sys.c | 4 + PDP10/pdp6_ge.c | 424 ++++++++++++++++++++++++++++++++++++++++++++++ makefile | 3 +- 4 files changed, 433 insertions(+), 1 deletion(-) create mode 100644 PDP10/pdp6_ge.c diff --git a/PDP10/kx10_defs.h b/PDP10/kx10_defs.h index 75da569..656cc78 100644 --- a/PDP10/kx10_defs.h +++ b/PDP10/kx10_defs.h @@ -542,6 +542,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 @@ -750,6 +752,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 diff --git a/PDP10/kx10_sys.c b/PDP10/kx10_sys.c index 6d2eb9a..ebce02d 100644 --- a/PDP10/kx10_sys.c +++ b/PDP10/kx10_sys.c @@ -245,6 +245,10 @@ DEVICE *sim_devices[] = { #endif #if NUM_DEVS_TYM > 0 &tym_dev, +#endif +#if NUM_DEVS_GE > 0 + &ge_dev, + >yo_dev, #endif NULL }; diff --git a/PDP10/pdp6_ge.c b/PDP10/pdp6_ge.c new file mode 100644 index 0000000..21aac50 --- /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/makefile b/makefile index 867985c..8826ddb 100644 --- a/makefile +++ b/makefile @@ -1421,7 +1421,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} ifneq (${PANDA_LIGHTS},) # ONLY for Panda display. From c35cb19bfc9a76f92df91eb081c6d3db25a25b35 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sat, 13 Jan 2024 15:48:46 -0500 Subject: [PATCH 2/7] IBM360: Added missing 3270 command that MVS wants. --- IBM360/ibm360_scom.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/IBM360/ibm360_scom.c b/IBM360/ibm360_scom.c index 475b375..151e89b 100644 --- a/IBM360/ibm360_scom.c +++ b/IBM360/ibm360_scom.c @@ -38,7 +38,9 @@ #define CMD_WRER 0x05 /* Erase and write data */ #define CMD_RDMD 0x06 /* Read modified */ #define CMD_SEL 0x0B /* Select */ +#define CMD_WRERALT 0x0D /* Write erase alternative */ #define CMD_EAU 0x0F /* Erase all un protected */ +#define CMD_WSF 0x11 /* Writye structured field */ /* u3 second byte */ #define RECV 0x00100 /* Recieving data */ @@ -102,12 +104,14 @@ #define TS_DO 4 /* Have seen IAC DO */ #define TS_DONT 5 /* Have seen IAC DONT */ -/* Remove orders */ +/* Remote orders */ #define REMOTE_EAU 0x6F /* Erase all unprotected */ #define REMOTE_EW 0xF5 /* Erase/Write */ #define REMOTE_RB 0xF2 /* Read Buffer */ #define REMOTE_RM 0x6e /* Read Modified */ +#define REMOTE_WRERALT 0x7e /* Write erase alternative */ #define REMOTE_WRT 0xF1 /* Write */ +#define REMOTE_WSF 0xF3 /* Write structured field */ struct _line { uint16 option_state[256]; /* Current telnet state */ @@ -247,6 +251,8 @@ uint8 scoml_haltio(UNIT *uptr) { case CMD_WRER: /* Erase and write data */ case CMD_RDMD: /* Read modified */ case CMD_EAU: /* Erase all un protected */ + case CMD_WSF: /* Write Structured field */ + case CMD_WRERALT: /* Write erase alternative */ uptr->CMD |= HALT; chan_end(addr, SNS_CHNEND|SNS_DEVEND); sim_activate(uptr, 20); @@ -325,6 +331,14 @@ t_stat scoml_srv(UNIT * uptr) break; + case CMD_WRERALT: /* Write erase alternative */ + ch = REMOTE_WRERALT; + goto write; + + case CMD_WSF: /* Write structured field */ + ch = REMOTE_WSF; + goto write; + case CMD_WRER: /* Erase and write data */ ch = REMOTE_EW; goto write; From 8cc79906e8c8ace193e66a745c47ed31f9ae11b6 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 25 Jan 2024 16:04:35 -0500 Subject: [PATCH 3/7] I7000: Fixed issues with I7080 test case not running correctly. --- I7000/i7080_cpu.c | 19 ++++++++++++++----- I7000/tests/i7080_test.ini | 10 ++++++---- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/I7000/i7080_cpu.c b/I7000/i7080_cpu.c index 744c88a..8e4a8a4 100644 --- a/I7000/i7080_cpu.c +++ b/I7000/i7080_cpu.c @@ -1609,11 +1609,12 @@ stop_cpu: case OP_RWW: /* RWW 705 only */ MAC2 = MAC; - if (CPU_MODEL == CPU_7080 && + if (iowait == 0 && CPU_MODEL == CPU_7080 && (cpu_unit.flags & IOIRQ) != 0 && (flags & EIGHTMODE) == 0 && ((selreg >> 8) & 0xff) != 5) { flags |= ANYFLAG|INSTFLAG; + selreg2 = 0; } else { selreg2 = selreg | 0x8000; } @@ -2567,8 +2568,6 @@ uint16 get_acstart(uint8 reg) { /* Store CPU state in CASU 15 */ void store_cpu(uint32 addr, int full) { uint8 t; - int j; - uint32 ta; store_addr(IC, &addr); /* Save status characters */ @@ -2625,8 +2624,6 @@ void store_cpu(uint32 addr, int full) { void load_cpu(uint32 addr, int full) { uint8 t; uint8 f; - int j; - uint32 ta; flags = 0; IC = load_addr(&addr); @@ -3378,6 +3375,18 @@ cpu_reset(DEVICE * dptr) selreg2 = 0; IC = 4; sim_brk_types = sim_brk_dflt = SWMASK('E'); + /* Leave 80 mode */ + if (CPU_MODEL == CPU_7080) { + cpu_type = (cpu_unit.flags & EMULATE3)? CPU_7053:CPU_705; + EMEMSIZE = MEMSIZE; + if (cpu_unit.flags & EMULATE2 && EMEMSIZE > 40000) + EMEMSIZE = 40000; + if (cpu_type == CPU_705 && (cpu_unit.flags & EMULATE2) == 0 && + EMEMSIZE > 20000) + EMEMSIZE = 20000; + if (EMEMSIZE > 80000) + EMEMSIZE = 80000; + } return SCPE_OK; } diff --git a/I7000/tests/i7080_test.ini b/I7000/tests/i7080_test.ini index 4e0f318..7fbb561 100644 --- a/I7000/tests/i7080_test.ini +++ b/I7000/tests/i7080_test.ini @@ -3,10 +3,10 @@ cd i7080 rm test.log set cpu 80k 7080 emu7053 hist=10000 set console -n -q log=test.log -at mta1 t1.tp -at mta2 t2.tp -at mtb1 t3.tp -at mtb2 t4.tp +at mta1 -n t1.tp +at mta2 -n t2.tp +at mtb1 -n t3.tp +at mtb2 -n t4.tp load 8cu10b.dck echo "8cu10b" br 18219 @@ -32,4 +32,6 @@ load 8cu30b.dck echo "8cu30b" br 2164 go 4 +detach -q all +del t*.tp quit From 32788919c400badb7461737e1a1dffd63b820874 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 25 Jan 2024 17:59:11 -0500 Subject: [PATCH 4/7] IBM360: Add support for 3400 tape drives. --- IBM360/ibm360_mt.c | 87 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/IBM360/ibm360_mt.c b/IBM360/ibm360_mt.c index dda9974..5b05237 100644 --- a/IBM360/ibm360_mt.c +++ b/IBM360/ibm360_mt.c @@ -43,6 +43,7 @@ #define DEV_BUF_NUM(x) (((x) & 07) << DEV_V_UF) #define GET_DEV_BUF(x) (((x) >> DEV_V_UF) & 07) #define MT_BUSY (1 << (MTUF_V_UF + 1)) /* Flag to send a CUE */ +#define MTUF_3400 (1 << (MTUF_V_UF + 2)) #define UNIT_MT(x) UNIT_ATTABLE | UNIT_DISABLE | UNIT_ROABLE | MTUF_9TR | \ DEV_BUF_NUM(x) @@ -59,14 +60,19 @@ #define MT_BSF 0x2f /* Back space file */ #define MT_FSR 0x37 /* Forward space record */ #define MT_FSF 0x3f /* Forward space file */ +#define MT_SECURE_ERA 0x97 /* 3400 Security erase */ +#define MT_SENSE_RES 0xf4 /* 3400 Sense reserve */ +#define MT_SENSE_REL 0xb4 /* 3400 Sense release */ +#define MT_RTIE 0x1b /* Request track in error */ #define MT_MODE 0x03 /* Mode command */ #define MT_MODEMSK 0x07 /* Mode Mask */ -#define MT_MDEN_200 0x00 /* 200 BPI mode 7 track only */ -#define MT_MDEN_556 0x40 /* 556 BPI mode 7 track only */ -#define MT_MDEN_800 0x80 /* 800 BPI mode 7 track only */ -#define MT_MDEN_1600 0xc0 /* 1600 BPI mode 9 track only */ -#define MT_MDEN_MSK 0xc0 /* Density mask */ +#define MT_MDEN_200 0x000 /* 200 BPI mode 7 track only */ +#define MT_MDEN_556 0x040 /* 556 BPI mode 7 track only */ +#define MT_MDEN_800 0x080 /* 800 BPI mode 7 track only */ +#define MT_MDEN_1600 0x0c0 /* 1600 BPI mode 9 track only */ +#define MT_MDEN_6520 0x1c0 /* 6520 BPI mode 9 track only */ +#define MT_MDEN_MSK 0x1c0 /* Density mask */ #define MT_CTL_MSK 0x38 /* Mask for control flags */ #define MT_CTL_NOP 0x00 /* Nop control mode */ @@ -163,6 +169,8 @@ MTAB mt_mod[] = { {MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL}, {MTUF_9TR, 0, "7 track", "7T", NULL}, {MTUF_9TR, MTUF_9TR, "9 track", "9T", NULL}, + {MTUF_3400, 0, "2400", "2400", NULL}, + {MTUF_3400, MTUF_3400, "3400", "3400", NULL}, {MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT", &sim_tape_set_fmt, &sim_tape_show_fmt, NULL}, {MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "DEV", "DEV", &set_dev_addr, @@ -284,9 +292,15 @@ uint8 mt_startcmd(UNIT *uptr, uint8 cmd) { case 0x2: /* Read command */ case 0xc: /* Read backward */ uptr->SNS = 0; - /* Fall through */ + goto do_cmd; case 0x4: /* Sense */ + if ((cmd & 0xf0) != 0) { + uptr->SNS |= SNS_CMDREJ; + uptr->flags &= ~MT_BUSY; + return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK|f; + } +do_cmd: if ((uptr->CMD & MT_CMDREW) != 0) { sim_debug(DEBUG_CMD, dptr, "CMD rewinding unit=%d %x\n", unit, cmd); return SNS_BSY; @@ -361,6 +375,8 @@ uint8 mt_startcmd(UNIT *uptr, uint8 cmd) { uptr->CMD &= ~MT_MDEN_MSK; if (cmd & 0x8) uptr->CMD |= MT_MDEN_800; + else if (cmd & 0x10) + uptr->CMD |= MT_MDEN_6520; else uptr->CMD |= MT_MDEN_1600; } @@ -499,6 +515,65 @@ t_stat mt_srv(UNIT * uptr) chan_write_byte(addr, &ch) ; ch = SNS_BYTE5; chan_write_byte(addr, &ch); + if ((uptr->flags & MTUF_3400) != 0) { + /* Sense byte 6 */ + ch = 0x23; /* Model 3, Support dual density */ + if ((uptr->flags & MTUF_9TR) == 0) { + ch |= 0x80; /* Indicate 7 track */ + } + chan_write_byte(addr, &ch); + /* Sense byte 7 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 8 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 9 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 10 */ + ch = (uptr->CMD & SNS_CMDREJ); + chan_write_byte(addr, &ch); + /* Sense byte 11 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 12 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 13 */ + ch = (uptr->flags & MTUF_9TR) ? 0x80 : 0x40; + chan_write_byte(addr, &ch); + /* Sense byte 14 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 15 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 16 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 17 */ + ch = 0; /* No features */ + chan_write_byte(addr, &ch); + /* Sense byte 18 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 19 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 20 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 21 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 22 */ + ch = 0; + chan_write_byte(addr, &ch); + /* Sense byte 23 */ + ch = 0; + chan_write_byte(addr, &ch); + } uptr->CMD &= ~MT_CMDMSK; mt_busy[bufnum] &= ~1; if (uptr->flags & MT_BUSY) { From 8a6ea8889eadd9a6027c340f6d635297aa760498 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Thu, 25 Jan 2024 18:00:52 -0500 Subject: [PATCH 5/7] IBM360: Fixes to better handle storage modification bits. --- IBM360/ibm360_chan.c | 38 ++++++++++-------------- IBM360/ibm360_con.c | 4 +++ IBM360/ibm360_cpu.c | 71 +++++++++++++++++++++++++++----------------- IBM360/ibm360_dasd.c | 27 +++++++++-------- IBM360/ibm360_defs.h | 10 ++++++- IBM360/ibm360_scon.c | 4 +++ IBM360/ibm360_sys.c | 2 ++ 7 files changed, 93 insertions(+), 63 deletions(-) diff --git a/IBM360/ibm360_chan.c b/IBM360/ibm360_chan.c index fb6aca9..5b6a74c 100644 --- a/IBM360/ibm360_chan.c +++ b/IBM360/ibm360_chan.c @@ -84,13 +84,7 @@ extern uint32 *M; extern uint8 key[MAXMEMSIZE / 2048]; -#define UNIT_V_TYPE (UNIT_V_UF + 0) -#define UNIT_SEL (1 << UNIT_V_TYPE) /* Selector channel */ -#define UNIT_MUX (0 << UNIT_V_TYPE) /* Multiplexer channel */ -#define UNIT_BMUX (2 << UNIT_V_TYPE) /* Multiplexer channel */ -#define UNIT_M_TYPE (3 << UNIT_V_TYPE) - -#define UNIT_V_SUBCHAN (UNIT_V_UF + 2) +#define UNIT_V_SUBCHAN (UNIT_V_CTYPE + 2) #define UNIT_M_SUBCHAN 0xff #define UNIT_G_SCHAN(x) ((((x) >> UNIT_V_SUBCHAN) & UNIT_M_SUBCHAN) + 1) #define UNIT_SCHAN(x) (((x - 1) & UNIT_M_SUBCHAN) << UNIT_V_SUBCHAN) @@ -103,9 +97,9 @@ t_stat chan_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char const char *chan_description (DEVICE *dptr); MTAB chan_mod[] = { - { UNIT_M_TYPE, UNIT_MUX, NULL, "MUX", NULL, NULL, NULL, "Multiplexer channel"}, - { UNIT_M_TYPE, UNIT_SEL, NULL, "SEL", NULL, NULL, NULL, "Selector channel"}, - { UNIT_M_TYPE, UNIT_BMUX, NULL, "BMUX", NULL, NULL, NULL, "Block Multiplexer channel"}, + { UNIT_M_CTYPE, UNIT_MUX, NULL, "MUX", NULL, NULL, NULL, "Multiplexer channel"}, + { UNIT_M_CTYPE, UNIT_SEL, NULL, "SEL", NULL, NULL, NULL, "Selector channel"}, + { UNIT_M_CTYPE, UNIT_BMUX, NULL, "BMUX", NULL, NULL, NULL, "Block Multiplexer channel"}, { MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "SUB", "SUB", set_subchan, show_subchan, NULL, "Number of subchannels"}, {0} @@ -231,11 +225,11 @@ find_subchan(uint16 device) { uptr = &chan_unit[chan]; if ((uptr->flags & UNIT_DIS) != 0) return NULL; - if ((uptr->flags & UNIT_M_TYPE) == UNIT_SEL) { + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_SEL) { return &(chan_ctl[0]); } device &= 0xff; - if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) { + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) { extern uint32 cregs[16]; if ((cpu_unit[0].flags & FEAT_370) != 0 && (cregs[0] & 0x80000000) != 0) { @@ -1150,13 +1144,13 @@ int testchan(uint16 channel) { } /* Multiplexer channels return channel is available */ - if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX) { + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX) { sim_debug(DEBUG_CMD, &cpu_dev, "TCH CC %x cc=0, mux\n", channel); return 0; } /* Block Multiplexer channels operating in select mode */ - if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) { + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) { extern uint32 cregs[16]; if ((cpu_unit[0].flags & FEAT_370) != 0 && (cregs[0] & 0x80000000) != 0) { @@ -1267,13 +1261,13 @@ scan_chan(uint16 mask, int irq_en) { if ((uptr->flags & UNIT_DIS) != 0) continue; nchan = 1; - if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) { + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) { extern uint32 cregs[16]; if ((cpu_unit[0].flags & FEAT_370) != 0 && (cregs[0] & 0x80000000) != 0) { nchan = 32; } - } else if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX) { + } else if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX) { nchan = UNIT_G_SCHAN(uptr->flags); } /* Scan all subchannels on this channel */ @@ -1386,9 +1380,9 @@ chan_reset(DEVICE * dptr) if (uptr->flags & UNIT_DIS) continue; n = 1; - if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX) + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX) n = UNIT_G_SCHAN(uptr->flags)+1; - if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) n = 32; uptr->schans = n; uptr->up7 = calloc(n, sizeof(struct _chanctl)); @@ -1425,9 +1419,9 @@ chan_set_devs() continue; } n = 1; - if ((uptr->flags & UNIT_M_TYPE) == UNIT_MUX) + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_MUX) n = UNIT_G_SCHAN(uptr->flags)+1; - if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) n = 32; /* If no device array, create one */ if (uptr->up8 == NULL) @@ -1516,9 +1510,9 @@ show_subchan(FILE * st, UNIT * uptr, int32 v, CONST void *desc) if (uptr == NULL) return SCPE_IERR; - if ((uptr->flags & UNIT_M_TYPE) == UNIT_SEL) { + if ((uptr->flags & UNIT_M_CTYPE) == UNIT_SEL) { fprintf(st, "SEL"); - } else if ((uptr->flags & UNIT_M_TYPE) == UNIT_BMUX) { + } else if ((uptr->flags & UNIT_M_CTYPE) == UNIT_BMUX) { fprintf(st, "BMUX"); } else { n = UNIT_G_SCHAN(uptr->flags); diff --git a/IBM360/ibm360_con.c b/IBM360/ibm360_con.c index 3dc586b..93a1acf 100644 --- a/IBM360/ibm360_con.c +++ b/IBM360/ibm360_con.c @@ -40,6 +40,7 @@ #define CON_WR 0x01 /* Write console */ #define CON_ACR 0x09 /* Auto carrage return */ #define CON_RD 0x0a /* Read console */ +#define CON_ALR 0x0b /* Control Alarm */ #define CON_NOP 0x03 /* No op command */ #define CON_MSK 0x0f /* Command mask */ @@ -174,6 +175,9 @@ uint8 con_startcmd(UNIT *uptr, uint8 cmd) { return 0; case 3: /* Control */ + if (cmd == 0xb) { + sim_putchar('\a'); + } sim_debug(DEBUG_CMD, &con_dev, "%d: Cmd NOP\n", u); if (uptr->CMD & CON_REQ) { uptr->CMD &= ~CON_REQ; diff --git a/IBM360/ibm360_cpu.c b/IBM360/ibm360_cpu.c index 0a467eb..98859e3 100644 --- a/IBM360/ibm360_cpu.c +++ b/IBM360/ibm360_cpu.c @@ -609,8 +609,7 @@ TransAddr(uint32 va, uint32 *pa) } /* Now we need to fetch the actual entry */ - addr = (entry & PTE_ADR) + (page << 1); - addr &= AMASK; + addr = ((entry & PTE_ADR) + (page << 1)) & AMASK; if (addr >= MEMSIZE) { storepsw(OPPSW, IRC_ADDR); return 1; @@ -650,7 +649,7 @@ TransAddr(uint32 va, uint32 *pa) page = (va >> page_shift); entry |= ((page & 0x1f00) << 4) | TLB_VALID; tlb[page & 0xff] = entry; - *pa = (va & page_mask) | ((entry & TLB_PHY) << page_shift); + *pa = ((va & page_mask) | ((entry & TLB_PHY) << page_shift)) & AMASK; if (*pa >= MEMSIZE) { storepsw(OPPSW, IRC_ADDR); return 1; @@ -688,9 +687,6 @@ ReadFull(uint32 addr, uint32 *data) } } - /* Update access flag */ - key[pa >> 11] |= 0x4; - offset = pa & 0x3; /* If not on word boundry and store feature not set */ @@ -730,6 +726,10 @@ ReadFull(uint32 addr, uint32 *data) temp >>= 8 * (4 - offset); *data |= temp; } + + /* Update access flag */ + key[pa >> 11] |= 0x4; + /* sim_debug(DEBUG_DATA, &cpu_dev, "RD A=%08x %08x\n", addr, *data); */ return 0; } @@ -840,7 +840,6 @@ WriteFull(uint32 addr, uint32 data) return 1; } } - key[pa >> 11] |= 0x6; pa2 = pa + 4; /* Check if we handle unaligned access */ @@ -874,6 +873,9 @@ WriteFull(uint32 addr, uint32 data) } key[pa2 >> 11] |= 0x6; } + + key[pa >> 11] |= 0x6; + pa >>= 2; pa2 >>= 2; @@ -1017,9 +1019,6 @@ WriteHalf(uint32 addr, uint32 data) } } - /* Flag as modified */ - key[pa >> 11] |= 0x6; - if (offset == 3) { addr += 4; /* Check if in storage area */ @@ -1051,8 +1050,10 @@ WriteHalf(uint32 addr, uint32 data) return 1; } } - key[pa2 >> 11] |= 0x6; } + + key[pa >> 11] |= 0x6; + key[pa2 >> 11] |= 0x6; pa >>= 2; pa2 >>= 2; M[pa] &= 0xffffff00; @@ -1061,6 +1062,10 @@ WriteHalf(uint32 addr, uint32 data) M[pa2] |= 0xff000000 & (data << 24); return 0; } + + /* Flag as modified */ + key[pa >> 11] |= 0x6; + pa >>= 2; mask = 0xffff; @@ -2346,8 +2351,7 @@ save_dbl: } /* Now we need to fetch the actual entry */ - addr2 = (entry & PTE_ADR) + (page << 1); - addr2 &= AMASK; + addr2 = ((entry & PTE_ADR) + (page << 1)) & AMASK; if (addr2 >= MEMSIZE) { storepsw(OPPSW, IRC_ADDR); goto supress; @@ -2369,7 +2373,7 @@ save_dbl: /* Convert to address */ entry >>= pte_shift; - addr2 = (addr1 & page_mask) | ((entry & TLB_PHY) << page_shift); + addr2 = ((addr1 & page_mask) | ((entry & TLB_PHY) << page_shift)) & AMASK; cc = 0; regs[reg1] = addr2; per_mod |= 1 << reg1; @@ -2963,7 +2967,7 @@ save_dbl: case OP_370: if (Q370) { - if (reg < 2 || reg > 0x13) { + if (reg > 0x13) { storepsw(OPPSW, IRC_OPR); goto supress; } @@ -2975,6 +2979,13 @@ save_dbl: goto supress; } switch(reg) { + case 0x0: /* CONCS */ + /* Connect channel set */ + case 0x1: /* DISCS */ + /* Disconnect channel set */ + cc = 3; + break; + case 0x2: /* STIDP */ /* Store CPUID in double word */ dest = 100; @@ -2987,15 +2998,18 @@ save_dbl: case 0x3: /* STIDC */ /* Store channel id */ - dest = (addr1 >> 8) & 0xff; - if (dest > MAX_CHAN) { + src1 = (addr1 >> 8) & 0xff; + if (src1 > MAX_CHAN) { cc = 3; break; } - if (dest == 0 || dest == 4) + dest = 0; + if ((chan_unit[src1].flags & UNIT_M_CTYPE) == UNIT_MUX) { dest = 0x10000000; - else - dest = 0; + } + if ((chan_unit[src1].flags & UNIT_M_CTYPE) == UNIT_BMUX) { + dest = 0x20000000; + } addr1 = 0xA8; if (WriteFull(addr1, dest)) goto supress; @@ -3102,9 +3116,7 @@ save_dbl: storepsw(OPPSW, IRC_OPR); goto supress; } - for (addr2 = 0; - addr2 < sizeof(tlb)/sizeof(uint32); - addr2++) + for (addr2 = 0; addr2 < sizeof(tlb)/sizeof(uint32); addr2++) tlb[addr2] = 0; break; case 0x10: /* SPX */ @@ -3118,6 +3130,7 @@ save_dbl: goto supress; case 0x13: /* RRB */ /* Set storage block reference bit to zero */ + addr1 &= AMASK; addr1 >>= 11; dest = key[addr1]; key[addr1] &= 0xfb; /* Clear reference bit */ @@ -3266,6 +3279,7 @@ save_dbl: break; case OP_LCTL: + temp = 0; if (Q360) { storepsw(OPPSW, IRC_OPR); } else if (flags & PROBLEM) { @@ -3326,12 +3340,10 @@ save_dbl: ~page_mask) & AMASK) >> page_shift; intval_en = ((dest & 0x400) != 0); tod_en = ((dest & 0x800) != 0); +// temp = 1; break; case 0x1: /* Segment table address and length */ - for (addr2 = 0; - addr2 < sizeof(tlb)/sizeof(uint32); - addr2++) - tlb[addr2] = 0; + temp = 1; seg_addr = dest & AMASK; seg_len = (((dest >> 24) & 0xff) + 1) << 4; break; @@ -3363,6 +3375,11 @@ save_dbl: reg1 &= 0xf; addr1 += 4; }; + /* Purge TLB if segment pointer updated */ + if (temp) { + for (addr2 = 0; addr2 < sizeof(tlb)/sizeof(uint32); addr2++) + tlb[addr2] = 0; + } } break; diff --git a/IBM360/ibm360_dasd.c b/IBM360/ibm360_dasd.c index 83ac5d9..37b2b5e 100644 --- a/IBM360/ibm360_dasd.c +++ b/IBM360/ibm360_dasd.c @@ -212,19 +212,20 @@ struct disk_t } disk_type[] = { - {"2301", 1, 200, 20483, 6, 0x01}, /* 4.1 M */ - {"2302", 250, 46, 4984, 6, 0x02}, /* 57.32 M 50ms, 120ms/10, 180ms> 10 */ - {"2303", 80, 10, 4984, 6, 0x03}, /* 4.00 M */ - {"2305", 48, 8, 14568, 6, 0x05}, /* 5.43 M */ - {"2305-2",96, 8, 14858, 6, 0x05}, /* 11.26 M */ - {"2311", 203, 10, 3717, 6, 0x11}, /* 7.32 M 156k/s 30 ms 145 full */ - {"2314", 202, 20, 7294, 6, 0x14}, /* 29.17 M */ - {"3330", 410, 19, 13165, 24, 0x30}, /* 100.00 M */ - {"3330-2",815, 19, 13165, 24, 0x30}, - {"3340", 349, 12, 8535, 24, 0x40}, /* 34.94 M */ - {"3340-2",698, 12, 8535, 24, 0x40}, /* 69.89 M */ - {"3350", 559, 30, 19254, 24, 0x50}, /* 304.80 M */ - {"5625", 403, 20, 7294, 6, 0x14}, /* 56.00 M */ + {"2301", 1, 200, 20483, 6, 0x01}, /* 4.1 M */ + {"2302", 250, 46, 4984, 6, 0x02}, /* 57.32 M 50ms, 120ms/10, 180ms> 10 */ + {"2303", 80, 10, 4984, 6, 0x03}, /* 4.00 M */ + {"2305", 48, 8, 14568, 6, 0x05}, /* 5.43 M */ + {"2305-2" ,96, 8, 14858, 6, 0x05}, /* 11.26 M */ + {"2311", 203, 10, 3717, 6, 0x11}, /* 7.32 M 156k/s 30 ms 145 full */ + {"2314", 202, 20, 7294, 6, 0x14}, /* 29.17 M */ + {"3330", 410, 19, 13165, 24, 0x30}, /* 100.00 M */ + {"3330-2" ,815, 19, 13165, 24, 0x30}, /* 194.00 M */ + {"3340", 349, 12, 8535, 24, 0x40}, /* 34.94 M */ + {"3340-2" ,698, 12, 8535, 24, 0x40}, /* 69.89 M */ + {"3350", 559, 30, 19254, 24, 0x50}, /* 304.80 M */ + {"3375", 962, 12, 36000, 24, 0x75}, /* 369.30 M */ + {"5625", 403, 20, 7294, 6, 0x14}, /* 56.00 M */ {NULL, 0} }; diff --git a/IBM360/ibm360_defs.h b/IBM360/ibm360_defs.h index efb8de7..308af96 100644 --- a/IBM360/ibm360_defs.h +++ b/IBM360/ibm360_defs.h @@ -299,6 +299,13 @@ typedef struct dib { #define OP_MP 0xFC #define OP_DP 0xFD +/* Channel type selection */ +#define UNIT_V_CTYPE (UNIT_V_UF + 0) +#define UNIT_SEL (0 << UNIT_V_CTYPE) /* Selector channel */ +#define UNIT_MUX (1 << UNIT_V_CTYPE) /* Multiplexer channel */ +#define UNIT_BMUX (2 << UNIT_V_CTYPE) /* Multiplexer channel */ +#define UNIT_M_CTYPE (3 << UNIT_V_CTYPE) + /* Channel sense bytes */ #define SNS_ATTN 0x80 /* Unit attention */ #define SNS_SMS 0x40 /* Status modifier */ @@ -393,6 +400,7 @@ extern DEVICE coml_dev; extern DEVICE com_dev; extern DEVICE scoml_dev; extern DEVICE scom_dev; -extern UNIT cpu_unit[]; +extern UNIT cpu_unit[]; +extern UNIT chan_unit[]; extern void fprint_inst(FILE *, uint16 *); diff --git a/IBM360/ibm360_scon.c b/IBM360/ibm360_scon.c index 96475b8..aa54fcb 100644 --- a/IBM360/ibm360_scon.c +++ b/IBM360/ibm360_scon.c @@ -42,6 +42,7 @@ #define CON_WR 0x01 /* Write console */ #define CON_ACR 0x09 /* Auto carrage return */ #define CON_RD 0x0a /* Read console */ +#define CON_ALR 0x0b /* Control Alarm */ #define CON_NOP 0x03 /* No op command */ #define CON_MSK 0x0f /* Command mask */ @@ -185,6 +186,9 @@ uint8 scon_startcmd(UNIT *uptr, uint8 cmd) { return 0; case 3: /* Control */ + if (cmd == CON_ALR) { + tmxr_putc_ln(&scon_ldsc[u], '\a'); + } sim_debug(DEBUG_CMD, &scon_dev, "%d: Cmd NOP\n", u); if (uptr->CMD & CON_REQ) { uptr->CMD &= ~CON_REQ; diff --git a/IBM360/ibm360_sys.c b/IBM360/ibm360_sys.c index 14e1c88..2f3c6bd 100644 --- a/IBM360/ibm360_sys.c +++ b/IBM360/ibm360_sys.c @@ -407,6 +407,8 @@ t_opcode optab[] = { }; t_opcode soptab[] = { + { 0x00, "CONCS", RS }, + { 0x01, "DISCS", RS }, { 0x02, "STIDP", RS }, { 0x03, "STIDC", RS }, { 0x04, "SCK", RS }, From 3266cff61d5cf51fd50d5ff782c50339fbf27f6e Mon Sep 17 00:00:00 2001 From: Lars Brinkhoff Date: Sat, 3 Feb 2024 10:59:27 +0100 Subject: [PATCH 6/7] KA10: Detect TEN11 dropped connection. --- PDP10/ka10_ten11.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PDP10/ka10_ten11.c b/PDP10/ka10_ten11.c index 89e231f..a6e7d79 100644 --- a/PDP10/ka10_ten11.c +++ b/PDP10/ka10_ten11.c @@ -236,6 +236,8 @@ static int transaction (unsigned char *request, unsigned char *response) do { tmxr_poll_rx (&ten11_desc); stat = tmxr_get_packet_ln (&ten11_ldsc, &ten11_request, &size); + if (!ten11_ldsc.conn) + return error ("Connection lost"); } while (stat != SCPE_OK || size == 0); if (size > 7) From 4cbff8455b482c76dec69e55352156cff4ce2d2e Mon Sep 17 00:00:00 2001 From: Lars Brinkhoff Date: Sat, 3 Feb 2024 10:59:50 +0100 Subject: [PATCH 7/7] KA10: Allow eight Unibus ports on the TEN11 device. --- PDP10/ka10_ten11.c | 65 ++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/PDP10/ka10_ten11.c b/PDP10/ka10_ten11.c index a6e7d79..fd6dfea 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,40 +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); - if (!ten11_ldsc.conn) - return error ("Connection lost"); + 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]; @@ -265,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; @@ -287,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; @@ -327,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, @@ -338,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]; @@ -357,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]) { @@ -370,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; @@ -419,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; }