mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-30 05:24:52 +00:00
Merge branch 'larsbrinkhoff-lars/ge'
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
424
PDP10/pdp6_ge.c
Normal file
424
PDP10/pdp6_ge.c
Normal file
@@ -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
|
||||
3
makefile
3
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.
|
||||
|
||||
Reference in New Issue
Block a user