KA10: Added support for KL10A/B.

This commit is contained in:
Author: Richard Cornwell 2020-03-09 23:07:47 -07:00 committed by Mark Pizzolato
parent c7d529c4db
commit c686f75894
49 changed files with 13982 additions and 2447 deletions

View file

@ -5,7 +5,7 @@ language: c
env: env:
# These are supposed to match ALL in makefile. # These are supposed to match ALL in makefile.
# Each job builds 15 simulators. # Each job builds 15 simulators.
- SIM="pdp1 pdp4 pdp6 pdp7 pdp8 pdp9 pdp10 pdp10-ka pdp10-ki pdp11 pdp15 vax microvax3900 microvax1 rtvax1000" - SIM="pdp1 pdp4 pdp6 pdp7 pdp8 pdp9 pdp10 pdp10-ka pdp10-ki pdp10-kl pdp11 pdp15 vax microvax3900 microvax1 rtvax1000"
- SIM="microvax2 vax730 vax750 vax780 vax8200 vax8600 microvax2000 infoserver100 infoserver150vxt microvax3100 microvax3100e vaxstation3100m30 vaxstation3100m38 vaxstation3100m76 vaxstation4000m60" - SIM="microvax2 vax730 vax750 vax780 vax8200 vax8600 microvax2000 infoserver100 infoserver150vxt microvax3100 microvax3100e vaxstation3100m30 vaxstation3100m38 vaxstation3100m76 vaxstation4000m60"
- SIM="microvax3100m80 vaxstation4000vlc infoserver1000 nova eclipse hp2100 hp3000 i1401 i1620 s3 altair altairz80 gri i7094 ibm1130" - SIM="microvax3100m80 vaxstation4000vlc infoserver1000 nova eclipse hp2100 hp3000 i1401 i1620 s3 altair altairz80 gri i7094 ibm1130"
- SIM="id16 id32 sds lgp h316 cdc1700 swtp6800mp-a swtp6800mp-a2 tx-0 ssem b5500 isys8010 isys8020 isys8030 isys8024" - SIM="id16 id32 sds lgp h316 cdc1700 swtp6800mp-a swtp6800mp-a2 tx-0 ssem b5500 isys8010 isys8020 isys8030 isys8024"

View file

@ -279,7 +279,7 @@ DEVICE ai_dev = {
AI_NAME, ai_unit, ai_reg, ai_mod, AI_NAME, ai_unit, ai_reg, ai_mod,
NUM_UNITS, 8, 18, 1, 8, 36, NUM_UNITS, 8, 18, 1, 8, 36,
NULL, NULL, &ai_reset, NULL, &ai_attach, &ai_detach, NULL, NULL, &ai_reset, NULL, &ai_attach, &ai_detach,
&ai_dib, DEV_DISABLE | DEV_DEBUG, 0, ai_debug, &ai_dib, DEV_DISABLE | DEV_DEBUG | DEV_DIS, 0, ai_debug,
NULL, NULL, &ai_help, NULL, NULL, &ai_description NULL, NULL, &ai_help, NULL, NULL, &ai_description
}; };
@ -997,7 +997,7 @@ t_stat ai_attach (UNIT *uptr, CONST char *cptr)
DIB *dib; DIB *dib;
r = attach_unit (uptr, cptr); r = attach_unit (uptr, cptr);
if (r != SCPE_OK) if (r != SCPE_OK || (sim_switches & SIM_SW_REST) != 0)
return r; return r;
rptr = find_dev_from_unit(uptr); rptr = find_dev_from_unit(uptr);
if (rptr == 0) if (rptr == 0)

View file

@ -31,9 +31,6 @@
#endif #endif
#if NUM_DEVS_AUXCPU > 0 #if NUM_DEVS_AUXCPU > 0
#include <fcntl.h>
//#include <unistd.h>
#include <sys/types.h>
/* External bus interface. */ /* External bus interface. */
#define DATO 1 #define DATO 1
@ -51,12 +48,11 @@
#define AUXCPU_POLL 1000 #define AUXCPU_POLL 1000
#define PIA u3
#define STATUS u4
t_addr auxcpu_base = 03000000;
static int pia = 0; static t_stat auxcpu_devio(uint32 dev, uint64 *data);
static int status = 0;
int auxcpu_base = 03000000;
static t_stat auxcpu_devio(uint32 dev, t_uint64 *data);
static t_stat auxcpu_svc (UNIT *uptr); static t_stat auxcpu_svc (UNIT *uptr);
static t_stat auxcpu_reset (DEVICE *dptr); static t_stat auxcpu_reset (DEVICE *dptr);
static t_stat auxcpu_attach (UNIT *uptr, CONST char *ptr); static t_stat auxcpu_attach (UNIT *uptr, CONST char *ptr);
@ -144,7 +140,6 @@ static t_stat auxcpu_attach (UNIT *uptr, CONST char *cptr)
return r; return r;
sim_debug(DBG_TRC, &auxcpu_dev, "activate connection\n"); sim_debug(DBG_TRC, &auxcpu_dev, "activate connection\n");
sim_activate (uptr, 10); /* start poll */ sim_activate (uptr, 10); /* start poll */
uptr->flags |= UNIT_ATT;
return SCPE_OK; return SCPE_OK;
} }
@ -156,8 +151,6 @@ static t_stat auxcpu_detach (UNIT *uptr)
return SCPE_OK; return SCPE_OK;
sim_cancel (uptr); sim_cancel (uptr);
r = tmxr_detach (&auxcpu_desc, uptr); r = tmxr_detach (&auxcpu_desc, uptr);
uptr->flags &= ~UNIT_ATT;
free (uptr->filename);
uptr->filename = NULL; uptr->filename = NULL;
return r; return r;
} }
@ -176,9 +169,9 @@ static t_stat auxcpu_svc (UNIT *uptr)
tmxr_reset_ln (&auxcpu_ldsc); tmxr_reset_ln (&auxcpu_ldsc);
} }
/* If incoming interrput => status |= 010 */ /* If incoming interrput => uptr->STATUS |= 010 */
if (status & 010) if (uptr->STATUS & 010)
set_interrupt(AUXCPU_DEVNUM, pia); set_interrupt(AUXCPU_DEVNUM, uptr->PIA);
else else
clr_interrupt(AUXCPU_DEVNUM); clr_interrupt(AUXCPU_DEVNUM);
@ -187,6 +180,7 @@ static t_stat auxcpu_svc (UNIT *uptr)
auxcpu_ldsc.rcve = 1; auxcpu_ldsc.rcve = 1;
uptr->wait = AUXCPU_POLL; uptr->wait = AUXCPU_POLL;
} }
sim_clock_coschedule (uptr, uptr->wait); sim_clock_coschedule (uptr, uptr->wait);
return SCPE_OK; return SCPE_OK;
} }
@ -239,25 +233,18 @@ static int transaction (unsigned char *request, unsigned char *response)
stat = tmxr_get_packet_ln (&auxcpu_ldsc, &auxcpu_request, &size); stat = tmxr_get_packet_ln (&auxcpu_ldsc, &auxcpu_request, &size);
} while (stat != SCPE_OK || size == 0); } while (stat != SCPE_OK || size == 0);
if (size > 7) if (size > 9)
return error ("Malformed transaction"); return error ("Malformed transaction");
memcpy (response, auxcpu_request, size); memcpy (response, auxcpu_request, size);
return 0; return 0;
} }
int auxcpu_read (int addr, t_uint64 *data) int auxcpu_read (t_addr addr, uint64 *data)
{ {
unsigned char request[12]; unsigned char request[12];
unsigned char response[12]; unsigned char response[12];
sim_interval -= AUXCPU_MEM_CYCLE;
if ((auxcpu_unit[0].flags & UNIT_ATT) == 0) {
*data = 0;
return 0;
}
addr &= 037777; addr &= 037777;
memset (request, 0, sizeof request); memset (request, 0, sizeof request);
@ -271,11 +258,11 @@ int auxcpu_read (int addr, t_uint64 *data)
switch (response[0]) switch (response[0])
{ {
case ACK: case ACK:
*data = (t_uint64)response[1]; *data = (uint64)response[1];
*data |= (t_uint64)response[2] << 8; *data |= (uint64)response[2] << 8;
*data |= (t_uint64)response[3] << 16; *data |= (uint64)response[3] << 16;
*data |= (t_uint64)response[4] << 24; *data |= (uint64)response[4] << 24;
*data |= (t_uint64)response[5] << 32; *data |= (uint64)response[5] << 32;
break; break;
case ERR: case ERR:
fprintf (stderr, "AUXCPU: Read error %06o\r\n", addr); fprintf (stderr, "AUXCPU: Read error %06o\r\n", addr);
@ -286,23 +273,18 @@ int auxcpu_read (int addr, t_uint64 *data)
*data = 0; *data = 0;
break; break;
default: default:
fprintf (stderr, "AUXCPU: recieved %o\r\n", response[0]);
return error ("Protocol error"); return error ("Protocol error");
} }
return 0; return 0;
} }
int auxcpu_write (int addr, t_uint64 data) int auxcpu_write (t_addr addr, uint64 data)
{ {
unsigned char request[12]; unsigned char request[12];
unsigned char response[12]; unsigned char response[12];
sim_interval -= AUXCPU_MEM_CYCLE;
if ((ten11_unit[0].flags & UNIT_ATT) == 0) {
return 0;
}
addr &= 037777; addr &= 037777;
memset (request, 0, sizeof request); memset (request, 0, sizeof request);
@ -318,8 +300,7 @@ int auxcpu_write (int addr, t_uint64 data)
transaction (request, response); transaction (request, response);
switch (response[0]) switch (response[0]) {
{
case ACK: case ACK:
break; break;
case ERR: case ERR:
@ -329,9 +310,9 @@ int auxcpu_write (int addr, t_uint64 data)
fprintf (stderr, "AUXCPU: Write timeout %06o\r\n", addr); fprintf (stderr, "AUXCPU: Write timeout %06o\r\n", addr);
break; break;
default: default:
fprintf (stderr, "AUXCPU: recieved %o\r\n", response[0]);
return error ("Protocol error"); return error ("Protocol error");
} }
return 0; return 0;
} }
@ -362,25 +343,26 @@ static int auxcpu_interrupt (void)
return 0; return 0;
} }
t_stat auxcpu_devio(uint32 dev, t_uint64 *data) t_stat auxcpu_devio(uint32 dev, uint64 *data)
{ {
DEVICE *dptr = &auxcpu_dev; DEVICE *dptr = &auxcpu_dev;
UNIT *uptr = &auxcpu_unit[0];
switch(dev & 07) { switch(dev & 07) {
case CONO: case CONO:
sim_debug(DEBUG_CONO, &auxcpu_dev, "CONO %012llo\n", *data); sim_debug(DEBUG_CONO, &auxcpu_dev, "CONO %012llo\n", *data);
pia = *data & 7; uptr->PIA = *data & 7;
if (*data & 010) if (*data & 010)
{ {
// Clear interrupt from the PDP-6. // Clear interrupt from the PDP-6.
status &= ~010; uptr->STATUS &= ~010;
clr_interrupt(AUXCPU_DEVNUM); clr_interrupt(AUXCPU_DEVNUM);
} }
if (*data & 020) if (*data & 020)
auxcpu_interrupt (); auxcpu_interrupt ();
break; break;
case CONI: case CONI:
*data = (status & 010) | pia; *data = (uptr->STATUS & 010) | uptr->PIA;
sim_debug(DEBUG_CONI, &auxcpu_dev, "CONI %012llo\n", *data); sim_debug(DEBUG_CONI, &auxcpu_dev, "CONI %012llo\n", *data);
break; break;
case DATAI: case DATAI:
@ -407,13 +389,14 @@ static t_stat auxcpu_set_base (UNIT *uptr, int32 val, CONST char *cptr, void *de
if (r != SCPE_OK) if (r != SCPE_OK)
return SCPE_ARG; return SCPE_ARG;
auxcpu_base = (int)x; auxcpu_base = (t_addr)(x&03777777);
return SCPE_OK; return SCPE_OK;
} }
static t_stat auxcpu_show_base (FILE *st, UNIT *uptr, int32 val, CONST void *desc) static t_stat auxcpu_show_base (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{ {
fprintf (st, "Base: %06o", auxcpu_base); fprintf (st, "Base: %011o", auxcpu_base);
return SCPE_OK; return SCPE_OK;
} }
#endif #endif

View file

@ -335,8 +335,6 @@ void ch10_command (uint32 data)
t_stat ch10_devio(uint32 dev, uint64 *data) t_stat ch10_devio(uint32 dev, uint64 *data)
{ {
DEVICE *dptr = &imx_dev;
switch(dev & 07) { switch(dev & 07) {
case CONO: case CONO:
sim_debug (DBG_REG, &ch10_dev, "CONO %012llo %012llo \n", *data, ch10_status); sim_debug (DBG_REG, &ch10_dev, "CONO %012llo %012llo \n", *data, ch10_status);

View file

@ -1,6 +1,6 @@
/* ka10_dkb.c:Stanford Microswitch scanner. /* ka10_dkb.c:Stanford Microswitch scanner.
Copyright (c) 2013-2017, Richard Cornwell Copyright (c) 2019-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -32,20 +32,40 @@
#if NUM_DEVS_DKB > 0 #if NUM_DEVS_DKB > 0
t_stat dkb_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); #include "sim_video.h"
const char *dkb_description (DEVICE *dptr);
#define DKB_DEVNUM 0310 #define DKB_DEVNUM 0310
#define DONE 010 /* Device has character */
#define SPW 020 /* Scanner in SPW mode */
#define VALID 010000
#define SPW_FLG 020000
#define CHAR 001777
#define SHFT 000100
#define TOP 000200
#define META 000400
#define CTRL 001000
#define STATUS u3 #define STATUS u3
#define DATA u4 #define DATA u4
#define PIA u5 #define PIA u5
#define LINE u6
t_stat dkb_devio(uint32 dev, uint64 *data); t_stat dkb_devio(uint32 dev, uint64 *data);
int dkb_keyboard (SIM_KEY_EVENT *kev);
t_stat dkb_svc(UNIT *uptr);
t_stat dkb_reset(DEVICE *dptr);
t_stat dkb_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
const char *dkb_description (DEVICE *dptr);
int dkb_kmod = 0;
DIB dkb_dib = { DKB_DEVNUM, 1, dkb_devio, NULL}; DIB dkb_dib = { DKB_DEVNUM, 1, dkb_devio, NULL};
UNIT dkb_unit[] = { UNIT dkb_unit[] = {
{UDATA (&dkb_svc, UNIT_IDLE, 0) },
{ 0 } { 0 }
}; };
@ -57,42 +77,368 @@ MTAB dkb_mod[] = {
DEVICE dkb_dev = { DEVICE dkb_dev = {
"DKB", dkb_unit, NULL, dkb_mod, "DKB", dkb_unit, NULL, dkb_mod,
2, 10, 31, 1, 8, 8, 2, 10, 31, 1, 8, 8,
NULL, NULL, NULL, NULL, NULL, dkb_reset,
NULL, NULL, NULL, &dkb_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS, 0, dev_debug, NULL, NULL, NULL, &dkb_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS, 0, dev_debug,
NULL, NULL, &dkb_help, NULL, NULL, &dkb_description NULL, NULL, &dkb_help, NULL, NULL, &dkb_description
}; };
int status;
t_stat dkb_devio(uint32 dev, uint64 *data) { t_stat dkb_devio(uint32 dev, uint64 *data) {
/* uint64 res; */ UNIT *uptr = &dkb_unit[0];
switch(dev & 3) { switch(dev & 3) {
case CONI: case CONI:
*data = status; *data = (uint64)(uptr->STATUS|uptr->PIA);
sim_debug(DEBUG_CONI, &dkb_dev, "DKB %03o CONI %06o\n", dev, (uint32)*data); sim_debug(DEBUG_CONI, &dkb_dev, "DKB %03o CONI %06o\n", dev, (uint32)*data);
break; break;
case CONO: case CONO:
status = (int)(*data&7); uptr->PIA = (int)(*data&7);
if (*data & DONE)
uptr->STATUS = 0;
clr_interrupt(DKB_DEVNUM);
sim_debug(DEBUG_CONO, &dkb_dev, "DKB %03o CONO %06o\n", dev, (uint32)*data); sim_debug(DEBUG_CONO, &dkb_dev, "DKB %03o CONO %06o\n", dev, (uint32)*data);
break; break;
case DATAI: case DATAI:
*data = (uint64)((uptr->LINE << 18) | (uptr->DATA));
uptr->STATUS = 0;
clr_interrupt(DKB_DEVNUM);
sim_debug(DEBUG_DATAIO, &dkb_dev, "DKB %03o DATAI %06o\n", dev, (uint32)*data); sim_debug(DEBUG_DATAIO, &dkb_dev, "DKB %03o DATAI %06o\n", dev, (uint32)*data);
break; break;
case DATAO: case DATAO:
if (*data & 010000) {
uptr->STATUS |= SPW;
uptr->LINE = (int)(*data & 077);
}
sim_debug(DEBUG_DATAIO, &dkb_dev, "DKB %03o DATAO %06o\n", dev, (uint32)*data); sim_debug(DEBUG_DATAIO, &dkb_dev, "DKB %03o DATAO %06o\n", dev, (uint32)*data);
break; break;
} }
return SCPE_OK; return SCPE_OK;
} }
int dkb_modifiers (SIM_KEY_EVENT *kev)
{
if (kev->state == SIM_KEYPRESS_UP) {
switch (kev->key) {
case SIM_KEY_SHIFT_L:
case SIM_KEY_SHIFT_R:
case SIM_KEY_CAPS_LOCK:
dkb_kmod |= SHFT;
return 1;
case SIM_KEY_CTRL_L:
case SIM_KEY_CTRL_R:
dkb_kmod |= CTRL;
return 1;
case SIM_KEY_WIN_L:
case SIM_KEY_WIN_R:
dkb_kmod |= META;
return 1;
case SIM_KEY_ALT_L:
case SIM_KEY_ALT_R:
dkb_kmod |= TOP;
return 1;
}
return 0;
}
if (kev->state == SIM_KEYPRESS_DOWN) {
switch (kev->key) {
case SIM_KEY_SHIFT_L:
case SIM_KEY_SHIFT_R:
case SIM_KEY_CAPS_LOCK:
dkb_kmod &= ~SHFT;
return 1;
case SIM_KEY_CTRL_L:
case SIM_KEY_CTRL_R:
dkb_kmod &= ~CTRL;
return 1;
case SIM_KEY_WIN_L:
case SIM_KEY_WIN_R:
dkb_kmod &= ~META;
return 1;
case SIM_KEY_ALT_L:
case SIM_KEY_ALT_R:
dkb_kmod &= ~TOP;
return 1;
}
return 0;
}
return 0;
}
int dkb_keys (SIM_KEY_EVENT *kev, UNIT *uptr)
{
if (kev->state == SIM_KEYPRESS_UP)
return 0;
switch (kev->key) {
case SIM_KEY_0: /* ok */
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = dkb_kmod | 051; /* ) */
else
uptr->DATA = dkb_kmod | 060;
return 1;
case SIM_KEY_1:
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 054) & ~TOP; /* ! */
else
uptr->DATA = dkb_kmod | 061;
return 1;
case SIM_KEY_2:
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 052) & ~TOP; /* Circle Star */
else
uptr->DATA = dkb_kmod | 062;
return 1;
case SIM_KEY_3:
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 022) & ~TOP; /* # */
else
uptr->DATA = dkb_kmod | 063;
return 1;
case SIM_KEY_4:
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 066) & ~TOP; /* $ */
else
uptr->DATA = dkb_kmod | 064;
return 1;
case SIM_KEY_5:
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 067) & ~TOP; /* % */
else
uptr->DATA = dkb_kmod | 065;
return 1;
case SIM_KEY_6:
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 073) & ~TOP; /* ^ */
else
uptr->DATA = dkb_kmod | 066;
return 1;
case SIM_KEY_7:
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 024) & ~TOP; /* & */
else
uptr->DATA = dkb_kmod | 067;
return 1;
case SIM_KEY_8: /* ok */
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 052) & ~TOP; /* * */
else
uptr->DATA = dkb_kmod | 070;
return 1;
case SIM_KEY_9: /* ok */
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = dkb_kmod | 050; /* ( */
else
uptr->DATA = dkb_kmod | 071;
return 1;
case SIM_KEY_A:
uptr->DATA = dkb_kmod | 001;
return 1;
case SIM_KEY_B:
uptr->DATA = dkb_kmod | 002;
return 1;
case SIM_KEY_C:
if (dkb_kmod == (META|TOP|SHFT)) /* Control C */
uptr->DATA = dkb_kmod | 043;
else
uptr->DATA = dkb_kmod | 003;
return 1;
case SIM_KEY_D:
uptr->DATA = dkb_kmod | 004;
return 1;
case SIM_KEY_E:
uptr->DATA = dkb_kmod | 005;
return 1;
case SIM_KEY_F:
uptr->DATA = dkb_kmod | 006;
return 1;
case SIM_KEY_G:
uptr->DATA = dkb_kmod | 007;
return 1;
case SIM_KEY_H:
uptr->DATA = dkb_kmod | 010;
return 1;
case SIM_KEY_I:
uptr->DATA = dkb_kmod | 011;
return 1;
case SIM_KEY_J:
uptr->DATA = dkb_kmod | 012;
return 1;
case SIM_KEY_K:
uptr->DATA = dkb_kmod | 013;
return 1;
case SIM_KEY_L:
uptr->DATA = dkb_kmod | 014;
return 1;
case SIM_KEY_M:
uptr->DATA = dkb_kmod | 015;
return 1;
case SIM_KEY_N:
uptr->DATA = dkb_kmod | 016;
return 1;
case SIM_KEY_O:
uptr->DATA = dkb_kmod | 017;
return 1;
case SIM_KEY_P:
uptr->DATA = dkb_kmod | 020;
return 1;
case SIM_KEY_Q:
uptr->DATA = dkb_kmod | 021;
return 1;
case SIM_KEY_R:
uptr->DATA = dkb_kmod | 022;
return 1;
case SIM_KEY_S:
uptr->DATA = dkb_kmod | 023;
return 1;
case SIM_KEY_T:
uptr->DATA = dkb_kmod | 024;
return 1;
case SIM_KEY_U:
uptr->DATA = dkb_kmod | 025;
return 1;
case SIM_KEY_V:
uptr->DATA = dkb_kmod | 026;
return 1;
case SIM_KEY_W:
uptr->DATA = dkb_kmod | 027;
return 1;
case SIM_KEY_X:
uptr->DATA = dkb_kmod | 030;
return 1;
case SIM_KEY_Y:
uptr->DATA = dkb_kmod | 031;
return 1;
case SIM_KEY_Z:
uptr->DATA = dkb_kmod | 032;
return 1;
case SIM_KEY_BACKQUOTE: /* ` ~ */
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = dkb_kmod | 043;
else
uptr->DATA = dkb_kmod | 00;
return 1;
case SIM_KEY_MINUS: /* - not */
uptr->DATA = dkb_kmod | 055;
return 1;
case SIM_KEY_EQUALS: /* = + */
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = dkb_kmod | 053;
else
uptr->DATA = (dkb_kmod | 010) & ~TOP;
return 1;
case SIM_KEY_LEFT_BRACKET: /* [ { */
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 017) & ~TOP;
else
uptr->DATA = (dkb_kmod | 050) & ~TOP;;
return 1;
case SIM_KEY_RIGHT_BRACKET: /* ] } */
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 020) & ~TOP;
else
uptr->DATA = (dkb_kmod | 051) & ~TOP;;
return 1;
case SIM_KEY_SEMICOLON: /* ; : */
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = dkb_kmod | 072 | TOP;
else
uptr->DATA = dkb_kmod | 073 | TOP;
return 1;
case SIM_KEY_SINGLE_QUOTE: /* ok */ /* ' " */
if ((dkb_kmod & (TOP|SHFT)) == TOP)
uptr->DATA = (dkb_kmod | 031) & ~TOP;
else
uptr->DATA = (dkb_kmod | 011) & ~TOP;
return 1;
case SIM_KEY_BACKSLASH: /* Ok */
if ((dkb_kmod & (TOP|SHFT)) == TOP) /* \ | */
uptr->DATA = (dkb_kmod | 053) & ~TOP;
else if ((dkb_kmod & (TOP|SHFT)) == SHFT)
uptr->DATA = (dkb_kmod | 034) & ~TOP;
else
uptr->DATA = dkb_kmod | 034 | TOP;
return 1;
case SIM_KEY_LEFT_BACKSLASH:
uptr->DATA = dkb_kmod | 034;
return 1;
case SIM_KEY_COMMA: /* ok */
if ((dkb_kmod & (TOP|SHFT)) == TOP) /* , < */
uptr->DATA = (dkb_kmod | 04) & ~TOP;
else
uptr->DATA = dkb_kmod | 054 | TOP;
return 1;
case SIM_KEY_PERIOD: /* Ok */
if ((dkb_kmod & (TOP|SHFT)) == TOP) /* . > */
uptr->DATA = (dkb_kmod | 06) & ~TOP;
else
uptr->DATA = dkb_kmod | 056;
return 1;
case SIM_KEY_SLASH: /* Ok */
if ((dkb_kmod & (TOP|SHFT)) == TOP) /* / ? */
uptr->DATA = (dkb_kmod | 056) & ~TOP;
else
uptr->DATA = dkb_kmod | 057;
return 1;
case SIM_KEY_ESC:
uptr->DATA = dkb_kmod | 042;
return 1;
case SIM_KEY_BACKSPACE:
uptr->DATA = dkb_kmod | 074;
return 1;
case SIM_KEY_DELETE:
uptr->DATA = dkb_kmod | 044;
return 1;
case SIM_KEY_TAB:
uptr->DATA = dkb_kmod | 045;
return 1;
case SIM_KEY_ENTER:
uptr->DATA = dkb_kmod | 033;
return 1;
case SIM_KEY_SPACE:
uptr->DATA = dkb_kmod | 040;
return 1;
default:
return 0;
}
}
int dkb_keyboard (SIM_KEY_EVENT *kev)
{
sim_debug(DEBUG_DETAIL, &dkb_dev, "DKB key %d %o\n", kev->key, kev->state);
if (dkb_modifiers (kev))
return 0;
if (dkb_keys (kev, &dkb_unit[0])) {
dkb_unit[0].DATA |= VALID;
dkb_unit[0].STATUS |= DONE;
set_interrupt(DKB_DEVNUM, dkb_unit[0].PIA);
return 0;
}
return 1;
}
t_stat dkb_svc( UNIT *uptr)
{
return SCPE_OK;
}
t_stat dkb_reset( DEVICE *dptr)
{
if ((dkb_dev.flags & DEV_DIS) == 0)
vid_display_kb_event_process = dkb_keyboard;
dkb_kmod = SHFT|TOP|META|CTRL;
return SCPE_OK;
}
t_stat dkb_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) t_stat dkb_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{ {
return SCPE_OK; fprintf (stderr, "This is the keyboard input for the Stanford III display\n");
return SCPE_OK;
} }
const char *dkb_description (DEVICE *dptr) const char *dkb_description (DEVICE *dptr)
{ {
return "Console TTY Line"; return "Keyboard scanner for III display devices";
} }
#endif #endif

View file

@ -1,6 +1,6 @@
/* ka10_dpk.c: Systems Concepts DK-10, Datapoint kludge. /* ka10_dpk.c: Systems Concepts DK-10, Datapoint kludge.
Copyright (c) 2018-2019, Lars Brinkhoff Copyright (c) 2018-2020, Lars Brinkhoff
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -65,7 +65,8 @@
#define PORT_INPUT 2 #define PORT_INPUT 2
static t_stat dpk_devio(uint32 dev, uint64 *data); static t_stat dpk_devio(uint32 dev, uint64 *data);
static t_stat dpk_svc (UNIT *uptr); static t_stat dpk_input_svc (UNIT *uptr);
static t_stat dpk_output_svc (UNIT *uptr);
static t_stat dpk_reset (DEVICE *dptr); static t_stat dpk_reset (DEVICE *dptr);
static t_stat dpk_attach (UNIT *uptr, CONST char *cptr); static t_stat dpk_attach (UNIT *uptr, CONST char *cptr);
static t_stat dpk_detach (UNIT *uptr); static t_stat dpk_detach (UNIT *uptr);
@ -84,9 +85,11 @@ static int dpk_port[16];
static int dpk_ibuf[16]; static int dpk_ibuf[16];
static int dpk_ird = 0; static int dpk_ird = 0;
static int dpk_iwr = 0; static int dpk_iwr = 0;
static int dpk_port_done = 0;
UNIT dpk_unit[] = { UNIT dpk_unit[] = {
{UDATA(dpk_svc, TT_MODE_8B|UNIT_IDLE|UNIT_ATTABLE, 0)}, /* 0 */ {UDATA(dpk_input_svc, TT_MODE_8B|UNIT_IDLE|UNIT_ATTABLE, 0)},
{UDATA(dpk_output_svc, UNIT_DIS|UNIT_IDLE, 0)},
}; };
DIB dpk_dib = {DPK_DEVNUM, 1, &dpk_devio, NULL}; DIB dpk_dib = {DPK_DEVNUM, 1, &dpk_devio, NULL};
@ -107,14 +110,26 @@ MTAB dpk_mod[] = {
DEVICE dpk_dev = { DEVICE dpk_dev = {
DPK_NAME, dpk_unit, NULL, dpk_mod, DPK_NAME, dpk_unit, NULL, dpk_mod,
1, 8, 0, 1, 8, 36, 2, 8, 0, 1, 8, 36,
NULL, NULL, dpk_reset, NULL, dpk_attach, dpk_detach, NULL, NULL, dpk_reset, NULL, dpk_attach, dpk_detach,
&dpk_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, dev_debug, &dpk_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, dev_debug,
NULL, NULL, dpk_help, NULL, NULL, dpk_description NULL, NULL, dpk_help, NULL, NULL, dpk_description
}; };
static void dpk_set_ospeed (int port, uint64 data)
{
static const char *map[] =
{ "134", "600", "110", "150", "300", "1200", "2400", "4800" };
static const char *speed;
speed = map[(data & DPK_SPEED) >> 9];
sim_debug(DEBUG_CMD, &dpk_dev, "Set port %d output speed %s\n",
port, speed);
tmxr_set_line_speed(&dpk_ldsc[port], speed);
}
static t_stat dpk_devio(uint32 dev, uint64 *data) static t_stat dpk_devio(uint32 dev, uint64 *data)
{ {
static int scan = 0;
DEVICE *dptr = &dpk_dev; DEVICE *dptr = &dpk_dev;
int port; int port;
@ -138,22 +153,27 @@ static t_stat dpk_devio(uint32 dev, uint64 *data)
break; break;
case DPK_OSTART: case DPK_OSTART:
dpk_port[port] |= PORT_OUTPUT; dpk_port[port] |= PORT_OUTPUT;
dpk_port_done &= ~(1 << port);
if (dpk_port_done == 0)
dpk_status &= ~DPK_ODONE; dpk_status &= ~DPK_ODONE;
sim_activate_abs (&dpk_unit[1], 0);
break; break;
case DPK_ISTOP: case DPK_ISTOP:
dpk_port[port] &= ~PORT_INPUT; dpk_port[port] &= ~PORT_INPUT;
break; break;
case DPK_ISTART: case DPK_ISTART:
dpk_port[port] |= PORT_OUTPUT; dpk_port[port] |= PORT_INPUT;
break; break;
case DPK_OSTOP: case DPK_OSTOP:
dpk_port[port] &= ~PORT_OUTPUT; dpk_port[port] &= ~PORT_OUTPUT;
dpk_port_done &= ~(1 << port);
if (dpk_port_done == 0)
dpk_status &= ~DPK_ODONE; dpk_status &= ~DPK_ODONE;
break; break;
case DPK_OSPEED: case DPK_OSPEED:
sim_debug(DEBUG_CMD, &dpk_dev, "Set port %d output speed %lld\n", dpk_set_ospeed (port, *data);
port, (*data & DPK_SPEED) >> 9);
dpk_port[port] |= PORT_OUTPUT; dpk_port[port] |= PORT_OUTPUT;
sim_activate_abs (&dpk_unit[1], 0);
break; break;
case DPK_ISPEED_STOP: case DPK_ISPEED_STOP:
dpk_port[port] &= ~PORT_INPUT; dpk_port[port] &= ~PORT_INPUT;
@ -173,13 +193,20 @@ static t_stat dpk_devio(uint32 dev, uint64 *data)
dpk_status |= *data & DPK_PIA; dpk_status |= *data & DPK_PIA;
break; break;
case CONI|4: case CONI|4:
dpk_status &= ~DPK_OLINE;
for (port = 0; port < DPK_LINES; port++) {
scan = (scan + 1) & 017;
if (dpk_port_done & (1 << scan)) {
dpk_status |= scan << 18;
break;
}
}
*data = dpk_status & DPK_CONI_BITS; *data = dpk_status & DPK_CONI_BITS;
sim_debug(DEBUG_CONI, &dpk_dev, "%07llo\n", *data); sim_debug(DEBUG_CONI, &dpk_dev, "%07llo\n", *data);
break; break;
case DATAO|4: case DATAO|4:
dpk_base = *data & 03777777; dpk_base = *data & 03777777;
if (*data & DPK_IEN) dpk_ien = ((*data & DPK_IEN) != 0);
dpk_ien = 1;
sim_debug(DEBUG_DATAIO, &dpk_dev, "DATAO %06llo\n", *data); sim_debug(DEBUG_DATAIO, &dpk_dev, "DATAO %06llo\n", *data);
break; break;
case DATAI|4: case DATAI|4:
@ -230,73 +257,60 @@ static int ildb (uint64 *pointer)
return ch; return ch;
} }
static int dpk_output (int port, TMLN *lp) static void dpk_output (int port, TMLN *lp)
{ {
uint64 count; uint64 count;
int ch; int ch;
if ((dpk_port[port] & PORT_OUTPUT) == 0) if ((dpk_port[port] & PORT_OUTPUT) == 0)
return 0; return;
if (tmxr_txdone_ln (lp) == 0)
return;
if (M[dpk_base + 2*port] == 0777777777777LL) { if (M[dpk_base + 2*port] == 0777777777777LL) {
dpk_port[port] &= ~PORT_OUTPUT; dpk_port[port] &= ~PORT_OUTPUT;
dpk_status &= ~DPK_OLINE;
dpk_status |= port << 18;
dpk_status |= DPK_ODONE; dpk_status |= DPK_ODONE;
dpk_port_done |= 1 << port;
if (dpk_ien) if (dpk_ien)
set_interrupt(DPK_DEVNUM, dpk_status & DPK_PIA); set_interrupt(DPK_DEVNUM, dpk_status & DPK_PIA);
return 0; return;
} }
ch = ildb (&M[dpk_base + 2*port + 1]); ch = ildb (&M[dpk_base + 2*port + 1]);
if (lp->conn) {
ch = sim_tt_outcvt(ch & 0377, TT_GET_MODE (dpk_unit[0].flags)); ch = sim_tt_outcvt(ch & 0377, TT_GET_MODE (dpk_unit[0].flags));
tmxr_putc_ln (lp, ch); tmxr_putc_ln (lp, ch);
}
count = M[dpk_base + 2*port] - 1; count = M[dpk_base + 2*port] - 1;
M[dpk_base + 2*port] = count & 0777777777777LL; M[dpk_base + 2*port] = count & 0777777777777LL;
return 1;
} }
static t_stat dpk_svc (UNIT *uptr) static t_stat dpk_input_svc (UNIT *uptr)
{ {
static int scan = 0; static int scan = 0;
int32 ch;
int i; int i;
/* 16 ports at 4800 baud, rounded up. */ sim_clock_coschedule (uptr, 1000);
sim_clock_coschedule (uptr, 200);
i = tmxr_poll_conn (&dpk_desc); i = tmxr_poll_conn (&dpk_desc);
if (i >= 0) { if (i >= 0) {
dpk_ldsc[i].conn = 1;
dpk_ldsc[i].rcve = 1; dpk_ldsc[i].rcve = 1;
dpk_ldsc[i].xmte = 1; dpk_ldsc[i].xmte = 1;
sim_debug(DEBUG_CMD, &dpk_dev, "Connect %d\n", i); sim_debug(DEBUG_CMD, &dpk_dev, "Connect %d\n", i);
} }
tmxr_poll_rx (&dpk_desc); tmxr_poll_rx (&dpk_desc);
tmxr_poll_tx (&dpk_desc);
for (i = 0; i < DPK_LINES; i++) { for (i = 0; i < DPK_LINES; i++) {
/* Round robin scan 16 lines. */ /* Round robin scan 16 lines. */
scan = (scan + 1) & 017; scan = (scan + 1) & 017;
/* 1 means the line became ready since the last check. Ignore ch = tmxr_getc_ln(&dpk_ldsc[scan]);
-1 which means "still ready". */ if (ch & TMXR_VALID) {
if (tmxr_txdone_ln (&dpk_ldsc[scan])) {
if (dpk_output (scan, &dpk_ldsc[scan]))
break;
}
if (!dpk_ldsc[scan].conn)
continue;
if (tmxr_input_pending_ln (&dpk_ldsc[scan])) {
if ((dpk_port[scan] & PORT_INPUT) == 0) if ((dpk_port[scan] & PORT_INPUT) == 0)
continue; continue;
dpk_ibuf[dpk_iwr++] = (scan << 18) | (tmxr_getc_ln (&dpk_ldsc[scan]) & 0177); dpk_ibuf[dpk_iwr++] = (scan << 18) | (ch & 0177);
dpk_iwr &= 15; dpk_iwr &= 15;
dpk_status |= DPK_IDONE; dpk_status |= DPK_IDONE;
if (dpk_ien) if (dpk_ien)
@ -308,26 +322,42 @@ static t_stat dpk_svc (UNIT *uptr)
return SCPE_OK; return SCPE_OK;
} }
static t_stat dpk_output_svc (UNIT *uptr)
{
int i;
for (i = 0; i < DPK_LINES; i++) {
dpk_output (i, &dpk_ldsc[i]);
}
tmxr_poll_tx (&dpk_desc);
sim_activate_after (uptr, 1000000);
return SCPE_OK;
}
static t_stat dpk_reset (DEVICE *dptr) static t_stat dpk_reset (DEVICE *dptr)
{ {
int i; int i;
sim_debug(DEBUG_CMD, &dpk_dev, "Reset\n"); sim_debug(DEBUG_CMD, &dpk_dev, "Reset\n");
if (dpk_unit->flags & UNIT_ATT) if (dpk_unit->flags & UNIT_ATT)
sim_activate (dpk_unit, tmxr_poll); sim_activate (&dpk_unit[0], tmxr_poll);
else else {
sim_cancel (dpk_unit); sim_cancel (&dpk_unit[0]);
sim_cancel (&dpk_unit[1]);
}
dpk_ien = 0; dpk_ien = 0;
dpk_base = 0; dpk_base = 0;
dpk_status = 0; dpk_status = 0;
dpk_ird = dpk_iwr = 0; dpk_ird = dpk_iwr = 0;
memset (dpk_port, 0, sizeof dpk_port); memset (dpk_port, 0, sizeof dpk_port);
dpk_port_done = 0;
clr_interrupt(DPK_DEVNUM); clr_interrupt(DPK_DEVNUM);
for (i = 0; i < DPK_LINES; i++) { for (i = 0; i < DPK_LINES; i++) {
tmxr_set_line_unit (&dpk_desc, i, dpk_unit); tmxr_set_line_unit (&dpk_desc, i, &dpk_unit[0]);
tmxr_set_line_output_unit (&dpk_desc, i, dpk_unit); tmxr_set_line_output_unit (&dpk_desc, i, &dpk_unit[1]);
} }
return SCPE_OK; return SCPE_OK;
@ -358,7 +388,8 @@ static t_stat dpk_detach (UNIT *uptr)
dpk_ldsc[i].xmte = 0; dpk_ldsc[i].xmte = 0;
} }
dpk_status = 0; dpk_status = 0;
sim_cancel (uptr); sim_cancel (&dpk_unit[0]);
sim_cancel (&dpk_unit[1]);
return stat; return stat;
} }

669
PDP10/ka10_iii.c Normal file
View file

@ -0,0 +1,669 @@
/* ka10_iii.c: Triple III display processor.
Copyright (c) 2019-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Richard Cornwell shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Richard Cornwell
*/
#include "kx10_defs.h"
#ifndef NUM_DEVS_III
#define NUM_DEVS_III 0
#endif
#if NUM_DEVS_III > 0
#include "display/display.h"
#include "display/iii.h"
#define III_DEVNUM 0430
#define STATUS u3
#define MAR u4
#define PIA u5
#define POS u6
/* CONO Bits */
#define SET_PIA 000000010 /* Set if this bit is zero */
#define STOP 000000020 /* Stop processor after instruction */
#define CONT 000000040 /* Start execution at address */
#define F 000000100 /* Clear flags */
#define SET_MSK 000360000 /* Set mask */
#define RST_MSK 007400000 /* Reset mask */
/* CONI Bits */
#define PIA_MSK 000000007
#define INST_HLT 000000010 /* 32 - Halt instruction */
#define WRAP_ENB 000000020 /* 31 - Wrap around mask */
#define EDGE_ENB 000000040 /* 30 - Edge interrupt mask */
#define LIGH_ENB 000000100 /* 29 - Light pen enable mask */
#define CLK_STOP 000000200 /* 28 - Clock stop */
/* 27 - Not used */
#define CLK_BIT 000001000 /* 26 - Clock */
#define NXM_BIT 000002000 /* 25 - Non-existent memory */
#define IRQ_BIT 000004000 /* 24 - Interrupt pending */
#define DATAO_LK 000010000 /* 23 - PDP10 gave DATAO when running */
#define CONT_BIT 000020000 /* 22 - Control bit */
#define LIGHT_FLG 000040000 /* 21 - Light pen flag */
#define WRAP_FLG 000100000 /* 20 - Wrap around flag */
#define EDGE_FLG 000200000 /* 19 - Edge overflow */
#define HLT_FLG 000400000 /* 18 - Not running */
#define WRAP_MSK 00001
#define EDGE_MSK 00002
#define LIGH_MSK 00004
#define HLT_MSK 00010
#define WRP_FBIT 00020
#define EDG_FBIT 00040
#define LIT_FBIT 00100
#define CTL_FBIT 00200
#define HLT_FBIT 00400
#define NXM_FLG 01000
#define DATA_FLG 02000
#define RUN_FLG 04000
#define TSS_INST 012 /* Test */
#define LVW_INST 006 /* Long Vector */
#define SVW_INST 002 /* Short vector */
#define JMP_INST 000 /* Jump or Halt */
#define JSR_INST 004 /* JSR(1) or JMS(0), SAVE(3) */
#define RES_INST 014 /* Restore */
#define SEL_INST 010 /* Select instruction */
#define POS_X 01777400000
#define POS_Y 00000377700
#define CBRT 00000000070 /* Current brightness */
#define CSIZE 00000000007 /* Current char size */
#define POS_X_V 16
#define POS_Y_V 6
#define CBRT_V 3
#define CSIZE_V 0
/*
* Character map.
* M(x,y) moves pointer to x,y.
* V(x,y) draws a vector between current pointer and x,y.
* All characters start at 0,6 and end at 8,6.
* In the map there are up to 18 points per character. For a character a M(0,0) indicates
* that drawing is done and a move to 8,6 should be done.
*/
#define M(x,y) (x << 4)|y|0000
#define V(x,y) (x << 4)|y|0200
uint8 map[128][18] = {
/* Blank */ { 0 },
/* Down */ { M(0,9), V(3,6), V(3,14), M(3,6), V(6,9) },
/* Alpha */ { M(6,6), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(6,9) },
/* Beta */ { V(2,8), V(2,13), V(3,14), V(5,14), V(6,13), V(6,12), V(5,11),
V(2,11), M(5,11), V(6,10), V(6,9), V(5,8), V(3,8), V(2,9) },
/* ^ */ { M(0,8), V(3,11), V(6,8) },
/* Not */ { M(0,10), V(6,10), V(6,7) },
/* Epsilon */ { M(3,9), V(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(2,6), V(3,7),
M(2,8), V(0,8) },
/* Pi */ { M(0,10), V(6,10), M(4,10), V(4,6), M(2,6), V(2,10) },
/* Lambda */ { V(3,9), M(0,11), V(1,11), V(6,6) },
/* ?? */ { M(0,11), V(1,12), V(2,12), V(5,9), V(5,7), V(4,6), V(3,6), V(2,7),
V(2,8), V(6,12) },
/* Delta */ { M(2,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9),
V(3,10), V(2,10), V(2,12), V(4,12) },
/* Integ */ { M(0,7), V(1,6), V(2,6), V(3,7), V(3,12), V(4,13), V(5,13), V(6,12) },
/* PlusMinus */{ M(0,9), V(4,9), M(2,11), V(2,7), M(0,7), V(4,7) },
/* Circross */ { M(0,8), V(0,7), V(1,6), V(3,6), V(4,7), V(4,9), V(3,10), V(1,10),
V(0,9), V(0,8), V(4,8), M(2,10), V(2,6) },
/* Sigma */ { M(0,10), V(1,9), V(2,9), V(4,11), V(5,11), V(6,10), V(5,9), V(4,9),
V(2,11), V(1,11), V(0,10) },
/* Union */ { M(4,8), V(3,9), V(1,9), V(0,8), V(0,7), V(1,6), V(3,6), V(4,7),
V(4,10), V(2,12), V(1,12) },
/* Intersect */{ M(3,11), V(1,11), V(0,10), V(0,8), V(1,7), V(3,7) },
/* Cap */ { M(0,11), V(2,11), V(3,10), V(3,8), V(2,7), V(0,7) },
/* Cup */ { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7) },
/* A */ { M(0,10), V(0,8), V(1,7), V(3,7), V(4,8), V(4,10) },
/* E */ { M(0,13), V(0,8), V(2,6), V(4,6), V(6,8), V(6,13), M(0,10), V(6,10) },
/* cx */ { V(6,6), V(6,14), V(0,14), M(2,10), V(6,10) },
{ V(4,10), M(0,10), V(4,6), M(3,6), V(1,6), V(0,7), V(0,9), V(1,10),
V(3,10), V(4,9), V(4,7), V(3,6) },
/* Dbl arrow */{ M(2,8), V(0,10), V(2,12), M(0,10), V(6,10), M(4,12), V(6,10),
V(4,8)},
/* Under */ { M(0,5), V(6,5) },
{ M(0,10), V(6,10), M(3,13), V(6,10), V(3,7) },
{ M(0,12), V(2,14), V(4,12), V(6,14) },
{ V(6,12), M(0,10), V(6,10), M(0,8), V(6,8) },
{ V(3,6), M(3,7), V(0,10), V(3,13) },
{ V(3,6), M(0,7), V(3,10), V(0,13) },
{ M(0,7), V(6,7), M(6,9), V(0,9), M(0,11), V(6,11) },
{ M(0,11), V(3,8), V(6,11) },
/* Blank */ { 0, },
/* ! */ { M(2,6), V(2,7), M(2,8), V(2,13) },
/* " */ { M(2,12), V(2,14), M(4,14), V(4,12) },
/* # */ { M(2,7), V(2,13), M(4,13), V(4,7), M(6,9), V(0,9), M(0,11), V(6,11) },
/* $ */ { M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14),
V(4,14), V(6,12), M(4,14), V(4,6), M(2,6), V(2,14) },
/* % */ { V(6,12), V(1,12), V(0,11), V(0,10), V(1,9), V(2,9), V(3,10), V(3,11),
V(2,12), M(4,9), V(3,8), V(3,7), V(4,6), V(5,6), V(6,7), V(6,8),
V(5,9), V(4,9) },
/* & */ { M(6,6), V(1,11), V(1,13), V(2,14), V(3,14), V(4,13), V(0,9), V(0,7),
V(1,6), V(3,6), V(5,8) },
/* ' */ { M(2,12), V(4,14) },
/* ( */ { M(2,6), V(0,8), V(0,12), V(2,14) },
/* ) */ { V(2,8), V(2,12), V(0,14) },
/* * */ { M(1,8), V(5,12), M(3,13), V(3,7), M(5,8), V(1,12), M(0,10),
V(6,10) },
/* + */ { M(2,7), V(2,11), M(0,9), V(4,9) },
/* , */ { M(0,7), V(1,6), V(1,5), V(0,4) },
/* - */ { M(0,9), V(4,9) },
/* . */ { M(2,6), V(3,6), V(3,7), V(2,7), V(2,6) },
/* / */ { V(6,12) },
/* 0 */ { M(0,7), V(6,13), M(6,12), V(4,14), V(2,14), V(0,12), V(0,8), V(2,6),
V(4,6), V(6,8), V(6,12) },
/* 1 */ { M(1,12), V(3,14), V(3,6) },
/* 2 */ { M(0,13), V(1,14), V(4,14), V(6,12), V(6,11), V(5,10), V(2,10),
V(0,8), V(0,6), V(6,6) },
/* 3 */ { M(0,14), V(6,14), V(6,12), V(4,10), V(5,10), V(6,9), V(6,7), V(5,6),
V(0,6) },
/* 4 */ { M(5,6), V(5,14), V(0,9), V(6,9) },
/* 5 */ { M(0,7), V(1,6), V(4,6), V(6,8), V(6,9), V(5,10), V(1,10), V(0,9),
V(0,14), V(6,14) },
/* 6 */ { M(0,9), V(1,10), V(5,10), V(6,9), V(6,7), V(5,6), V(1,6), V(0,7),
V(0,10), V(4,14) },
/* 7 */ { V(6,12), V(6,14), V(0,14) },
/* 8 */ { M(1,10), V(0,9), V(0,7), V(1,6), V(5,6), V(6,7), V(6,9), V(5,10),
V(6,11), V(6,13), V(5,14), V(1,14), V(0,13), V(0,11), V(1,10),
V(5,10) },
/* 9 */ { M(2,6), V(6,10), V(6,13), V(5,14), V(1,14), V(0,13), V(0,11),
V(1,10), V(5,10), V(6,11) },
/* : */ { M(2,6), V(3,6), V(3,7), V(2,7), V(2,6), M(2,10), V(3,10), V(3,11),
V(2,11), V(2,10) },
/* ; */ { M(2,7), V(3,6), V(3,5), V(2,4), M(2,10), V(3,10), V(3,11), V(2,11),
V(2,10) },
/* < */ { M(3,7), V(0,10), V(3,13) },
/* = */ { M(0,8), V(6,8), M(6,10), V(0,10) },
/* > */ { M(0,7), V(3,10), V(0,13) },
/* ? */ { M(0,13), V(1,14), V(2,13), V(2,12), V(1,11), V(1,8), M(1,7),
V(1,6) },
/* @ */ { M(1,6), V(0,7), V(0,11), V(1,12), V(5,12), V(6,11), V(6,8), V(5,7),
V(4,8), V(4,11), M(4,10), V(3,11), V(2,11), V(1,10), V(1,9), V(2,8),
V(3,8), V(4,9) },
/* A */ { V(0,12), V(2,14), V(4,14), V(6,12), V(6,9), V(0,9), V(6,9), V(6,6) },
/* B */ { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(5,10),
V(6,9), V(6,7), V(5,6), V(0,6) },
/* C */ { M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(5,6), V(6,7) },
/* D */ { V(0,14), V(4,14), V(6,12), V(6,8), V(4,6), V(0,6) },
/* E */ { M(6,6), V(0,6), V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) },
/* F */ { V(0,10), V(4,10), V(0,10), V(0,14), V(6,14) },
/* G */ { M(6,13), V(5,14), V(2,14), V(0,12), V(0,8), V(2,6), V(4,6), V(6,8),
V(6,10), V(4,10) },
/* H */ { V(0,14), V(0,10), V(6,10), V(6,14), V(6,6) },
/* I */ { M(1,6), V(5,6), V(3,6), V(3,14), V(1,14), V(5,14) },
/* J */ { M(1,9), V(1,7), V(2,6), V(3,6), V(4,7), V(4,14), V(2,14), V(6,14) },
/* K */ { V(0,14), V(0,8), V(6,14), V(2,10), V(6,6) },
/* L */ { M(0,14), V(0,6), V(6,6) },
/* M */ { V(0,14), V(3,11), V(6,14), V(6,6) },
/* N */ { V(0,14), V(0,13), V(6,7), V(6,6), V(6,14) },
/* O */ { M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6),
V(0,8) },
/* P */ { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10) },
/* Q */ { M(0,8), V(0,12), V(2,14), V(4,14), V(6,12), V(6,8), V(4,6), V(2,6),
V(0,8), M(3,9), V(6,6) },
/* R */ { V(0,14), V(5,14), V(6,13), V(6,11), V(5,10), V(0,10), V(2,10),
V(6,6) },
/* S */ { M(0,8), V(2,6), V(4,6), V(6,8), V(4,10), V(2,10), V(0,12), V(2,14),
V(4,14), V(6,12) },
/* T */ { M(3,6), V(3,14), V(0,14), V(6,14) },
/* U */ { M(0,14), V(0,7), V(1,6), V(5,6), V(6,7), V(6,14) },
/* V */ { M(0,14), V(0,9), V(3,6), V(6,9), V(6,14) },
/* W */ { M(0,14), V(0,6), V(3,9), V(6,6), V(6,14) },
/* X */ { V(0,7), V(6,13), V(6,14), M(0,14), V(0,13), V(6,7), V(6,6) },
/* Y */ { M(0,14), V(3,11), V(6,14), V(3,11), V(3,6) },
/* Z */ { M(0,14), V(6,14), V(6,13), V(0,7), V(0,6), V(6,6) },
/* [ */ { M(3,5), V(0,5), V(0,15), V(3,15) },
/* \ */ { M(0,12), V(6,6) },
/* ] */ { M(0,5), V(3,5), V(3,15), V(0,15) },
/* up arrow */ { M(0,11), V(3,14), V(6,11), M(3,14), V(3,6) },
/* left arrow*/{ M(3,7), V(0,10), V(3,13), M(0,10), V(6,10) },
/* ` */ { M(2,14), V(4,12) },
/* a */ { M(0,9), V(1,10), V(3,10), V(4,9), V(4,6), M(4,8), V(3,9), V(1,9),
V(0,8), V(0,7), V(1,6), V(3,6), V(4,7) },
/* b */ { V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6),
V(0,7) },
/* c */ { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7) },
/* d */ { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6),
V(0,7), M(4,6), V(4,13) },
/* e */ { M(4,7), V(3,6), V(1,6), V(0,7), V(0,9), V(1,10), V(3,10), V(4,9),
V(4,8), V(0,8) },
/* f */ { M(2,6), V(2,12), V(3,13), V(4,13), V(5,12), M(0,11), V(4,11) },
/* g */ { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7),
M(4,10), V(4,5), V(3,4), V(1,4), V(0,5) },
/* h */ { V(0,13), M(0,9), V(1,10), V(3,10), V(4,9), V(4,6) },
/* i */ { M(3,12), V(3,11), M(3,10), V(3,7), V(4,6), V(5,6) },
/* k */ { M(3,12), V(3,11), M(3,10), V(3,5), V(2,4), V(1,3) },
/* j */ { V(0,13), M(0,8), V(2,10), M(0,8), V(2,6) },
/* l */ { M(2,6), V(2,13) },
/* m */ { V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6), M(3,9), V(4,10),
V(5,10), V(6,9), V(6,6) },
/* n */ { V(0,10), M(0,9), V(1,10), V(2,10), V(3,9), V(3,6) },
/* o */ { M(0,7), V(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6), V(1,6),
V(0,7) },
/* p */ { M(0,4), V(0,10), M(0,9), V(1,10), V(3,10), V(4,9), V(4,7), V(3,6),
V(1,6), V(0,7) },
/* q */ { M(4,9), V(3,10), V(1,10), V(0,9), V(0,7), V(1,6), V(3,6), V(4,7),
M(4,10), V(4,4) },
/* r */ { V(0,10), M(0,9), V(1,10), V(3,10), V(4,9) },
/* s */ { M(0,7), V(1,6), V(3,6), V(4,7), V(3,8), V(1,8), V(0,9), V(1,10),
V(3,10), V(4,9) },
/* t */ { M(2,13), V(2,7), V(3,6), V(4,6), V(5,7), M(1,11), V(3,11) },
/* u */ { M(0,10), V(0,7), V(1,6), V(3,6), V(4,7), V(4,10), V(4,6) },
/* v */ { M(0,9), V(3,6), V(6,9) },
/* w */ { M(0,10), V(0,6), V(2,8), V(4,6), V(4,10) },
/* x */ { V(4,10), M(0,10), V(4,6) },
/* y */ { M(0,9), V(3,6), M(6,9), V(1,4), V(0,4) },
/* z */ { M(0,10), V(4,10), V(0,6), V(4,6) },
/* { */ { M(3,15), V(2,14), V(2,12), V(0,10), V(2,8), V(2,6), V(3,5) },
/* | */ { M(2,4), V(2,14) },
/* diamon */ { M(3,6), V(0,9), V(3,12), V(6,9), V(3,6) },
/* } */ { M(0,15), V(1,14), V(1,12), V(3,10), V(1,8), V(1,6), V(0,5) },
/* \ */ { M(0,12), V(6,6) },
};
float scale[] = { 1.0F,
1.0F, /* 128 chars per line */
1.3F, /* 96 chars per line */
2.0F, /* 64 chars per line */
2.5F, /* 48 chars per line */
4.0F, /* 32 chars per line */
5.3F, /* 24 chars per line */
8.0F /* 16 chars per line */
};
uint64 iii_instr; /* Currently executing instruction */
int iii_sel; /* Select mask */
t_stat iii_devio(uint32 dev, uint64 *data);
t_stat iii_svc(UNIT *uptr);
t_stat iii_reset(DEVICE *dptr);
static void draw_point(int x, int y, int b, UNIT *uptr);
static void draw_line(int x1, int y1, int x2, int y2, int b, UNIT *uptr);
t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
const char *iii_description (DEVICE *dptr);
DIB iii_dib = { III_DEVNUM, 1, iii_devio, NULL};
UNIT iii_unit[] = {
{UDATA (&iii_svc, UNIT_IDLE, 0) },
{ 0 }
};
MTAB iii_mod[] = {
{ 0 }
};
DEVICE iii_dev = {
"III", iii_unit, NULL, iii_mod,
2, 10, 31, 1, 8, 8,
NULL, NULL, iii_reset,
NULL, NULL, NULL, &iii_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS, 0, dev_debug,
NULL, NULL, &iii_help, NULL, NULL, &iii_description
};
t_stat iii_devio(uint32 dev, uint64 *data) {
UNIT *uptr = &iii_unit[0];
switch(dev & 3) {
case CONI:
*data = (((uint64)iii_sel) << 18) | (uint64)(uptr->PIA);
if ((iii_instr & 037) == 0)
*data |= INST_HLT;
*data |= (uptr->STATUS & 07) << 4;
if (uptr->STATUS & NXM_FLG)
*data |= NXM_BIT;
if (uptr->STATUS & DATA_FLG)
*data |= DATAO_LK;
if ((uptr->STATUS & RUN_FLG) == 0)
*data |= HLT_FLG;
if (uptr->STATUS & CTL_FBIT)
*data |= CONT_BIT;
if (uptr->STATUS & WRP_FBIT)
*data |= WRAP_FLG;
if (uptr->STATUS & EDG_FBIT)
*data |= EDGE_FLG;
if (uptr->STATUS & LIT_FBIT)
*data |= LIGHT_FLG;
sim_debug(DEBUG_CONI, &iii_dev, "III %03o CONI %06o %06o\n", dev, (uint32)*data,
PC);
break;
case CONO:
clr_interrupt(III_DEVNUM);
if (*data & SET_PIA)
uptr->PIA = (int)(*data&PIA_MSK);
if (*data & F)
uptr->STATUS &= ~(WRP_FBIT|EDG_FBIT|LIT_FBIT|DATA_FLG|NXM_FLG);
uptr->STATUS &= ~(017 & ((*data >> 14) ^ (*data >> 10)));
uptr->STATUS ^= (017 & (*data >> 10));
if (*data & STOP)
uptr->STATUS &= ~RUN_FLG;
if (*data & CONT) {
uptr->STATUS |= RUN_FLG;
iii_instr = M[uptr->MAR];
sim_activate(uptr, 10);
}
if (((uptr->STATUS >> 3) & (uptr->STATUS & (WRAP_MSK|EDGE_MSK|LIGH_MSK))) != 0)
set_interrupt(III_DEVNUM, uptr->PIA);
if (uptr->STATUS & HLT_MSK)
set_interrupt(III_DEVNUM, uptr->PIA);
sim_debug(DEBUG_CONO, &iii_dev, "III %03o CONO %06o %06o\n", dev,
(uint32)*data, PC);
break;
case DATAI:
sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAI %06o\n", dev, (uint32)*data);
break;
case DATAO:
if (uptr->STATUS & RUN_FLG)
uptr->STATUS |= DATA_FLG;
else {
iii_instr = *data;
sim_activate(uptr, 10);
}
sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAO %06o\n", dev, (uint32)*data);
break;
}
return SCPE_OK;
}
t_stat
iii_svc (UNIT *uptr)
{
uint64 temp;
int A;
int ox, oy, nx, ny, br, sz;
int i, j, ch;
float ch_sz;
iii_cycle(10, 0);
/* Extract X,Y,Bright and Size */
sz = (uptr->POS & CSIZE) >> CSIZE_V;
br = (uptr->POS & CBRT) >> CBRT_V;
ox = (uptr->POS & POS_X) >> POS_X_V;
oy = (uptr->POS & POS_Y) >> POS_Y_V;
nx = ox = (ox ^ 02000) - 02000;
ny = oy = (oy ^ 02000) - 02000;
ch_sz = scale[sz];
sim_debug(DEBUG_DETAIL, &iii_dev, "III: pos %d %d %d %d %o\n", ox, oy, br, sz,
uptr->STATUS );
switch(iii_instr & 017) {
case 000: /* JMP and HLT */
if (iii_instr & 020) {
uptr->MAR = (iii_instr >> 18) & RMASK;
} else {
uptr->STATUS &= ~RUN_FLG;
if (uptr->STATUS & HLT_MSK)
set_interrupt(III_DEVNUM, uptr->PIA);
return SCPE_OK;
}
goto skip_up;
case 001:
case 003:
case 005:
case 007:
case 011:
case 013:
case 015:
case 017: /* Draw 4 characters */
for (i = 29; i >= 1; i -= 7) {
/* Extract character and compute initial point */
int cx, cy;
int lx, ly;
ch = (iii_instr >> i) & 0177;
cx = 0;
cy = (int)(6.0 * ch_sz);
lx = ox;
ly = oy + cy;
sim_debug(DEBUG_DETAIL, &iii_dev, "III: ch %d %d %o '%c' %o %o\n",
lx, ly, ch, (ch < ' ')? '.' : ch, sz, br);
if (ch == '\t' || ch == 0)
continue;
if (ch == '\r') {
ox = -512;
continue;
}
if (ch == '\n') {
oy -= (int)(16.0 * ch_sz);
continue;
}
/* Scan map and draw lines as needed */
if ((iii_sel & 04000) != 0) {
for(j = 0; j < 18; j++) {
uint8 v = map[ch][j];
if (v == 0)
break;
cx = (int)((float)((v >> 4) & 07) * ch_sz);
cy = (int)((float)(v & 017) * ch_sz);
nx = ox + cx;
ny = oy + cy;
sim_debug(DEBUG_DATA, &iii_dev, "III: map %d %d %d %d %02x\n",
lx, ly, nx, ny, v);
if (v & 0200)
draw_line(lx, ly, nx, ny, br, uptr);
lx = nx;
ly = ny;
}
}
ox += (int)(8.0 * ch_sz);
}
nx = ox;
ny = oy;
break;
case 002: /* Short Vector */
if ((iii_sel & 04000) == 0)
break;
/* Do first point */
nx = (iii_instr >> 26) & 077;
ny = (iii_instr >> 20) & 077;
/* Sign extend */
nx = (nx ^ 040) - 040;
ny = (ny ^ 040) - 040;
/* Compute relative position. */
sim_debug(DEBUG_DETAIL, &iii_dev, "III: short %d %d %o %d\n",
nx, ny, sz, br);
nx += ox;
ny += oy;
if (nx < -512 || nx > 512 || ny < -512 || ny > 512)
uptr->STATUS |= EDG_FBIT;
i = (int)((iii_instr >> 18) & 3);
if ((i & 02) == 0 && (iii_sel & 04000) != 0) { /* Check if visible */
if ((i & 01) == 0) { /* Draw a line */
draw_line(ox, oy, nx, ny, br, uptr);
} else {
draw_point(nx, ny, br, uptr);
}
}
ox = nx;
oy = ny;
/* Do second point */
nx = (iii_instr >> 12) & 0177;
ny = (iii_instr >> 6) & 0177;
/* Sign extend */
nx = (nx ^ 040) - 040;
ny = (ny ^ 040) - 040;
sim_debug(DEBUG_DETAIL, &iii_dev, "III: short2 %d %d %o %d\n",
nx, ny, sz, br);
/* Compute relative position. */
nx += ox;
ny += oy;
if (nx < -512 || nx > 512 || ny < -512 || ny > 512)
uptr->STATUS |= EDG_FBIT;
/* Check if visible */
if ((iii_instr & 040) == 0 && (iii_sel & 04000) != 0) {
if ((iii_instr & 020) == 0) { /* Draw a line */
draw_line(ox, oy, nx, ny, br, uptr);
} else {
draw_point(nx, ny, br, uptr);
}
}
break;
case 004: /* JSR, JMS, SAVE */
temp = (((uint64)uptr->MAR) << 18) | 020 /* | CPC */;
A = (iii_instr >> 18) & RMASK;
if ((iii_instr & 030) != 030) {
M[A] = temp;
A++;
}
if ((iii_instr & 020) != 020) {
temp = uptr->STATUS & 0377;
temp |= ((uint64)uptr->POS) << 8;
M[A] = temp;
A++;
}
if ((iii_instr & 030) != 030) {
uptr->MAR = A;
}
goto skip_up;
case 006: /* Long Vector */
/* Update sizes if needed */
if (((iii_instr >> 8) & CSIZE) != 0)
sz = (iii_instr >> 8) & CSIZE;
if (((iii_instr >> 11) & 7) != 0)
br = (iii_instr > 11) & 7;
nx = (iii_instr >> 25) & 03777;
ny = (iii_instr >> 14) & 03777;
nx = (nx ^ 02000) - 02000;
ny = (ny ^ 02000) - 02000;
sim_debug(DEBUG_DETAIL, &iii_dev, "III: long %d %d %o %o\n",
nx, ny, sz, br);
if ((iii_instr & 0100) == 0) { /* Relative mode */
nx += ox;
ny += oy;
if (nx < -512 || nx > 512 || ny < -512 || ny > 512)
uptr->STATUS |= EDG_FBIT;
}
/* Check if visible */
if ((iii_instr & 040) == 0 && (iii_sel & 04000) != 0) {
if ((iii_instr & 020) == 0) /* Draw a line */
draw_line(ox, oy, nx, ny, br, uptr);
else
draw_point(nx, ny, br, uptr);
}
break;
case 010: /* Select instruction */
i = (iii_instr >> 24) & 07777; /* Set mask */
j = (iii_instr >> 12) & 07777; /* Reset mask */
ch = i & j; /* Compliment mask */
i &= ~ch;
j &= ~ch;
iii_sel = ((iii_sel | i) & ~j) ^ ch;
goto skip_up;
case 012: /* Test instruction */
A = (uptr->STATUS & (int32)(iii_instr >> 12) & 0377) != 0;
j = (int)((iii_instr >> 20) & 0377); /* set mask */
i = (int)((iii_instr >> 28) & 0377); /* Reset */
uptr->STATUS &= ~(i ^ j);
uptr->STATUS ^= j;
if (A ^ ((iii_instr & 020) != 0))
uptr->MAR++;
goto skip_up;
case 014: /* Restore */
A = (iii_instr >> 18) & RMASK;
temp = M[A];
if ((iii_instr & 020) != 0) {
uptr->STATUS &= ~0377;
uptr->STATUS |= temp & 0377;
}
if ((iii_instr & 040) != 0) {
uptr->POS = (temp >> 8) & (POS_X|POS_Y|CBRT|CSIZE);
}
goto skip_up;
case 016: /* Nop */
break;
}
/* Repack to new position. */
sim_debug(DEBUG_DATA, &iii_dev, "III: update %d %d %8o ", nx, ny, uptr->POS);
uptr->POS = (POS_X & ((nx & 03777) << POS_X_V)) |
(POS_Y & ((ny & 03777) << POS_Y_V)) |
(CBRT & (br << CBRT_V)) |
(CSIZE & (sz << CSIZE_V));
sim_debug(DEBUG_DATA, &iii_dev, "-> %8o\n", uptr->POS);
skip_up:
if (uptr->STATUS & RUN_FLG) {
iii_instr = M[uptr->MAR];
sim_debug(DEBUG_DETAIL, &iii_dev, "III: fetch %06o %012llo\n",
uptr->MAR, iii_instr);
uptr->MAR++;
uptr->MAR &= RMASK;
sim_activate(uptr, 50);
}
if (((uptr->STATUS >> 3) & (uptr->STATUS & (WRAP_MSK|EDGE_MSK|LIGH_MSK))) != 0)
set_interrupt(III_DEVNUM, uptr->PIA);
return SCPE_OK;
}
t_stat iii_reset (DEVICE *dptr)
{
if (dptr->flags & DEV_DIS) {
display_close(dptr);
} else {
display_reset();
dptr->units[0].POS = 0;
iii_init(dptr, 1);
}
return SCPE_OK;
}
/* Draw a point at x,y with intensity b. */
/* X and Y runs from -512 to 512. */
static void
draw_point(int x, int y, int b, UNIT *uptr)
{
if (x < -512 || x > 512 || y < -512 || y > 512)
uptr->STATUS |= WRP_FBIT;
iii_point(x, y, b);
}
/* Draw a line between two points */
static void
draw_line(int x1, int y1, int x2, int y2, int b, UNIT *uptr)
{
if (x1 < -512 || x1 > 512 || y1 < -512 || y1 > 512)
uptr->STATUS |= WRP_FBIT;
if (x2 < -512 || x2 > 512 || y2 < -512 || y2 > 512)
uptr->STATUS |= WRP_FBIT;
iii_draw_line(x1, y1, x2, y2, b);
}
t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{
return SCPE_OK;
}
const char *iii_description (DEVICE *dptr)
{
return "Triple III Display";
}
#endif

View file

@ -1,6 +1,6 @@
/* ka10_imx.c: Input multplexor for A/D. /* ka10_imx.c: Input multplexor for A/D.
Copyright (c) 2018, Lars Brinkhoff Copyright (c) 2018,2020, Lars Brinkhoff
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,7 @@
#include <time.h> #include <time.h>
#include "kx10_defs.h" #include "kx10_defs.h"
#include "sim_video.h"
#ifndef NUM_DEVS_IMX #ifndef NUM_DEVS_IMX
#define NUM_DEVS_IMX 0 #define NUM_DEVS_IMX 0
@ -47,33 +48,78 @@
#define IMX_CHANNEL 0000177 #define IMX_CHANNEL 0000177
#define JOY_MAX_UNITS 4
#define JOY_MAX_AXES 4
#define JOY_NO_CHAN (IMX_CHANNEL + 1)
t_stat imx_devio(uint32 dev, uint64 *data); t_stat imx_devio(uint32 dev, uint64 *data);
t_stat imx_svc (UNIT *uptr);
t_stat imx_reset (DEVICE *dptr);
const char *imx_description (DEVICE *dptr); const char *imx_description (DEVICE *dptr);
#if MPX_DEV
t_stat imx_set_mpx (UNIT *uptr, int32 val, CONST char *cptr, void *desc) ;
t_stat imx_show_mpx (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
#endif
t_stat imx_show_channel (FILE* st, UNIT* uptr, int32 val, CONST void* desc);
t_stat imx_set_channel (UNIT* uptr, int32 val, CONST char* cptr, void* desc);
static uint64 status = IMX_ASSIGNED; static uint64 status = IMX_ASSIGNED;
static uint64 imx_data;
static uint64 imx_samples;
static int initial_channel = 0; static int initial_channel = 0;
static int current_channel = 0; static int current_channel = 0;
static int imx_mpx_lvl;
static int imx_inputs[0200];
static int imx_map[JOY_MAX_UNITS][JOY_MAX_AXES];
UNIT imx_unit[] = { UNIT imx_unit[] = {
{UDATA(NULL, UNIT_DISABLE, 0)}, /* 0 */ { UDATA (&imx_svc, UNIT_IDLE, 0) }
}; };
DIB imx_dib = {IMX_DEVNUM, 1, &imx_devio, NULL}; DIB imx_dib = {IMX_DEVNUM, 1, &imx_devio, NULL};
MTAB imx_mod[] = { MTAB imx_mod[] = {
#if MPX_DEV
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "MPX", "MPX",
&imx_set_mpx, &imx_show_mpx, NULL},
#endif
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "CHANNEL", "CHANNEL",
&imx_set_channel, &imx_show_channel, NULL},
{ 0 } { 0 }
}; };
DEVICE imx_dev = { DEVICE imx_dev = {
"IMX", imx_unit, NULL, imx_mod, "IMX", imx_unit, NULL, imx_mod,
1, 8, 0, 1, 8, 36, 1, 8, 0, 1, 8, 36,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, imx_reset, NULL, NULL, NULL,
&imx_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, NULL, &imx_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, NULL,
NULL, NULL, NULL, NULL, NULL, &imx_description NULL, NULL, NULL, NULL, NULL, &imx_description
}; };
static void imx_joy_motion(int which, int axis, int value)
{
int chan;
if (which < JOY_MAX_UNITS && axis < JOY_MAX_AXES) {
chan = imx_map[which][axis];
if (chan == JOY_NO_CHAN)
return;
value += 32768;
if (chan < 0) {
chan = -chan;
value = 65535 - value;
}
imx_inputs[chan] = value >> 5;
sim_debug(DEBUG_DETAIL, &imx_dev, "Channel %d value %o\n",
chan, imx_inputs[chan]);
}
}
static int imx_sample (void) static int imx_sample (void)
{ {
int sample = 2048; int sample = imx_inputs[current_channel];
if (status & IMX_SEQUENCE) if (status & IMX_SEQUENCE)
current_channel = (current_channel + 1) & IMX_CHANNEL; current_channel = (current_channel + 1) & IMX_CHANNEL;
else else
@ -81,36 +127,217 @@ static int imx_sample (void)
return sample; return sample;
} }
static void imx_activate (void)
{
int micros;
if (status & IMX_DONE) {
sim_cancel (imx_unit);
sim_debug(DEBUG_IRQ, &imx_dev, "Cancel\n");
return;
}
micros = (status >> 16) & 0377;
if (micros < 10)
micros = 10;
sim_activate_after (imx_unit, micros);
sim_debug(DEBUG_IRQ, &imx_dev, "Activate\n");
}
t_stat imx_reset (DEVICE *dptr)
{
static int init = 1;
int i, j;
if (dptr->flags & DEV_DIS) {
imx_samples = 0;
imx_data = 0;
for (i = 0; i <= IMX_CHANNEL; i++)
imx_inputs[i] = 1000;
for (i = 0; i < JOY_MAX_UNITS; i++) {
for (j = 0; j < JOY_MAX_UNITS; j++)
imx_map[i][j] = JOY_NO_CHAN;
}
} else {
if (init) {
vid_register_gamepad_motion_callback (imx_joy_motion);
init = 0;
}
}
return SCPE_OK;
}
t_stat imx_devio(uint32 dev, uint64 *data) t_stat imx_devio(uint32 dev, uint64 *data)
{ {
DEVICE *dptr = &imx_dev; DEVICE *dptr = &imx_dev;
switch(dev & 07) { switch(dev & 07) {
case CONO|4: case CONO|4:
status &= ~IMX_CONO; sim_debug(DEBUG_CONO, &imx_dev, "%06llo\n", *data);
status &= ~(IMX_CONO|IMX_DONE);
status |= *data & IMX_CONO; status |= *data & IMX_CONO;
imx_data = 0;
imx_samples = 0;
current_channel = initial_channel; current_channel = initial_channel;
clr_interrupt (IMX_DEVNUM);
imx_activate ();
break; break;
case CONI|4: case CONI|4:
status |= IMX_DONE;
*data = status & IMX_CONI; *data = status & IMX_CONI;
sim_debug(DEBUG_CONI, &imx_dev, "%012llo\n", *data);
break; break;
case DATAO|4: case DATAO|4:
sim_debug(DEBUG_DATAIO, &imx_dev, "DATAO %012llo\n", *data);
initial_channel = *data & IMX_CHANNEL; initial_channel = *data & IMX_CHANNEL;
break; break;
case DATAI|4: case DATAI|4:
*data = imx_sample(); *data = imx_data;
if (status & IMX_PACK) { sim_debug(DEBUG_DATAIO, &imx_dev, "DATAI %012llo\n", *data);
*data <<= 24; imx_data = 0;
*data |= imx_sample() << 12; imx_samples = 0;
*data |= imx_sample(); status &= ~IMX_DONE;
} clr_interrupt (IMX_DEVNUM);
sim_debug(DEBUG_IRQ, &imx_dev, "Clear interrupt\n");
imx_activate ();
break; break;
} }
return SCPE_OK; return SCPE_OK;
} }
t_stat imx_svc (UNIT *uptr)
{
int max_samples;
if (status & IMX_PACK) {
max_samples = 3;
} else {
max_samples = 1;
}
if (imx_samples < max_samples) {
imx_data <<= 12;
imx_data |= imx_sample();
imx_samples++;
}
if (imx_samples == max_samples) {
status |= IMX_DONE;
if (status & 7) {
set_interrupt_mpx (IMX_DEVNUM, status & 7, imx_mpx_lvl);
sim_debug(DEBUG_IRQ, &imx_dev, "Raise interrupt\n");
}
}
imx_activate ();
return SCPE_OK;
}
#if MPX_DEV
/* set MPX level number */
t_stat imx_set_mpx (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
int32 mpx;
t_stat r;
if (cptr == NULL)
return SCPE_ARG;
mpx = (int32) get_uint (cptr, 8, 8, &r);
if (r != SCPE_OK)
return r;
imx_mpx_lvl = mpx;
return SCPE_OK;
}
t_stat imx_show_mpx (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
if (uptr == NULL)
return SCPE_IERR;
fprintf (st, "MPX=%o", imx_mpx_lvl);
return SCPE_OK;
}
#endif
t_stat imx_set_channel (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
int chan, unit, axis, negate = 0;
char gbuf[CBUFSIZE];
CONST char *tptr;
t_stat r;
if (cptr == NULL || *cptr == 0)
return SCPE_ARG;
tptr = get_glyph (cptr, gbuf, ';');
if (tptr == NULL)
return SCPE_ARG;
chan = (int) get_uint (gbuf, 8, IMX_CHANNEL, &r);
if (r != SCPE_OK)
return r;
tptr = get_glyph (tptr, gbuf, ';');
if (tptr == NULL || strncasecmp (gbuf, "unit", 4) != 0)
return SCPE_ARG;
unit = (int) get_uint (gbuf + 4, 10, JOY_MAX_UNITS - 1, &r);
if (r != SCPE_OK)
return r;
tptr = get_glyph (tptr, gbuf, ';');
if (strncasecmp (gbuf, "axis", 4) != 0)
return SCPE_ARG;
axis = (int) get_uint (gbuf + 4, 10, JOY_MAX_AXES - 1, &r);
if (r != SCPE_OK)
return r;
if (*tptr != 0) {
if (strcasecmp (tptr, "negate") != 0)
return SCPE_ARG;
negate = 1;
}
if (negate)
chan = -chan;
imx_map[unit][axis] = chan;
return SCPE_OK;
}
t_stat imx_show_channel (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
int nothing = 1;
const char *negate, *comma = "";
int chan, i, j;
if (uptr == NULL)
return SCPE_IERR;
for (i = 0; i < JOY_MAX_UNITS; i++) {
for (j = 0; j < JOY_MAX_AXES; j++) {
chan = imx_map[i][j];
if (chan != JOY_NO_CHAN) {
if (chan < 0) {
chan = -chan;
negate = ";NEGATE";
} else
negate = "";
fprintf (st, "%sCHANNEL=%o;JOY%d;AXIS%d%s", comma, chan, i, j, negate);
comma = ", ";
nothing = 0;
}
}
}
if (nothing)
fprintf (st, "CHANNEL=(NO MAPPINGS)");
return SCPE_OK;
}
const char *imx_description (DEVICE *dptr) const char *imx_description (DEVICE *dptr)
{ {
return "A/D input multiplexor"; return "A/D input multiplexor";

View file

@ -47,8 +47,6 @@
#define PIA_FLG 07 #define PIA_FLG 07
#define CLK_IRQ 010 #define CLK_IRQ 010
#define TMR_PD 3
int pd_tps = 60; int pd_tps = 60;
t_stat pd_devio(uint32 dev, uint64 *data); t_stat pd_devio(uint32 dev, uint64 *data);
@ -126,9 +124,6 @@ t_stat pd_devio(uint32 dev, uint64 *data)
t_stat t_stat
pd_srv(UNIT * uptr) pd_srv(UNIT * uptr)
{ {
int32 t;
t = sim_rtcn_calb (pd_tps, TMR_PD);
sim_activate_after(uptr, 1000000/pd_tps); sim_activate_after(uptr, 1000000/pd_tps);
if (uptr->PIA_CH & PIA_FLG) { if (uptr->PIA_CH & PIA_FLG) {
uptr->PIA_CH |= CLK_IRQ; uptr->PIA_CH |= CLK_IRQ;
@ -139,7 +134,6 @@ pd_srv(UNIT * uptr)
return SCPE_OK; return SCPE_OK;
} }
const char *pd_description (DEVICE *dptr) const char *pd_description (DEVICE *dptr)
{ {
return "Paul DeCoriolis clock"; return "Paul DeCoriolis clock";

View file

@ -1,6 +1,6 @@
/* PMP disk controller interface for WAITS. /* PMP disk controller interface for WAITS.
Copyright (c) 2017, Richard Cornwell Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -348,9 +348,9 @@ uint64 pmp_status; /* CONI status for device 500 */
int pmp_statusb; int pmp_statusb;
uint32 pmp_cmd_hold; /* Command hold register */ uint32 pmp_cmd_hold; /* Command hold register */
uint32 pmp_wc_hold; /* Word count hold */ uint32 pmp_wc_hold; /* Word count hold */
uint32 pmp_addr_hold; /* Address register hold */ t_addr pmp_addr_hold; /* Address register hold */
uint32 pmp_wc; /* Current word count register */ uint32 pmp_wc; /* Current word count register */
uint32 pmp_addr; /* Current address register */ t_addr pmp_addr; /* Current address register */
uint64 pmp_data; /* Data assembly register */ uint64 pmp_data; /* Data assembly register */
int pmp_cnt; /* Character count in asm register */ int pmp_cnt; /* Character count in asm register */
int pmp_cmd; /* Current command */ int pmp_cmd; /* Current command */
@ -550,22 +550,25 @@ pmp_checkirq() {
sim_debug(DEBUG_DETAIL, &pmp_dev, "parity irq\n"); sim_debug(DEBUG_DETAIL, &pmp_dev, "parity irq\n");
f = 1; f = 1;
} }
if ((pmp_irq & IRQ_EMPTY) != 0 && (pmp_statusb & (WCMA_LD|CMD_LD)) != (WCMA_LD|CMD_LD)) { if ((pmp_irq & IRQ_EMPTY) != 0 &&
(pmp_statusb & (WCMA_LD|CMD_LD)) != (WCMA_LD|CMD_LD)) {
sim_debug(DEBUG_DETAIL, &pmp_dev, "load irq\n"); sim_debug(DEBUG_DETAIL, &pmp_dev, "load irq\n");
f = 1; f = 1;
} }
if ((pmp_irq & IRQ_IDLE) != 0 && (pmp_statusb & (OP1|IDLE_CH)) == IDLE_CH) { if ((pmp_irq & IRQ_IDLE) != 0 && (pmp_statusb & (OP1|IDLE_CH)) == IDLE_CH) {
sim_debug(DEBUG_DETAIL, &pmp_dev, "idle irq\n"); sim_debug(DEBUG_DETAIL, &pmp_dev, "idle irq\n");
f = 1; f = 1;
} }
if ((pmp_irq & IRQ_UEND) != 0 && (pmp_status & (NXM_ERR|CHA_ERR|SEL_ERR|UNU_END)) != 0) { if ((pmp_irq & IRQ_UEND) != 0 &&
(pmp_status & (NXM_ERR|CHA_ERR|SEL_ERR|UNU_END)) != 0) {
sim_debug(DEBUG_DETAIL, &pmp_dev, "uend irq\n"); sim_debug(DEBUG_DETAIL, &pmp_dev, "uend irq\n");
f = 1; f = 1;
} }
if ((pmp_status & pmp_irq & (IRQ_NSTS|IRQ_STS)) != 0) { if ((pmp_status & pmp_irq & (IRQ_NSTS|IRQ_STS)) != 0) {
sim_debug(DEBUG_DETAIL, &pmp_dev, "mem sts %o\n", (int)(pmp_status & pmp_irq & (IRQ_NSTS|IRQ_STS))); sim_debug(DEBUG_DETAIL, &pmp_dev, "mem sts %o\n",
(int)(pmp_status & pmp_irq & (IRQ_NSTS|IRQ_STS)));
f = 1; f = 1;
} }
if (f) if (f)
set_interrupt(PMP_DEV, pmp_pia); set_interrupt(PMP_DEV, pmp_pia);
return f; return f;
@ -597,10 +600,10 @@ chan_read_byte(uint8 *data) {
pmp_statusb |= TRANS_CH; /* Tranfer in progress */ pmp_statusb |= TRANS_CH; /* Tranfer in progress */
/* Read in next work if buffer is in empty status */ /* Read in next work if buffer is in empty status */
if (pmp_cnt & BUFF_EMPTY) { if (pmp_cnt & BUFF_EMPTY) {
if (pmp_addr >= (int)MEMSIZE) if (Mem_read_word(pmp_addr, &pmp_data, 0))
return pmp_posterror(NXM_ERR); return pmp_posterror(NXM_ERR);
pmp_data = M[pmp_addr]; sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read %06o %012llo\n",
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read %06o %012llo\n", pmp_addr, pmp_data); pmp_addr, pmp_data);
pmp_addr++; pmp_addr++;
pmp_cnt = 0; pmp_cnt = 0;
xfer = 1; /* Read in a word */ xfer = 1; /* Read in a word */
@ -616,10 +619,10 @@ chan_read_byte(uint8 *data) {
if ((pmp_cnt & 0xf) > 0x3) { if ((pmp_cnt & 0xf) > 0x3) {
if ((pmp_cnt & 0xf) == 0x4) { /* Split byte */ if ((pmp_cnt & 0xf) == 0x4) { /* Split byte */
byte = (pmp_data << 4) & 0xf0; byte = (pmp_data << 4) & 0xf0;
if (pmp_addr >= (int)MEMSIZE) if (Mem_read_word(pmp_addr, &pmp_data, 0))
return pmp_posterror(NXM_ERR); return pmp_posterror(NXM_ERR);
pmp_data = M[pmp_addr]; sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read %06o %012llo\n",
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read %06o %012llo\n", pmp_addr, pmp_data); pmp_addr, pmp_data);
pmp_addr++; pmp_addr++;
xfer = 1; /* Read in a word */ xfer = 1; /* Read in a word */
byte |= pmp_data & 0xf; byte |= pmp_data & 0xf;
@ -642,27 +645,6 @@ chan_read_byte(uint8 *data) {
if (pmp_wc & 07000000) if (pmp_wc & 07000000)
pmp_cnt |= BUFF_CHNEND; pmp_cnt |= BUFF_CHNEND;
return 0; return 0;
#if 0
next:
/* If not data channing, let device know there will be no
* more data to come
*/
if ((pmp_cmd & DATCH_ON) == 0) {
pmp_cnt = BUFF_CHNEND;
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_read_end\n");
return 1;
} else {
if (pmp_statusb & WCMA_LD) {
pmp_statusb &= ~(WCMA_LD);
pmp_addr = pmp_addr_hold;
pmp_wc = pmp_wc_hold;
pmp_data = 0;
} else {
return pmp_posterror(CHA_ERR);
}
}
goto load;
#endif
} }
/* write byte to memory */ /* write byte to memory */
@ -693,10 +675,10 @@ chan_write_byte(uint8 *data) {
pmp_cnt |= BUFF_DIRTY; pmp_cnt |= BUFF_DIRTY;
if ((pmp_cnt & 03) == 0) { if ((pmp_cnt & 03) == 0) {
pmp_cnt &= ~(BUFF_DIRTY|7); pmp_cnt &= ~(BUFF_DIRTY|7);
if (pmp_addr >= (int)MEMSIZE) if (Mem_write_word(pmp_addr, &pmp_data, 0))
return pmp_posterror(NXM_ERR); return pmp_posterror(NXM_ERR);
M[pmp_addr] = pmp_data; sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo\n",
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo\n", pmp_addr, pmp_data); pmp_addr, pmp_data);
pmp_addr++; pmp_addr++;
xfer = 1; xfer = 1;
} }
@ -705,10 +687,10 @@ chan_write_byte(uint8 *data) {
if ((pmp_cnt & 0xf) == 0x4) { /* Split byte */ if ((pmp_cnt & 0xf) == 0x4) { /* Split byte */
pmp_data &= ~0xf; pmp_data &= ~0xf;
pmp_data |= (uint64)((*data >> 4) & 0xf); pmp_data |= (uint64)((*data >> 4) & 0xf);
if (pmp_addr >= (int)MEMSIZE) if (Mem_write_word(pmp_addr, &pmp_data, 0))
return pmp_posterror(NXM_ERR); return pmp_posterror(NXM_ERR);
M[pmp_addr] = pmp_data; sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo %2x\n",
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo %2x\n", pmp_addr, pmp_data, pmp_cnt); pmp_addr, pmp_data, pmp_cnt);
pmp_addr++; pmp_addr++;
xfer = 1; /* Read in a word */ xfer = 1; /* Read in a word */
pmp_data = *data & 0xf; pmp_data = *data & 0xf;
@ -726,10 +708,10 @@ chan_write_byte(uint8 *data) {
pmp_cnt++; pmp_cnt++;
if ((pmp_cnt & 0xf) == 9) { if ((pmp_cnt & 0xf) == 9) {
pmp_cnt = BUFF_EMPTY; pmp_cnt = BUFF_EMPTY;
if (pmp_addr >= (int)MEMSIZE) if (Mem_write_word(pmp_addr, &pmp_data, 0))
return pmp_posterror(NXM_ERR); return pmp_posterror(NXM_ERR);
M[pmp_addr] = pmp_data; sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo %2x\n",
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo %2x\n", pmp_addr, pmp_data, pmp_cnt); pmp_addr, pmp_data, pmp_cnt);
pmp_addr++; pmp_addr++;
xfer = 1; /* Read in a word */ xfer = 1; /* Read in a word */
} }
@ -774,11 +756,10 @@ chan_end(uint8 flags) {
/* Flush buffer if there was any change */ /* Flush buffer if there was any change */
if (pmp_cnt & BUFF_DIRTY) { if (pmp_cnt & BUFF_DIRTY) {
pmp_cnt = BUFF_EMPTY; pmp_cnt = BUFF_EMPTY;
if (pmp_addr >= (int)MEMSIZE) { if (Mem_write_word(pmp_addr, &pmp_data, 0)) {
(void) pmp_posterror(NXM_ERR); (void) pmp_posterror(NXM_ERR);
return; return;
} }
M[pmp_addr] = pmp_data;
sim_debug(DEBUG_DATA, &pmp_dev, "chan_write %012llo\n", pmp_data); sim_debug(DEBUG_DATA, &pmp_dev, "chan_write %012llo\n", pmp_data);
pmp_addr++; pmp_addr++;
} }
@ -792,7 +773,8 @@ chan_end(uint8 flags) {
/* If channel is also finished, then skip any more data commands. */ /* If channel is also finished, then skip any more data commands. */
if (pmp_status & (CHN_END|DEV_END)) { if (pmp_status & (CHN_END|DEV_END)) {
pmp_cnt = BUFF_CHNEND; pmp_cnt = BUFF_CHNEND;
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_endc %012llo %06o\n", pmp_status, pmp_cmd); sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_endc %012llo %06o\n",
pmp_status, pmp_cmd);
/* While command has chain data set, continue to skip */ /* While command has chain data set, continue to skip */
if (pmp_cmd & DATCH_ON) { if (pmp_cmd & DATCH_ON) {
@ -808,7 +790,8 @@ chan_end(uint8 flags) {
/* Indicate that device is done */ /* Indicate that device is done */
pmp_statusb &= ~OP1; pmp_statusb &= ~OP1;
} }
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_endf %012llo %06o\n", pmp_status, pmp_statusb); sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_endf %012llo %06o\n",
pmp_status, pmp_statusb);
(void)pmp_checkirq(); (void)pmp_checkirq();
} }
@ -959,7 +942,8 @@ pmp_startcmd() {
pmp_statusb &= ~IDLE_CH; pmp_statusb &= ~IDLE_CH;
pmp_cur_unit->CMD &= ~(DK_PARAM); pmp_cur_unit->CMD &= ~(DK_PARAM);
pmp_cur_unit->CMD |= cmd; pmp_cur_unit->CMD |= cmd;
sim_debug(DEBUG_CMD, &pmp_dev, "CMD unit=%d CMD=%02x\n", unit, pmp_cur_unit->CMD); sim_debug(DEBUG_CMD, &pmp_dev, "CMD unit=%d CMD=%02x\n", unit,
pmp_cur_unit->CMD);
return; return;
case 0x0: /* Status */ case 0x0: /* Status */
@ -1233,8 +1217,8 @@ index:
/* Compute delay based of difference. */ /* Compute delay based of difference. */
/* Set next state = index */ /* Set next state = index */
i = (uptr->POS >> 8) - data->cyl; i = (uptr->POS >> 8) - data->cyl;
sim_debug(DEBUG_DETAIL, dptr, "seek unit=%d %d %d s=%x\n", unit, uptr->POS >> 8, i, sim_debug(DEBUG_DETAIL, dptr, "seek unit=%d %d %d s=%x\n", unit, uptr->POS >> 8,
data->state); i, data->state);
if (i == 0) { if (i == 0) {
uptr->CMD &= ~(DK_INDEX|DK_INDEX2); uptr->CMD &= ~(DK_INDEX|DK_INDEX2);
data->state = DK_POS_INDEX; data->state = DK_POS_INDEX;
@ -1256,8 +1240,8 @@ index:
sim_activate(uptr, 200); sim_activate(uptr, 200);
} }
} }
sim_debug(DEBUG_DETAIL, dptr, "seek next unit=%d %d %d %x\n", unit, uptr->POS >> 8, sim_debug(DEBUG_DETAIL, dptr, "seek next unit=%d %d %d %x\n", unit,
data->cyl, data->state); uptr->POS >> 8, data->cyl, data->state);
break; break;
} }
@ -1449,7 +1433,6 @@ sense_end:
uptr->CMD |= DK_PARAM; uptr->CMD |= DK_PARAM;
data->state = DK_POS_SEEK; data->state = DK_POS_SEEK;
sim_debug(DEBUG_DETAIL, dptr, "seek unit=%d doing\n", unit); sim_debug(DEBUG_DETAIL, dptr, "seek unit=%d doing\n", unit);
// chan_end(SNS_CHNEND);
} else { } else {
pmp_adjpos(uptr); pmp_adjpos(uptr);
uptr->LASTCMD = cmd; uptr->LASTCMD = cmd;
@ -1598,7 +1581,8 @@ sense_end:
if (state == DK_POS_CNT && count == 0) { if (state == DK_POS_CNT && count == 0) {
sim_debug(DEBUG_DETAIL, dptr, "search ID unit=%d %x %d %x %d\n", sim_debug(DEBUG_DETAIL, dptr, "search ID unit=%d %x %d %x %d\n",
unit, state, count, uptr->POS, data->rec); unit, state, count, uptr->POS, data->rec);
sim_debug(DEBUG_DETAIL, dptr, "ID unit=%d %02x %02x %02x %02x %02x %02x %02x %02x\n", sim_debug(DEBUG_DETAIL, dptr,
"ID unit=%d %02x %02x %02x %02x %02x %02x %02x %02x\n",
unit, da[0], da[1], da[2], da[3], da[4], da[5], da[6], da[7]); unit, da[0], da[1], da[2], da[3], da[4], da[5], da[6], da[7]);
uptr->CMD &= ~(DK_SRCOK|DK_SHORTSRC|DK_NOEQ|DK_HIGH); uptr->CMD &= ~(DK_SRCOK|DK_SHORTSRC|DK_NOEQ|DK_HIGH);
uptr->CMD |= DK_PARAM; uptr->CMD |= DK_PARAM;
@ -1770,7 +1754,8 @@ sense_end:
if (count == 0 && state == DK_POS_CNT && data->rec != 0) { if (count == 0 && state == DK_POS_CNT && data->rec != 0) {
uptr->CMD |= DK_PARAM; uptr->CMD |= DK_PARAM;
uptr->CMD &= ~(DK_INDEX|DK_INDEX2); uptr->CMD &= ~(DK_INDEX|DK_INDEX2);
sim_debug(DEBUG_DETAIL, dptr, "RD CKD unit=%d %d k=%d d=%d %02x %04x %04x\n", sim_debug(DEBUG_DETAIL, dptr,
"RD CKD unit=%d %d k=%d d=%d %02x %04x %04x\n",
unit, data->rec, data->klen, data->dlen, data->state, data->dlen, unit, data->rec, data->klen, data->dlen, data->state, data->dlen,
8 + data->klen + data->dlen); 8 + data->klen + data->dlen);
} }
@ -2251,7 +2236,8 @@ pmp_attach(UNIT * uptr, CONST char *file)
return r; return r;
if (sim_fread(&hdr, 1, sizeof(struct pmp_header), uptr->fileref) != if (sim_fread(&hdr, 1, sizeof(struct pmp_header), uptr->fileref) !=
sizeof(struct pmp_header) || strncmp((CONST char *)&hdr.devid[0], "CKD_P370", 8) != 0 || flag) { sizeof(struct pmp_header) || strncmp((CONST char *)&hdr.devid[0],
"CKD_P370", 8) != 0 || flag) {
if (pmp_format(uptr, flag)) { if (pmp_format(uptr, flag)) {
detach_unit(uptr); detach_unit(uptr);
return SCPE_FMT; return SCPE_FMT;
@ -2292,12 +2278,14 @@ pmp_attach(UNIT * uptr, CONST char *file)
detach_unit(uptr); detach_unit(uptr);
return SCPE_ARG; return SCPE_ARG;
} }
if ((sim_switches & SIM_SW_REST) == 0) {
(void)sim_fseek(uptr->fileref, sizeof(struct pmp_header), SEEK_SET); (void)sim_fseek(uptr->fileref, sizeof(struct pmp_header), SEEK_SET);
(void)sim_fread(data->cbuf, 1, tsize, uptr->fileref); (void)sim_fread(data->cbuf, 1, tsize, uptr->fileref);
data->cpos = sizeof(struct pmp_header); data->cpos = sizeof(struct pmp_header);
data->ccyl = 0; data->ccyl = 0;
uptr->CMD |= DK_ATTN; uptr->CMD |= DK_ATTN;
pmp_statusb |= REQ_CH; pmp_statusb |= REQ_CH;
}
sim_activate(uptr, 100); sim_activate(uptr, 100);
return SCPE_OK; return SCPE_OK;
} }

View file

@ -387,6 +387,7 @@ t_stat stk_devio(uint32 dev, uint64 *data)
static t_stat stk_reset (DEVICE *dptr) static t_stat stk_reset (DEVICE *dptr)
{ {
if ((stk_dev.flags & DEV_DIS) == 0)
vid_display_kb_event_process = stk_keyboard; vid_display_kb_event_process = stk_keyboard;
return SCPE_OK; return SCPE_OK;
} }

View file

@ -239,7 +239,7 @@ static int transaction (unsigned char *request, unsigned char *response)
return 0; return 0;
} }
static int read_word (int addr, int *data) static int read_word (t_addr addr, int *data)
{ {
unsigned char request[8]; unsigned char request[8];
unsigned char response[8]; unsigned char response[8];
@ -285,7 +285,7 @@ static int read_word (int addr, int *data)
return 0; return 0;
} }
int ten11_read (int addr, uint64 *data) int ten11_read (t_addr addr, uint64 *data)
{ {
int offset = addr & 01777; int offset = addr & 01777;
int word1, word2; int word1, word2;
@ -328,7 +328,7 @@ int ten11_read (int addr, uint64 *data)
return 0; return 0;
} }
static int write_word (int addr, uint16 data) static int write_word (t_addr addr, uint16 data)
{ {
unsigned char request[8]; unsigned char request[8];
unsigned char response[8]; unsigned char response[8];
@ -366,7 +366,7 @@ static int write_word (int addr, uint16 data)
return 0; return 0;
} }
int ten11_write (int addr, uint64 data) int ten11_write (t_addr addr, uint64 data)
{ {
int offset = addr & 01777; int offset = addr & 01777;

2484
PDP10/kl10_fe.c Normal file

File diff suppressed because it is too large Load diff

1674
PDP10/kl10_nia.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* ka10_cp.c: PDP10 Card Punch /* kx10_cp.c: PDP10 Card Punch
Copyright (c) 2016-2017, Richard Cornwell Copyright (c) 2016-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* ka10_cr.c: PDP10 Card reader. /* kx10_cr.c: PDP10 Card reader.
Copyright (c) 2016-2017, Richard Cornwell Copyright (c) 2016-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* ka10_cty.c: KA-10 front end (console terminal) simulator /* kx10_cty.c: PDP6, KA-10 and KI-10 front end (console terminal) simulator
Copyright (c) 2013-2017, Richard Cornwell Copyright (c) 2013-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -74,8 +74,13 @@ MTAB cty_mod[] = {
{ 0 } { 0 }
}; };
REG cty_reg[] = {
{ HRDATAD (WRU, sim_int_char, 8, "interrupt character") },
{ 0 }
};
DEVICE cty_dev = { DEVICE cty_dev = {
"CTY", cty_unit, NULL, cty_mod, "CTY", cty_unit, cty_reg, cty_mod,
2, 10, 31, 1, 8, 8, 2, 10, 31, 1, 8, 8,
NULL, NULL, &cty_reset, NULL, NULL, &cty_reset,
NULL, NULL, NULL, &cty_dib, DEV_DEBUG, 0, dev_debug, NULL, NULL, NULL, &cty_dib, DEV_DEBUG, 0, dev_debug,
@ -154,6 +159,8 @@ t_stat ctyi_svc (UNIT *uptr)
sim_clock_coschedule (uptr, tmxr_poll); sim_clock_coschedule (uptr, tmxr_poll);
/* continue poll */ /* continue poll */
if (uptr->STATUS & KEY_RDY)
return SCPE_OK;
if ((ch = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */ if ((ch = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */
return ch; return ch;
if (ch & SCPE_BREAK) /* ignore break */ if (ch & SCPE_BREAK) /* ignore break */

View file

@ -1,6 +1,6 @@
/* ka10_dc.c: PDP-10 DC10 communication server simulator /* kx10_dc.c: PDP-10 DC10 communication server simulator
Copyright (c) 2011-2017, Richard Cornwell Copyright (c) 2011-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* ka10_defs.h: PDP-10 simulator definitions /* kx10_defs.h: PDP-10 simulator definitions
Copyright (c) 2011-2017, Richard Cornwell Copyright (c) 2011-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -46,16 +46,12 @@
#define KI 0 #define KI 0
#endif #endif
#ifndef KLA #ifndef KL
#define KLA 0 #define KL 0
#endif #endif
#ifndef KLB #if KL
#define KLB 0 #define EPT440 0 /* Force KL10 to use as 440 section address */
#endif
#ifndef KL /* Either KL10A or KL10B */
#define KL (KLA+KLB)
#endif #endif
#if (PDP6 + KA + KI + KL) != 1 #if (PDP6 + KA + KI + KL) != 1
@ -81,10 +77,19 @@
#define WAITS KA #define WAITS KA
#endif #endif
/* Support for ITS on KL */
#ifndef KL_ITS
#define KL_ITS KL
#endif
#ifndef PDP6_DEV /* Include PDP6 devices */ #ifndef PDP6_DEV /* Include PDP6 devices */
#define PDP6_DEV PDP6|WAITS #define PDP6_DEV PDP6|WAITS
#endif #endif
#ifndef MAGIC_SWITCH /* Infamous MIT magic switch. */
#define MAGIC_SWITCH 0
#endif
/* MPX interrupt multiplexer for ITS systems */ /* MPX interrupt multiplexer for ITS systems */
#define MPX_DEV ITS #define MPX_DEV ITS
@ -131,6 +136,10 @@ typedef t_uint64 uint64;
#define STOP_HALT 1 /* halted */ #define STOP_HALT 1 /* halted */
#define STOP_IBKPT 2 /* breakpoint */ #define STOP_IBKPT 2 /* breakpoint */
#define STOP_ACCESS 3 /* invalid access */
#if MAGIC_SWITCH
#define STOP_MAGIC 4 /* low on magic */
#endif
/* Debuging controls */ /* Debuging controls */
#define DEBUG_CMD 0x0000001 /* Show device commands */ #define DEBUG_CMD 0x0000001 /* Show device commands */
@ -161,12 +170,19 @@ extern DEBTAB crd_debug[];
#define XMASK 03777777777777LL #define XMASK 03777777777777LL
#define EMASK 00777000000000LL #define EMASK 00777000000000LL
#define MMASK 00000777777777LL #define MMASK 00000777777777LL
#define SECTM 00007777000000LL
#define BIT1 00200000000000LL #define BIT1 00200000000000LL
#define BIT2 00100000000000LL
#define BIT3 00040000000000LL
#define BIT4 00020000000000LL
#define BIT5 00010000000000LL
#define BIT6 00004000000000LL
#define BIT7 00002000000000LL #define BIT7 00002000000000LL
#define BIT8 00001000000000LL #define BIT8 00001000000000LL
#define BIT9 00000400000000LL #define BIT9 00000400000000LL
#define BIT10 00000200000000LL #define BIT10 00000200000000LL
#define BIT10_35 00000377777777LL #define BIT10_35 00000377777777LL
#define BIT12 00000040000000LL
#define BIT17 00000001000000LL #define BIT17 00000001000000LL
#define MANT 00000777777777LL #define MANT 00000777777777LL
#define EXPO 00377000000000LL #define EXPO 00377000000000LL
@ -181,6 +197,7 @@ extern DEBTAB crd_debug[];
#define FPRBIT1 00000000000200000000000LL #define FPRBIT1 00000000000200000000000LL
#define CM(x) (FMASK ^ (x)) #define CM(x) (FMASK ^ (x))
#define CCM(x) ((CMASK ^ (x)) & CMASK)
#define INST_V_OP 27 /* opcode */ #define INST_V_OP 27 /* opcode */
#define INST_M_OP 0777 #define INST_M_OP 0777
@ -205,6 +222,8 @@ extern DEBTAB crd_debug[];
#define LRZ(x) (((x) >> 18) & RMASK) #define LRZ(x) (((x) >> 18) & RMASK)
#define JRST1 (((uint64)OP_JRST << 27) + 1) #define JRST1 (((uint64)OP_JRST << 27) + 1)
#define OP_PORTAL(x) (((x) & 00777740000000LL) == 0254040000000LL)
#if PDP6 #if PDP6
#define NODIV 000000 #define NODIV 000000
#define FLTUND 000000 #define FLTUND 000000
@ -275,6 +294,12 @@ extern DEBTAB crd_debug[];
#define AMASK 00000017777777LL #define AMASK 00000017777777LL
#define WMASK 0037777LL #define WMASK 0037777LL
#define CSHIFT 22 #define CSHIFT 22
#if KL
#define RH20_WMASK 003777LL
#define RH20_XFER SMASK
#define RH20_HALT BIT1
#define RH20_REV BIT2
#endif
#else #else
#define AMASK RMASK #define AMASK RMASK
#define WMASK RMASK #define WMASK RMASK
@ -285,11 +310,19 @@ extern DEBTAB crd_debug[];
#define PI_ENABLE 0000000010 /* Clear DONE */ #define PI_ENABLE 0000000010 /* Clear DONE */
#define BUSY 0000000020 /* STOP */ #define BUSY 0000000020 /* STOP */
#define CCW_COMP 0000000040 /* Write Final CCW */ #define CCW_COMP 0000000040 /* Write Final CCW */
/* RH10 / RH20 interrupt */
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
#define CCW_COMP_1 0000000040000LL /* Control word written. */
#if KI #if KI
#define DEF_SERIAL 514 /* Default DEC test machine */ #define DEF_SERIAL 514 /* Default DEC test machine */
#endif #endif
#if KL
#define DEF_SERIAL 1025 /* Default DEC test machine */
#endif
#if BBN #if BBN
#define BBN_PAGE 0000017777777LL #define BBN_PAGE 0000017777777LL
#define BBN_TRPPG 0000017000000LL #define BBN_TRPPG 0000017000000LL
@ -306,13 +339,36 @@ extern DEBTAB crd_debug[];
#define BBN_MERGE 0161740000000LL #define BBN_MERGE 0161740000000LL
#endif #endif
#if KL
/* KL10 TLB paging bits */
#define KL_PAG_A 0400000 /* Access */
#define KL_PAG_P 0200000 /* Public */
#define KL_PAG_W 0100000 /* Writable (M Tops 20) */
#define KL_PAG_S 0040000 /* Software (W Writable Tops 20) */
#define KL_PAG_C 0020000 /* Cacheable */
#endif
#if KI
/* KI10 TLB paging bits */
#define KI_PAG_A 0400000 /* Access */
#define KI_PAG_P 0200000 /* Public */
#define KI_PAG_W 0100000 /* Writable */
#define KI_PAG_S 0040000 /* Software */
#define KI_PAG_X 0020000 /* Reserved */
#endif
/* Flags for CPU unit */ /* Flags for CPU unit */
#define UNIT_V_MSIZE (UNIT_V_UF + 0) #define UNIT_V_MSIZE (UNIT_V_UF + 0)
#define UNIT_MSIZE (0177 << UNIT_V_MSIZE) #define UNIT_MSIZE (0177 << UNIT_V_MSIZE)
#define UNIT_V_MAOFF (UNIT_V_MSIZE + 8) #define UNIT_V_MAOFF (UNIT_V_MSIZE + 8)
#define UNIT_V_PAGE (UNIT_V_MAOFF + 1) #define UNIT_V_PAGE (UNIT_V_MAOFF + 1)
#define UNIT_MAOFF (1 << UNIT_V_MAOFF) #define UNIT_MAOFF (1 << UNIT_V_MAOFF)
#if KL
#define UNIT_KL10B (1 << UNIT_V_PAGE)
#define UNIT_TWOSEG (0)
#else
#define UNIT_TWOSEG (1 << UNIT_V_PAGE) #define UNIT_TWOSEG (1 << UNIT_V_PAGE)
#endif
#define UNIT_ITSPAGE (2 << UNIT_V_PAGE) #define UNIT_ITSPAGE (2 << UNIT_V_PAGE)
#define UNIT_BBNPAGE (4 << UNIT_V_PAGE) #define UNIT_BBNPAGE (4 << UNIT_V_PAGE)
#define UNIT_M_PAGE (007 << UNIT_V_PAGE) #define UNIT_M_PAGE (007 << UNIT_V_PAGE)
@ -322,7 +378,29 @@ extern DEBTAB crd_debug[];
#define UNIT_V_MPX (UNIT_V_WAITS + 1) #define UNIT_V_MPX (UNIT_V_WAITS + 1)
#define UNIT_M_MPX (1 << UNIT_V_MPX) #define UNIT_M_MPX (1 << UNIT_V_MPX)
#define UNIT_MPX (UNIT_M_MPX) /* MPX Device for ITS */ #define UNIT_MPX (UNIT_M_MPX) /* MPX Device for ITS */
#define CNTRL_V_RH (UNIT_V_UF + 4)
#define CNTRL_M_RH 7
#define GET_CNTRL_RH(x) (((x) >> CNTRL_V_RH) & CNTRL_M_RH)
#define CNTRL_RH(x) (((x) & CNTRL_M_RH) << CNTRL_V_RH)
#define DEV_V_RH (DEV_V_UF + 1) /* Type RH20 */
#define DEV_M_RH (1 << DEV_V_RH)
#define TYPE_RH10 (0 << DEV_V_RH)
#define TYPE_RH20 (1 << DEV_V_RH)
#if KL
/* DTE memory access functions, n = DTE# */
extern int Mem_examine_word(int n, int wrd, uint64 *data);
extern int Mem_deposit_word(int n, int wrd, uint64 *data);
extern int Mem_read_byte(int n, uint16 *data, int byte);
extern int Mem_write_byte(int n, uint16 *data);
#endif
/*
* Access main memory. Returns 0 if access ok, 1 if out of memory range.
* On KI10 and KL10, optional EPT flag indicates address relative to ept.
*/
extern int Mem_read_word(t_addr addr, uint64 *data, int ept);
extern int Mem_write_word(t_addr addr, uint64 *data, int ept);
#if MPX_DEV #if MPX_DEV
extern void set_interrupt_mpx(int dev, int lvl, int mpx); extern void set_interrupt_mpx(int dev, int lvl, int mpx);
@ -337,9 +415,15 @@ extern void restore_pi_hold();
extern void set_pi_hold(); extern void set_pi_hold();
extern UNIT cpu_unit[]; extern UNIT cpu_unit[];
extern UNIT ten11_unit[]; extern UNIT ten11_unit[];
extern UNIT auxcpu_unit[]; #if KL
extern DEVICE cpu_dev; extern DEVICE dte_dev;
extern DEVICE lp20_dev;
extern DEVICE tty_dev;
extern DEVICE nia_dev;
#else
extern DEVICE cty_dev; extern DEVICE cty_dev;
#endif
extern DEVICE cpu_dev;
extern DEVICE mt_dev; extern DEVICE mt_dev;
extern DEVICE dpa_dev; extern DEVICE dpa_dev;
extern DEVICE dpb_dev; extern DEVICE dpb_dev;
@ -365,6 +449,7 @@ extern DEVICE pmp_dev;
extern DEVICE dk_dev; extern DEVICE dk_dev;
extern DEVICE pd_dev; extern DEVICE pd_dev;
extern DEVICE dpy_dev; extern DEVICE dpy_dev;
extern DEVICE iii_dev;
extern DEVICE imx_dev; extern DEVICE imx_dev;
extern DEVICE imp_dev; extern DEVICE imp_dev;
extern DEVICE ch10_dev; extern DEVICE ch10_dev;
@ -374,8 +459,10 @@ extern DEVICE mty_dev;
extern DEVICE ten11_dev; extern DEVICE ten11_dev;
extern DEVICE dkb_dev; extern DEVICE dkb_dev;
extern DEVICE auxcpu_dev; extern DEVICE auxcpu_dev;
extern DEVICE slave_dev;
extern DEVICE dpk_dev; extern DEVICE dpk_dev;
extern DEVICE wcnsls_dev; /* MIT Spacewar Consoles */ extern DEVICE wcnsls_dev; /* MIT Spacewar Consoles */
extern DEVICE ocnsls_dev; /* Old MIT Spacewar Consoles */
extern DEVICE ai_dev; extern DEVICE ai_dev;
extern DEVICE dct_dev; /* PDP6 devices. */ extern DEVICE dct_dev; /* PDP6 devices. */
extern DEVICE dtc_dev; extern DEVICE dtc_dev;
@ -387,41 +474,67 @@ extern t_stat (*dev_tab[128])(uint32 dev, t_uint64 *data);
#define VEC_DEVMAX 8 /* max device vec */ #define VEC_DEVMAX 8 /* max device vec */
/* DF10 Interface */
struct df10 {
uint32 status; /* DF10 status word */
uint32 cia; /* Initial transfer address */
uint32 ccw; /* Next control word address */
uint32 wcr; /* CUrrent word count */
uint32 cda; /* Current transfer address */
uint32 devnum; /* Device number */
t_uint64 buf; /* Data buffer */
uint8 nxmerr; /* Bit to set for NXM */
uint8 ccw_comp; /* Have we written out CCW */
} ;
/* RH10/RH20 Interface */
struct rh_if {
void (*dev_write)(DEVICE *dptr, struct rh_if *rh, int reg, uint32 data);
uint32 (*dev_read)(DEVICE *dptr, struct rh_if *rh, int reg);
void (*dev_reset)(DEVICE *dptr);
t_uint64 buf; /* Data buffer */
uint32 status; /* DF10 status word */
uint32 cia; /* Initial transfer address */
uint32 ccw; /* Current word count */
uint32 wcr;
uint32 cda; /* Current transfer address */
uint32 devnum; /* Device number */
int ivect; /* Interrupt vector */
uint8 imode; /* Mode of vector */
int cop; /* RH20 Channel operator */
uint32 sbar; /* RH20 Starting address */
uint32 stcr; /* RH20 Count */
uint32 pbar;
uint32 ptcr;
int reg; /* Last register selected */
int drive; /* Last drive selected */
int rae; /* Access register error */
int attn; /* Attention bits */
int xfer_drive; /* Current transfering drive */
};
/* Device context block */ /* Device context block */
struct pdp_dib { struct pdp_dib {
uint32 dev_num; /* device address */ uint32 dev_num; /* device address */
uint32 num_devs; /* length */ uint32 num_devs; /* length */
t_stat (*io)(uint32 dev, t_uint64 *data); t_stat (*io)(uint32 dev, t_uint64 *data);
int (*irq)(uint32 dev, int addr); t_addr (*irq)(uint32 dev, t_addr addr);
struct rh_if *rh;
}; };
#define RH10_DEV 01000 #define RH10_DEV 01000
#define RH20_DEV 02000
struct rh_dev { struct rh_dev {
uint32 dev_num; uint32 dev_num;
DEVICE *dev; DEVICE *dev;
struct rh_if *rh;
}; };
typedef struct pdp_dib DIB; typedef struct pdp_dib DIB;
void df10_setirq(struct df10 *df);
/* DF10 Interface */ void df10_writecw(struct df10 *df);
struct df10 { void df10_finish_op(struct df10 *df, int flags);
uint32 status;
uint32 cia;
uint32 ccw;
uint32 wcr;
uint32 cda;
uint32 devnum;
t_uint64 buf;
uint8 nxmerr;
uint8 ccw_comp;
} ;
void df10_setirq(struct df10 *df) ;
void df10_writecw(struct df10 *df) ;
void df10_finish_op(struct df10 *df, int flags) ;
void df10_setup(struct df10 *df, uint32 addr); void df10_setup(struct df10 *df, uint32 addr);
int df10_fetch(struct df10 *df); int df10_fetch(struct df10 *df);
int df10_read(struct df10 *df); int df10_read(struct df10 *df);
@ -432,8 +545,27 @@ int dct_write(int u, t_uint64 *data, int c);
int dct_is_connect(int u); int dct_is_connect(int u);
#endif #endif
int ten11_read (int addr, t_uint64 *data); /* Define RH10/RH20 functions */
int ten11_write (int addr, t_uint64 data); t_stat rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat rh_devio(uint32 dev, t_uint64 *data);
t_addr rh_devirq(uint32 dev, t_addr addr);
#if KL
void rh20_setup(struct rh_if *rhc);
#endif
void rh_setup(struct rh_if *rh, uint32 addr);
void rh_setattn(struct rh_if *rh, int unit);
void rh_error(struct rh_if *rh);
int rh_blkend(struct rh_if *rh);
void rh_setirq(struct rh_if *rh);
void rh_writecw(struct rh_if *rh, int nxm);
void rh_finish_op(struct rh_if *rh, int flags);
int rh_read(struct rh_if *rh);
int rh_write(struct rh_if *rh);
int ten11_read (t_addr addr, t_uint64 *data);
int ten11_write (t_addr addr, t_uint64 data);
/* Console lights. */ /* Console lights. */
extern void ka10_lights_init (void); extern void ka10_lights_init (void);
@ -441,36 +573,57 @@ extern void ka10_lights_main (t_uint64);
extern void ka10_lights_set_aux (int); extern void ka10_lights_set_aux (int);
extern void ka10_lights_clear_aux (int); extern void ka10_lights_clear_aux (int);
int auxcpu_read (int addr, t_uint64 *);
int auxcpu_write (int addr, t_uint64);
/* I/O system parameters */ /* I/O system parameters */
#define NUM_DEVS_LP 1 #define NUM_DEVS_LP 1
#if KL
#define NUM_DEVS_PT 0
#define NUM_DEVS_CR 0
#define NUM_DEVS_CP 0
#else
#define NUM_DEVS_PT 1 #define NUM_DEVS_PT 1
#define NUM_DEVS_CR 1 #define NUM_DEVS_CR 1
#define NUM_DEVS_CP 1 #define NUM_DEVS_CP 1
#endif
#define NUM_DEVS_DPY USE_DISPLAY #define NUM_DEVS_DPY USE_DISPLAY
#define NUM_DEVS_WCNSLS USE_DISPLAY #define NUM_DEVS_WCNSLS USE_DISPLAY
#define NUM_DEVS_OCNSLS USE_DISPLAY
#if PDP6_DEV #if PDP6_DEV
#define NUM_DEVS_DTC 1 #define NUM_DEVS_DTC 1
#define NUM_DEVS_DCT 2 #define NUM_DEVS_DCT 2
#define NUM_DEVS_MTC 1 #define NUM_DEVS_MTC 1
#define NUM_DEVS_DSK 1 #define NUM_DEVS_DSK 1
#define NUM_DEVS_DCS 1 #define NUM_DEVS_DCS 1
#define NUM_DEVS_SLAVE PDP6
#endif #endif
#if !PDP6 #if !PDP6
#define NUM_DEVS_DC 1 #define NUM_DEVS_DC 1
#define NUM_DEVS_MT 1 #define NUM_DEVS_MT 1
#if KL
#define NUM_DEVS_RC 0
#define NUM_DEVS_DT 0
#define NUM_DEVS_DK 0
#define NUM_DEVS_DP 0
#define NUM_DEVS_LP20 1
#define NUM_DEVS_TTY 1
#define NUM_LINES_TTY 40
#define NUM_DEVS_NIA 1
#else
#define NUM_DEVS_RC 1 #define NUM_DEVS_RC 1
#define NUM_DEVS_DT 1 #define NUM_DEVS_DT 1
#define NUM_DEVS_DK 1 #define NUM_DEVS_DK 1
#define NUM_DEVS_DP 2 #define NUM_DEVS_DP 2
#define NUM_DEVS_LP20 0
#define NUM_DEVS_TTY 0
#define NUM_DEVS_NIA 0
#endif
#define NUM_DEVS_RP 4 #define NUM_DEVS_RP 4
#define NUM_DEVS_RS 1 #define NUM_DEVS_RS 1
#define NUM_DEVS_TU 1 #define NUM_DEVS_TU 1
#define NUM_DEVS_PMP WAITS #define NUM_DEVS_PMP WAITS
#define NUM_DEVS_DKB WAITS #define NUM_DEVS_DKB (WAITS * USE_DISPLAY)
#define NUM_DEVS_PD ITS #define NUM_DEVS_III (WAITS * USE_DISPLAY)
#define NUM_DEVS_PD ITS | KL_ITS
#define NUM_DEVS_IMX ITS #define NUM_DEVS_IMX ITS
#define NUM_DEVS_STK ITS #define NUM_DEVS_STK ITS
#define NUM_DEVS_TK10 ITS #define NUM_DEVS_TK10 ITS
@ -478,10 +631,14 @@ int auxcpu_write (int addr, t_uint64);
#define NUM_DEVS_TEN11 ITS #define NUM_DEVS_TEN11 ITS
#define NUM_DEVS_AUXCPU ITS #define NUM_DEVS_AUXCPU ITS
#define NUM_DEVS_IMP 1 #define NUM_DEVS_IMP 1
#define NUM_DEVS_CH10 ITS #define NUM_DEVS_CH10 ITS | KL_ITS
#define NUM_DEVS_DPK ITS #define NUM_DEVS_DPK ITS
#define NUM_DEVS_AI ITS #define NUM_DEVS_AI ITS
#endif #endif
#if MAGIC_SWITCH && !KA && !ITS
#error "Magic switch only valid on KA10 with ITS mods"
#endif
/* Global data */ /* Global data */
@ -492,4 +649,16 @@ extern t_uint64 FM[];
extern uint32 PC; extern uint32 PC;
extern uint32 FLAGS; extern uint32 FLAGS;
#if NUM_DEVS_AUXCPU
extern t_addr auxcpu_base;
int auxcpu_read (t_addr addr, uint64 *);
int auxcpu_write (t_addr addr, uint64);
extern UNIT auxcpu_unit[];
#endif
#if NUM_DEVS_SLAVE
//int slave_read (t_addr addr);
//int slave_write (t_addr addr, uint64);
//extern UNIT slave_unit[];
#endif
#endif #endif

View file

@ -1,6 +1,6 @@
/* ka10_df.c: DF10 common routines. /* kx10_df.c: DF10 common routines.
Copyright (c) 2015-2017, Richard Cornwell Copyright (c) 2015-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -23,18 +23,24 @@
#include "kx10_defs.h" #include "kx10_defs.h"
/* Set an IRQ for a DF10 device */
void df10_setirq(struct df10 *df) { void df10_setirq(struct df10 *df) {
df->status |= PI_ENABLE; df->status |= PI_ENABLE;
set_interrupt(df->devnum, df->status); set_interrupt(df->devnum, df->status);
} }
/* Generate the DF10 complete word */
void df10_writecw(struct df10 *df) { void df10_writecw(struct df10 *df) {
uint64 wrd;
df->status |= 1 << df->ccw_comp; df->status |= 1 << df->ccw_comp;
if (df->wcr != 0) if (df->wcr != 0)
df->cda++; df->cda++;
M[df->cia|1] = ((uint64)(df->ccw & WMASK) << CSHIFT) | ((uint64)(df->cda) & AMASK); wrd = ((uint64)(df->ccw & WMASK) << CSHIFT) | ((uint64)(df->cda) & AMASK);
(void)Mem_write_word(df->cia|1, &wrd, 0);
} }
/* Finish off a DF10 transfer */
void df10_finish_op(struct df10 *df, int flags) { void df10_finish_op(struct df10 *df, int flags) {
df->status &= ~BUSY; df->status &= ~BUSY;
df->status |= flags; df->status |= flags;
@ -42,6 +48,7 @@ void df10_finish_op(struct df10 *df, int flags) {
df10_setirq(df); df10_setirq(df);
} }
/* Setup for a DF10 transfer */
void df10_setup(struct df10 *df, uint32 addr) { void df10_setup(struct df10 *df, uint32 addr) {
df->cia = addr & ICWA; df->cia = addr & ICWA;
df->ccw = df->cia; df->ccw = df->cia;
@ -50,24 +57,23 @@ void df10_setup(struct df10 *df, uint32 addr) {
df->status &= ~(1 << df->ccw_comp); df->status &= ~(1 << df->ccw_comp);
} }
/* Fetch the next IO control word */
int df10_fetch(struct df10 *df) { int df10_fetch(struct df10 *df) {
uint64 data; uint64 data;
if (df->ccw > MEMSIZE) { if (Mem_read_word(df->ccw, &data, 0)) {
df10_finish_op(df, df->nxmerr); df10_finish_op(df, df->nxmerr);
return 0; return 0;
} }
data = M[df->ccw];
while((data & (WMASK << CSHIFT)) == 0) { while((data & (WMASK << CSHIFT)) == 0) {
if ((data & AMASK) == 0 || (uint32)(data & AMASK) == df->ccw) { if ((data & AMASK) == 0 || (uint32)(data & AMASK) == df->ccw) {
df10_finish_op(df,0); df10_finish_op(df,0);
return 0; return 0;
} }
df->ccw = (uint32)(data & AMASK); df->ccw = (uint32)(data & AMASK);
if (df->ccw > MEMSIZE) { if (Mem_read_word(df->ccw, &data, 0)) {
df10_finish_op(df, 1<<df->nxmerr); df10_finish_op(df, 1<<df->nxmerr);
return 0; return 0;
} }
data = M[df->ccw];
} }
#if KA & ITS #if KA & ITS
if (cpu_unit[0].flags & UNIT_ITSPAGE) { if (cpu_unit[0].flags & UNIT_ITSPAGE) {
@ -84,6 +90,7 @@ int df10_fetch(struct df10 *df) {
return 1; return 1;
} }
/* Read next word */
int df10_read(struct df10 *df) { int df10_read(struct df10 *df) {
uint64 data; uint64 data;
if (df->wcr == 0) { if (df->wcr == 0) {
@ -102,7 +109,10 @@ int df10_read(struct df10 *df) {
else else
#endif #endif
df->cda = (uint32)((df->cda + 1) & AMASK); df->cda = (uint32)((df->cda + 1) & AMASK);
data = M[df->cda]; if (Mem_read_word(df->cda, &data, 0)) {
df10_finish_op(df, 1<<df->nxmerr);
return 0;
}
} else { } else {
data = 0; data = 0;
} }
@ -113,6 +123,7 @@ int df10_read(struct df10 *df) {
return 1; return 1;
} }
/* Write next word */
int df10_write(struct df10 *df) { int df10_write(struct df10 *df) {
if (df->wcr == 0) { if (df->wcr == 0) {
if (!df10_fetch(df)) if (!df10_fetch(df))
@ -130,7 +141,10 @@ int df10_write(struct df10 *df) {
else else
#endif #endif
df->cda = (uint32)((df->cda + 1) & AMASK); df->cda = (uint32)((df->cda + 1) & AMASK);
M[df->cda] = df->buf; if (Mem_write_word(df->cda, &df->buf, 0)) {
df10_finish_op(df, 1<<df->nxmerr);
return 0;
}
} }
if (df->wcr == 0) { if (df->wcr == 0) {
return df10_fetch(df); return df10_fetch(df);

289
PDP10/kx10_disk.c Normal file
View file

@ -0,0 +1,289 @@
/* kx10_disk.c: Disk translator.
Copyright (c) 2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "kx10_defs.h"
#include "kx10_disk.h"
/*
* SIMH format is number words per sector stored as a 64 bit word.
*
* DBD9 format is: 9 character per pair of words.
*
* 0 - B0 1 2 3 4 5 6 7
* 0 - 8 9 10 11 12 13 14 15
* 0 - 16 17 18 19 20 21 22 23
* 0 - 24 25 26 27 28 29 30 31
* 0 - 32 33 34 35 B0 1 2 3
* 1 - 4 5 6 7 8 9 10 11
* 1 - 12 13 14 15 16 17 18 19
* 1 - 20 21 22 23 24 25 26 27
* 1 - 28 29 30 31 32 33 34 35
*
*
* DLD9 format is: 9 character per pair of words.
*
* 0 - 28 29 30 31 32 33 34 35
* 0 - 20 21 22 23 24 25 26 27
* 0 - 12 13 14 15 16 17 18 19
* 0 - 4 5 6 7 8 9 10 11
* 0 - 32 33 34 35 B0 1 2 3
* 1 - 24 25 26 27 28 29 30 31
* 1 - 16 17 18 19 20 21 22 23
* 1 - 8 9 10 11 12 13 14 15
* 1 - B0 1 2 3 4 5 6 7
*/
struct disk_formats {
uint32 mode;
const char *name;
};
static struct disk_formats fmts[] = {
{SIMH, "SIMH"},
{DBD9, "DBD9"},
{DLD9, "DLD9"},
{0, 0},
};
t_stat
disk_read(UNIT *uptr, uint64 *buffer, int sector, int wps)
{
int da;
int wc;
int bc;
int wp;
uint64 temp;
uint8 conv_buff[2048];
switch(GET_FMT(uptr->flags)) {
case SIMH:
da = sector * wps;
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET);
wc = sim_fread (buffer, sizeof(uint64), wps, uptr->fileref);
while (wc < wps)
buffer[wc++] = 0;
break;
case DBD9:
bc = (wps / 2) * 9;
da = sector * bc;
(void)sim_fseek(uptr->fileref, da, SEEK_SET);
wc = sim_fread (&conv_buff, 1, bc, uptr->fileref);
while (wc < bc)
conv_buff[wc++] = 0;
for (wp = wc = 0; wp < wps;) {
temp = ((uint64)conv_buff[wc++]) << 28;
temp |= ((uint64)conv_buff[wc++]) << 20;
temp |= ((uint64)conv_buff[wc++]) << 12;
temp |= ((uint64)conv_buff[wc++]) << 4;
temp |= ((uint64)conv_buff[wc]) >> 4;
buffer[wp++] = temp;
temp = ((uint64)conv_buff[wc++] & 0xf) << 32;
temp |= ((uint64)conv_buff[wc++]) << 24;
temp |= ((uint64)conv_buff[wc++]) << 16;
temp |= ((uint64)conv_buff[wc++]) << 8;
temp |= ((uint64)conv_buff[wc++]);
buffer[wp++] = temp;
}
break;
case DLD9:
bc = (wps / 2) * 9;
da = sector * bc;
(void)sim_fseek(uptr->fileref, da, SEEK_SET);
wc = sim_fread (&conv_buff, 1, bc, uptr->fileref);
while (wc < bc)
conv_buff[wc++] = 0;
for (wp = wc = 0; wp < wps;) {
temp = ((uint64)conv_buff[wc++]);
temp |= ((uint64)conv_buff[wc++]) << 8;
temp |= ((uint64)conv_buff[wc++]) << 16;
temp |= ((uint64)conv_buff[wc++]) << 24;
temp |= ((uint64)conv_buff[wc] & 0xf) << 32;
buffer[wp++] = temp;
temp = ((uint64)conv_buff[wc++] & 0xf0) >> 4;
temp |= ((uint64)conv_buff[wc++]) << 4;
temp |= ((uint64)conv_buff[wc++]) << 12;
temp |= ((uint64)conv_buff[wc++]) << 20;
temp |= ((uint64)conv_buff[wc++]) << 28;
buffer[wp++] = temp;
}
break;
}
return SCPE_OK;
}
t_stat
disk_write(UNIT *uptr, uint64 *buffer, int sector, int wps)
{
int da;
int wc;
int bc;
int wp;
uint64 temp;
uint8 conv_buff[2048];
switch(GET_FMT(uptr->flags)) {
case SIMH:
da = sector * wps;
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET);
wc = sim_fwrite (buffer, sizeof(uint64), wps, uptr->fileref);
break;
case DBD9:
bc = (wps / 2) * 9;
for (wp = wc = 0; wp < wps;) {
temp = buffer[wp++];
conv_buff[wc++] = (uint8)((temp >> 28) & 0xff);
conv_buff[wc++] = (uint8)((temp >> 20) & 0xff);
conv_buff[wc++] = (uint8)((temp >> 12) & 0xff);
conv_buff[wc++] = (uint8)((temp >> 4) & 0xff);
conv_buff[wc] = (uint8)((temp & 0xf) << 4);
temp = buffer[wp++];
conv_buff[wc++] |= (uint8)((temp >> 32) & 0xf);
conv_buff[wc++] = (uint8)((temp >> 24) & 0xff);
conv_buff[wc++] = (uint8)((temp >> 16) & 0xff);
conv_buff[wc++] = (uint8)((temp >> 8) & 0xff);
conv_buff[wc++] = (uint8)(temp & 0xff);
}
da = sector * bc;
(void)sim_fseek(uptr->fileref, da, SEEK_SET);
wc = sim_fwrite (&conv_buff, 1, bc, uptr->fileref);
return SCPE_OK;
case DLD9:
bc = (wps / 2) * 9;
for (wp = wc = 0; wp < wps;) {
temp = buffer[wp++];
conv_buff[wc++] = (uint8)(temp & 0xff);
conv_buff[wc++] = (uint8)((temp >> 8) & 0xff);
conv_buff[wc++] = (uint8)((temp >> 16) & 0xff);
conv_buff[wc++] = (uint8)((temp >> 24) & 0xff);
conv_buff[wc] = (uint8)((temp >> 32) & 0xf);
temp = buffer[wp++];
conv_buff[wc++] |= (uint8)((temp << 4) & 0xf0);
conv_buff[wc++] = (uint8)((temp >> 4) & 0xff);
conv_buff[wc++] = (uint8)((temp >> 12) & 0xff);
conv_buff[wc++] = (uint8)((temp >> 20) & 0xff);
conv_buff[wc++] = (uint8)((temp >> 28) & 0xff);
}
da = sector * bc;
(void)sim_fseek(uptr->fileref, da, SEEK_SET);
wc = sim_fwrite (&conv_buff, 1, bc, uptr->fileref);
return SCPE_OK;
}
return SCPE_OK;
}
/* Set disk format */
t_stat disk_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
int f;
if (uptr == NULL) return SCPE_IERR;
if (cptr == NULL) return SCPE_ARG;
for (f = 0; fmts[f].name != 0; f++) {
if (strcmp (cptr, fmts[f].name) == 0) {
uptr->flags &= ~UNIT_FMT;
uptr->flags |= SET_FMT(fmts[f].mode);
return SCPE_OK;
}
}
return SCPE_ARG;
}
/* Show disk format */
t_stat disk_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
int fmt = GET_FMT(uptr->flags);
int f;
for (f = 0; fmts[f].name != 0; f++) {
if (fmt == fmts[f].mode) {
fprintf (st, "%s format", fmts[f].name);
return SCPE_OK;
}
}
fprintf (st, "invalid format");
return SCPE_OK;
}
/* Device attach */
t_stat disk_attach (UNIT *uptr, CONST char *cptr)
{
t_stat r;
char gbuf[30];
/* Reset to SIMH format on attach */
uptr->flags &= ~UNIT_FMT;
/* Pickup optional format specifier during RESTORE */
cptr = get_sim_sw (cptr);
if (sim_switches & SWMASK ('F')) { /* format spec? */
cptr = get_glyph (cptr, gbuf, 0); /* get spec */
if (*cptr == 0) return SCPE_2FARG; /* must be more */
if (disk_set_fmt (uptr, 0, gbuf, NULL) != SCPE_OK)
return SCPE_ARG;
}
r = attach_unit (uptr, cptr);
if (r != SCPE_OK)
return r;
return SCPE_OK;
}
/* Device detach */
t_stat disk_detach (UNIT *uptr)
{
return detach_unit (uptr);
}
t_stat disk_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{
fprintf (st, "%s Disk Attach Help\n\n", dptr->name);
fprintf (st, "Disk container files can be one of 3 different types:\n\n");
fprintf (st, " SIMH A disk is an unstructured binary file of 64bit integers\n");
fprintf (st, " DBD9 Compatible with KLH10 is a packed big endian word\n");
fprintf (st, " DLD9 Compatible with KLH10 is a packed little endian word\n");
if (dptr->numunits > 1) {
uint32 i;
for (i=0; (i < dptr->numunits); ++i)
if ((dptr->units[i].flags & UNIT_ATTABLE) &&
!(dptr->units[i].flags & UNIT_DIS)) {
fprintf (st, " sim> ATTACH {switches} %s%d diskfile\n", dptr->name, i);
}
}
else
fprintf (st, " sim> ATTACH {switches} %s diskfile\n", dptr->name);
fprintf (st, "\n%s attach command switches\n", dptr->name);
fprintf (st, " -R Attach Read Only.\n");
fprintf (st, " -E Must Exist (if not specified an attempt to create the indicated\n");
fprintf (st, " disk container will be attempted).\n");
fprintf (st, " -F Open the indicated disk container in a specific format (default\n");
fprintf (st, " is SIMH), other options are DBD9 and DLD9\n");
fprintf (st, " -Y Answer Yes to prompt to overwrite last track (on disk create)\n");
fprintf (st, " -N Answer No to prompt to overwrite last track (on disk create)\n");
return SCPE_OK;
}

81
PDP10/kx10_disk.h Normal file
View file

@ -0,0 +1,81 @@
/* kx10_disk.h: Disk translator.
Copyright (c) 2020, 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.
*/
/* Flags in the unit flags word */
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_WLK (1 << UNIT_V_WLK)
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
#define UNIT_V_FMT (UNIT_V_UF + 8)
#define UNIT_M_FMT 7
#define GET_FMT(x) (((x) >> UNIT_V_FMT) & UNIT_M_FMT)
#define SET_FMT(x) (((x) & UNIT_M_FMT) << UNIT_V_FMT)
#define UNIT_FMT (UNIT_M_FMT << UNIT_V_FMT)
#define SIMH 0 /* Default raw uint64 word format */
#define DBD9 1 /* KLH10 Disb Big End Double */
#define DLD9 2 /* KLH10 Disb Little End Double */
/*
* SIMH format is number words per sector stored as a 64 bit word.
*
* DBD9 format is: 9 character per pair of words.
*
* 0 - B0 1 2 3 4 5 6 7
* 0 - 8 9 10 11 12 13 14 15
* 0 - 16 17 18 19 20 21 22 23
* 0 - 24 25 26 27 28 29 30 31
* 0 - 32 33 34 35 B0 1 2 3
* 1 - 4 5 6 7 8 9 10 11
* 1 - 12 13 14 15 16 17 18 19
* 1 - 20 21 22 23 24 25 26 27
* 1 - 28 29 30 31 32 33 34 35
*
*
* DLD9 format is: 9 character per pair of words.
*
* 0 - 28 29 30 31 32 33 34 35
* 0 - 20 21 22 23 24 25 26 27
* 0 - 12 13 14 15 16 17 18 19
* 0 - 4 5 6 7 8 9 10 11
* 0 - 32 33 34 35 B0 1 2 3
* 1 - 24 25 26 27 28 29 30 31
* 1 - 16 17 18 19 20 21 22 23
* 1 - 8 9 10 11 12 13 14 15
* 1 - B0 1 2 3 4 5 6 7
*/
t_stat disk_read(UNIT *uptr, uint64 *buffer, int sector, int wps);
t_stat disk_write(UNIT *uptr, uint64 *buffer, int sector, int wps);
/* Set disk format */
t_stat disk_set_fmt (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
/* Show disk format */
t_stat disk_show_fmt (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
/* Device attach */
t_stat disk_attach (UNIT *uptr, CONST char *cptr);
/* Device detach */
t_stat disk_detach (UNIT *uptr);
/* Print attach help */
t_stat disk_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);

View file

@ -1,6 +1,6 @@
/* ka10_dk.c: PDP-10 DK subsystem simulator /* kx10_dk.c: PDP-10 DK subsystem simulator
Copyright (c) 2013-2017, Richard Cornwell Copyright (c) 2013-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* ka10_dp.c: Dec Data Products Disk Drive. /* kx10_dp.c: Dec Data Products Disk Drive.
Copyright (c) 2013-2017, Richard Cornwell Copyright (c) 2013-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -22,6 +22,7 @@
*/ */
#include "kx10_defs.h" #include "kx10_defs.h"
#include "kx10_disk.h"
#ifndef NUM_DEVS_DP #ifndef NUM_DEVS_DP
#define NUM_DEVS_DP 0 #define NUM_DEVS_DP 0
@ -39,13 +40,10 @@
/* Flags in the unit flags word */ /* Flags in the unit flags word */
#define DEV_WHDR (1 << DEV_V_UF) /* Enable write headers */ #define DEV_WHDR (1 << DEV_V_UF) /* Enable write headers */
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */ #define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */
#define UNIT_M_DTYPE 3 #define UNIT_M_DTYPE 3
#define UNIT_WLK (1 << UNIT_V_WLK)
#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE) #define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) #define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
/* Parameters in the unit descriptor */ /* Parameters in the unit descriptor */
@ -271,6 +269,7 @@ MTAB dp_mod[] = {
{UNIT_DTYPE, (RP03_DTYPE << UNIT_V_DTYPE), "RP03", "RP03", &dp_set_type }, {UNIT_DTYPE, (RP03_DTYPE << UNIT_V_DTYPE), "RP03", "RP03", &dp_set_type },
{UNIT_DTYPE, (RP02_DTYPE << UNIT_V_DTYPE), "RP02", "RP02", &dp_set_type }, {UNIT_DTYPE, (RP02_DTYPE << UNIT_V_DTYPE), "RP02", "RP02", &dp_set_type },
{UNIT_DTYPE, (RP01_DTYPE << UNIT_V_DTYPE), "RP01", "RP01", &dp_set_type }, {UNIT_DTYPE, (RP01_DTYPE << UNIT_V_DTYPE), "RP01", "RP01", &dp_set_type },
{MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT", NULL, &disk_show_fmt },
{0}, {0},
}; };
@ -301,7 +300,7 @@ DEVICE dpa_dev = {
#if (NUM_DEVS_DP > 1) #if (NUM_DEVS_DP > 1)
REG dpb_reg[] = { REG dpb_reg[] = {
{BRDATA(BUFF, dp_buf[1], 16, 64, RP_NUMWD), REG_HRO}, {BRDATA(BUFF, dp_buf[1], 16, 64, RP_NUMWD), REG_HRO},
{HRDATA(UNIT, dp_cur_unit[1], 32), REG_HRO}, {HRDATA(DF10, dp_cur_unit[1], 32), REG_HRO},
{ORDATA(STATUS, dp_df10[1].status, 18), REG_RO}, {ORDATA(STATUS, dp_df10[1].status, 18), REG_RO},
{ORDATA(CIA, dp_df10[1].cia, 18)}, {ORDATA(CIA, dp_df10[1].cia, 18)},
{ORDATA(CCW, dp_df10[1].ccw, 18)}, {ORDATA(CCW, dp_df10[1].ccw, 18)},
@ -325,7 +324,7 @@ DEVICE dpb_dev = {
#if (NUM_DEVS_DP > 2) #if (NUM_DEVS_DP > 2)
REG dpc_reg[] = { REG dpc_reg[] = {
{BRDATA(BUFF, dp_buf[2], 16, 64, RP_NUMWD), REG_HRO}, {BRDATA(BUFF, dp_buf[2], 16, 64, RP_NUMWD), REG_HRO},
{BRDATA(DF10, &dp_cur_unit[2], 16, 8, 1), REG_HRO}, {HRDATA(DF10, dp_cur_unit[2], 32), REG_HRO},
{ORDATA(STATUS, dp_df10[2].status, 18), REG_RO}, {ORDATA(STATUS, dp_df10[2].status, 18), REG_RO},
{ORDATA(CIA, dp_df10[2].cia, 18)}, {ORDATA(CIA, dp_df10[2].cia, 18)},
{ORDATA(CCW, dp_df10[2].ccw, 18)}, {ORDATA(CCW, dp_df10[2].ccw, 18)},
@ -348,8 +347,8 @@ DEVICE dpc_dev = {
#if (NUM_DEVS_DP > 3) #if (NUM_DEVS_DP > 3)
REG dpd_reg[] = { REG dpd_reg[] = {
{BRDATA(BUFF, dp_buf[3], 16, 64, RP_NUMWD), REG_HRO}, {BRDATA(BUFF, &dp_buf[3][0], 16, 64, RP_NUMWD), REG_HRO},
{BRDATA(DF10, &dp_cur_unit[3], 16, 8, 1), REG_HRO}, {BRDATA(DF10, dp_cur_unit[3], 32), REG_HRO},
{ORDATA(STATUS, dp_df10[3].status, 18), REG_RO}, {ORDATA(STATUS, dp_df10[3].status, 18), REG_RO},
{ORDATA(CIA, dp_df10[3].cia, 18)}, {ORDATA(CIA, dp_df10[3].cia, 18)},
{ORDATA(CCW, dp_df10[3].ccw, 18)}, {ORDATA(CCW, dp_df10[3].ccw, 18)},
@ -423,7 +422,6 @@ t_stat dp_devio(uint32 dev, uint64 *data) {
if (*data & BUSY) { if (*data & BUSY) {
/* Stop controller */ /* Stop controller */
sim_cancel(uptr); sim_cancel(uptr);
uptr->STATUS &= ~BUSY;
df10_finish_op(df10, 0); df10_finish_op(df10, 0);
} }
/* Clear flags */ /* Clear flags */
@ -603,7 +601,7 @@ t_stat dp_svc (UNIT *uptr)
int cyl = (uptr->UFLAGS >> 20) & 0777; int cyl = (uptr->UFLAGS >> 20) & 0777;
DEVICE *dptr = dp_devs[ctlr]; DEVICE *dptr = dp_devs[ctlr];
struct df10 *df10 = &dp_df10[ctlr]; struct df10 *df10 = &dp_df10[ctlr];
int diff, diffs, wc; int diff, diffs;
int r; int r;
sect &= 017; sect &= 017;
@ -647,12 +645,8 @@ t_stat dp_svc (UNIT *uptr)
if (cmd != WR) { if (cmd != WR) {
/* Read the block */ /* Read the block */
int da = ((cyl * dp_drv_tab[dtype].surf + surf) int da = ((cyl * dp_drv_tab[dtype].surf + surf)
* dp_drv_tab[dtype].sect + sect) * RP_NUMWD; * dp_drv_tab[dtype].sect + sect);
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); (void)disk_read(uptr, &dp_buf[ctlr][0], da, RP_NUMWD);
wc = sim_fread (&dp_buf[ctlr][0], sizeof(uint64), RP_NUMWD,
uptr->fileref);
for (; wc < RP_NUMWD; wc++)
dp_buf[ctlr][wc] = 0;
uptr->hwmark = RP_NUMWD; uptr->hwmark = RP_NUMWD;
uptr->DATAPTR = 0; uptr->DATAPTR = 0;
sect = sect + 1; sect = sect + 1;
@ -695,13 +689,11 @@ t_stat dp_svc (UNIT *uptr)
if (uptr->DATAPTR >= RP_NUMWD || r == 0 ) { if (uptr->DATAPTR >= RP_NUMWD || r == 0 ) {
if (cmd == WR) { if (cmd == WR) {
int da = ((cyl * dp_drv_tab[dtype].surf + surf) int da = ((cyl * dp_drv_tab[dtype].surf + surf)
* dp_drv_tab[dtype].sect + sect) * RP_NUMWD; * dp_drv_tab[dtype].sect + sect);
/* write block the block */ /* write block the block */
for (; uptr->DATAPTR < RP_NUMWD; uptr->DATAPTR++) for (; uptr->DATAPTR < RP_NUMWD; uptr->DATAPTR++)
dp_buf[ctlr][uptr->DATAPTR] = 0; dp_buf[ctlr][uptr->DATAPTR] = 0;
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); (void)disk_write(uptr, &dp_buf[ctlr][0], da, RP_NUMWD);
wc = sim_fwrite(&dp_buf[ctlr][0],sizeof(uint64), RP_NUMWD,
uptr->fileref);
uptr->STATUS |= SRC_DONE; uptr->STATUS |= SRC_DONE;
sect = sect + 1; sect = sect + 1;
if (sect >= dp_drv_tab[dtype].sect) { if (sect >= dp_drv_tab[dtype].sect) {
@ -722,7 +714,7 @@ t_stat dp_svc (UNIT *uptr)
CLR_BUF(uptr); CLR_BUF(uptr);
} }
if (r) if (r)
sim_activate(uptr, 25); sim_activate(uptr, 40);
else { else {
uptr->STATUS &= ~(SRC_DONE|END_CYL|BUSY); uptr->STATUS &= ~(SRC_DONE|END_CYL|BUSY);
uptr->UFLAGS |= DONE; uptr->UFLAGS |= DONE;
@ -780,13 +772,11 @@ t_stat dp_svc (UNIT *uptr)
uptr->DATAPTR++; uptr->DATAPTR++;
if (uptr->DATAPTR >= RP_NUMWD || r == 0 ) { if (uptr->DATAPTR >= RP_NUMWD || r == 0 ) {
int da = ((cyl * dp_drv_tab[dtype].surf + surf) int da = ((cyl * dp_drv_tab[dtype].surf + surf)
* dp_drv_tab[dtype].sect + sect) * RP_NUMWD; * dp_drv_tab[dtype].sect + sect);
/* write block the block */ /* write block the block */
for (; uptr->DATAPTR < RP_NUMWD; uptr->DATAPTR++) for (; uptr->DATAPTR < RP_NUMWD; uptr->DATAPTR++)
dp_buf[ctlr][uptr->DATAPTR] = 0; dp_buf[ctlr][uptr->DATAPTR] = 0;
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); (void)disk_write(uptr, &dp_buf[ctlr][0], da, RP_NUMWD);
wc = sim_fwrite(&dp_buf[ctlr][0],sizeof(uint64), RP_NUMWD,
uptr->fileref);
uptr->STATUS |= SRC_DONE; uptr->STATUS |= SRC_DONE;
sect = sect + 1; sect = sect + 1;
if (sect >= dp_drv_tab[dtype].sect) { if (sect >= dp_drv_tab[dtype].sect) {
@ -931,8 +921,7 @@ dp_boot(int32 unit_num, DEVICE * dptr)
addr = (MEMSIZE - 512) & RMASK; addr = (MEMSIZE - 512) & RMASK;
for (sect = 4; sect <= 7; sect++) { for (sect = 4; sect <= 7; sect++) {
(void)sim_fseek(uptr->fileref, (sect * RP_NUMWD) * sizeof(uint64), SEEK_SET); (void)disk_read(uptr, &dp_buf[0][0], sect, RP_NUMWD);
(void)sim_fread (&dp_buf[0][0], sizeof(uint64), RP_NUMWD, uptr->fileref);
ptr = 0; ptr = 0;
for(wc = RP_NUMWD; wc > 0; wc--) for(wc = RP_NUMWD; wc > 0; wc--)
M[addr++] = dp_buf[0][ptr++]; M[addr++] = dp_buf[0][ptr++];
@ -950,10 +939,10 @@ t_stat dp_attach (UNIT *uptr, CONST char *cptr)
DIB *dib; DIB *dib;
int ctlr; int ctlr;
uptr->capac = dp_drv_tab[GET_DTYPE (uptr->flags)].size; r = disk_attach (uptr, cptr);
r = attach_unit (uptr, cptr); if (r != SCPE_OK || (sim_switches & SIM_SW_REST) != 0)
if (r != SCPE_OK)
return r; return r;
uptr->capac = dp_drv_tab[GET_DTYPE (uptr->flags)].size;
dptr = find_dev_from_unit(uptr); dptr = find_dev_from_unit(uptr);
if (dptr == 0) if (dptr == 0)
return SCPE_OK; return SCPE_OK;
@ -962,7 +951,7 @@ t_stat dp_attach (UNIT *uptr, CONST char *cptr)
uptr->CUR_CYL = 0; uptr->CUR_CYL = 0;
uptr->UFLAGS = (NO << 3) | SEEK_DONE | (ctlr >> 2); uptr->UFLAGS = (NO << 3) | SEEK_DONE | (ctlr >> 2);
dp_df10[ctlr].status |= PI_ENABLE; dp_df10[ctlr].status |= PI_ENABLE;
set_interrupt(DP_DEVNUM + (ctlr), dp_df10[ctlr >> 2].status); set_interrupt(DP_DEVNUM + (ctlr), dp_df10[ctlr].status);
return SCPE_OK; return SCPE_OK;
} }
@ -974,7 +963,7 @@ t_stat dp_detach (UNIT *uptr)
return SCPE_OK; return SCPE_OK;
if (sim_is_active (uptr)) /* unit active? */ if (sim_is_active (uptr)) /* unit active? */
sim_cancel (uptr); /* cancel operation */ sim_cancel (uptr); /* cancel operation */
return detach_unit (uptr); return disk_detach (uptr);
} }
t_stat dp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr) t_stat dp_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
@ -983,6 +972,7 @@ fprintf (st, "RP10 RP01/2/3 Disk Pack Drives (DP)\n\n");
fprintf (st, "The DP controller implements the RP10 disk drives. RP\n"); fprintf (st, "The DP controller implements the RP10 disk drives. RP\n");
fprintf (st, "options include the ability to set units write enabled or write locked, to\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 three disk types.\n"); fprintf (st, "set the drive type to one of three disk types.\n");
disk_attach_help(st, dptr, uptr, flag, cptr);
fprint_set_help (st, dptr); fprint_set_help (st, dptr);
fprint_show_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"); fprintf (st, "\nThe type options can be used only when a unit is not attached to a file.\n");

View file

@ -85,6 +85,7 @@
*/ */
#include "kx10_defs.h" #include "kx10_defs.h"
#include "sim_video.h"
#include <time.h> #include <time.h>
#ifndef NUM_DEVS_DPY #ifndef NUM_DEVS_DPY
@ -296,13 +297,40 @@ t_stat dpy_svc (UNIT *uptr)
return SCPE_OK; return SCPE_OK;
} }
#define JOY_MAX_UNITS 4
#define JOY_MAX_AXES 4
#define JOY_MAX_BUTTONS 4
static int joy_axes[JOY_MAX_UNITS * JOY_MAX_AXES];
static int joy_buttons[JOY_MAX_UNITS * JOY_MAX_BUTTONS];
static void dpy_joy_motion(int which, int axis, int value)
{
int result = FALSE;
if (which < JOY_MAX_UNITS && axis < JOY_MAX_AXES) {
joy_axes[which * JOY_MAX_AXES + axis] = value;
}
}
static void dpy_joy_button(int which, int button, int state)
{
int result = FALSE;
if (which < JOY_MAX_UNITS && button < JOY_MAX_BUTTONS) {
joy_buttons[which * JOY_MAX_UNITS + button] = state;
}
}
/* Reset routine */ /* Reset routine */
t_stat dpy_reset (DEVICE *dptr) t_stat dpy_reset (DEVICE *dptr)
{ {
if (!(dptr->flags & DEV_DIS)) { if (dptr->flags & DEV_DIS) {
display_close(dptr);
} else {
display_reset(); display_reset();
ty340_reset(dptr); ty340_reset(dptr);
vid_register_gamepad_motion_callback (dpy_joy_motion);
vid_register_gamepad_button_callback (dpy_joy_button);
} }
sim_cancel (&dpy_unit[0]); /* deactivate unit */ sim_cancel (&dpy_unit[0]); /* deactivate unit */
return SCPE_OK; return SCPE_OK;
@ -367,17 +395,25 @@ cpu_set_switches(unsigned long w1, unsigned long w2) {
#if NUM_DEVS_WCNSLS > 0 #if NUM_DEVS_WCNSLS > 0
#define WCNSLS_DEVNUM 0420 #define WCNSLS_DEVNUM 0420
#define UNIT_JOY (1 << DEV_V_UF)
t_stat wcnsls_devio(uint32 dev, uint64 *data); t_stat wcnsls_devio(uint32 dev, uint64 *data);
const char *wcnsls_description (DEVICE *dptr); const char *wcnsls_description (DEVICE *dptr);
DIB wcnsls_dib[] = { DIB wcnsls_dib[] = {
{ WCNSLS_DEVNUM, 1, &wcnsls_devio, NULL }}; { WCNSLS_DEVNUM, 1, &wcnsls_devio, NULL }};
MTAB wcnsls_mod[] = {
{ UNIT_JOY, UNIT_JOY, "JOYSTICK", "JOYSTICK", NULL, NULL, NULL,
"Use USB joysticks"},
{ 0 }
};
UNIT wcnsls_unit[] = { UNIT wcnsls_unit[] = {
{ UDATA (NULL, UNIT_IDLE, 0) }}; { UDATA (NULL, UNIT_IDLE, 0) }};
DEVICE wcnsls_dev = { DEVICE wcnsls_dev = {
"WCNSLS", wcnsls_unit, NULL, NULL, "WCNSLS", wcnsls_unit, NULL, wcnsls_mod,
NUM_DEVS_WCNSLS, 0, 0, 0, 0, 0, NUM_DEVS_WCNSLS, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL,
@ -390,27 +426,16 @@ const char *wcnsls_description (DEVICE *dptr)
return "MIT Spacewar Consoles"; return "MIT Spacewar Consoles";
} }
t_stat wcnsls_devio(uint32 dev, uint64 *data) {
uint64 switches;
switch (dev & 3) {
case CONO:
/* CONO WCNSLS,40 ;enable spacewar consoles */
break;
case DATAI:
switches = 0777777777777LL; /* 1 is off */
/* /*
* map 32-bit "spacewar_switches" value to what PDP-6/10 game expects * map 32-bit "spacewar_switches" value to what PDP-6/10 game expects
* (four 9-bit bytes) * (four 9-bit bytes)
*/ */
/* bits inside the bytes */ /* bits inside the bytes */
#define CCW 0400 /* counter clockwise (L) */ #define CCW 0400LL /* counter clockwise (L) */
#define CW 0200 /* clockwise (R) */ #define CW 0200LL /* clockwise (R) */
#define THRUST 0100 #define THRUST 0100LL
#define HYPER 040 #define HYPER 040LL
#define FIRE 020 #define FIRE 020LL
/* shift values for the players' bytes */ /* shift values for the players' bytes */
#define UR 0 /* upper right: enterprise "top plug" */ #define UR 0 /* upper right: enterprise "top plug" */
@ -418,6 +443,71 @@ t_stat wcnsls_devio(uint32 dev, uint64 *data) {
#define LL 18 /* lower left: thin ship "third plug" */ #define LL 18 /* lower left: thin ship "third plug" */
#define UL 27 /* upper left: fat ship "bottom plug" */ #define UL 27 /* upper left: fat ship "bottom plug" */
#define JOY_TRIG 5000
#define JOY0 (JOY_MAX_AXES*0)
#define JOY1 (JOY_MAX_AXES*1)
#define JOY2 (JOY_MAX_AXES*2)
#define JOY3 (JOY_MAX_AXES*3)
#define BUT0 (JOY_MAX_BUTTONS*0)
#define BUT1 (JOY_MAX_BUTTONS*1)
#define BUT2 (JOY_MAX_BUTTONS*2)
#define BUT3 (JOY_MAX_BUTTONS*3)
static uint64 joystick_switches (void)
{
uint64 switches = 0777777777777LL;
if (joy_axes[JOY0] > JOY_TRIG)
switches &= ~(CCW << UR);
else if (joy_axes[JOY0] < -JOY_TRIG)
switches &= ~(CW << UR);
if (joy_axes[JOY0+1] < -JOY_TRIG)
switches &= ~(THRUST << UR);
if (joy_buttons[BUT0])
switches &= ~(FIRE << UR);
if (joy_buttons[BUT0+1])
switches &= ~(HYPER << UR);
if (joy_axes[JOY1] > JOY_TRIG)
switches &= ~(CCW << LR);
else if (joy_axes[JOY1] < -JOY_TRIG)
switches &= ~(CW << LR);
if (joy_axes[JOY1+1] < -JOY_TRIG)
switches &= ~(THRUST << LR);
if (joy_buttons[BUT1])
switches &= ~(FIRE << LR);
if (joy_buttons[BUT1+1])
switches &= ~(HYPER << LR);
if (joy_axes[JOY2] > JOY_TRIG)
switches &= ~(CCW << LL);
else if (joy_axes[JOY2] < -JOY_TRIG)
switches &= ~(CW << LL);
if (joy_axes[JOY2+1] < -JOY_TRIG)
switches &= ~(THRUST << LL);
if (joy_buttons[BUT2])
switches &= ~(FIRE << LL);
if (joy_buttons[BUT2+1])
switches &= ~(HYPER << LL);
if (joy_axes[JOY3] > JOY_TRIG)
switches &= ~((uint64)CCW << UL);
else if (joy_axes[JOY3] < -JOY_TRIG)
switches &= ~((uint64)CW << UL);
if (joy_axes[JOY3+1] < -JOY_TRIG)
switches &= ~((uint64)THRUST << UL);
if (joy_buttons[BUT3])
switches &= ~((uint64)FIRE << UL);
if (joy_buttons[BUT3+1])
switches &= ~(HYPER << UL);
return switches;
}
static uint64 keyboard_switches (void)
{
uint64 switches = 0777777777777LL; /* 1 is off */
#if 1 #if 1
#define DEBUGSW(X) (void)0 #define DEBUGSW(X) (void)0
#else #else
@ -436,12 +526,115 @@ t_stat wcnsls_devio(uint32 dev, uint64 *data) {
if (spacewar_switches) if (spacewar_switches)
DEBUGSW(("in %#lo out %#llo\r\n", spacewar_switches, switches)); DEBUGSW(("in %#lo out %#llo\r\n", spacewar_switches, switches));
*data = switches;
return switches;
}
t_stat wcnsls_devio(uint32 dev, uint64 *data) {
switch (dev & 3) {
case CONO:
/* CONO WCNSLS,40 ;enable spacewar consoles */
break;
case DATAI:
if (wcnsls_unit->flags & UNIT_JOY) {
*data = joystick_switches ();
} else {
*data = keyboard_switches ();
}
sim_debug(DEBUG_DATAIO, &wcnsls_dev, "WCNSLS %03o DATI %012llo PC=%06o\n", sim_debug(DEBUG_DATAIO, &wcnsls_dev, "WCNSLS %03o DATI %012llo PC=%06o\n",
dev, switches, PC); dev, *data, PC);
break;
}
return SCPE_OK;
}
/*
* Old MIT Spacewar console switches
*/
#if NUM_DEVS_OCNSLS > 0
#define OCNSLS_DEVNUM 0724
t_stat ocnsls_devio(uint32 dev, uint64 *data);
const char *ocnsls_description (DEVICE *dptr);
DIB ocnsls_dib[] = {
{ OCNSLS_DEVNUM, 1, &ocnsls_devio, NULL }};
UNIT ocnsls_unit[] = {
{ UDATA (NULL, UNIT_IDLE, 0) }};
DEVICE ocnsls_dev = {
"OCNSLS", ocnsls_unit, NULL, NULL,
NUM_DEVS_OCNSLS, 0, 0, 0, 0, 0,
NULL, NULL, NULL,
NULL, NULL, NULL,
&ocnsls_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, NULL,
NULL, NULL, NULL, NULL, NULL, &ocnsls_description
};
const char *ocnsls_description (DEVICE *dptr)
{
return "Old MIT Spacewar Consoles";
}
#define OHYPER 0004LL /* Hyperspace. */
#define OFIRE 0010LL /* Fire torpedo. */
#define OCW 0020LL /* Turn clockwise. */
#define OCCW 0040LL /* Turn counter clockwise. */
#define SLOW 0100LL /* Weak thrust. */
#define FAST 0200LL /* Strong thrust. */
#define BEACON 020000LL /* Aiming beacon. */
static uint64 old_switches (void)
{
uint64 switches = 0;
if (joy_axes[JOY0] > JOY_TRIG)
switches |= OCCW;
else if (joy_axes[JOY0] < -JOY_TRIG)
switches |= OCW;
if (joy_axes[JOY0+1] < -JOY_TRIG)
switches |= FAST;
if (joy_axes[JOY0+1] > JOY_TRIG)
switches |= SLOW;
if (joy_buttons[BUT0])
switches |= OFIRE;
if (joy_buttons[BUT0+1])
switches |= OHYPER;
if (joy_buttons[BUT0+2])
switches |= BEACON;
if (joy_axes[JOY1] > JOY_TRIG)
switches |= OCCW << 18;
else if (joy_axes[JOY1] < -JOY_TRIG)
switches |= OCW << 18;
if (joy_axes[JOY1+1] < -JOY_TRIG)
switches |= FAST << 18;
if (joy_axes[JOY1+1] > JOY_TRIG)
switches |= SLOW << 18;
if (joy_buttons[BUT1])
switches |= OFIRE << 18;
if (joy_buttons[BUT1+1])
switches |= OHYPER << 18;
if (joy_buttons[BUT1+2])
switches |= BEACON << 18;
return switches;
}
t_stat ocnsls_devio(uint32 dev, uint64 *data) {
switch (dev & 3) {
case DATAI:
*data = old_switches ();
break;
case CONI:
*data = 0;
break; break;
} }
return SCPE_OK; return SCPE_OK;
} }
#endif #endif
#endif #endif
#endif

View file

@ -1,6 +1,9 @@
/* pdp10_dt.c: 18b DECtape simulator /* kx10_dt.c: 18b DECtape simulator
Copyright (c) 2017 Richard Cornwell Copyright (c) 2017-2020 Richard Cornwell based on work by Bob Supnik
Based on PDP18B/pdp18b_dt.c by:
Copyright (c) 1993-2017, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -19,6 +22,10 @@
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 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. 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.
Except as contained in this notice, the name of Richard Cornwell shall not be 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 used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Richard Cornwell. in this Software without prior written authorization from Richard Cornwell.
@ -169,6 +176,7 @@
#define DTC_FWDRV 0200000 /* Move unit forward */ #define DTC_FWDRV 0200000 /* Move unit forward */
#define DTC_STSTOP 0400000 /* Stop unit */ #define DTC_STSTOP 0400000 /* Stop unit */
#define CMD u3
/* Flags in lower bits of u3 */ /* Flags in lower bits of u3 */
#define DTC_FNC_STOP 001 /* Unit stopping */ #define DTC_FNC_STOP 001 /* Unit stopping */
#define DTC_FNC_START 002 /* Start unit motion */ #define DTC_FNC_START 002 /* Start unit motion */
@ -250,7 +258,9 @@
#define ABS(x) (((x) < 0)? (-(x)): (x)) #define ABS(x) (((x) < 0)? (-(x)): (x))
#define DT_WRDTIM 15000 #define DT_WRDTIM 10000
#define WRITTEN u6 /* Set when tape modified */
int32 dtsa = 0; /* status A */ int32 dtsa = 0; /* status A */
uint64 dtsb = 0; /* status B */ uint64 dtsb = 0; /* status B */
@ -262,6 +272,7 @@ t_stat dt_svc (UNIT *uptr);
t_stat dt_boot(int32 unit_num, DEVICE * dptr); t_stat dt_boot(int32 unit_num, DEVICE * dptr);
t_stat dt_reset (DEVICE *dptr); t_stat dt_reset (DEVICE *dptr);
t_stat dt_attach (UNIT *uptr, CONST char *cptr); t_stat dt_attach (UNIT *uptr, CONST char *cptr);
void dt_flush (UNIT *uptr);
t_stat dt_detach (UNIT *uptr); t_stat dt_detach (UNIT *uptr);
#if MPX_DEV #if MPX_DEV
t_stat dt_set_mpx (UNIT *uptr, int32 val, CONST char *cptr, void *desc) ; t_stat dt_set_mpx (UNIT *uptr, int32 val, CONST char *cptr, void *desc) ;
@ -369,7 +380,7 @@ t_stat dt_devio(uint32 dev, uint64 *data) {
/* Stop all drives and clear drive unit */ /* Stop all drives and clear drive unit */
dtsa &= 0770777; dtsa &= 0770777;
for (i = 0; i < DT_NUMDR; i++) { for (i = 0; i < DT_NUMDR; i++) {
dt_unit[i].u3 &= ~0700; dt_unit[i].CMD &= ~0700;
} }
if ((*data & DTC_SEL) == 0) if ((*data & DTC_SEL) == 0)
break; break;
@ -426,14 +437,14 @@ t_stat dt_devio(uint32 dev, uint64 *data) {
} }
if (*data & DTC_STSTOP) { if (*data & DTC_STSTOP) {
if ((dt_unit[i].DSTATE & (DTC_MOT)) != 0) { if ((dt_unit[i].DSTATE & (DTC_MOT)) != 0) {
dt_unit[i].u3 |= DTC_FNC_STOP; dt_unit[i].CMD |= DTC_FNC_STOP;
} }
dtsa &=~ (DTC_FWDRV|DTC_RVDRV); dtsa &=~ (DTC_FWDRV|DTC_RVDRV);
} else { } else {
/* Start the unit if not already running */ /* Start the unit if not already running */
dt_unit[i].u3 &= ~DTC_FNC_STOP; dt_unit[i].CMD &= ~DTC_FNC_STOP;
if ((dt_unit[i].DSTATE & (DTC_MOT)) == 0) { if ((dt_unit[i].DSTATE & (DTC_MOT)) == 0) {
dt_unit[i].u3 |= DTC_FNC_START; dt_unit[i].CMD |= DTC_FNC_START;
dtsb |= DTB_DLY; dtsb |= DTB_DLY;
if (!sim_is_active(&dt_unit[i])) if (!sim_is_active(&dt_unit[i]))
sim_activate(&dt_unit[i], 10000); sim_activate(&dt_unit[i], 10000);
@ -442,20 +453,20 @@ t_stat dt_devio(uint32 dev, uint64 *data) {
switch(*data & (DTC_FWDRV|DTC_RVDRV)) { switch(*data & (DTC_FWDRV|DTC_RVDRV)) {
case DTC_FWDRV: case DTC_FWDRV:
if (dt_unit[i].DSTATE & DTC_REV) { if (dt_unit[i].DSTATE & DTC_REV) {
dt_unit[i].u3 |= DTC_FNC_REV; dt_unit[i].CMD |= DTC_FNC_REV;
dtsa |= (DTC_RVDRV); dtsa |= (DTC_RVDRV);
} else } else
dtsa |= (DTC_FWDRV); dtsa |= (DTC_FWDRV);
break; break;
case DTC_RVDRV: case DTC_RVDRV:
if ((dt_unit[i].DSTATE & DTC_REV) == 0) { if ((dt_unit[i].DSTATE & DTC_REV) == 0) {
dt_unit[i].u3 |= DTC_FNC_REV; dt_unit[i].CMD |= DTC_FNC_REV;
dtsa |= (DTC_RVDRV); dtsa |= (DTC_RVDRV);
} else } else
dtsa |= (DTC_FWDRV); dtsa |= (DTC_FWDRV);
break; break;
case DTC_FWDRV|DTC_RVDRV: case DTC_FWDRV|DTC_RVDRV:
dt_unit[i].u3 |= DTC_FNC_REV; dt_unit[i].CMD |= DTC_FNC_REV;
if ((dt_unit[i].DSTATE & DTC_REV) == 0) if ((dt_unit[i].DSTATE & DTC_REV) == 0)
dtsa |= (DTC_RVDRV); dtsa |= (DTC_RVDRV);
else else
@ -500,7 +511,7 @@ t_stat dt_devio(uint32 dev, uint64 *data) {
for (i = 0; i < DT_NUMDR; i++) { for (i = 0; i < DT_NUMDR; i++) {
if (i != DTC_GETUNI(dtsa) && if (i != DTC_GETUNI(dtsa) &&
(dt_unit[i].DSTATE & DTC_MOT) != 0) (dt_unit[i].DSTATE & DTC_MOT) != 0)
dt_unit[i].u3 |= DTC_FNC_STOP; dt_unit[i].CMD |= DTC_FNC_STOP;
} }
} }
dtsb = (uint64)((*data & (DTS_PAR_ERR|DTS_DATA_MISS|DTS_JOB_DONE| \ dtsb = (uint64)((*data & (DTS_PAR_ERR|DTS_DATA_MISS|DTS_JOB_DONE| \
@ -569,11 +580,11 @@ t_stat dt_svc (UNIT *uptr)
*/ */
if (uptr->DSTATE & DTC_MOT) { if (uptr->DSTATE & DTC_MOT) {
/* Check if stoping */ /* Check if stoping */
if (uptr->u3 & DTC_FNC_STOP) { if (uptr->CMD & DTC_FNC_STOP) {
/* Stop delay */ /* Stop delay */
sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o stopping\n", u); sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o stopping\n", u);
sim_activate(uptr, DT_WRDTIM*10); sim_activate(uptr, DT_WRDTIM*10);
uptr->u3 &= ~DTC_FNC_STOP; uptr->CMD &= ~DTC_FNC_STOP;
uptr->DSTATE &= ~(DTC_MOT); uptr->DSTATE &= ~(DTC_MOT);
blk = (uptr->DSTATE >> DTC_V_BLK) & DTC_M_BLK; blk = (uptr->DSTATE >> DTC_V_BLK) & DTC_M_BLK;
uptr->DSTATE = (0100 << DTC_V_WORD) | DTC_BLOCK | (DTC_MOTMASK & uptr->DSTATE); uptr->DSTATE = (0100 << DTC_V_WORD) | DTC_BLOCK | (DTC_MOTMASK & uptr->DSTATE);
@ -591,10 +602,10 @@ if (uptr->DSTATE & DTC_MOT) {
uptr->DSTATE |= (blk << DTC_V_BLK); uptr->DSTATE |= (blk << DTC_V_BLK);
return SCPE_OK; return SCPE_OK;
} }
if (uptr->u3 & DTC_FNC_REV) { if (uptr->CMD & DTC_FNC_REV) {
sim_activate(uptr, DT_WRDTIM*10); sim_activate(uptr, DT_WRDTIM*10);
sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o reversing\n", u); sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o reversing\n", u);
uptr->u3 &= ~DTC_FNC_REV; uptr->CMD &= ~DTC_FNC_REV;
uptr->DSTATE ^= DTC_REV; uptr->DSTATE ^= DTC_REV;
return SCPE_OK; return SCPE_OK;
} }
@ -614,7 +625,7 @@ if (uptr->DSTATE & DTC_MOT) {
case DTC_FEND: /* Tape in endzone */ case DTC_FEND: /* Tape in endzone */
/* Set stop */ /* Set stop */
sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o rev forward end\n", u); sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o rev forward end\n", u);
uptr->u3 |= DTC_FNC_STOP; uptr->CMD |= DTC_FNC_STOP;
uptr->u6 = 0; uptr->u6 = 0;
dtsb |= DTB_END; dtsb |= DTB_END;
dtsb &= ~DTB_IDL; dtsb &= ~DTB_IDL;
@ -636,7 +647,7 @@ if (uptr->DSTATE & DTC_MOT) {
if (dtsb & DTB_STOP) if (dtsb & DTB_STOP)
dtsa &= ~0700; /* Clear command */ dtsa &= ~0700; /* Clear command */
sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o rev forward block\n", u); sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o rev forward block\n", u);
switch (DTC_GETFNC(uptr->u3)) { switch (DTC_GETFNC(uptr->CMD)) {
case FNC_MOVE: case FNC_MOVE:
case FNC_SRCH: case FNC_SRCH:
case FNC_WBLK: case FNC_WBLK:
@ -647,7 +658,7 @@ if (uptr->DSTATE & DTC_MOT) {
case FNC_RALL: case FNC_RALL:
case FNC_WRIT: case FNC_WRIT:
case FNC_READ: case FNC_READ:
uptr->u3 &= 077077; uptr->CMD &= 077077;
dtsb |= DTB_DONE; dtsb |= DTB_DONE;
if (dtsb & DTB_JOBENB) if (dtsb & DTB_JOBENB)
set_interrupt(DT_DEVNUM, dtsa); set_interrupt(DT_DEVNUM, dtsa);
@ -661,11 +672,11 @@ if (uptr->DSTATE & DTC_MOT) {
break; break;
} }
if (dtsb & (DTB_PAR|DTB_MIS|DTB_ILL|DTB_END|DTB_INCBLK|DTB_MRKERR)) { if (dtsb & (DTB_PAR|DTB_MIS|DTB_ILL|DTB_END|DTB_INCBLK|DTB_MRKERR)) {
uptr->u3 |= DTC_FNC_STOP; uptr->CMD |= DTC_FNC_STOP;
} }
if (DTC_GETUNI(dtsa) == u) { if (DTC_GETUNI(dtsa) == u) {
uptr->u3 &= 077077; uptr->CMD &= 077077;
uptr->u3 |= dtsa & 0700; /* Copy command */ uptr->CMD |= dtsa & 0700; /* Copy command */
} }
if (word <= 0) { if (word <= 0) {
uptr->DSTATE = DTC_FEND | (DTC_MOTMASK & uptr->DSTATE); uptr->DSTATE = DTC_FEND | (DTC_MOTMASK & uptr->DSTATE);
@ -698,7 +709,7 @@ if (uptr->DSTATE & DTC_MOT) {
uptr->DSTATE |= (word - 1) << DTC_V_WORD; uptr->DSTATE |= (word - 1) << DTC_V_WORD;
} }
uptr->u6-=2; uptr->u6-=2;
switch (DTC_GETFNC(uptr->u3)) { switch (DTC_GETFNC(uptr->CMD)) {
case FNC_MOVE: case FNC_MOVE:
case FNC_SRCH: case FNC_SRCH:
case FNC_WBLK: case FNC_WBLK:
@ -724,6 +735,7 @@ if (uptr->DSTATE & DTC_MOT) {
data = dtdb; data = dtdb;
fbuf[off] = (data >> 18) & RMASK; fbuf[off] = (data >> 18) & RMASK;
fbuf[off+1] = data & RMASK; fbuf[off+1] = data & RMASK;
uptr->WRITTEN = 1;
uptr->hwmark = uptr->capac; uptr->hwmark = uptr->capac;
break; break;
} }
@ -740,15 +752,16 @@ if (uptr->DSTATE & DTC_MOT) {
sim_activate(uptr,DT_WRDTIM*2); sim_activate(uptr,DT_WRDTIM*2);
sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o rev reverse check\n", u); sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o rev reverse check\n", u);
word = (uptr->DSTATE >> DTC_V_BLK) & DTC_M_BLK; word = (uptr->DSTATE >> DTC_V_BLK) & DTC_M_BLK;
uptr->DSTATE = DTC_BLOCK|(word << DTC_V_BLK)|(DTC_M_WORD << DTC_V_WORD) | (DTC_MOTMASK & uptr->DSTATE); uptr->DSTATE = DTC_BLOCK|(word << DTC_V_BLK)|(DTC_M_WORD << DTC_V_WORD) |
(DTC_MOTMASK & uptr->DSTATE);
if (dtsb & DTB_STOP) if (dtsb & DTB_STOP)
dtsa &= ~0700; /* Clear command */ dtsa &= ~0700; /* Clear command */
if (DTC_GETUNI(dtsa) == u) { if (DTC_GETUNI(dtsa) == u) {
uptr->u3 &= 077077; uptr->CMD &= 077077;
uptr->u3 |= dtsa & 0700; /* Copy command */ uptr->CMD |= dtsa & 0700; /* Copy command */
} }
dtsb &= ~DTB_BLKRD; dtsb &= ~DTB_BLKRD;
switch (DTC_GETFNC(uptr->u3)) { switch (DTC_GETFNC(uptr->CMD)) {
case FNC_WRIT: case FNC_WRIT:
case FNC_WALL: case FNC_WALL:
dtsb |= DTB_DATREQ; dtsb |= DTB_DATREQ;
@ -772,7 +785,7 @@ if (uptr->DSTATE & DTC_MOT) {
break; break;
} }
if (dtsb & (DTB_PAR|DTB_MIS|DTB_ILL|DTB_END|DTB_INCBLK|DTB_MRKERR)) { if (dtsb & (DTB_PAR|DTB_MIS|DTB_ILL|DTB_END|DTB_INCBLK|DTB_MRKERR)) {
uptr->u3 |= DTC_FNC_STOP; uptr->CMD |= DTC_FNC_STOP;
} }
break; break;
@ -780,15 +793,16 @@ if (uptr->DSTATE & DTC_MOT) {
sim_activate(uptr,DT_WRDTIM*2); sim_activate(uptr,DT_WRDTIM*2);
word = (uptr->DSTATE >> DTC_V_BLK) & DTC_M_BLK; word = (uptr->DSTATE >> DTC_V_BLK) & DTC_M_BLK;
data = (uint64)word; data = (uint64)word;
uptr->DSTATE = DTC_RCHK|(word << DTC_V_BLK)|(DTC_M_WORD << DTC_V_WORD) | (DTC_MOTMASK & uptr->DSTATE); uptr->DSTATE = DTC_RCHK|(word << DTC_V_BLK)|(DTC_M_WORD << DTC_V_WORD) |
(DTC_MOTMASK & uptr->DSTATE);
sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o rev reverse block %04o\n", u, word); sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o rev reverse block %04o\n", u, word);
dtsb &= ~DTB_END; dtsb &= ~DTB_END;
dtsb |= DTB_BLKRD; dtsb |= DTB_BLKRD;
if (DTC_GETUNI(dtsa) == u) { if (DTC_GETUNI(dtsa) == u) {
uptr->u3 &= 077077; uptr->CMD &= 077077;
uptr->u3 |= dtsa & 0700; /* Copy command */ uptr->CMD |= dtsa & 0700; /* Copy command */
} }
switch (DTC_GETFNC(uptr->u3)) { switch (DTC_GETFNC(uptr->CMD)) {
case FNC_MOVE: case FNC_MOVE:
case FNC_READ: case FNC_READ:
case FNC_WMRK: case FNC_WMRK:
@ -839,10 +853,10 @@ if (uptr->DSTATE & DTC_MOT) {
sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o forward block %04o\n", u, word); sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o forward block %04o\n", u, word);
data = (uint64)word; data = (uint64)word;
if (DTC_GETUNI(dtsa) == u) { if (DTC_GETUNI(dtsa) == u) {
uptr->u3 &= 077077; uptr->CMD &= 077077;
uptr->u3 |= dtsa & 0700; /* Copy command */ uptr->CMD |= dtsa & 0700; /* Copy command */
} }
switch (DTC_GETFNC(uptr->u3)) { switch (DTC_GETFNC(uptr->CMD)) {
case FNC_RALL: case FNC_RALL:
case FNC_SRCH: case FNC_SRCH:
dt_putword(&data); dt_putword(&data);
@ -872,10 +886,10 @@ if (uptr->DSTATE & DTC_MOT) {
if (dtsb & DTB_STOP) if (dtsb & DTB_STOP)
dtsa &= ~0700; /* Clear command */ dtsa &= ~0700; /* Clear command */
if (DTC_GETUNI(dtsa) == u) { if (DTC_GETUNI(dtsa) == u) {
uptr->u3 &= 077077; uptr->CMD &= 077077;
uptr->u3 |= dtsa & 0700; /* Copy command */ uptr->CMD |= dtsa & 0700; /* Copy command */
} }
switch (DTC_GETFNC(uptr->u3)) { switch (DTC_GETFNC(uptr->CMD)) {
case FNC_WRIT: case FNC_WRIT:
case FNC_WALL: case FNC_WALL:
dtsb |= DTB_DATREQ; dtsb |= DTB_DATREQ;
@ -899,7 +913,7 @@ if (uptr->DSTATE & DTC_MOT) {
break; break;
} }
if (dtsb & (DTB_PAR|DTB_MIS|DTB_ILL|DTB_END|DTB_INCBLK|DTB_MRKERR)) { if (dtsb & (DTB_PAR|DTB_MIS|DTB_ILL|DTB_END|DTB_INCBLK|DTB_MRKERR)) {
uptr->u3 |= DTC_FNC_STOP; uptr->CMD |= DTC_FNC_STOP;
} }
break; break;
@ -918,7 +932,7 @@ if (uptr->DSTATE & DTC_MOT) {
uptr->DSTATE &= ~(DTC_M_WORD << DTC_V_WORD); uptr->DSTATE &= ~(DTC_M_WORD << DTC_V_WORD);
uptr->DSTATE |= (word + 1) << DTC_V_WORD; uptr->DSTATE |= (word + 1) << DTC_V_WORD;
} }
switch (DTC_GETFNC(uptr->u3)) { switch (DTC_GETFNC(uptr->CMD)) {
case FNC_MOVE: case FNC_MOVE:
case FNC_SRCH: case FNC_SRCH:
case FNC_WALL: case FNC_WALL:
@ -931,17 +945,18 @@ if (uptr->DSTATE & DTC_MOT) {
if ((dtsb & DTB_STOP) == 0) if ((dtsb & DTB_STOP) == 0)
dt_putword(&data); dt_putword(&data);
else else
uptr->u3 &= 077077; uptr->CMD &= 077077;
break; break;
case FNC_WRIT: case FNC_WRIT:
if ((dtsb & DTB_STOP) == 0) if ((dtsb & DTB_STOP) == 0)
dt_getword(&data, (word != DTC_M_WORD)); dt_getword(&data, (word != DTC_M_WORD));
else { else {
uptr->u3 &= 077077; uptr->CMD &= 077077;
data = dtdb; data = dtdb;
} }
fbuf[off] = (data >> 18) & RMASK; fbuf[off] = (data >> 18) & RMASK;
fbuf[off+1] = data & RMASK; fbuf[off+1] = data & RMASK;
uptr->WRITTEN = 1;
uptr->hwmark = uptr->capac; uptr->hwmark = uptr->capac;
break; break;
case FNC_WMRK: case FNC_WMRK:
@ -972,20 +987,21 @@ if (uptr->DSTATE & DTC_MOT) {
dtsb &= ~(DTB_CHK); dtsb &= ~(DTB_CHK);
dtsb |= DTB_IDL; dtsb |= DTB_IDL;
if (DTC_GETUNI(dtsa) == u) { if (DTC_GETUNI(dtsa) == u) {
uptr->u3 &= 077077; uptr->CMD &= 077077;
uptr->u3 |= dtsa & 0700; /* Copy command */ uptr->CMD |= dtsa & 0700; /* Copy command */
} }
word = (uptr->DSTATE >> DTC_V_BLK) & DTC_M_BLK; word = (uptr->DSTATE >> DTC_V_BLK) & DTC_M_BLK;
word++; word++;
if (word > 01101) { if (word > 01101) {
uptr->DSTATE = DTC_REND|(word << DTC_V_BLK)|(DTC_M_WORD << DTC_V_WORD) | (DTC_MOTMASK & uptr->DSTATE); uptr->DSTATE = DTC_REND|(word << DTC_V_BLK)|(DTC_M_WORD << DTC_V_WORD) |
(DTC_MOTMASK & uptr->DSTATE);
} else { } else {
uptr->DSTATE = DTC_FBLK|(word << DTC_V_BLK) | (DTC_MOTMASK & uptr->DSTATE); uptr->DSTATE = DTC_FBLK|(word << DTC_V_BLK) | (DTC_MOTMASK & uptr->DSTATE);
} }
if (dtsb & DTB_STOP) if (dtsb & DTB_STOP)
dtsa &= ~0700; /* Clear command */ dtsa &= ~0700; /* Clear command */
sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o reverse block %o\n", u, word); sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o reverse block %o\n", u, word);
switch (DTC_GETFNC(uptr->u3)) { switch (DTC_GETFNC(uptr->CMD)) {
case FNC_MOVE: case FNC_MOVE:
case FNC_WBLK: case FNC_WBLK:
case FNC_SRCH: case FNC_SRCH:
@ -997,7 +1013,7 @@ if (uptr->DSTATE & DTC_MOT) {
case FNC_WRIT: case FNC_WRIT:
case FNC_READ: case FNC_READ:
case FNC_WMRK: case FNC_WMRK:
uptr->u3 &= 077077; uptr->CMD &= 077077;
dtsb |= DTB_DONE; dtsb |= DTB_DONE;
if (dtsb & DTB_JOBENB) if (dtsb & DTB_JOBENB)
set_interrupt(DT_DEVNUM, dtsa); set_interrupt(DT_DEVNUM, dtsa);
@ -1006,13 +1022,13 @@ if (uptr->DSTATE & DTC_MOT) {
break; break;
} }
if (dtsb & (DTB_PAR|DTB_MIS|DTB_ILL|DTB_END|DTB_INCBLK|DTB_MRKERR)) { if (dtsb & (DTB_PAR|DTB_MIS|DTB_ILL|DTB_END|DTB_INCBLK|DTB_MRKERR)) {
uptr->u3 |= DTC_FNC_STOP; uptr->CMD |= DTC_FNC_STOP;
} }
break; break;
case DTC_REND: /* In final endzone */ case DTC_REND: /* In final endzone */
/* Set stop */ /* Set stop */
uptr->u3 |= DTC_FNC_STOP; uptr->CMD |= DTC_FNC_STOP;
sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o reverse end\n", u); sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o reverse end\n", u);
dtsb &= ~DTB_IDL; dtsb &= ~DTB_IDL;
dtsb |= DTB_END; dtsb |= DTB_END;
@ -1023,18 +1039,18 @@ if (uptr->DSTATE & DTC_MOT) {
} }
} }
/* Check if starting */ /* Check if starting */
} else if (uptr->u3 & DTC_FNC_START) { } else if (uptr->CMD & DTC_FNC_START) {
/* Start up delay */ /* Start up delay */
sim_activate(uptr, DT_WRDTIM*10); sim_activate(uptr, DT_WRDTIM*10);
uptr->u3 &= ~(0700 | DTC_FNC_START); uptr->CMD &= ~(0700 | DTC_FNC_START);
if (DTC_GETUNI(dtsa) == u) if (DTC_GETUNI(dtsa) == u)
uptr->u3 |= dtsa & 0700; /* Copy command */ uptr->CMD |= dtsa & 0700; /* Copy command */
uptr->DSTATE |= DTC_MOT; uptr->DSTATE |= DTC_MOT;
if (uptr->u3 & DTC_FNC_REV) { if (uptr->CMD & DTC_FNC_REV) {
uptr->u3 &= ~DTC_FNC_REV; uptr->CMD &= ~DTC_FNC_REV;
uptr->DSTATE ^= DTC_REV; uptr->DSTATE ^= DTC_REV;
} }
sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o start %06o\n", u, uptr->u3); sim_debug(DEBUG_DETAIL, &dt_dev, "DTA %o start %06o\n", u, uptr->CMD);
return SCPE_OK; return SCPE_OK;
} }
return SCPE_OK; return SCPE_OK;
@ -1111,7 +1127,7 @@ t_stat dt_reset (DEVICE *dptr)
dtsb = dtsa = 0; /* clear status */ dtsb = dtsa = 0; /* clear status */
for (i = 0; i < DT_NUMDR; i++) { for (i = 0; i < DT_NUMDR; i++) {
if ((dt_unit[i].DSTATE & DTC_MOT) != 0) if ((dt_unit[i].DSTATE & DTC_MOT) != 0)
dt_unit[i].u3 |= DTC_FNC_STOP; dt_unit[i].CMD |= DTC_FNC_STOP;
} }
clr_interrupt(DT_DEVNUM); clr_interrupt(DT_DEVNUM);
clr_interrupt(DT_DEVNUM|4); clr_interrupt(DT_DEVNUM|4);
@ -1129,16 +1145,16 @@ t_stat dt_reset (DEVICE *dptr)
t_stat dt_attach (UNIT *uptr, CONST char *cptr) t_stat dt_attach (UNIT *uptr, CONST char *cptr)
{ {
uint16 pdp8b[D8_NBSIZE]; uint16 pdp8b[D8_NBSIZE];
uint16 pdp11b[D18_BSIZE]; uint16 pdp11b[D18_BSIZE];
uint32 ba, sz, k, *fbuf; uint32 ba, sz, k, *fbuf;
int32 u = uptr - dt_dev.units; int32 u = uptr - dt_dev.units;
t_stat r; t_stat r;
r = attach_unit (uptr, cptr); /* attach */ r = attach_unit (uptr, cptr); /* attach */
if (r != SCPE_OK) /* error? */ if (r != SCPE_OK) /* error? */
return r; return r;
if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */ if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */
uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default 18b */ uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default 18b */
if (sim_switches & SWMASK ('T')) /* att 12b? */ if (sim_switches & SWMASK ('T')) /* att 12b? */
uptr->flags = uptr->flags | UNIT_8FMT; uptr->flags = uptr->flags | UNIT_8FMT;
@ -1152,21 +1168,22 @@ if ((sim_switches & SIM_SW_REST) == 0) { /* not from rest? */
uptr->flags = uptr->flags | UNIT_11FMT; uptr->flags = uptr->flags | UNIT_11FMT;
} }
} }
uptr->capac = DTU_CAPAC (uptr); /* set capacity */ uptr->capac = DTU_CAPAC (uptr); /* set capacity */
uptr->filebuf = calloc (uptr->capac, sizeof (uint32)); uptr->filebuf = calloc (uptr->capac, sizeof (uint32));
if (uptr->filebuf == NULL) { /* can't alloc? */ if (uptr->filebuf == NULL) { /* can't alloc? */
detach_unit (uptr); detach_unit (uptr);
return SCPE_MEM; return SCPE_MEM;
} }
fbuf = (uint32 *) uptr->filebuf; /* file buffer */ fbuf = (uint32 *) uptr->filebuf; /* file buffer */
printf ("%s%d: ", sim_dname (&dt_dev), u); sim_printf ("%s%d: ", sim_dname (&dt_dev), u);
if (uptr->flags & UNIT_8FMT) if (uptr->flags & UNIT_8FMT)
printf ("12b format"); sim_printf ("12b format");
else if (uptr->flags & UNIT_11FMT) else if (uptr->flags & UNIT_11FMT)
printf ("16b format"); sim_printf ("16b format");
else printf ("18b/36b format"); else sim_printf ("18b/36b format");
printf (", buffering file in memory\n"); sim_printf (", buffering file in memory\n");
if (uptr->flags & UNIT_8FMT) { /* 12b? */ uptr->io_flush = dt_flush;
if (uptr->flags & UNIT_8FMT) { /* 12b? */
for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ for (ba = 0; ba < uptr->capac; ) { /* loop thru file */
k = fxread (pdp8b, sizeof (uint16), D8_NBSIZE, uptr->fileref); k = fxread (pdp8b, sizeof (uint16), D8_NBSIZE, uptr->fileref);
if (k == 0) if (k == 0)
@ -1182,8 +1199,7 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */
} }
} /* end file loop */ } /* end file loop */
uptr->hwmark = ba; uptr->hwmark = ba;
} /* end if */ } else if (uptr->flags & UNIT_11FMT) { /* 16b? */
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ for (ba = 0; ba < uptr->capac; ) { /* loop thru file */
k = fxread (pdp11b, sizeof (uint16), D18_BSIZE, uptr->fileref); k = fxread (pdp11b, sizeof (uint16), D18_BSIZE, uptr->fileref);
if (k == 0) if (k == 0)
@ -1194,15 +1210,15 @@ else if (uptr->flags & UNIT_11FMT) { /* 16b? */
fbuf[ba++] = pdp11b[k]; fbuf[ba++] = pdp11b[k];
} }
uptr->hwmark = ba; uptr->hwmark = ba;
} /* end elif */ } else uptr->hwmark = fxread (uptr->filebuf, sizeof (uint32),
else uptr->hwmark = fxread (uptr->filebuf, sizeof (uint32),
uptr->capac, uptr->fileref); uptr->capac, uptr->fileref);
uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */ uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */
uptr->pos = DT_EZLIN; /* beyond leader */ uptr->pos = DT_EZLIN; /* beyond leader */
return SCPE_OK; uptr->WRITTEN = 0;
return SCPE_OK;
} }
/* Detach routine /* Flush tape image to disk
Cancel in progress operation Cancel in progress operation
If 12b, convert 18b buffer to 12b and write to file If 12b, convert 18b buffer to 12b and write to file
@ -1211,23 +1227,16 @@ return SCPE_OK;
Deallocate buffer Deallocate buffer
*/ */
t_stat dt_detach (UNIT* uptr) void dt_flush (UNIT* uptr)
{ {
uint16 pdp8b[D8_NBSIZE]; uint16 pdp8b[D8_NBSIZE];
uint16 pdp11b[D18_BSIZE]; uint16 pdp11b[D18_BSIZE];
uint32 ba, k, *fbuf; uint32 ba, k, *fbuf;
int32 u = uptr - dt_dev.units; int32 u = uptr - dt_dev.units;
if (!(uptr->flags & UNIT_ATT)) if (uptr->WRITTEN && uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
return SCPE_OK;
if (sim_is_active (uptr)) {
sim_cancel (uptr);
uptr->u3 = uptr->pos = 0;
}
fbuf = (uint32 *) uptr->filebuf; /* file buffer */
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
rewind (uptr->fileref); /* start of file */ rewind (uptr->fileref); /* start of file */
fbuf = (uint32 *) uptr->filebuf; /* file buffer */
if (uptr->flags & UNIT_8FMT) { /* 12b? */ if (uptr->flags & UNIT_8FMT) { /* 12b? */
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */ for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */
@ -1241,8 +1250,7 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
if (ferror (uptr->fileref)) if (ferror (uptr->fileref))
break; break;
} /* end loop file */ } /* end loop file */
} /* end if 12b */ } else if (uptr->flags & UNIT_11FMT) { /* 16b? */
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
for (k = 0; k < D18_BSIZE; k++) /* loop blk */ for (k = 0; k < D18_BSIZE; k++) /* loop blk */
pdp11b[k] = fbuf[ba++] & 0177777; pdp11b[k] = fbuf[ba++] & 0177777;
@ -1254,13 +1262,39 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
else fxwrite (uptr->filebuf, sizeof (uint32), /* write file */ else fxwrite (uptr->filebuf, sizeof (uint32), /* write file */
uptr->hwmark, uptr->fileref); uptr->hwmark, uptr->fileref);
if (ferror (uptr->fileref)) if (ferror (uptr->fileref))
perror ("I/O error"); sim_perror ("I/O error");
} /* end if hwmark */ } /* end if hwmark */
free (uptr->filebuf); /* release buf */ uptr->WRITTEN = 0;
uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ }
uptr->filebuf = NULL; /* clear buf ptr */
uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default fmt */ /* Detach routine
uptr->capac = DT_CAPAC; /* default size */
return detach_unit (uptr); Cancel in progress operation
If 12b, convert 18b buffer to 12b and write to file
If 16b, convert 18b buffer to 16b and write to file
If 18b/36b, write buffer to file
Deallocate buffer
*/
t_stat dt_detach (UNIT* uptr)
{
int32 u = uptr - dt_dev.units;
if (!(uptr->flags & UNIT_ATT))
return SCPE_OK;
if (sim_is_active (uptr)) {
sim_cancel (uptr);
uptr->CMD = uptr->pos = 0;
}
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
sim_printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
dt_flush(uptr);
} /* end if hwmark */
free (uptr->filebuf); /* release buf */
uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */
uptr->filebuf = NULL; /* clear buf ptr */
uptr->flags = uptr->flags & ~(UNIT_8FMT | UNIT_11FMT); /* default fmt */
uptr->capac = DT_CAPAC; /* default size */
return detach_unit (uptr);
} }
#endif #endif

View file

@ -1,6 +1,6 @@
/* ka10_imp.c: IMP, interface message processor. /* kx10_imp.c: IMP, interface message processor.
Copyright (c) 2018, Richard Cornwell based on code provided by Copyright (c) 2018-2020, Richard Cornwell based on code provided by
Lars Brinkhoff and Danny Gasparovski. Lars Brinkhoff and Danny Gasparovski.
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
@ -451,6 +451,7 @@ static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff};
static CONST in_addr_T broadcast_ipaddr = {0xffffffff}; static CONST in_addr_T broadcast_ipaddr = {0xffffffff};
t_stat imp_devio(uint32 dev, uint64 *data); t_stat imp_devio(uint32 dev, uint64 *data);
t_addr imp_devirq(uint32 dev, t_addr addr);
t_stat imp_srv(UNIT *); t_stat imp_srv(UNIT *);
t_stat imp_eth_srv(UNIT *); t_stat imp_eth_srv(UNIT *);
t_stat imp_tim_srv(UNIT *); t_stat imp_tim_srv(UNIT *);
@ -503,7 +504,13 @@ UNIT imp_unit[] = {
{UDATA(imp_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ {UDATA(imp_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */
{UDATA(imp_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */ {UDATA(imp_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */
}; };
DIB imp_dib = {IMP_DEVNUM, 1, &imp_devio, NULL}; DIB imp_dib = {IMP_DEVNUM, 1, &imp_devio,
#if KL
&imp_devirq,
#else
NULL
#endif
};
MTAB imp_mod[] = { MTAB imp_mod[] = {
{ MTAB_XTD|MTAB_VDV|MTAB_VALR|MTAB_NC, 0, "MAC", "MAC=xx:xx:xx:xx:xx:xx", { MTAB_XTD|MTAB_VDV|MTAB_VALR|MTAB_NC, 0, "MAC", "MAC=xx:xx:xx:xx:xx:xx",
@ -562,10 +569,13 @@ DEBTAB imp_debug[] = {
{0, 0} {0, 0}
}; };
REG imp_reg[] = {
{SAVEDATA(DATA, imp_data) },
{0}
};
DEVICE imp_dev = { DEVICE imp_dev = {
"IMP", imp_unit, NULL, imp_mod, "IMP", imp_unit, imp_reg, imp_mod,
3, 8, 0, 1, 8, 36, 3, 8, 0, 1, 8, 36,
NULL, NULL, &imp_reset, NULL, &imp_attach, &imp_detach, NULL, NULL, &imp_reset, NULL, &imp_attach, &imp_detach,
&imp_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, imp_debug, &imp_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, imp_debug,
@ -635,6 +645,7 @@ t_stat imp_devio(uint32 dev, uint64 *data)
uptr->STATUS |= IMPIHE; uptr->STATUS |= IMPIHE;
if (*data & IMPLHW) /* Last host word. */ if (*data & IMPLHW) /* Last host word. */
uptr->STATUS |= IMPLHW; uptr->STATUS |= IMPLHW;
check_interrupts(uptr);
break; break;
case TYPE_BBN: case TYPE_BBN:
break; break;
@ -731,6 +742,20 @@ t_stat imp_devio(uint32 dev, uint64 *data)
return SCPE_OK; return SCPE_OK;
} }
#if KL
/* Handle KL style interrupt vectors for ITS */
t_addr
imp_devirq(uint32 dev, t_addr addr) {
if ((cpu_unit[0].flags & UNIT_ITSPAGE) != 0 && (imp_data.pia & 7) == 1) {
if (imp_unit[0].STATUS & IMPID && (imp_unit[0].STATUS & IMPLW) == 0)
return 070|RSIGN;
if (imp_unit[0].STATUS & IMPOD)
return 072|RSIGN;
}
return addr;
}
#endif
t_stat imp_srv(UNIT * uptr) t_stat imp_srv(UNIT * uptr)
{ {
DEVICE *dptr = find_dev_from_unit(uptr); DEVICE *dptr = find_dev_from_unit(uptr);
@ -2669,6 +2694,7 @@ t_stat imp_attach(UNIT* uptr, CONST char* cptr)
if (tptr == NULL) return SCPE_MEM; if (tptr == NULL) return SCPE_MEM;
strcpy(tptr, cptr); strcpy(tptr, cptr);
memset(&imp_data.ReadQ, 0, sizeof(ETH_QUE));
status = eth_open(&imp_data.etherface, cptr, &imp_dev, DEBUG_ETHER); status = eth_open(&imp_data.etherface, cptr, &imp_dev, DEBUG_ETHER);
if (status != SCPE_OK) { if (status != SCPE_OK) {
free(tptr); free(tptr);
@ -2747,12 +2773,12 @@ t_stat imp_detach(UNIT* uptr)
if (uptr->flags & UNIT_DHCP) { if (uptr->flags & UNIT_DHCP) {
imp_dhcp_release(&imp_data); imp_dhcp_release(&imp_data);
} }
sim_cancel (uptr+1); /* stop the packet timing services */
sim_cancel (uptr+2); /* stop the clock timer services */
eth_close (&imp_data.etherface); eth_close (&imp_data.etherface);
free(uptr->filename); free(uptr->filename);
uptr->filename = NULL; uptr->filename = NULL;
uptr->flags &= ~UNIT_ATT; uptr->flags &= ~UNIT_ATT;
sim_cancel (uptr+1); /* stop the packet timing services */
sim_cancel (uptr+2); /* stop the clock timer services */
} }
return SCPE_OK; return SCPE_OK;
} }

View file

@ -1,6 +1,6 @@
/* ka10_lp.c: PDP-10 line printer simulator /* kx10_lp.c: PDP-10 line printer simulator
Copyright (c) 2011-2017, Richard Cornwell Copyright (c) 2011-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -394,6 +394,8 @@ t_stat lpt_attach (UNIT *uptr, CONST char *cptr)
t_stat reason; t_stat reason;
reason = attach_unit (uptr, cptr); reason = attach_unit (uptr, cptr);
if (sim_switches & SIM_SW_REST)
return reason;
uptr->STATUS &= ~ERR_FLG; uptr->STATUS &= ~ERR_FLG;
clr_interrupt(LP_DEVNUM); clr_interrupt(LP_DEVNUM);
return reason; return reason;

View file

@ -1,6 +1,6 @@
/* ka10_mt.c: TM10A/B Magnetic tape controller /* kx10_mt.c: TM10A/B Magnetic tape controller
Copyright (c) 2013-2017, Richard Cornwell Copyright (c) 2013-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* ka10_pt.c: PDP-10 reader/punch simulator /* kx10_pt.c: PDP-10 paper tape reader/punch simulator
Copyright (c) 2011-2017, Richard Cornwell Copyright (c) 2011-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* ka10_rc.c: RC10 Disk Controller. /* kx10_rc.c: RC10 Disk Controller.
Copyright (c) 2013-2017, Richard Cornwell Copyright (c) 2013-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -187,7 +187,7 @@ DEVICE rca_dev = {
#if (NUM_DEVS_RC > 1) #if (NUM_DEVS_RC > 1)
REG rcb_reg[] = { REG rcb_reg[] = {
{BRDATA(BUFF, rc_buf[1], 16, 64, RM10_WDS), REG_HRO}, {BRDATA(BUFF, &rc_buf[1][0], 16, 64, RM10_WDS), REG_HRO},
{ORDATA(IPR, rc_ipr[1], 2), REG_HRO}, {ORDATA(IPR, rc_ipr[1], 2), REG_HRO},
{ORDATA(STATUS, rc_df10[1].status, 18), REG_RO}, {ORDATA(STATUS, rc_df10[1].status, 18), REG_RO},
{ORDATA(CIA, rc_df10[1].cia, 18)}, {ORDATA(CIA, rc_df10[1].cia, 18)},
@ -533,7 +533,7 @@ t_stat r;
uptr->capac = rc_drv_tab[GET_DTYPE (uptr->flags)].size; uptr->capac = rc_drv_tab[GET_DTYPE (uptr->flags)].size;
r = attach_unit (uptr, cptr); r = attach_unit (uptr, cptr);
if (r != SCPE_OK) if (r != SCPE_OK || (sim_switches & SIM_SW_REST) != 0)
return r; return r;
uptr->CUR_CYL = 0; uptr->CUR_CYL = 0;
uptr->UFLAGS = 0; uptr->UFLAGS = 0;

801
PDP10/kx10_rh.c Normal file
View file

@ -0,0 +1,801 @@
/* kx10_rh.c: RH10/RH20 interace routines.
Copyright (c) 2019-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "kx10_defs.h"
/* CONI Flags */
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
#define DIB_CBOV 0000000000200LL /* Control bus overrun */
#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */
#define CXR_ILC 0000000004000LL /* Illegal function code */
#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */
#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */
#define CCW_COMP_1 0000000040000LL /* Control word written. */
#define CXR_CHAN_ER 0000000100000LL /* Channel Error */
#define CXR_EXC 0000000200000LL /* Error in drive transfer */
#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */
#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */
#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */
#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */
#define CXR_SD_RAE 0000200000000LL /* Register access error */
#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */
#define B22_FLAG 0004000000000LL /* 22 bit channel */
#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */
#define CC_CHAN_ACT 0020000000000LL /* Channel in use */
#define CC_INH 0040000000000LL /* Disconnect channel */
#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */
#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */
/* RH20 CONI Flags */
#define RH20_PCR_FULL 0000000000020LL /* Primary command file full */
#define RH20_ATTN_ENA 0000000000040LL /* Attention enable */
#define RH20_SCR_FULL 0000000000100LL /* Secondary command full */
#define RH20_ATTN 0000000000200LL /* Attention */
#define RH20_MASS_ENA 0000000000400LL /* Mass bus enable */
#define RH20_DATA_OVR 0000000001000LL /* Data overrun */
#define RH20_CHAN_RDY 0000000002000LL /* Channel ready to start */
#define RH20_RAE 0000000004000LL /* Register access error */
#define RH20_DR_RESP 0000000010000LL /* Drive no response */
#define RH20_CHAN_ERR 0000000020000LL /* Channel error */
#define RH20_SHRT_WC 0000000040000LL /* Short word count */
#define RH20_LONG_WC 0000000100000LL /* Long word count */
#define RH20_DR_EXC 0000000200000LL /* Exception */
#define RH20_DATA_PRI 0000000400000LL /* Data parity error */
#define RH20_SBAR 0000001000000LL /* SBAR set */
#define RH20_XEND 0000002000000LL /* Transfer ended */
/* CONO Flags */
#define ATTN_EN 0000000000040LL /* enable attention interrupt. */
#define REA_EN 0000000000100LL /* enable register error interrupt */
#define CBOV_CLR 0000000000200LL /* Clear CBOV */
#define CONT_RESET 0000000002000LL /* Clear All error bits */
#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */
#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */
#define OVER_CLR 0000000020000LL /* Clear DTC overrun */
#define WRT_CW 0000000040000LL /* Write control word */
#define CHN_CLR 0000000100000LL /* Clear Channel Error */
#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */
#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */
/* RH20 CONO Flags */
#define RH20_DELETE_SCR 0000000000100LL /* Clear SCR */
#define RH20_RCLP 0000000000200LL /* Reset command list */
#define RH20_MASS_EN 0000000000400LL /* Mass bus enable */
#define RH20_XFER_CLR 0000000001000LL /* Clear XFER error */
#define RH20_CLR_MBC 0000000002000LL /* Clear MBC */
#define RH20_CLR_RAE 0000000004000LL /* Clear RAE error */
/* DATAO/DATAI */
#define CR_REG 0770000000000LL /* Register number */
#define LOAD_REG 0004000000000LL /* Load register */
#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */
#define CR_DRIVE 0000007000000LL
#define CR_GEN_EVD 0000000400000LL /* Enable Parity */
#define CR_DXES 0000000200000LL /* Disable DXES errors */
#define CR_INAD 0000000077600LL
#define CR_WTEVM 0000000000100LL /* Verify Parity */
#define CR_FUNC 0000000000076LL
#define CR_GO 0000000000001LL
#define IRQ_VECT 0000000000777LL /* Interupt vector */
#define IRQ_KI10 0000002000000LL
#define IRQ_KA10 0000001000000LL
#define FNC_XFER 024 /* >=? data xfr */
/* Status register settings */
#define DS_OFF 0000001 /* offset mode */
#define DS_VV 0000100 /* volume valid */
#define DS_DRY 0000200 /* drive ready */
#define DS_DPR 0000400 /* drive present */
#define DS_PGM 0001000 /* programable NI */
#define DS_LST 0002000 /* last sector */
#define DS_WRL 0004000 /* write locked */
#define DS_MOL 0010000 /* medium online */
#define DS_PIP 0020000 /* pos in progress */
#define DS_ERR 0040000 /* error */
#define DS_ATA 0100000 /* attention active */
/* RH20 channel status flags */
#define RH20_MEM_PAR 00200000000000LL /* Memory parity error */
#define RH20_NADR_PAR 00100000000000LL /* Address parity error */
#define RH20_NOT_WC0 00040000000000LL /* Word count not zero */
#define RH20_NXM_ERR 00020000000000LL /* Non existent memory */
#define RH20_LAST_ERR 00000400000000LL /* Last transfer error */
#define RH20_ERROR 00000200000000LL /* RH20 error */
#define RH20_LONG_STS 00000100000000LL /* Did not reach wc */
#define RH20_SHRT_STS 00000040000000LL /* WC reached zero */
#define RH20_OVER 00000020000000LL /* Overrun error */
/* 0-37 mass bus register.
70 SBAR, block address.
71 STCR, neg block count, func
72 PBAR
73 PTCR
74 IVIR Interrupt vector address.
75 Diags read.
76 Diags write.
77 Status (tra,cb test, bar test, ev par, r/w, exc,ebl, 0, attn, sclk
*/
/*
* CCW 000..... New channel comand list pointer HALT.
010..... Next CCW Address JUMP
1xycount-address. x=halt last xfer, y=reverse
*/
extern uint32 eb_ptr;
t_stat
rh_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
DEVICE *dptr;
DIB *dibp;
dptr = find_dev_from_unit (uptr);
if (dptr == NULL)
return SCPE_IERR;
dibp = (DIB *) dptr->ctxt;
dptr->flags &= ~DEV_M_RH;
dptr->flags |= val;
dibp->dev_num &= ~(RH10_DEV|RH20_DEV);
dibp->dev_num |= (val) ? RH20_DEV: RH10_DEV;
return SCPE_OK;
}
t_stat rh_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
{
DEVICE *dptr;
if (uptr == NULL)
return SCPE_IERR;
dptr = find_dev_from_unit(uptr);
if (dptr == NULL)
return SCPE_IERR;
fprintf (st, "%s", (dptr->flags & TYPE_RH20) ? "RH20" : "RH10");
return SCPE_OK;
}
t_stat rh_devio(uint32 dev, uint64 *data) {
DEVICE *dptr = NULL;
struct rh_if *rhc = NULL;
int drive;
for (drive = 0; rh[drive].dev_num != 0; drive++) {
if (rh[drive].dev_num == (dev & 0774)) {
rhc = rh[drive].rh;
dptr = rh[drive].dev;
break;
}
}
if (rhc == NULL)
return SCPE_OK;
#if KL
if (dptr->flags & TYPE_RH20) {
switch(dev & 3) {
case CONI:
*data = rhc->status & RMASK;
if (rhc->attn != 0)
*data |= RH20_ATTN;
if (rhc->rae != 0)
*data |= RH20_RAE;
sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n",
dptr->name, dev, (uint32)*data, PC, rhc->attn);
return SCPE_OK;
case CONO:
clr_interrupt(dev);
/* Clear flags */
if (*data & RH20_CLR_MBC) {
if (rhc->dev_reset != NULL)
rhc->dev_reset(dptr);
rhc->attn = 0;
rhc->imode = 2;
}
rhc->status &= ~(07LL|IADR_ATTN|RH20_MASS_EN);
rhc->status |= *data & (07LL|IADR_ATTN|RH20_MASS_EN);
if (*data & RH20_DELETE_SCR)
rhc->status &= ~(RH20_SBAR|RH20_SCR_FULL);
if (*data & (RH20_RCLP|RH20_CLR_MBC))
rhc->cia = eb_ptr | (rhc->devnum - 0540);
if (*data & (RH20_CLR_RAE|RH20_CLR_MBC))
rhc->rae = 0;
if (*data & PI_ENABLE)
rhc->status &= ~PI_ENABLE;
if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0)
|| (rhc->status & PI_ENABLE))
set_interrupt(rhc->devnum, rhc->status);
sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n",
dptr->name, dev, (uint32)*data, PC, rhc->status);
return SCPE_OK;
case DATAI:
*data = 0;
if (rhc->status & BUSY && rhc->reg != 04) {
rhc->status |= CC_CHAN_ACT;
return SCPE_OK;
}
if (rhc->reg < 040) {
int parity;
*data = (uint64)(rhc->dev_read(dptr, rhc, rhc->reg) & 0177777);
parity = (int)((*data >> 8) ^ *data);
parity = (parity >> 4) ^ parity;
parity = (parity >> 2) ^ parity;
parity = ((parity >> 1) ^ parity) & 1;
*data |= ((uint64)(!parity)) << 16;
*data |= ((uint64)(rhc->drive)) << 18;
*data |= BIT10;
} else if ((rhc->reg & 070) != 070) {
rhc->rae = 1;
break;
} else {
switch(rhc->reg & 07) {
case 0: *data = rhc->sbar; break;
case 1: *data = rhc->stcr; break;
case 2: *data = rhc->pbar; break;
case 3: *data = rhc->ptcr; break;
case 4: *data = rhc->ivect; break;
case 5:
case 6: break;
case 7: *data = 0; break;
}
}
*data |= ((uint64)(rhc->reg)) << 30;
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n",
dptr->name, dev, *data, rhc->drive, PC);
return SCPE_OK;
case DATAO:
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n",
dptr->name, dev, *data, PC, rhc->status);
rhc->reg = ((int)(*data >> 30)) & 077;
rhc->imode |= 2;
if (rhc->reg < 040)
rhc->drive = (int)(*data >> 18) & 07;
if (*data & LOAD_REG) {
if (rhc->reg < 040) {
clr_interrupt(dev);
/* Check if access error */
if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0) {
set_interrupt(rhc->devnum, rhc->status);
return SCPE_OK;
}
rhc->dev_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777));
if (((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0)
|| (rhc->status & PI_ENABLE))
set_interrupt(rhc->devnum, rhc->status);
/* Check if access error */
if (rhc->rae & (1 << rhc->drive) && (*data & BIT9) == 0)
set_interrupt(rhc->devnum, rhc->status);
else
rhc->rae &= ~(1 << rhc->drive);
} else if ((rhc->reg & 070) != 070) {
if ((*data & BIT9) == 0) {
rhc->rae = (1 << rhc->drive);
set_interrupt(rhc->devnum, rhc->status);
}
} else {
switch(rhc->reg & 07) {
case 0:
rhc->sbar = (*data) & (CR_DRIVE|RMASK);
rhc->status |= RH20_SBAR;
break;
case 1:
rhc->stcr = (*data) & (BIT10|BIT7|CR_DRIVE|RMASK);
rhc->status |= RH20_SCR_FULL;
break;
case 4:
rhc->ivect = (*data & IRQ_VECT);
break;
case 2:
case 3:
case 5:
case 6:
case 7:
break;
}
}
}
}
if ((rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL))
rh20_setup(rhc);
return SCPE_OK;
}
#endif
switch(dev & 3) {
case CONI:
*data = rhc->status & ~(IADR_ATTN|IARD_RAE);
if (rhc->attn != 0 && (rhc->status & IADR_ATTN))
*data |= IADR_ATTN;
if (rhc->rae != 0 && (rhc->status & IARD_RAE))
*data |= IARD_RAE;
#if KI_22BIT
*data |= B22_FLAG;
#endif
sim_debug(DEBUG_CONI, dptr, "%s %03o CONI %06o PC=%o %o\n",
dptr->name, dev, (uint32)*data, PC, rhc->attn);
return SCPE_OK;
case CONO:
clr_interrupt(dev);
rhc->status &= ~(07LL|IADR_ATTN|IARD_RAE);
rhc->status |= *data & (07LL|IADR_ATTN|IARD_RAE);
/* Clear flags */
if (*data & CONT_RESET && rhc->dev_reset != NULL)
rhc->dev_reset(dptr);
if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR))
rhc->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR));
if (*data & OVER_CLR)
rhc->status &= ~(DTC_OVER);
if (*data & CBOV_CLR)
rhc->status &= ~(DIB_CBOV);
if (*data & CXR_ILC)
rhc->status &= ~(CXR_ILFC|CXR_SD_RAE);
if (*data & WRT_CW)
rh_writecw(rhc, 0);
if (*data & PI_ENABLE)
rhc->status &= ~PI_ENABLE;
if (rhc->status & PI_ENABLE)
set_interrupt(dev, rhc->status);
if ((rhc->status & IADR_ATTN) != 0 && rhc->attn != 0)
set_interrupt(dev, rhc->status);
sim_debug(DEBUG_CONO, dptr, "%s %03o CONO %06o PC=%06o %06o\n",
dptr->name, dev, (uint32)*data, PC, rhc->status);
return SCPE_OK;
case DATAI:
*data = 0;
if (rhc->status & BUSY && rhc->reg != 04) {
rhc->status |= CC_CHAN_ACT;
return SCPE_OK;
}
if (rhc->reg == 040) {
*data = (uint64)(rhc->dev_read(dptr, rhc, 0) & 077);
*data |= ((uint64)(rhc->cia)) << 6;
*data |= ((uint64)(rhc->xfer_drive)) << 18;
} else if (rhc->reg == 044) {
*data = (uint64)rhc->ivect;
if (rhc->imode)
*data |= IRQ_KI10;
else
*data |= IRQ_KA10;
} else if (rhc->reg == 054) {
*data = (uint64)(rhc->rae);
} else if ((rhc->reg & 040) == 0) {
int parity;
*data = (uint64)(rhc->dev_read(dptr, rhc, rhc->reg) & 0177777);
parity = (int)((*data >> 8) ^ *data);
parity = (parity >> 4) ^ parity;
parity = (parity >> 2) ^ parity;
parity = ((parity >> 1) ^ parity) & 1;
*data |= ((uint64)(parity ^ 1)) << 17;
*data |= ((uint64)(rhc->drive)) << 18;
}
*data |= ((uint64)(rhc->reg)) << 30;
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATI %012llo %d PC=%06o\n",
dptr->name, dev, *data, rhc->drive, PC);
return SCPE_OK;
case DATAO:
sim_debug(DEBUG_DATAIO, dptr, "%s %03o DATO %012llo PC=%06o %06o\n",
dptr->name, dev, *data, PC, rhc->status);
rhc->reg = ((int)(*data >> 30)) & 077;
rhc->imode &= ~2;
if (rhc->reg < 040 && rhc->reg != 04) {
rhc->drive = (int)(*data >> 18) & 07;
}
if (*data & LOAD_REG) {
if (rhc->reg == 040) {
if ((*data & 1) == 0) {
return SCPE_OK;
}
if (rhc->status & BUSY) {
rhc->status |= CC_CHAN_ACT;
return SCPE_OK;
}
rhc->status &= ~(CCW_COMP_1|PI_ENABLE);
if (((*data >> 1) & 037) < FNC_XFER) {
rhc->status |= CXR_ILC;
rh_setirq(rhc);
sim_debug(DEBUG_DATAIO, dptr,
"%s %03o command abort %012llo, %d PC=%06o %06o\n",
dptr->name, dev, *data, rhc->drive, PC, rhc->status);
return SCPE_OK;
}
/* Check if access error */
if (rhc->rae & (1 << rhc->drive))
return SCPE_OK;
/* Start command */
rh_setup(rhc, (uint32)(*data >> 6));
rhc->xfer_drive = (int)(*data >> 18) & 07;
rhc->dev_write(dptr, rhc, 0, (uint32)(*data & 077));
sim_debug(DEBUG_DATAIO, dptr,
"%s %03o command %012llo, %d PC=%06o %06o\n",
dptr->name, dev, *data, rhc->drive, PC, rhc->status);
} else if (rhc->reg == 044) {
/* Set KI10 Irq vector */
rhc->ivect = (int)(*data & IRQ_VECT);
rhc->imode = (*data & IRQ_KI10) != 0;
} else if (rhc->reg == 050) {
; /* Diagnostic access to mass bus. */
} else if (rhc->reg == 054) {
/* clear flags */
rhc->rae &= ~(*data & 0377);
if (rhc->rae == 0)
clr_interrupt(dev);
} else if ((rhc->reg & 040) == 0) {
rhc->drive = (int)(*data >> 18) & 07;
/* Check if access error */
if (rhc->rae & (1 << rhc->drive)) {
return SCPE_OK;
}
rhc->dev_write(dptr, rhc, rhc->reg & 037, (int)(*data & 0777777));
}
}
clr_interrupt(dev);
if (((rhc->status & (IADR_ATTN|BUSY)) == IADR_ATTN && rhc->attn != 0)
|| (rhc->status & PI_ENABLE))
set_interrupt(rhc->devnum, rhc->status);
return SCPE_OK;
}
return SCPE_OK; /* Unreached */
}
/* Handle KI and KL style interrupt vectors */
t_addr
rh_devirq(uint32 dev, t_addr addr) {
DEVICE *dptr = NULL;
struct rh_if *rhc = NULL;
int drive;
for (drive = 0; rh[drive].dev_num != 0; drive++) {
if (rh[drive].dev_num == (dev & 0774)) {
rhc = rh[drive].rh;
break;
}
}
if (rhc != NULL) {
if (rhc->imode == 1) /* KI10 Style */
addr = RSIGN | rhc->ivect;
else if (rhc->imode == 2) /* RH20 style */
addr = rhc->ivect;
}
return addr;
}
/* Set the attention flag for a unit */
void rh_setattn(struct rh_if *rhc, int unit)
{
rhc->attn |= 1<<unit;
if ((rhc->status & BUSY) == 0 && (rhc->status & IADR_ATTN) != 0)
set_interrupt(rhc->devnum, rhc->status);
}
void rh_error(struct rh_if *rhc)
{
if (rhc->imode == 2)
rhc->status |= RH20_DR_EXC;
}
/* Decrement block count for RH20, nop for RH10 */
int rh_blkend(struct rh_if *rhc)
{
#if KL
if (rhc->imode == 2) {
//fprintf(stderr, "RH blkend %o\n\r", rhc->cia);
rhc->cia = (rhc->cia + 1) & 01777;
if (rhc->cia == 0) {
rhc->status |= RH20_XEND;
return 1;
}
}
#endif
return 0;
}
/* Set an IRQ for a DF10 device */
void rh_setirq(struct rh_if *rhc) {
rhc->status |= PI_ENABLE;
set_interrupt(rhc->devnum, rhc->status);
}
/* Generate the DF10 complete word */
void rh_writecw(struct rh_if *rhc, int nxm) {
uint64 wrd1;
#if KL
if (rhc->imode == 2) {
uint32 chan = (rhc->devnum - 0540);
int wc = ((rhc->wcr ^ RH20_WMASK) + 1) & RH20_WMASK;
rhc->status |= RH20_CHAN_RDY;
rhc->status &= ~(RH20_PCR_FULL);
if (wc != 0 || (rhc->status & RH20_XEND) == 0 ||
(rhc->ptcr & BIT10) != 0 || nxm) {
uint64 wrd2;
wrd1 = SMASK|(uint64)(rhc->ccw);
if ((rhc->ptcr & BIT10) == 0 || (rhc->status & RH20_DR_EXC) != 0)
return;
if (nxm) {
wrd1 |= RH20_NXM_ERR;
rhc->status |= RH20_CHAN_ERR;
}
if (wc != 0) {
wrd1 |= RH20_NOT_WC0;
if (rhc->status & RH20_XEND) {
wrd1 |= RH20_LONG_STS;
if ((rhc->ptcr & 070) == 060) { /* Write command */
rhc->status |= RH20_LONG_WC|RH20_CHAN_ERR;
}
}
} else if ((rhc->status & RH20_XEND) == 0) {
wrd1 |= RH20_SHRT_STS;
if ((rhc->ptcr & 070) == 060) { /* Write command */
rhc->status |= RH20_SHRT_WC|RH20_CHAN_ERR;
}
}
/* No error and not storing */
if ((rhc->status & RH20_CHAN_ERR) == 0 && (rhc->ptcr & BIT10) == 0)
return;
wrd1 |= RH20_NADR_PAR;
wrd2 = ((uint64)rhc->cop << 33) | (((uint64)wc) << CSHIFT) |
((uint64)(rhc->cda) & AMASK);
(void)Mem_write_word(chan+1, &wrd1, 1);
(void)Mem_write_word(chan+2, &wrd2, 1);
//fprintf(stderr, "RH20 final %012llo %012llo %06o\n\r", wrd1, wrd2, wc);
}
return;
}
#endif
if (nxm)
rhc->status |= CXR_NXM;
rhc->status |= CCW_COMP_1;
if (rhc->wcr != 0)
rhc->cda++;
wrd1 = ((uint64)(rhc->ccw & WMASK) << CSHIFT) | ((uint64)(rhc->cda) & AMASK);
(void)Mem_write_word(rhc->cia|1, &wrd1, 0);
}
/* Finish off a DF10 transfer */
void rh_finish_op(struct rh_if *rhc, int nxm) {
#if KL
if (rhc->imode != 2)
#endif
rhc->status &= ~BUSY;
rh_writecw(rhc, nxm);
rh_setirq(rhc);
#if KL
if (rhc->imode == 2 &&
(rhc->status & (RH20_SCR_FULL|RH20_PCR_FULL)) == (RH20_SCR_FULL) &&
(rhc->status & (RH20_DR_EXC|RH20_CHAN_ERR)) == 0)
rh20_setup(rhc);
#endif
}
#if KL
/* Set up for a RH20 transfer */
void rh20_setup(struct rh_if *rhc)
{
DEVICE *dptr = NULL;
int reg;
for (reg = 0; rh[reg].dev_num != 0; reg++) {
if (rh[reg].rh == rhc) {
dptr = rh[reg].dev;
break;
}
}
if (dptr == 0)
return;
rhc->pbar = rhc->sbar;
rhc->ptcr = rhc->stcr;
/* Read drive status */
rhc->drive = (rhc->ptcr >> 18) & 07;
rhc->status &= ~(RH20_DATA_OVR|RH20_CHAN_RDY|RH20_DR_RESP|RH20_CHAN_ERR|RH20_SHRT_WC|\
RH20_LONG_WC|RH20_DR_EXC|RH20_SCR_FULL|PI_ENABLE|RH20_XEND);
rhc->status |= RH20_PCR_FULL;
if (rhc->status & RH20_SBAR) {
rhc->drive = (rhc->pbar >> 18) & 07;
if (rhc->dev_write != NULL)
rhc->dev_write(dptr, rhc, 5, (rhc->pbar & 0177777));
rhc->status &= ~RH20_SBAR;
}
if (rhc->ptcr & BIT7) { /* If RCPL reset I/O pointers */
rhc->ccw = eb_ptr + (rhc->devnum - 0540);
rhc->wcr = 0;
}
/* Hold block count in cia */
rhc->drive = (rhc->ptcr >> 18) & 07;
rhc->cia = (rhc->ptcr >> 6) & 01777;
if (rhc->dev_write != NULL)
rhc->dev_write(dptr, rhc, 0, (rhc->ptcr & 077));
rhc->cop = 0;
rhc->wcr = 0;
rhc->status &= ~RH20_CHAN_RDY;
//fprintf(stderr, "RH setup %06o %06o %o\n\r", rhc->ptcr, rhc->ccw, rhc->cia);
}
#endif
/* Setup for a DF10 transfer */
void rh_setup(struct rh_if *rhc, uint32 addr)
{
rhc->cia = addr & ICWA;
rhc->ccw = rhc->cia;
rhc->wcr = 0;
rhc->status |= BUSY;
}
/* Fetch the next IO control word */
int rh_fetch(struct rh_if *rhc) {
uint64 data;
int reg;
DEVICE *dptr = NULL;
for (reg = 0; rh[reg].dev_num != 0; reg++) {
if (rh[reg].rh == rhc) {
dptr = rh[reg].dev;
break;
}
}
#if KL
if (rhc->imode == 2 && (rhc->cop & 2) != 0) {
return 0;
}
#endif
if (Mem_read_word(rhc->ccw, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
sim_debug(DEBUG_EXP, dptr, "%s fetch %06o %012llo\n\r", dptr->name, rhc->ccw, data);
#if KL
if (rhc->imode == 2) {
while((data & RH20_XFER) == 0) {
rhc->ccw = (uint32)(data & AMASK);
if ((data & (BIT1|BIT2)) == 0) {
return 0;
}
if (Mem_read_word(rhc->ccw, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
sim_debug(DEBUG_EXP, dptr, "%s fetch2 %06o %012llo\n\r", dptr->name, rhc->ccw, data);
//fprintf(stderr, "RH20 fetch2 %06o %012llo\n\r", rhc->ccw, data);
}
rhc->wcr = (((data >> CSHIFT) & RH20_WMASK) ^ WMASK) + 1;
rhc->cda = (data & AMASK);
rhc->cop = (data >> 33) & 07;
rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK);
return 1;
}
#endif
while((data & (WMASK << CSHIFT)) == 0) {
if ((data & AMASK) == 0 || (uint32)(data & AMASK) == rhc->ccw) {
rh_finish_op(rhc, 0);
return 0;
}
rhc->ccw = (uint32)(data & AMASK);
if (Mem_read_word(rhc->ccw, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
sim_debug(DEBUG_EXP, dptr, "%s fetch2 %06o %012llo\n\r", dptr->name, rhc->ccw, data);
}
rhc->wcr = (uint32)((data >> CSHIFT) & WMASK);
rhc->cda = (uint32)(data & AMASK);
rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK);
return 1;
}
/* Read next word */
int rh_read(struct rh_if *rhc) {
uint64 data;
if (rhc->wcr == 0) {
if (!rh_fetch(rhc))
return 0;
}
rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK);
if (rhc->cda != 0) {
if (rhc->cda > MEMSIZE) {
rh_finish_op(rhc, 1);
return 0;
}
#if KL
if (rhc->imode == 2) {
if (Mem_read_word(rhc->cda, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
if (rhc->cop & 01)
rhc->cda = (uint32)((rhc->cda - 1) & AMASK);
else
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
} else {
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
if (Mem_read_word(rhc->cda, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
}
#else
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
if (Mem_read_word(rhc->cda, &data, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
#endif
} else {
data = 0;
}
rhc->buf = data;
if (rhc->wcr == 0) {
return rh_fetch(rhc);
}
return 1;
}
/* Write next word */
int rh_write(struct rh_if *rhc) {
if (rhc->wcr == 0) {
if (!rh_fetch(rhc))
return 0;
}
rhc->wcr = (uint32)((rhc->wcr + 1) & WMASK);
if (rhc->cda != 0) {
if (rhc->cda > MEMSIZE) {
rh_finish_op(rhc, 1);
return 0;
}
#if KL
if (rhc->imode == 2) {
if (Mem_write_word(rhc->cda, &rhc->buf, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
if (rhc->cop & 01)
rhc->cda = (uint32)((rhc->cda - 1) & AMASK);
else
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
} else {
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
if (Mem_write_word(rhc->cda, &rhc->buf, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
}
#else
rhc->cda = (uint32)((rhc->cda + 1) & AMASK);
if (Mem_write_word(rhc->cda, &rhc->buf, 0)) {
rh_finish_op(rhc, 1);
return 0;
}
#endif
}
if (rhc->wcr == 0) {
return rh_fetch(rhc);
}
return 1;
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* ka10_rs.c: Dec RH10 RS04 /* kx10_rs.c: DEC Massbus RS04
Copyright (c) 2017, Richard Cornwell Copyright (c) 2017-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -28,6 +28,8 @@
#endif #endif
#if (NUM_DEVS_RS > 0) #if (NUM_DEVS_RS > 0)
#define BUF_EMPTY(u) (u->hwmark == 0xFFFFFFFF)
#define CLR_BUF(u) u->hwmark = 0xFFFFFFFF
#define RS_NUMWD 128 /* 36bit words/sec */ #define RS_NUMWD 128 /* 36bit words/sec */
#define NUM_UNITS_RS 8 #define NUM_UNITS_RS 8
@ -42,72 +44,14 @@
#define DTYPE(x) (((x) & UNIT_M_DTYPE) << UNIT_V_DTYPE) #define DTYPE(x) (((x) & UNIT_M_DTYPE) << UNIT_V_DTYPE)
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE) #define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */ #define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
#define CNTRL_V_CTYPE (UNIT_V_UF + 4)
#define CNTRL_M_CTYPE 7
#define GET_CNTRL(x) (((x) >> CNTRL_V_CTYPE) & CNTRL_M_CTYPE)
#define CNTRL(x) (((x) & CNTRL_M_CTYPE) << CNTRL_V_CTYPE)
/* Parameters in the unit descriptor */ /* Parameters in the unit descriptor */
/* CONI Flags */
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
#define DIB_CBOV 0000000000200LL /* Control bus overrun */
#define CXR_PS_FAIL 0000000002000LL /* Power supply fail (not implemented) */
#define CXR_ILC 0000000004000LL /* Illegal function code */
#define CR_DRE 0000000010000LL /* Or Data and Control Timeout */
#define DTC_OVER 0000000020000LL /* DF10 did not supply word on time (not implemented) */
#define CCW_COMP_1 0000000040000LL /* Control word written. */
#define CXR_CHAN_ER 0000000100000LL /* Channel Error */
#define CXR_EXC 0000000200000LL /* Error in drive transfer */
#define CXR_DBPE 0000000400000LL /* Device Parity error (not implemented) */
#define CXR_NXM 0000001000000LL /* Channel non-existent memory (not implemented) */
#define CXR_CWPE 0000002000000LL /* Channel Control word parity error (not implemented) */
#define CXR_CDPE 0000004000000LL /* Channel Data Parity Error (not implemented) */
#define CXR_SD_RAE 0000200000000LL /* Register access error */
#define CXR_ILFC 0000400000000LL /* Illegal CXR function code */
#define B22_FLAG 0004000000000LL /* 22 bit channel */
#define CC_CHAN_PLS 0010000000000LL /* Channel transfer pulse (not implemented) */
#define CC_CHAN_ACT 0020000000000LL /* Channel in use */
#define CC_INH 0040000000000LL /* Disconnect channel */
#define CB_FULL 0200000000000LL /* Set when channel buffer is full (not implemented) */
#define AR_FULL 0400000000000LL /* Set when AR is full (not implemented) */
/* CONO Flags */
#define ATTN_EN 0000000000040LL /* enable attention interrupt. */
#define REA_EN 0000000000100LL /* enable register error interrupt */
#define CBOV_CLR 0000000000200LL /* Clear CBOV */
#define CONT_RESET 0000000002000LL /* Clear All error bits */
#define ILC_CLR 0000000004000LL /* Clear ILC and SD RAE */
#define DRE_CLR 0000000010000LL /* Clear CR_CBTO and CR_DBTO */
#define OVER_CLR 0000000020000LL /* Clear DTC overrun */
#define WRT_CW 0000000040000LL /* Write control word */
#define CHN_CLR 0000000100000LL /* Clear Channel Error */
#define DR_EXC_CLR 0000000200000LL /* Clear DR_EXC */
#define DBPE_CLR 0000000400000LL /* Clear CXR_DBPE */
/* DATAO/DATAI */
#define CR_REG 0770000000000LL /* Register number */
#define LOAD_REG 0004000000000LL /* Load register */
#define CR_MAINT_MODE 0000100000000LL /* Maint mode... not implemented */
#define CR_DRIVE 0000007000000LL
#define CR_GEN_EVD 0000000400000LL /* Enable Parity */
#define CR_DXES 0000000200000LL /* Disable DXES errors */
#define CR_INAD 0000000077600LL
#define CR_WTEVM 0000000000100LL /* Verify Parity */
#define CR_FUNC 0000000000076LL
#define CR_GO 0000000000001LL
#define IRQ_VECT 0000000000177LL /* Interupt vector */
#define IRQ_KI10 0000002000000LL
#define IRQ_KA10 0000001000000LL
#define CMD u3 #define CMD u3
/* u3 low */ /* u3 low */
/* RSC - 00 - control */ /* RSC - 00 - control */
#define CS1_GO CR_GO /* go */ #define CS1_GO 1 /* go */
#define CS1_V_FNC 1 /* function pos */ #define CS1_V_FNC 1 /* function pos */
#define CS1_M_FNC 037 /* function mask */ #define CS1_M_FNC 037 /* function mask */
#define CS1_FNC (CS1_M_FNC << CS1_V_FNC) #define CS1_FNC (CS1_M_FNC << CS1_V_FNC)
@ -228,21 +172,10 @@ struct drvtyp rs_drv_tab[] = {
}; };
struct df10 rs_df10[NUM_DEVS_RS];
uint32 rs_xfer_drive[NUM_DEVS_RS];
uint64 rs_buf[NUM_DEVS_RS][RS_NUMWD]; uint64 rs_buf[NUM_DEVS_RS][RS_NUMWD];
int rs_reg[NUM_DEVS_RS]; void rs_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data);
int rs_ivect[NUM_DEVS_RS]; uint32 rs_read(DEVICE *dptr, struct rh_if *rhc, int reg);
int rs_imode[NUM_DEVS_RS]; void rs_rst(DEVICE *dptr);
int rs_drive[NUM_DEVS_RS];
int rs_rae[NUM_DEVS_RS];
int rs_attn[NUM_DEVS_RS];
extern int readin_flag;
t_stat rs_devio(uint32 dev, uint64 *data);
int rs_devirq(uint32 dev, int addr);
void rs_write(int ctlr, int unit, int reg, uint32 data);
uint32 rs_read(int ctlr, int unit, int reg);
t_stat rs_svc(UNIT *); t_stat rs_svc(UNIT *);
t_stat rs_boot(int32, DEVICE *); t_stat rs_boot(int32, DEVICE *);
void rs_ini(UNIT *, t_bool); void rs_ini(UNIT *, t_bool);
@ -258,28 +191,38 @@ const char *rs_description (DEVICE *dptr);
UNIT rs_unit[] = { UNIT rs_unit[] = {
/* Controller 1 */ /* Controller 1 */
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+ { UDATA (&rs_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL(0), RS04_SIZE) }, UNIT_ROABLE+DTYPE(RS04_DTYPE)+CNTRL_RH(0), RS04_SIZE) },
};
struct rh_if rs_rh[] = {
{ &rs_write, &rs_read, &rs_rst},
}; };
DIB rs_dib[] = { DIB rs_dib[] = {
{RH10_DEV, 1, &rs_devio, &rs_devirq} {RH10_DEV, 1, &rh_devio, &rh_devirq, &rs_rh[0]}
}; };
MTAB rs_mod[] = { MTAB rs_mod[] = {
#if KL
{MTAB_XTD|MTAB_VDV, TYPE_RH10, NULL, "RH10", &rh_set_type, NULL,
NULL, "Sets controller to RH10" },
{MTAB_XTD|MTAB_VDV, TYPE_RH20, "RH20", "RH20", &rh_set_type, &rh_show_type,
NULL, "Sets controller to RH20"},
#endif
{UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL}, {UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL},
{UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL}, {UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL},
{UNIT_DTYPE, (RS03_DTYPE << UNIT_V_DTYPE), "RS03", "RS03", &rs_set_type }, {UNIT_DTYPE, (RS03_DTYPE << UNIT_V_DTYPE), "RS03", "RS03", &rs_set_type },
@ -288,23 +231,20 @@ MTAB rs_mod[] = {
}; };
REG rsa_reg[] = { REG rsa_reg[] = {
{ORDATA(IVECT, rs_ivect[0], 18)}, {ORDATA(IVECT, rs_rh[0].ivect, 18)},
{FLDATA(IMODE, rs_imode[0], 0)}, {FLDATA(IMODE, rs_rh[0].imode, 0)},
{ORDATA(XFER, rs_xfer_drive[0], 3), REG_HRO}, {ORDATA(XFER, rs_rh[0].xfer_drive, 3), REG_HRO},
{ORDATA(DRIVE, rs_drive[0], 3), REG_HRO}, {ORDATA(DRIVE, rs_rh[0].drive, 3), REG_HRO},
{ORDATA(REG, rs_reg[0], 6), REG_RO}, {ORDATA(REG, rs_rh[0].reg, 6), REG_RO},
{ORDATA(RAE, rs_rae[0], 8), REG_RO}, {ORDATA(RAE, rs_rh[0].rae, 8), REG_RO},
{ORDATA(ATTN, rs_attn[0], 8), REG_RO}, {ORDATA(ATTN, rs_rh[0].attn, 8), REG_RO},
{FLDATA(READIN, readin_flag, 0), REG_HRO}, {ORDATA(STATUS, rs_rh[0].status, 18), REG_RO},
{ORDATA(STATUS, rs_df10[0].status, 18), REG_RO}, {ORDATA(CIA, rs_rh[0].cia, 18)},
{ORDATA(CIA, rs_df10[0].cia, 18)}, {ORDATA(CCW, rs_rh[0].ccw, 18)},
{ORDATA(CCW, rs_df10[0].ccw, 18)}, {ORDATA(WCR, rs_rh[0].wcr, 18)},
{ORDATA(WCR, rs_df10[0].wcr, 18)}, {ORDATA(CDA, rs_rh[0].cda, 18)},
{ORDATA(CDA, rs_df10[0].cda, 18)}, {ORDATA(DEVNUM, rs_rh[0].devnum, 9), REG_HRO},
{ORDATA(DEVNUM, rs_df10[0].devnum, 9), REG_HRO}, {ORDATA(BUF, rs_rh[0].buf, 36), REG_HRO},
{ORDATA(BUF, rs_df10[0].buf, 36), REG_HRO},
{ORDATA(NXM, rs_df10[0].nxmerr, 8), REG_HRO},
{ORDATA(COMP, rs_df10[0].ccw_comp, 8), REG_HRO},
{BRDATA(BUFF, rs_buf[0], 16, 64, RS_NUMWD), REG_HRO}, {BRDATA(BUFF, rs_buf[0], 16, 64, RS_NUMWD), REG_HRO},
{0} {0}
}; };
@ -322,213 +262,44 @@ DEVICE *rs_devs[] = {
}; };
t_stat rs_devio(uint32 dev, uint64 *data) { void
int ctlr = -1; rs_rst(DEVICE *dptr)
DEVICE *dptr = NULL; {
struct df10 *df10;
int drive;
for (drive = 0; rh[drive].dev_num != 0; drive++) {
if (rh[drive].dev_num == (dev & 0774)) {
dptr = rh[drive].dev;
break;
}
}
if (dptr == NULL)
return SCPE_OK;
ctlr = GET_CNTRL(dptr->units[0].flags);
df10 = &rs_df10[ctlr];
df10->devnum = dev;
switch(dev & 3) {
case CONI:
*data = df10->status & ~(IADR_ATTN|IARD_RAE);
if (rs_attn[ctlr] != 0 && (df10->status & IADR_ATTN))
*data |= IADR_ATTN;
if (rs_rae[ctlr] != 0 && (df10->status & IARD_RAE))
*data |= IARD_RAE;
#if KI_22BIT
*data |= B22_FLAG;
#endif
sim_debug(DEBUG_CONI, dptr, "RS %03o CONI %06o PC=%o %o\n",
dev, (uint32)*data, PC, rs_attn[ctlr]);
return SCPE_OK;
case CONO:
clr_interrupt(dev);
df10->status &= ~(07LL|IADR_ATTN|IARD_RAE);
df10->status |= *data & (07LL|IADR_ATTN|IARD_RAE);
/* Clear flags */
if (*data & CONT_RESET) {
UNIT *uptr=dptr->units; UNIT *uptr=dptr->units;
int drive;
for(drive = 0; drive < NUM_UNITS_RS; drive++, uptr++) { for(drive = 0; drive < NUM_UNITS_RS; drive++, uptr++) {
uptr->CMD &= DS_MOL|DS_WRL|DS_DPR|DS_DRY|DS_VV|076; uptr->CMD &= DS_MOL|DS_WRL|DS_DPR|DS_DRY|DS_VV|076;
uptr->DA &= 003400177777; uptr->DA &= 003400177777;
} }
}
if (*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR))
df10->status &= ~(*data & (DBPE_CLR|DR_EXC_CLR|CHN_CLR));
if (*data & OVER_CLR)
df10->status &= ~(DTC_OVER);
if (*data & CBOV_CLR)
df10->status &= ~(DIB_CBOV);
if (*data & CXR_ILC)
df10->status &= ~(CXR_ILFC|CXR_SD_RAE);
if (*data & WRT_CW)
df10_writecw(df10);
if (*data & PI_ENABLE)
df10->status &= ~PI_ENABLE;
if (df10->status & PI_ENABLE)
set_interrupt(dev, df10->status);
if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0)
set_interrupt(dev, df10->status);
sim_debug(DEBUG_CONO, dptr, "RS %03o CONO %06o %d PC=%06o %06o\n",
dev, (uint32)*data, ctlr, PC, df10->status);
return SCPE_OK;
case DATAI:
*data = 0;
if (df10->status & BUSY && rs_reg[ctlr] != 04) {
df10->status |= CC_CHAN_ACT;
return SCPE_OK;
}
if (rs_reg[ctlr] == 040) {
*data = (uint64)(rs_read(ctlr, rs_drive[ctlr], 0) & 077);
*data |= ((uint64)(df10->cia)) << 6;
*data |= ((uint64)(rs_xfer_drive[ctlr])) << 18;
} else if (rs_reg[ctlr] == 044) {
*data = (uint64)rs_ivect[ctlr];
if (rs_imode[ctlr])
*data |= IRQ_KI10;
else
*data |= IRQ_KA10;
} else if (rs_reg[ctlr] == 054) {
*data = (uint64)(rs_rae[ctlr]);
} else if ((rs_reg[ctlr] & 040) == 0) {
int parity;
*data = (uint64)(rs_read(ctlr, rs_drive[ctlr], rs_reg[ctlr]) & 0177777);
parity = (int)((*data >> 8) ^ *data);
parity = (parity >> 4) ^ parity;
parity = (parity >> 2) ^ parity;
parity = ((parity >> 1) ^ parity) & 1;
*data |= ((uint64)(parity ^ 1)) << 17;
*data |= ((uint64)(rs_drive[ctlr])) << 18;
}
*data |= ((uint64)(rs_reg[ctlr])) << 30;
sim_debug(DEBUG_DATAIO, dptr, "RS %03o DATI %012llo, %d %d PC=%06o\n",
dev, *data, ctlr, rs_drive[ctlr], PC);
return SCPE_OK;
case DATAO:
sim_debug(DEBUG_DATAIO, dptr, "RS %03o DATO %012llo, %d PC=%06o %06o\n",
dev, *data, ctlr, PC, df10->status);
rs_reg[ctlr] = ((int)(*data >> 30)) & 077;
if (rs_reg[ctlr] < 040 && rs_reg[ctlr] != 04) {
rs_drive[ctlr] = (int)(*data >> 18) & 07;
}
if (*data & LOAD_REG) {
if (rs_reg[ctlr] == 040) {
if ((*data & 1) == 0) {
return SCPE_OK;
}
if (df10->status & BUSY) {
df10->status |= CC_CHAN_ACT;
return SCPE_OK;
}
df10->status &= ~(1 << df10->ccw_comp);
df10->status &= ~PI_ENABLE;
if (((*data >> 1) & 077) < FNC_XFER) {
df10->status |= CXR_ILC;
df10_setirq(df10);
sim_debug(DEBUG_DATAIO, dptr,
"RS %03o command abort %012llo, %d[%d] PC=%06o %06o\n",
dev, *data, ctlr, rs_drive[ctlr], PC, df10->status);
return SCPE_OK;
}
/* Start command */
df10_setup(df10, (uint32)(*data >> 6));
rs_xfer_drive[ctlr] = (int)(*data >> 18) & 07;
rs_write(ctlr, rs_drive[ctlr], 0, (uint32)(*data & 077));
sim_debug(DEBUG_DATAIO, dptr,
"RS %03o command %012llo, %d[%d] PC=%06o %06o\n",
dev, *data, ctlr, rs_drive[ctlr], PC, df10->status);
} else if (rs_reg[ctlr] == 044) {
/* Set KI10 Irq vector */
rs_ivect[ctlr] = (int)(*data & IRQ_VECT);
rs_imode[ctlr] = (*data & IRQ_KI10) != 0;
} else if (rs_reg[ctlr] == 050) {
; /* Diagnostic access to mass bus. */
} else if (rs_reg[ctlr] == 054) {
/* clear flags */
rs_rae[ctlr] &= ~(*data & 0377);
if (rs_rae[ctlr] == 0)
clr_interrupt(dev);
} else if ((rs_reg[ctlr] & 040) == 0) {
rs_drive[ctlr] = (int)(*data >> 18) & 07;
/* Check if access error */
if (rs_rae[ctlr] & (1 << rs_drive[ctlr])) {
return SCPE_OK;
}
rs_drive[ctlr] = (int)(*data >> 18) & 07;
rs_write(ctlr, rs_drive[ctlr], rs_reg[ctlr] & 037,
(int)(*data & 0777777));
}
}
return SCPE_OK;
}
return SCPE_OK; /* Unreached */
}
/* Handle KI and KL style interrupt vectors */
int
rs_devirq(uint32 dev, int addr) {
DEVICE *dptr = NULL;
int drive;
for (drive = 0; rh[drive].dev_num != 0; drive++) {
if (rh[drive].dev_num == (dev & 0774)) {
dptr = rh[drive].dev;
break;
}
}
if (dptr != NULL) {
drive = GET_CNTRL(dptr->units[0].flags);
return (rs_imode[drive] ? rs_ivect[drive] : addr);
}
return addr;
} }
void void
rs_write(int ctlr, int unit, int reg, uint32 data) { rs_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) {
int i; int i;
DEVICE *dptr = rs_devs[ctlr]; int unit = rhc->drive;
struct df10 *df10 = &rs_df10[ctlr];
UNIT *uptr = &dptr->units[unit]; UNIT *uptr = &dptr->units[unit];
if ((uptr->CMD & CR_GO) && reg != 04) { if ((uptr->CMD & CS1_GO) && reg != 04) {
uptr->CMD |= (ER1_RMR << 16)|DS_ERR; uptr->CMD |= (ER1_RMR << 16)|DS_ERR;
return; return;
} }
switch(reg) { switch(reg) {
case 000: /* control */ case 000: /* control */
sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d Status=%06o\n", unit, ctlr, uptr->CMD); sim_debug(DEBUG_DETAIL, dptr, "%s%o Status=%06o\n", dptr->name, unit, uptr->CMD);
/* Set if drive not writable */ /* Set if drive not writable */
if (uptr->flags & UNIT_WLK) if (uptr->flags & UNIT_WLK)
uptr->CMD |= DS_WRL; uptr->CMD |= DS_WRL;
/* If drive not ready don't do anything */ /* If drive not ready don't do anything */
if ((uptr->CMD & DS_DRY) == 0) { if ((uptr->CMD & DS_DRY) == 0) {
uptr->CMD |= (ER1_RMR << 16)|DS_ERR; uptr->CMD |= (ER1_RMR << 16)|DS_ERR;
sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d busy\n", unit, ctlr); sim_debug(DEBUG_DETAIL, dptr, "%s%o busy\n", dptr->name, unit);
return; return;
} }
/* Check if GO bit set */ /* Check if GO bit set */
if ((data & 1) == 0) { if ((data & 1) == 0) {
uptr->CMD &= ~076; uptr->CMD &= ~076;
uptr->CMD |= data & 076; uptr->CMD |= data & 076;
sim_debug(DEBUG_DETAIL, dptr, "RSA%o %d no go\n", unit, ctlr); sim_debug(DEBUG_DETAIL, dptr, "%s%o no go\n", dptr->name, unit);
return; /* No, nop */ return; /* No, nop */
} }
uptr->CMD &= DS_ATA|DS_VV|DS_DPR|DS_MOL|DS_WRL; uptr->CMD &= DS_ATA|DS_VV|DS_DPR|DS_MOL|DS_WRL;
@ -542,7 +313,8 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
case FNC_WCHK: /* write check */ case FNC_WCHK: /* write check */
case FNC_WRITE: /* write */ case FNC_WRITE: /* write */
case FNC_READ: /* read */ case FNC_READ: /* read */
uptr->CMD |= DS_PIP|CR_GO; uptr->CMD |= DS_PIP|CS1_GO;
CLR_BUF(uptr);
uptr->DATAPTR = 0; uptr->DATAPTR = 0;
break; break;
@ -551,30 +323,26 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
if ((uptr->flags & UNIT_ATT) != 0) if ((uptr->flags & UNIT_ATT) != 0)
uptr->CMD |= DS_VV; uptr->CMD |= DS_VV;
uptr->CMD |= DS_DRY; uptr->CMD |= DS_DRY;
df10_setirq(df10); rh_setirq(rhc);
break; break;
case FNC_DCLR: /* drive clear */ case FNC_DCLR: /* drive clear */
uptr->CMD |= DS_DRY; uptr->CMD |= DS_DRY;
uptr->CMD &= ~(DS_ATA|CR_GO); uptr->CMD &= ~(DS_ATA|CS1_GO);
rs_attn[ctlr] = 0; rhc->attn = 0;
clr_interrupt(df10->devnum); clr_interrupt(rhc->devnum);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA) if (dptr->units[i].CMD & DS_ATA)
rs_attn[ctlr] = 1; rhc->attn |= 1 << i;
} }
if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0)
df10_setirq(df10);
break; break;
default: default:
uptr->CMD |= DS_DRY|DS_ERR|DS_ATA; uptr->CMD |= DS_DRY|DS_ERR|DS_ATA;
uptr->CMD |= (ER1_ILF << 16); uptr->CMD |= (ER1_ILF << 16);
if ((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0)
df10_setirq(df10);
} }
if (uptr->CMD & CR_GO) if (uptr->CMD & CS1_GO)
sim_activate(uptr, 100); sim_activate(uptr, 100);
sim_debug(DEBUG_DETAIL, dptr, "RSA%o AStatus=%06o\n", unit, uptr->CMD); sim_debug(DEBUG_DETAIL, dptr, "%s%o AStatus=%06o\n", dptr->name, unit, uptr->CMD);
return; return;
case 001: /* status */ case 001: /* status */
break; break;
@ -587,17 +355,13 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
case 003: /* maintenance */ case 003: /* maintenance */
break; break;
case 004: /* atten summary */ case 004: /* atten summary */
rs_attn[ctlr] = 0; rhc->attn = 0;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (data & (1<<i)) if (data & (1<<i))
rs_unit[(ctlr * 8) + i].CMD &= ~DS_ATA; dptr->units[i].CMD &= ~DS_ATA;
if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA) if (dptr->units[i].CMD & DS_ATA)
rs_attn[ctlr] = 1; rhc->attn |= 1 << i;
} }
clr_interrupt(df10->devnum);
if (((df10->status & IADR_ATTN) != 0 && rs_attn[ctlr] != 0) ||
(df10->status & PI_ENABLE))
df10_setirq(df10);
break; break;
case 005: /* sector/track */ case 005: /* sector/track */
uptr->DA = data & 0177777; uptr->DA = data & 0177777;
@ -607,14 +371,13 @@ rs_write(int ctlr, int unit, int reg, uint32 data) {
break; break;
default: default:
uptr->CMD |= (ER1_ILR<<16)|DS_ERR; uptr->CMD |= (ER1_ILR<<16)|DS_ERR;
rs_rae[ctlr] &= ~(1<<unit); rhc->rae |= 1 << unit;
} }
} }
uint32 uint32
rs_read(int ctlr, int unit, int reg) { rs_read(DEVICE *dptr, struct rh_if *rhc, int reg) {
DEVICE *dptr = rs_devs[ctlr]; int unit = rhc->drive;
struct df10 *df10 = &rs_df10[ctlr];
UNIT *uptr = &dptr->units[unit]; UNIT *uptr = &dptr->units[unit];
uint32 temp = 0; uint32 temp = 0;
int i; int i;
@ -628,7 +391,7 @@ rs_read(int ctlr, int unit, int reg) {
temp = uptr->CMD & 077; temp = uptr->CMD & 077;
if (uptr->flags & UNIT_ATT) if (uptr->flags & UNIT_ATT)
temp |= CS1_DVA; temp |= CS1_DVA;
if ((df10->status & BUSY) == 0 && (uptr->CMD & CR_GO) == 0) if ((uptr->CMD & CS1_GO) == 0)
temp |= CS1_GO; temp |= CS1_GO;
break; break;
case 001: /* status */ case 001: /* status */
@ -639,7 +402,7 @@ rs_read(int ctlr, int unit, int reg) {
break; break;
case 004: /* atten summary */ case 004: /* atten summary */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (rs_unit[(ctlr * 8) + i].CMD & DS_ATA) { if (dptr->units[i].CMD & DS_ATA) {
temp |= 1 << i; temp |= 1 << i;
} }
} }
@ -655,7 +418,7 @@ rs_read(int ctlr, int unit, int reg) {
break; break;
default: default:
uptr->CMD |= (ER1_ILR<<16); uptr->CMD |= (ER1_ILR<<16);
rs_rae[ctlr] &= ~(1<<unit); rhc->rae |= 1 << unit;
} }
return temp; return temp;
} }
@ -664,21 +427,20 @@ rs_read(int ctlr, int unit, int reg) {
t_stat rs_svc (UNIT *uptr) t_stat rs_svc (UNIT *uptr)
{ {
int dtype = GET_DTYPE(uptr->flags); int dtype = GET_DTYPE(uptr->flags);
int ctlr = GET_CNTRL(uptr->flags); int ctlr = GET_CNTRL_RH(uptr->flags);
int unit; int unit;
DEVICE *dptr; DEVICE *dptr;
struct df10 *df; struct rh_if *rhc;
int da; int da;
t_stat r; int sts;
/* Find dptr, and df10 */ /* Find dptr, and df10 */
dptr = rs_devs[ctlr]; dptr = rs_devs[ctlr];
rhc = &rs_rh[ctlr];
unit = uptr - dptr->units; unit = uptr - dptr->units;
df = &rs_df10[ctlr];
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
uptr->CMD |= (ER1_UNS << 16) | DS_ATA|DS_ERR; /* set drive error */ uptr->CMD |= (ER1_UNS << 16) | DS_ATA|DS_ERR; /* set drive error */
df->status &= ~BUSY; rh_setirq(rhc);
df10_setirq(df);
return (SCPE_OK); return (SCPE_OK);
} }
@ -693,42 +455,35 @@ t_stat rs_svc (UNIT *uptr)
case FNC_DCLR: /* drive clear */ case FNC_DCLR: /* drive clear */
break; break;
case FNC_PRESET: /* read-in preset */ case FNC_PRESET: /* read-in preset */
rs_attn[ctlr] = 1;
uptr->CMD |= DS_DRY|DS_ATA; uptr->CMD |= DS_DRY|DS_ATA;
uptr->CMD &= ~CR_GO; uptr->CMD &= ~CS1_GO;
df->status &= ~BUSY; rh_setattn(rhc, unit);
if (df->status & IADR_ATTN) sim_debug(DEBUG_DETAIL, dptr, "%s%o seekdone\n", dptr->name, unit);
df10_setirq(df);
sim_debug(DEBUG_DETAIL, dptr, "RSA%o seekdone\n", unit);
break; break;
case FNC_SEARCH: /* search */ case FNC_SEARCH: /* search */
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect || if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf)
uptr->CMD |= (ER1_IAE << 16)|DS_ERR; uptr->CMD |= (ER1_IAE << 16)|DS_ERR;
rs_attn[ctlr] = 1;
uptr->CMD |= DS_DRY|DS_ATA; uptr->CMD |= DS_DRY|DS_ATA;
uptr->CMD &= ~CR_GO; uptr->CMD &= ~CS1_GO;
df->status &= ~BUSY; rh_setattn(rhc, unit);
if ((df->status & (IADR_ATTN|BUSY)) == IADR_ATTN) sim_debug(DEBUG_DETAIL, dptr, "%s%o searchdone\n", dptr->name, unit);
df10_setirq(df);
sim_debug(DEBUG_DETAIL, dptr, "RSA%o searchdone\n", unit);
break; break;
case FNC_READ: /* read */ case FNC_READ: /* read */
case FNC_WCHK: /* write check */ case FNC_WCHK: /* write check */
if (uptr->DATAPTR == 0) { if (BUF_EMPTY(uptr)) {
int wc; int wc;
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect || if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) { GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) {
uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA; uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA;
df->status &= ~BUSY; uptr->CMD &= ~CS1_GO;
uptr->CMD &= ~CR_GO; sim_debug(DEBUG_DETAIL, dptr, "%s%o readx done\n", dptr->name, unit);
sim_debug(DEBUG_DETAIL, dptr, "RSA%o readx done\n", unit); rh_finish_op(rhc, 0);
df10_finish_op(df, 0);
return SCPE_OK; return SCPE_OK;
} }
sim_debug(DEBUG_DETAIL, dptr, "RSA%o read (%d,%d)\n", unit, sim_debug(DEBUG_DETAIL, dptr, "%s%o read (%d,%d)\n", dptr->name, unit,
GET_SC(uptr->DA), GET_SF(uptr->DA)); GET_SC(uptr->DA), GET_SF(uptr->DA));
da = GET_DA(uptr->DA, dtype) * RS_NUMWD; da = GET_DA(uptr->DA, dtype) * RS_NUMWD;
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); (void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET);
@ -737,15 +492,17 @@ t_stat rs_svc (UNIT *uptr)
while (wc < RS_NUMWD) while (wc < RS_NUMWD)
rs_buf[ctlr][wc++] = 0; rs_buf[ctlr][wc++] = 0;
uptr->hwmark = RS_NUMWD; uptr->hwmark = RS_NUMWD;
uptr->DATAPTR = 0;
} }
df->buf = rs_buf[ctlr][uptr->DATAPTR++]; rhc->buf = rs_buf[ctlr][uptr->DATAPTR++];
sim_debug(DEBUG_DATA, dptr, "RSA%o read word %d %012llo %09o %06o\n", sim_debug(DEBUG_DATA, dptr, "%s%o read word %d %012llo %09o %06o\n",
unit, uptr->DATAPTR, df->buf, df->cda, df->wcr); dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr);
if (df10_write(df)) { if (rh_write(rhc)) {
if (uptr->DATAPTR == uptr->hwmark) { if (uptr->DATAPTR == RS_NUMWD) {
/* Increment to next sector. Set Last Sector */ /* Increment to next sector. Set Last Sector */
uptr->DATAPTR = 0; uptr->DATAPTR = 0;
CLR_BUF(uptr);
uptr->DA += 1 << DA_V_SC; uptr->DA += 1 << DA_V_SC;
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect) { if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect) {
uptr->DA &= (DA_M_SF << DA_V_SF); uptr->DA &= (DA_M_SF << DA_V_SF);
@ -753,43 +510,53 @@ t_stat rs_svc (UNIT *uptr)
if (GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) if (GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf)
uptr->CMD |= DS_LST; uptr->CMD |= DS_LST;
} }
if (rh_blkend(rhc))
goto rd_end;
} }
sim_activate(uptr, 20); sim_activate(uptr, 10);
} else { } else {
sim_debug(DEBUG_DETAIL, dptr, "RSA%o read done\n", unit); rd_end:
sim_debug(DEBUG_DETAIL, dptr, "%s%o read done\n", dptr->name, unit);
uptr->CMD |= DS_DRY; uptr->CMD |= DS_DRY;
uptr->CMD &= ~CR_GO; uptr->CMD &= ~CS1_GO;
df10_finish_op(df, 0); if (uptr->DATAPTR == RS_NUMWD)
(void)rh_blkend(rhc);
rh_finish_op(rhc, 0);
return SCPE_OK; return SCPE_OK;
} }
break; break;
case FNC_WRITE: /* write */ case FNC_WRITE: /* write */
if (uptr->DATAPTR == 0) { if (BUF_EMPTY(uptr)) {
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect || if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) { GET_SF(uptr->DA) >= rs_drv_tab[dtype].surf) {
uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA; uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA;
uptr->CMD &= ~CR_GO; uptr->CMD &= ~CS1_GO;
sim_debug(DEBUG_DETAIL, dptr, "RSA%o writex done\n", unit); sim_debug(DEBUG_DETAIL, dptr, "%s%o writex done\n", dptr->name, unit);
df10_finish_op(df, 0); rh_finish_op(rhc, 0);
return SCPE_OK; return SCPE_OK;
} }
uptr->DATAPTR = 0;
uptr->hwmark = 0;
} }
r = df10_read(df); sts = rh_read(rhc);
rs_buf[ctlr][uptr->DATAPTR++] = df->buf; rs_buf[ctlr][uptr->DATAPTR++] = rhc->buf;
sim_debug(DEBUG_DATA, dptr, "RSA%o write word %d %012llo %09o %06o\n", sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %09o %06o\n",
unit, uptr->DATAPTR, df->buf, df->cda, df->wcr); dptr->name, unit, uptr->DATAPTR, rhc->buf, rhc->cda, rhc->wcr);
if (r == 0 || uptr->DATAPTR == RS_NUMWD) { if (sts == 0) {
while (uptr->DATAPTR < RS_NUMWD) while (uptr->DATAPTR < RS_NUMWD)
rs_buf[ctlr][uptr->DATAPTR++] = 0; rs_buf[ctlr][uptr->DATAPTR++] = 0;
sim_debug(DEBUG_DETAIL, dptr, "RSA%o write (%d,%d)\n", unit, }
if (uptr->DATAPTR == RS_NUMWD) {
sim_debug(DEBUG_DETAIL, dptr, "%s%o write (%d,%d)\n", dptr->name, unit,
GET_SC(uptr->DA), GET_SF(uptr->DA)); GET_SC(uptr->DA), GET_SF(uptr->DA));
da = GET_DA(uptr->DA, dtype) * RS_NUMWD; da = GET_DA(uptr->DA, dtype) * RS_NUMWD;
(void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET); (void)sim_fseek(uptr->fileref, da * sizeof(uint64), SEEK_SET);
(void)sim_fwrite (&rs_buf[ctlr][0], sizeof(uint64), RS_NUMWD, (void)sim_fwrite (&rs_buf[ctlr][0], sizeof(uint64), RS_NUMWD,
uptr->fileref); uptr->fileref);
uptr->DATAPTR = 0; uptr->DATAPTR = 0;
if (r) { CLR_BUF(uptr);
if (sts) {
uptr->DA += 1 << DA_V_SC; uptr->DA += 1 << DA_V_SC;
if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect) { if (GET_SC(uptr->DA) >= rs_drv_tab[dtype].sect) {
uptr->DA &= (DA_M_SF << DA_V_SF); uptr->DA &= (DA_M_SF << DA_V_SF);
@ -798,14 +565,17 @@ t_stat rs_svc (UNIT *uptr)
uptr->CMD |= DS_LST; uptr->CMD |= DS_LST;
} }
} }
if (rh_blkend(rhc))
goto wr_end;
} }
if (r) { if (sts) {
sim_activate(uptr, 20); sim_activate(uptr, 10);
} else { } else {
sim_debug(DEBUG_DETAIL, dptr, "RSA%o write done\n", unit); wr_end:
sim_debug(DEBUG_DETAIL, dptr, "%s%o write done\n", dptr->name, unit);
uptr->CMD |= DS_DRY; uptr->CMD |= DS_DRY;
uptr->CMD &= ~CR_GO; uptr->CMD &= ~CS1_GO;
df10_finish_op(df, 0); rh_finish_op(rhc, 0);
return SCPE_OK; return SCPE_OK;
} }
break; break;
@ -833,12 +603,9 @@ rs_reset(DEVICE * rstr)
{ {
int ctlr; int ctlr;
for (ctlr = 0; ctlr < NUM_DEVS_RS; ctlr++) { for (ctlr = 0; ctlr < NUM_DEVS_RS; ctlr++) {
rs_df10[ctlr].devnum = rs_dib[ctlr].dev_num; rs_rh[ctlr].status = 0;
rs_df10[ctlr].nxmerr = 19; rs_rh[ctlr].attn = 0;
rs_df10[ctlr].ccw_comp = 14; rs_rh[ctlr].rae = 0;
rs_df10[ctlr].status = 0;
rs_attn[ctlr] = 0;
rs_rae[ctlr] = 0;
} }
return SCPE_OK; return SCPE_OK;
} }
@ -848,16 +615,16 @@ t_stat
rs_boot(int32 unit_num, DEVICE * rptr) rs_boot(int32 unit_num, DEVICE * rptr)
{ {
UNIT *uptr = &rptr->units[unit_num]; UNIT *uptr = &rptr->units[unit_num];
int ctlr = GET_CNTRL(uptr->flags); int ctlr = GET_CNTRL_RH(uptr->flags);
struct rh_if *rhc;
DEVICE *dptr; DEVICE *dptr;
struct df10 *df;
uint32 addr; uint32 addr;
uint32 ptr = 0; uint32 ptr = 0;
uint64 word; uint64 word;
int wc; int wc;
df = &rs_df10[ctlr];
dptr = rs_devs[ctlr]; dptr = rs_devs[ctlr];
rhc = &rs_rh[ctlr];
(void)sim_fseek(uptr->fileref, 0, SEEK_SET); (void)sim_fseek(uptr->fileref, 0, SEEK_SET);
(void)sim_fread (&rs_buf[0][0], sizeof(uint64), RS_NUMWD, uptr->fileref); (void)sim_fread (&rs_buf[0][0], sizeof(uint64), RS_NUMWD, uptr->fileref);
uptr->CMD |= DS_VV; uptr->CMD |= DS_VV;
@ -875,9 +642,9 @@ rs_boot(int32 unit_num, DEVICE * rptr)
addr = rs_buf[0][ptr] & RMASK; addr = rs_buf[0][ptr] & RMASK;
wc = (rs_buf[0][ptr++] >> 18) & RMASK; wc = (rs_buf[0][ptr++] >> 18) & RMASK;
word = rs_buf[0][ptr++]; word = rs_buf[0][ptr++];
rs_reg[ctlr] = 040; rhc->reg = 040;
rs_drive[ctlr] = uptr - dptr->units; rhc->drive = uptr - dptr->units;
df->status |= CCW_COMP_1|PI_ENABLE; rhc->status |= CCW_COMP_1|PI_ENABLE;
PC = word & RMASK; PC = word & RMASK;
return SCPE_OK; return SCPE_OK;
@ -901,14 +668,19 @@ t_stat rs_attach (UNIT *uptr, CONST char *cptr)
if (rstr == 0) if (rstr == 0)
return SCPE_OK; return SCPE_OK;
dib = (DIB *) rstr->ctxt; dib = (DIB *) rstr->ctxt;
ctlr = dib->dev_num & 014; for (ctlr = 0; rh[ctlr].dev_num != 0; ctlr++) {
if (rh[ctlr].dev == rstr)
break;
}
if (uptr->flags & UNIT_WLK)
uptr->CMD |= DS_WRL;
if (sim_switches & SIM_SW_REST)
return SCPE_OK;
uptr->DA = 0; uptr->DA = 0;
uptr->CMD &= ~DS_VV; uptr->CMD &= ~DS_VV;
uptr->CMD |= DS_DPR|DS_MOL|DS_DRY; uptr->CMD |= DS_DPR|DS_MOL|DS_DRY;
if (uptr->flags & UNIT_WLK) rs_rh[ctlr].status |= PI_ENABLE;
uptr->CMD |= DS_WRL; set_interrupt(dib->dev_num, rs_rh[ctlr].status);
rs_df10[ctlr].status |= PI_ENABLE;
set_interrupt(dib->dev_num, rs_df10[ctlr].status);
return SCPE_OK; return SCPE_OK;
} }

View file

@ -1,9 +1,9 @@
/* ka10_sys.c: PDP-10 simulator interface /* kx10_sys.c: PDP-10 simulator interface
Derived from Bob Supnik's pdp10_sys.c Derived from Bob Supnik's pdp10_sys.c
Copyright (c) 2005-2009, Robert M Supnik Copyright (c) 2005-2009, Robert M Supnik
Copyright (c) 2011-2018, Richard Cornwell Copyright (c) 2011-2020, Richard Cornwell
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -42,11 +42,8 @@
sim_load binary loader sim_load binary loader
*/ */
#if KLB #if KL
char sim_name[] = "KL-10B"; char sim_name[] = "KL-10";
#endif
#if KLA
char sim_name[] = "KL-10A";
#endif #endif
#if KI #if KI
char sim_name[] = "KI-10"; char sim_name[] = "KI-10";
@ -68,6 +65,9 @@ DEVICE *sim_devices[] = {
#if PDP6 | KA | KI #if PDP6 | KA | KI
&cty_dev, &cty_dev,
#endif #endif
#if KL
&dte_dev,
#endif
#if (NUM_DEVS_PT > 0) #if (NUM_DEVS_PT > 0)
&ptp_dev, &ptp_dev,
&ptr_dev, &ptr_dev,
@ -75,6 +75,9 @@ DEVICE *sim_devices[] = {
#if (NUM_DEVS_LP > 0) #if (NUM_DEVS_LP > 0)
&lpt_dev, &lpt_dev,
#endif #endif
#if (NUM_DEVS_LP20 > 0)
&lp20_dev,
#endif
#if (NUM_DEVS_CR > 0) #if (NUM_DEVS_CR > 0)
&cr_dev, &cr_dev,
#endif #endif
@ -141,6 +144,9 @@ DEVICE *sim_devices[] = {
#if (NUM_DEVS_DC > 0) #if (NUM_DEVS_DC > 0)
&dc_dev, &dc_dev,
#endif #endif
#if (NUM_DEVS_TTY > 0)
&tty_dev,
#endif
#if (NUM_DEVS_DCS > 0) #if (NUM_DEVS_DCS > 0)
&dcs_dev, &dcs_dev,
#endif #endif
@ -155,10 +161,19 @@ DEVICE *sim_devices[] = {
#if (NUM_DEVS_WCNSLS > 0) #if (NUM_DEVS_WCNSLS > 0)
&wcnsls_dev, &wcnsls_dev,
#endif #endif
#if (NUM_DEVS_OCNSLS > 0)
&ocnsls_dev,
#endif
#endif
#if (NUM_DEVS_III > 0)
&iii_dev,
#endif #endif
#if NUM_DEVS_IMP > 0 #if NUM_DEVS_IMP > 0
&imp_dev, &imp_dev,
#endif #endif
#if NUM_DEVS_NIA > 0
&nia_dev,
#endif
#if NUM_DEVS_CH10 > 0 #if NUM_DEVS_CH10 > 0
&ch10_dev, &ch10_dev,
#endif #endif
@ -182,6 +197,9 @@ DEVICE *sim_devices[] = {
#if NUM_DEVS_AUXCPU > 0 #if NUM_DEVS_AUXCPU > 0
&auxcpu_dev, &auxcpu_dev,
#endif #endif
#if NUM_DEVS_SLAVE > 0
&slave_dev,
#endif
#if NUM_DEVS_DKB > 0 #if NUM_DEVS_DKB > 0
&dkb_dev, &dkb_dev,
#endif #endif
@ -197,7 +215,11 @@ DEVICE *sim_devices[] = {
const char *sim_stop_messages[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"HALT instruction", "HALT instruction",
"Breakpoint" "Breakpoint",
"Invalid access",
#if MAGIC_SWITCH
"No magic"
#endif
}; };
/* Simulator debug controls */ /* Simulator debug controls */
@ -232,6 +254,7 @@ DEBTAB crd_debug[] = {
#define FMT_E 3 /* EXE */ #define FMT_E 3 /* EXE */
#define FMT_D 4 /* WAITS DMP */ #define FMT_D 4 /* WAITS DMP */
#define FMT_I 5 /* ITS SBLK */ #define FMT_I 5 /* ITS SBLK */
#define FMT_B 6 /* EXB format */
#define EXE_DIR 01776 /* EXE directory */ #define EXE_DIR 01776 /* EXE directory */
#define EXE_VEC 01775 /* EXE entry vec */ #define EXE_VEC 01775 /* EXE entry vec */
@ -510,18 +533,27 @@ return SCPE_OK;
} }
int get_word(FILE *fileref, uint64 *word) int get_word(FILE *fileref, uint64 *word, int ftype)
{ {
char cbuf[5]; char cbuf[5];
if (sim_fread(cbuf, 1, 5, fileref) != 5) if (sim_fread(cbuf, 1, 5, fileref) != 5)
return 1; return 1;
*word = ((uint64)(cbuf[0]) << 29) | if (ftype) {
((uint64)(cbuf[1]) << 22) | *word = ((uint64)(cbuf[0] & 0177) << 29) |
((uint64)(cbuf[2]) << 15) | ((uint64)(cbuf[1] & 0177) << 22) |
((uint64)(cbuf[3]) << 8) | ((uint64)(cbuf[2] & 0177) << 15) |
((uint64)(cbuf[4] & 0177) << 1) | ((uint64)(cbuf[3] & 0177) << 8) |
((uint64)(cbuf[4] & 0200) >> 7); ((uint64)(cbuf[4] & 0177) << 1);
if (cbuf[4] & 0200)
*word |= 1;
} else {
*word = ((uint64)(cbuf[0] & 0377) << 28) |
((uint64)(cbuf[1] & 0377) << 20) |
((uint64)(cbuf[2] & 0377) << 12) |
((uint64)(cbuf[3] & 0377) << 4) |
(uint64)(cbuf[4] & 017);
}
return 0; return 0;
} }
@ -538,14 +570,14 @@ int get_word(FILE *fileref, uint64 *word)
JRST start JRST start
*/ */
t_stat load_sav (FILE *fileref) t_stat load_sav (FILE *fileref, int ftype)
{ {
uint64 data; uint64 data;
uint32 pa; uint32 pa;
int32 wc; int32 wc;
for ( ;; ) { /* loop */ for ( ;; ) { /* loop */
if (get_word(fileref, &data)) if (get_word(fileref, &data, ftype))
return SCPE_OK; return SCPE_OK;
wc = (int32)(data >> 18); wc = (int32)(data >> 18);
pa = (uint32) (data & RMASK); pa = (uint32) (data & RMASK);
@ -559,7 +591,7 @@ t_stat load_sav (FILE *fileref)
pa &= RMASK; pa &= RMASK;
wc++; wc++;
wc &= RMASK; wc &= RMASK;
if (get_word(fileref, &data)) if (get_word(fileref, &data, ftype))
return SCPE_FMT; return SCPE_FMT;
M[pa] = data; M[pa] = data;
} /* end if count*/ } /* end if count*/
@ -594,7 +626,7 @@ t_stat load_sav (FILE *fileref)
#define PAG_V_PN 9 #define PAG_V_PN 9
#define DIRSIZ (2 * PAG_SIZE) #define DIRSIZ (2 * PAG_SIZE)
t_stat load_exe (FILE *fileref) t_stat load_exe (FILE *fileref, int ftype)
{ {
uint64 data, dirbuf[DIRSIZ], pagbuf[PAG_SIZE], entbuf[2]; uint64 data, dirbuf[DIRSIZ], pagbuf[PAG_SIZE], entbuf[2];
int32 ndir, entvec, i, j, k, cont, bsz, bty, rpt, wc; int32 ndir, entvec, i, j, k, cont, bsz, bty, rpt, wc;
@ -604,8 +636,9 @@ uint32 ma;
ndir = entvec = 0; /* no dir, entvec */ ndir = entvec = 0; /* no dir, entvec */
cont = 1; cont = 1;
do { do {
wc = sim_fread (&data, sizeof (uint64), 1, fileref);/* read blk hdr */
if (wc == 0) /* error? */ wc = get_word(fileref, &data, ftype);
if (wc != 0) /* error? */
return SCPE_FMT; return SCPE_FMT;
bsz = (int32) ((data & RMASK) - 1); /* get count */ bsz = (int32) ((data & RMASK) - 1); /* get count */
if (bsz < 0) /* zero? */ if (bsz < 0) /* zero? */
@ -616,9 +649,11 @@ do {
case EXE_DIR: /* directory */ case EXE_DIR: /* directory */
if (ndir != 0) /* got one */ if (ndir != 0) /* got one */
return SCPE_FMT; return SCPE_FMT;
ndir = sim_fread (dirbuf, sizeof (uint64), bsz, fileref); for (i = 0; i < bsz; i++) {
if (ndir < bsz) /* error */ if (get_word(fileref, &dirbuf[i], ftype))
return SCPE_FMT; return SCPE_FMT;
}
ndir = bsz;
break; break;
case EXE_PDV: /* optional */ case EXE_PDV: /* optional */
@ -628,9 +663,11 @@ do {
case EXE_VEC: /* entry vec */ case EXE_VEC: /* entry vec */
if (bsz != 2) /* must be 2 wds */ if (bsz != 2) /* must be 2 wds */
return SCPE_FMT; return SCPE_FMT;
entvec = sim_fread (entbuf, sizeof (uint64), bsz, fileref); for (i = 0; i < bsz; i++) {
if (entvec < 2) /* error? */ if (get_word(fileref, &entbuf[i], ftype))
return SCPE_FMT; return SCPE_FMT;
}
entvec = bsz;
cont = 0; /* stop */ cont = 0; /* stop */
break; break;
@ -651,10 +688,11 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */
rpt = ((int32) ((dirbuf[i + 1] >> 27) + 1)) & 0777; /* repeat count */ rpt = ((int32) ((dirbuf[i + 1] >> 27) + 1)) & 0777; /* repeat count */
for (j = 0; j < rpt; j++, mpage++) { /* loop thru rpts */ for (j = 0; j < rpt; j++, mpage++) { /* loop thru rpts */
if (fpage) { /* file pages? */ if (fpage) { /* file pages? */
(void)sim_fseek (fileref, (fpage << PAG_V_PN) * sizeof (uint64), SEEK_SET); (void)sim_fseek (fileref, (fpage << PAG_V_PN) * 5, SEEK_SET);
wc = sim_fread (pagbuf, sizeof (uint64), PAG_SIZE, fileref); for (k = 0; k < PAG_SIZE; k++) {
if (wc < PAG_SIZE) if (get_word(fileref, &pagbuf[k], ftype))
return SCPE_FMT; break;
}
fpage++; fpage++;
} }
ma = mpage << PAG_V_PN; /* mem addr */ ma = mpage << PAG_V_PN; /* mem addr */
@ -667,18 +705,103 @@ for (i = 0; i < ndir; i = i + 2) { /* loop thru dir */
} /* end directory */ } /* end directory */
if (entvec && entbuf[1]) if (entvec && entbuf[1])
PC = (int32) (entbuf[1] & RMASK); /* start addr */ PC = (int32) (entbuf[1] & RMASK); /* start addr */
else if (entvec == 0)
PC = (int32) (M[0120] & RMASK);
return SCPE_OK; return SCPE_OK;
} }
static int exb_pos = -1;
int get_exb_byte (FILE *fileref, int *byt, int ftype)
{
static uint64 word;
exb_pos++;
switch(exb_pos & 3) {
case 0: if (get_word(fileref, &word, ftype))
return 1;
*byt = ((word >> 18) & 0377);
break;
case 1: *byt = ((word >> 26) & 0377);
break;
case 2: *byt = ((word >> 0) & 0377);
break;
case 3: *byt = ((word >> 8) & 0377);
break;
}
return 0;
}
t_stat load_exb (FILE *fileref, int ftype)
{
int odd = 0;
int pos = 0;
int wc;
int byt;
uint64 word;
t_addr addr;
exb_pos = -1;
for ( ;; ) {
/* All records start on even byte */
if (odd && get_exb_byte (fileref, &byt, ftype))
return SCPE_FMT;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
wc = byt;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
wc |= byt << 8;
wc -= 4;
odd = wc & 1;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
addr = byt;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
addr |= byt << 8;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
addr |= byt << 16;
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
addr |= byt << 24;
/* Empty record gives start address */
if (wc == 0) {
PC = addr;
return SCPE_OK;
}
pos = 0;
for (; wc > 0; wc--, pos++) {
if (get_exb_byte(fileref, &byt, ftype))
return SCPE_FMT;
switch(pos) {
case 0: word = ((uint64)byt); break;
case 1: word |= ((uint64)byt) << 8; break;
case 2: word |= ((uint64)byt) << 16; break;
case 3: word |= ((uint64)byt) << 24; break;
case 4: word |= ((uint64)(byt & 017)) << 32;
M[addr++] = word;
pos = -1;
break;
}
}
}
return SCPE_FMT;
}
/* Master loader */ /* Master loader */
t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag) t_stat sim_load (FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
{ {
uint64 data; uint64 data;
int32 wc, fmt; int32 wc, fmt;
int ftype;
extern int32 sim_switches; extern int32 sim_switches;
fmt = 0; /* no fmt */ fmt = 0; /* no fmt */
ftype = 0;
if (sim_switches & SWMASK ('C')) /* -c? core dump */
ftype = 1;
if (sim_switches & SWMASK ('R')) /* -r? */ if (sim_switches & SWMASK ('R')) /* -r? */
fmt = FMT_R; fmt = FMT_R;
else if (sim_switches & SWMASK ('S')) /* -s? */ else if (sim_switches & SWMASK ('S')) /* -s? */
@ -689,12 +812,16 @@ else if (sim_switches & SWMASK ('D')) /* -d? */
fmt = FMT_D; fmt = FMT_D;
else if (sim_switches & SWMASK ('I')) /* -i? */ else if (sim_switches & SWMASK ('I')) /* -i? */
fmt = FMT_I; fmt = FMT_I;
else if (sim_switches & SWMASK ('B')) /* -b? */
fmt = FMT_B;
else if (match_ext (fnam, "RIM")) /* .RIM? */ else if (match_ext (fnam, "RIM")) /* .RIM? */
fmt = FMT_R; fmt = FMT_R;
else if (match_ext (fnam, "SAV")) /* .SAV? */ else if (match_ext (fnam, "SAV")) /* .SAV? */
fmt = FMT_S; fmt = FMT_S;
else if (match_ext (fnam, "EXE")) /* .EXE? */ else if (match_ext (fnam, "EXE")) /* .EXE? */
fmt = FMT_E; fmt = FMT_E;
else if (match_ext (fnam, "EXB")) /* .EXB? */
fmt = FMT_B;
else if (match_ext (fnam, "DMP")) /* .DMP? */ else if (match_ext (fnam, "DMP")) /* .DMP? */
fmt = FMT_D; fmt = FMT_D;
else if (match_ext (fnam, "BIN")) /* .BIN? */ else if (match_ext (fnam, "BIN")) /* .BIN? */
@ -716,16 +843,19 @@ switch (fmt) { /* case fmt */
return load_rim (fileref); return load_rim (fileref);
case FMT_S: /* SAV */ case FMT_S: /* SAV */
return load_sav (fileref); return load_sav (fileref, ftype);
case FMT_E: /* EXE */ case FMT_E: /* EXE */
return load_exe (fileref); return load_exe (fileref, ftype);
case FMT_D: /* DMP */ case FMT_D: /* DMP */
return load_dmp (fileref); return load_dmp (fileref);
case FMT_I: /* SBLK */ case FMT_I: /* SBLK */
return load_sblk (fileref); return load_sblk (fileref);
case FMT_B: /* EXB */
return load_exb (fileref, ftype);
} }
printf ("Can't determine load file format\n"); printf ("Can't determine load file format\n");
@ -759,13 +889,22 @@ static const char *opcode[] = {
"LUUO10", "LUUO11", "LUUO12", "LUUO13", "LUUO14", "LUUO15", "LUUO16", "LUUO17", "LUUO10", "LUUO11", "LUUO12", "LUUO13", "LUUO14", "LUUO15", "LUUO16", "LUUO17",
"LUUO20", "LUUO21", "LUUO22", "LUUO23", "LUUO24", "LUUO25", "LUUO26", "LUUO27", "LUUO20", "LUUO21", "LUUO22", "LUUO23", "LUUO24", "LUUO25", "LUUO26", "LUUO27",
"LUUO30", "LUUO31", "LUUO32", "LUUO33", "LUUO34", "LUUO35", "LUUO36", "LUUO37", "LUUO30", "LUUO31", "LUUO32", "LUUO33", "LUUO34", "LUUO35", "LUUO36", "LUUO37",
"MUUO40", "MUUO41", "MUUO42", "MUUO43", "MUUO44", "MUUO45", "MUUO46", "MUUO47", "CALL", "INITI", "MUUO42", "MUUO43", "MUUO44", "MUUO45", "MUUO46", "CALLI",
"MUUO50", "MUUO51", "MUUO52", "MUUO53", "MUUO54", "MUUO55", "MUUO56", "MUUO57", #if KL
"MUUO60", "MUUO61", "MUUO62", "MUUO63", "MUUO64", "MUUO65", "MUUO66", "MUUO67", "OPEN", "TTCALL", "PMOVE", "PMOVEM", "MUUO54", "RENAME", "IN", "OUT",
"MUUO70", "MUUO71", "MUUO72", "MUUO73", "MUUO74", "MUUO75", "MUUO76", "MUUO77", #else
"OPEN", "TTCALL", "MUUO52", "MUUO53", "MUUO54", "RENAME", "IN", "OUT",
#endif
"SETSTS", "STATO", "STATUS", "GETSTS", "INBUF", "OUTBUF", "INPUT", "OUTPUT",
"CLOSE", "RELEAS", "MTAPE", "UGETF", "USETI", "USETO", "LOOKUP", "ENTER",
"UJEN", "MUUO101", "MUUO102", "JSYS", "MUUO104", "MUUO105", "MUUO106", #if KL
"UJEN", "GFAD", "GFSB", "JSYS", "ADJSP", "GFMP", "GFDV ",
"DFAD", "DFSB", "DFMP", "DFDV", "DADD", "DSUB", "DMUL", "DDIV", "DFAD", "DFSB", "DFMP", "DFDV", "DADD", "DSUB", "DMUL", "DDIV",
#else
"UJEN", "MUUO101", "MUUO102", "JSYS", "MUUO104", "MUUO105", "MUUO106",
"DFAD", "DFSB", "DFMP", "DFDV", "MUUO114", "MUUO115", "MUUO116", "MUUO117",
#endif
"DMOVE", "DMOVN", "FIX", "EXTEND", "DMOVEM", "DMOVNM", "FIXR", "FLTR", "DMOVE", "DMOVN", "FIX", "EXTEND", "DMOVEM", "DMOVNM", "FIXR", "FLTR",
"UFA", "DFN", "FSC", "ADJBP", "ILDB", "LDB", "IDPB", "DPB", "UFA", "DFN", "FSC", "ADJBP", "ILDB", "LDB", "IDPB", "DPB",
"FAD", "FADL", "FADM", "FADB", "FADR", "FADRL", "FADRM", "FADRB", "FAD", "FADL", "FADM", "FADB", "FADR", "FADRL", "FADRM", "FADRB",

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,9 @@
Copyright (c) 2017 Richard Cornwell Copyright (c) 2017 Richard Cornwell
Based on PDP18B/pdp18b_dt.c by:
Copyright (c) 1993-2017, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation to deal in the Software without restriction, including without limitation
@ -19,6 +22,10 @@
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 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. 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.
Except as contained in this notice, the name of Richard Cornwell shall not be 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 used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Richard Cornwell. in this Software without prior written authorization from Richard Cornwell.
@ -228,6 +235,8 @@
#define DT_WRDTIM 15000 #define DT_WRDTIM 15000
#define WRITTEN u6
int32 dtc_dtsa = 0; /* status A */ int32 dtc_dtsa = 0; /* status A */
int32 dtc_dtsb = 0; /* status B */ int32 dtc_dtsb = 0; /* status B */
int dtc_dct = 0; int dtc_dct = 0;
@ -239,6 +248,7 @@ t_stat dtc_set_dct (UNIT *, int32, CONST char *, void *);
t_stat dtc_show_dct (FILE *, UNIT *, int32, CONST void *); t_stat dtc_show_dct (FILE *, UNIT *, int32, CONST void *);
t_stat dtc_reset (DEVICE *dptr); t_stat dtc_reset (DEVICE *dptr);
t_stat dtc_attach (UNIT *uptr, CONST char *cptr); t_stat dtc_attach (UNIT *uptr, CONST char *cptr);
void dtc_flush (UNIT *uptr);
t_stat dtc_detach (UNIT *uptr); t_stat dtc_detach (UNIT *uptr);
/* DT data structures /* DT data structures
@ -495,7 +505,6 @@ dtc_svc (UNIT *uptr)
case DTC_FEND: /* Tape in endzone */ case DTC_FEND: /* Tape in endzone */
/* Set stop */ /* Set stop */
sim_debug(DEBUG_DETAIL, &dtc_dev, "DTC %o rev forward end\n", u); sim_debug(DEBUG_DETAIL, &dtc_dev, "DTC %o rev forward end\n", u);
uptr->u6 = 0;
dtc_dtsb |= DTB_EOT|DTB_NULL; dtc_dtsb |= DTB_EOT|DTB_NULL;
dtc_dtsb &= ~(DTB_REQ|DTB_ACT); dtc_dtsb &= ~(DTB_REQ|DTB_ACT);
if (uptr->CMD & DTC_ETF) if (uptr->CMD & DTC_ETF)
@ -607,7 +616,6 @@ dtc_svc (UNIT *uptr)
uptr->DSTATE &= ~(DTC_M_WORD << DTC_V_WORD); uptr->DSTATE &= ~(DTC_M_WORD << DTC_V_WORD);
uptr->DSTATE |= (word - 1) << DTC_V_WORD; uptr->DSTATE |= (word - 1) << DTC_V_WORD;
} }
uptr->u6-=2;
if ((dtc_dtsb & DTB_DLY) || (dtc_dtsb & DTB_ACT) == 0) if ((dtc_dtsb & DTB_DLY) || (dtc_dtsb & DTB_ACT) == 0)
break; break;
switch (DTC_GETFNC(uptr->CMD)) { switch (DTC_GETFNC(uptr->CMD)) {
@ -636,6 +644,7 @@ dtc_svc (UNIT *uptr)
} }
fbuf[off] = (data >> 18) & RMASK; fbuf[off] = (data >> 18) & RMASK;
fbuf[off+1] = data & RMASK; fbuf[off+1] = data & RMASK;
uptr->WRITTEN = 1;
uptr->hwmark = uptr->capac; uptr->hwmark = uptr->capac;
break; break;
} }
@ -749,7 +758,6 @@ dtc_svc (UNIT *uptr)
sim_debug(DEBUG_DETAIL, &dtc_dev, "DTC %o forward end\n", u); sim_debug(DEBUG_DETAIL, &dtc_dev, "DTC %o forward end\n", u);
/* Move to first block */ /* Move to first block */
uptr->DSTATE = DTC_FBLK | (uptr->DSTATE & DTC_MOTMASK); uptr->DSTATE = DTC_FBLK | (uptr->DSTATE & DTC_MOTMASK);
uptr->u6 = 0;
break; break;
case DTC_FBLK: /* In forward block number */ case DTC_FBLK: /* In forward block number */
@ -887,6 +895,7 @@ dtc_svc (UNIT *uptr)
dtc_dtsb |= DTB_DONE; dtc_dtsb |= DTB_DONE;
fbuf[off] = (data >> 18) & RMASK; fbuf[off] = (data >> 18) & RMASK;
fbuf[off+1] = data & RMASK; fbuf[off+1] = data & RMASK;
uptr->WRITTEN = 1;
uptr->hwmark = uptr->capac; uptr->hwmark = uptr->capac;
break; break;
case FNC_WMRK: case FNC_WMRK:
@ -1178,13 +1187,15 @@ dtc_attach (UNIT *uptr, CONST char *cptr)
return SCPE_MEM; return SCPE_MEM;
} }
fbuf = (uint32 *) uptr->filebuf; /* file buffer */ fbuf = (uint32 *) uptr->filebuf; /* file buffer */
printf ("%s%d: ", sim_dname (&dtc_dev), u); sim_printf ("%s%d: ", sim_dname (&dtc_dev), u);
if (uptr->flags & UNIT_8FMT) if (uptr->flags & UNIT_8FMT)
printf ("12b format"); sim_printf ("12b format");
else if (uptr->flags & UNIT_11FMT) else if (uptr->flags & UNIT_11FMT)
printf ("16b format"); sim_printf ("16b format");
else printf ("18b/36b format"); else sim_printf ("18b/36b format");
printf (", buffering file in memory\n"); sim_printf (", buffering file in memory\n");
uptr->WRITTEN = 0;
uptr->io_flush = dtc_flush;
if (uptr->flags & UNIT_8FMT) { /* 12b? */ if (uptr->flags & UNIT_8FMT) { /* 12b? */
for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ for (ba = 0; ba < uptr->capac; ) { /* loop thru file */
k = fxread (pdp8b, sizeof (uint16), D8_NBSIZE, uptr->fileref); k = fxread (pdp8b, sizeof (uint16), D8_NBSIZE, uptr->fileref);
@ -1201,8 +1212,7 @@ dtc_attach (UNIT *uptr, CONST char *cptr)
} }
} /* end file loop */ } /* end file loop */
uptr->hwmark = ba; uptr->hwmark = ba;
} /* end if */ } else if (uptr->flags & UNIT_11FMT) { /* 16b? */
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
for (ba = 0; ba < uptr->capac; ) { /* loop thru file */ for (ba = 0; ba < uptr->capac; ) { /* loop thru file */
k = fxread (pdp11b, sizeof (uint16), D18_BSIZE, uptr->fileref); k = fxread (pdp11b, sizeof (uint16), D18_BSIZE, uptr->fileref);
if (k == 0) if (k == 0)
@ -1213,8 +1223,7 @@ dtc_attach (UNIT *uptr, CONST char *cptr)
fbuf[ba++] = pdp11b[k]; fbuf[ba++] = pdp11b[k];
} }
uptr->hwmark = ba; uptr->hwmark = ba;
} /* end elif */ } else uptr->hwmark = fxread (uptr->filebuf, sizeof (uint32),
else uptr->hwmark = fxread (uptr->filebuf, sizeof (uint32),
uptr->capac, uptr->fileref); uptr->capac, uptr->fileref);
uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */ uptr->flags = uptr->flags | UNIT_BUF; /* set buf flag */
uptr->pos = DT_EZLIN; /* beyond leader */ uptr->pos = DT_EZLIN; /* beyond leader */
@ -1230,23 +1239,15 @@ dtc_attach (UNIT *uptr, CONST char *cptr)
Deallocate buffer Deallocate buffer
*/ */
t_stat void
dtc_detach (UNIT* uptr) dtc_flush (UNIT* uptr)
{ {
uint16 pdp8b[D8_NBSIZE]; uint16 pdp8b[D8_NBSIZE];
uint16 pdp11b[D18_BSIZE]; uint16 pdp11b[D18_BSIZE];
uint32 ba, k, *fbuf; uint32 ba, k, *fbuf;
int32 u = uptr - dtc_dev.units;
if (!(uptr->flags & UNIT_ATT)) if (uptr->WRITTEN && uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
return SCPE_OK;
if (sim_is_active (uptr)) {
sim_cancel (uptr);
uptr->CMD = uptr->pos = 0;
}
fbuf = (uint32 *) uptr->filebuf; /* file buffer */ fbuf = (uint32 *) uptr->filebuf; /* file buffer */
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
printf ("%s%d: writing buffer to file\n", sim_dname (&dtc_dev), u);
rewind (uptr->fileref); /* start of file */ rewind (uptr->fileref); /* start of file */
if (uptr->flags & UNIT_8FMT) { /* 12b? */ if (uptr->flags & UNIT_8FMT) { /* 12b? */
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
@ -1261,8 +1262,7 @@ dtc_detach (UNIT* uptr)
if (ferror (uptr->fileref)) if (ferror (uptr->fileref))
break; break;
} /* end loop file */ } /* end loop file */
} /* end if 12b */ } else if (uptr->flags & UNIT_11FMT) { /* 16b? */
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */ for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
for (k = 0; k < D18_BSIZE; k++) /* loop blk */ for (k = 0; k < D18_BSIZE; k++) /* loop blk */
pdp11b[k] = fbuf[ba++] & 0177777; pdp11b[k] = fbuf[ba++] & 0177777;
@ -1270,11 +1270,28 @@ dtc_detach (UNIT* uptr)
if (ferror (uptr->fileref)) if (ferror (uptr->fileref))
break; break;
} /* end loop file */ } /* end loop file */
} /* end if 16b */ } else fxwrite (uptr->filebuf, sizeof (uint32), /* write file */
else fxwrite (uptr->filebuf, sizeof (uint32), /* write file */
uptr->hwmark, uptr->fileref); uptr->hwmark, uptr->fileref);
if (ferror (uptr->fileref)) if (ferror (uptr->fileref))
perror ("I/O error"); sim_perror ("I/O error");
uptr->WRITTEN = 0;
} /* end if hwmark */
}
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)) {
sim_cancel (uptr);
uptr->CMD = uptr->pos = 0;
}
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
sim_printf ("%s%d: writing buffer to file\n", sim_dname (&dtc_dev), u);
dtc_flush (uptr);
} /* end if hwmark */ } /* end if hwmark */
free (uptr->filebuf); /* release buf */ free (uptr->filebuf); /* release buf */
uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */ uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */

329
PDP10/pdp6_slave.c Normal file
View file

@ -0,0 +1,329 @@
/* pdp6_slave.c: Slaved processor.
Copyright (c) 2018, 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 is a device which interfaces with a master processor through
shared memory and inter-processor interrupts.
*/
#include "kx10_defs.h"
#include "sim_tmxr.h"
#ifndef NUM_DEVS_SLAVE
#define NUM_DEVS_SLAVE 0
#endif
#if NUM_DEVS_SLAVE > 0
/* External bus interface. */
#define DATO 1
#define DATI 2
#define ACK 3
#define ERR 4
#define TIMEOUT 5
#define IRQ 6
/* Simulator time units for a Unibus memory cycle. */
#define SLAVE_MEM_CYCLE 100
/* Interprocessor interrupt device. */
#define SLAVE_DEVNUM 020
#define SLAVE_POLL 1000
#define PIA u3
#define STATUS u4
static t_stat slave_devio(uint32 dev, uint64 *data);
static t_stat slave_svc (UNIT *uptr);
static t_stat slave_reset (DEVICE *dptr);
static t_stat slave_attach (UNIT *uptr, CONST char *ptr);
static t_stat slave_detach (UNIT *uptr);
static t_stat slave_attach_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
static const char *slave_description (DEVICE *dptr);
static uint8 slave_valid[040000];
UNIT slave_unit[1] = {
{ UDATA (&slave_svc, UNIT_IDLE|UNIT_ATTABLE, 0), 1000 },
};
static REG slave_reg[] = {
{ DRDATAD (POLL, slave_unit[0].wait, 24, "poll interval"), PV_LEFT },
{BRDATA(BUFF, slave_valid, 8, 8, sizeof(slave_valid)), REG_HRO},
{ NULL }
};
static MTAB slave_mod[] = {
{ 0 }
};
#define DEBUG_TRC 0x0000400
static DEBTAB slave_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"},
{0},
};
DEVICE slave_dev = {
"SLAVE", slave_unit, slave_reg, slave_mod,
1, 8, 16, 2, 8, 16,
NULL, /* examine */
NULL, /* deposit */
&slave_reset, /* reset */
NULL, /* boot */
slave_attach, /* attach */
slave_detach, /* detach */
NULL, /* context */
DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_MUX,
DEBUG_CMD, /* debug control */
slave_debug, /* debug flags */
NULL, /* memory size chage */
NULL, /* logical name */
NULL, /* help */
&slave_attach_help, /* attach help */
NULL, /* help context */
&slave_description, /* description */
};
static TMLN slave_ldsc; /* line descriptor */
static TMXR slave_desc = { 1, 0, 0, &slave_ldsc }; /* mux descriptor */
static t_stat slave_reset (DEVICE *dptr)
{
sim_debug(DEBUG_TRC, dptr, "slave_reset()\n");
slave_unit[0].flags |= UNIT_ATTABLE | UNIT_IDLE;
slave_desc.packet = TRUE;
slave_desc.notelnet = TRUE;
slave_desc.buffered = 2048;
if (slave_unit[0].flags & UNIT_ATT)
sim_activate (&slave_unit[0], 1000);
else
sim_cancel (&slave_unit[0]);
return SCPE_OK;
}
static t_stat slave_attach (UNIT *uptr, CONST char *cptr)
{
t_stat r;
if (!cptr || !*cptr)
return SCPE_ARG;
if (!(uptr->flags & UNIT_ATTABLE))
return SCPE_NOATT;
r = tmxr_attach_ex (&slave_desc, uptr, cptr, FALSE);
if (r != SCPE_OK) /* error? */
return r;
sim_debug(DEBUG_TRC, &slave_dev, "activate connection\n");
sim_activate (uptr, 10); /* start poll */
return SCPE_OK;
}
static t_stat slave_detach (UNIT *uptr)
{
t_stat r;
if (!(uptr->flags & UNIT_ATT))
return SCPE_OK;
sim_cancel (uptr);
r = tmxr_detach (&slave_desc, uptr);
uptr->filename = NULL;
return r;
}
static int error (const char *message)
{
sim_debug (DEBUG_TRC, &slave_dev, "%s\r\n", message);
sim_debug (DEBUG_TRC, &slave_dev, "CLOSE\r\n");
slave_ldsc.rcve = 0;
tmxr_reset_ln (&slave_ldsc);
return -1;
}
static void build (uint8 *request, uint8 octet)
{
request[0]++;
request[request[0]] = octet & 0377;
}
static t_stat process_request (UNIT *uptr, const uint8 *request, size_t size)
{
uint8 response[12];
t_addr address;
uint64 data;
t_stat stat;
if (size == 0)
return SCPE_OK;
if (size > 9)
return error ("Malformed transaction");
sim_debug(DEBUG_CMD, &slave_dev, "got packet\n");
memset (response, 0, sizeof response);
switch (request[0]) {
case DATI:
address = request[1] + (request[2] << 8) + (request[3] << 16);
if (address < MEMSIZE) {
data = M[address];
build (response, ACK);
build (response, (uint8)(data & 0xff));
build (response, (uint8)((data >> 8)) & 0xff);
build (response, (uint8)((data >> 16) & 0xff));
build (response, (uint8)((data >> 24) & 0xff));
build (response, (uint8)((data >> 32) & 0xff));
sim_debug(DEBUG_DATAIO, &slave_dev, "DATI %06o -> %012llo\n",
address, data);
} else {
build (response, ERR);
sim_debug(DEBUG_DATAIO, &slave_dev, "DATI %06o -> NXM\n", address);
}
break;
case DATO:
address = request[1] + (request[2] << 8) + (request[3] << 16);
if (address < MEMSIZE) {
data = request[4];
data |= ((uint64)request[5]) << 8;
data |= ((uint64)request[6]) << 16;
data |= ((uint64)request[7]) << 24;
data |= ((uint64)request[8]) << 32;
M[address] = data;
build (response, ACK);
sim_debug(DEBUG_DATAIO, &slave_dev, "DATO %06o <- %012llo\n",
address, data);
} else {
build (response, ERR);
sim_debug(DEBUG_DATAIO, &slave_dev, "DATO %06o -> NXM\n", address);
}
break;
case ACK:
break;
case IRQ:
uptr->STATUS |= 010;
set_interrupt(SLAVE_DEVNUM, uptr->PIA);
build (response, ACK);
sim_debug(DEBUG_DATAIO, &slave_dev, "IRQ\n");
break;
default:
return error ("Malformed transaction");
}
stat = tmxr_put_packet_ln (&slave_ldsc, response + 1, (size_t)response[0]);
if (stat != SCPE_OK)
return error ("Write error in transaction");
return stat;
}
static t_stat slave_svc (UNIT *uptr)
{
const uint8 *slave_request;
size_t size;
if (tmxr_poll_conn(&slave_desc) >= 0) {
sim_debug(DEBUG_CMD, &slave_dev, "got connection\n");
slave_ldsc.rcve = 1;
memset(&slave_valid[0], 0, sizeof(slave_valid));
uptr->wait = SLAVE_POLL;
}
tmxr_poll_rx (&slave_desc);
if (slave_ldsc.rcve && !slave_ldsc.conn) {
slave_ldsc.rcve = 0;
tmxr_reset_ln (&slave_ldsc);
sim_debug(DEBUG_CMD, &slave_dev, "reset\n");
}
if (tmxr_get_packet_ln (&slave_ldsc, &slave_request, &size) == SCPE_OK)
process_request (uptr, slave_request, size);
sim_clock_coschedule (uptr, uptr->wait);
return SCPE_OK;
}
static t_stat slave_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);
return SCPE_OK;
}
static const char *slave_description (DEVICE *dptr)
{
return "Auxiliary processor";
}
t_stat slave_devio(uint32 dev, uint64 *data)
{
DEVICE *dptr = &slave_dev;
UNIT *uptr = &slave_unit[0];
switch(dev & 03) {
case CONO:
sim_debug(DEBUG_CONO, &slave_dev, "CONO %012llo\n", *data);
uptr->PIA = *data & 7;
if (*data & 010)
{
// Clear interrupt from the PDP-10.
uptr->STATUS &= ~010;
clr_interrupt(SLAVE_DEVNUM);
}
#if 0
if (*data & 020)
slave_interrupt ();
#endif
break;
case CONI:
*data = (uptr->STATUS & 010) | uptr->PIA;
sim_debug(DEBUG_CONI, &slave_dev, "CONI %012llo\n", *data);
break;
case DATAI:
*data = 0;
sim_debug(DEBUG_CONI, &slave_dev, "DATAI %012llo\n", *data);
break;
case DATAO:
sim_debug(DEBUG_CONI, &slave_dev, "DATAO %012llo\n", *data);
break;
}
return SCPE_OK;
}
#endif

View file

@ -82,7 +82,7 @@
#### Richard Cornwell has implemented the IBM 701, IBM 704, IBM 7010/1410, IBM 7070/7074, IBM 7080/702/705/7053 and IBM 7090/7094/709/704 simulators. #### Richard Cornwell has implemented the IBM 701, IBM 704, IBM 7010/1410, IBM 7070/7074, IBM 7080/702/705/7053 and IBM 7090/7094/709/704 simulators.
#### Richard Cornwell has implemented the PDP6, PDP10-KA, and PDP10-KI simulators. #### Richard Cornwell has implemented the PDP6, PDP10-KA, PDP10-KI and PDP10-KL simulators.
#### Dave Bryan has implemented an HP-3000 Series III simulator. #### Dave Bryan has implemented an HP-3000 Series III simulator.
@ -229,7 +229,7 @@ Host platforms which have libSDL2 available can leverage this functionality.
RAW Disk Access (including CDROM) RAW Disk Access (including CDROM)
Virtual Disk Container files, including differencing disks Virtual Disk Container files, including differencing disks
File System type detection to accurately autosize disks. File System type detection to accurately autosize disks.
Recognized file systems are: DEC ODS1, DEC ODS2, DEC RT11, Ultrix Partitions Recognized file systems are: DEC ODS1, DEC ODS2, DEC RT11, DEC RSX11, Ultrix Partitions
#### Tape Extensions #### Tape Extensions
AWS format tape support AWS format tape support
@ -304,6 +304,9 @@ The following extensions to the SCP command language without affecting prior beh
Restores the default CTRL+C behavior for the Restores the default CTRL+C behavior for the
currently running command procedure. currently running command procedure.
DO <stdin>
Invokes a nested DO command with input from the
running console.
Error traps can be taken for any command which returns a status other than SCPE_STEP, SCPE_OK, and SCPE_EXIT. Error traps can be taken for any command which returns a status other than SCPE_STEP, SCPE_OK, and SCPE_EXIT.
@ -541,6 +544,7 @@ Different Linux distributions have different package management systems:
Ubuntu: Ubuntu:
# apt-get install libpcap-dev # apt-get install libpcap-dev
# apt-get install libpcre3-dev
# apt-get install vde2 # apt-get install vde2
# apt-get install libsdl2 # apt-get install libsdl2
# apt-get install libsdl2_ttf # apt-get install libsdl2_ttf

View file

@ -213,6 +213,10 @@
RelativePath="..\PDP10\ka10_dpk.c" RelativePath="..\PDP10\ka10_dpk.c"
> >
</File> </File>
<File
RelativePath="..\PDP10\ka10_iii.c"
>
</File>
<File <File
RelativePath="..\PDP10\ka10_imx.c" RelativePath="..\PDP10\ka10_imx.c"
> >
@ -265,6 +269,10 @@
RelativePath="..\PDP10\kx10_df.c" RelativePath="..\PDP10\kx10_df.c"
> >
</File> </File>
<File
RelativePath="..\PDP10\kx10_disk.c"
>
</File>
<File <File
RelativePath="..\PDP10\kx10_dk.c" RelativePath="..\PDP10\kx10_dk.c"
> >
@ -301,6 +309,10 @@
RelativePath="..\PDP10\kx10_rc.c" RelativePath="..\PDP10\kx10_rc.c"
> >
</File> </File>
<File
RelativePath="..\PDP10\kx10_rh.c"
>
</File>
<File <File
RelativePath="..\PDP10\kx10_rp.c" RelativePath="..\PDP10\kx10_rp.c"
> >
@ -419,6 +431,10 @@
RelativePath="..\display\display.h" RelativePath="..\display\display.h"
> >
</File> </File>
<File
RelativePath="..\display\iii.c"
>
</File>
<File <File
RelativePath="..\display\sim_ws.c" RelativePath="..\display\sim_ws.c"
> >
@ -601,10 +617,18 @@
Name="Header Files" Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc" Filter="h;hpp;hxx;hm;inl;inc"
> >
<File
RelativePath="..\display\iii.h"
>
</File>
<File <File
RelativePath="..\PDP10\kx10_defs.h" RelativePath="..\PDP10\kx10_defs.h"
> >
</File> </File>
<File
RelativePath="..\PDP10\kx10_disk.h"
>
</File>
<File <File
RelativePath="..\scp.h" RelativePath="..\scp.h"
> >

View file

@ -217,6 +217,10 @@
RelativePath="..\PDP10\kx10_df.c" RelativePath="..\PDP10\kx10_df.c"
> >
</File> </File>
<File
RelativePath="..\PDP10\kx10_disk.c"
>
</File>
<File <File
RelativePath="..\PDP10\kx10_dk.c" RelativePath="..\PDP10\kx10_dk.c"
> >
@ -253,6 +257,10 @@
RelativePath="..\PDP10\kx10_rc.c" RelativePath="..\PDP10\kx10_rc.c"
> >
</File> </File>
<File
RelativePath="..\PDP10\kx10_rh.c"
>
</File>
<File <File
RelativePath="..\PDP10\kx10_rp.c" RelativePath="..\PDP10\kx10_rp.c"
> >
@ -537,6 +545,10 @@
RelativePath="..\PDP10\kx10_defs.h" RelativePath="..\PDP10\kx10_defs.h"
> >
</File> </File>
<File
RelativePath="..\PDP10\kx10_disk.h"
>
</File>
<File <File
RelativePath="..\scp.h" RelativePath="..\scp.h"
> >

View file

@ -0,0 +1,573 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="PDP10-KL"
ProjectGUID="{DA2AA7A0-B679-456B-B152-DEF40FAE5A7A}"
RootNamespace="PDP10-KL"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="..\BIN\NT\$(PlatformName)-$(ConfigurationName)"
IntermediateDirectory="..\BIN\NT\Project\simh\$(ProjectName)\$(PlatformName)-$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
Description="Check for required build dependencies &amp; git commit id"
CommandLine="Pre-Build-Event.cmd &quot;$(TargetDir)$(TargetName).exe&quot; LIBPCRE BUILD LIBSDL"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../PDP10;.;..;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KL=1;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC"
KeepComments="false"
BasicRuntimeChecks="0"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
ShowIncludes="false"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/fixed:no"
AdditionalDependencies="libcmtd.lib wsock32.lib winmm.lib Iphlpapi.lib pcrestaticd.lib zlib.lib dxguid.lib Imm32.lib Version.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="../../windows-build/lib/Debug/"
GenerateDebugInformation="true"
SubSystem="1"
StackReserveSize="10485760"
StackCommitSize="10485760"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
Description="Running Available Tests"
CommandLine="Post-Build-Event.cmd PDP10 &quot;$(TargetDir)$(TargetName).exe&quot;"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="..\BIN\NT\$(PlatformName)-$(ConfigurationName)"
IntermediateDirectory="..\BIN\NT\Project\simh\$(ProjectName)\$(PlatformName)-$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
Description="Check for required build dependencies &amp; git commit id"
CommandLine="Pre-Build-Event.cmd &quot;$(TargetDir)$(TargetName).exe&quot; LIBPCRE BUILD LIBSDL"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="../PDP10;.;..;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/include;;../../windows-build/include/SDL2"
PreprocessorDefinitions="USE_INT64;USE_SIM_CARD;KL=1;USE_SHARED;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG;SIM_BUILD_TOOL=simh-Visual-Studio-Project;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCRE_H;PCRE_STATIC"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
CompileAs="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="/fixed:no"
AdditionalDependencies="libcmtd.lib wsock32.lib winmm.lib Iphlpapi.lib pcrestaticd.lib zlib.lib dxguid.lib Imm32.lib Version.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="../../windows-build/lib/Release/"
GenerateDebugInformation="false"
SubSystem="1"
StackReserveSize="10485760"
StackCommitSize="10485760"
OptimizeReferences="2"
EnableCOMDATFolding="2"
LinkTimeCodeGeneration="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
Description="Running Available Tests"
CommandLine="Post-Build-Event.cmd PDP10 &quot;$(TargetDir)$(TargetName).exe&quot;"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
>
<File
RelativePath="..\PDP10\ka10_ch10.c"
>
</File>
<File
RelativePath="..\PDP10\ka10_pd.c"
>
</File>
<File
RelativePath="..\PDP10\kl10_fe.c"
>
</File>
<File
RelativePath="..\PDP10\kl10_nia.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_cpu.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_dc.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_df.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_disk.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_imp.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_lp.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_mt.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_rh.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_rp.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_rs.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_sys.c"
>
</File>
<File
RelativePath="..\PDP10\kx10_tu.c"
>
</File>
<File
RelativePath="..\..\windows-build\pthreads\pthread.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="HAVE_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;__CLEANUP_C;$(NOINHERIT)"
CompileAs="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
WholeProgramOptimization="false"
PreprocessorDefinitions="HAVE_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;__CLEANUP_C;$(NOINHERIT)"
CompileAs="1"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\scp.c"
>
</File>
<File
RelativePath="..\sim_card.c"
>
</File>
<File
RelativePath="..\sim_console.c"
>
</File>
<File
RelativePath="..\sim_disk.c"
>
</File>
<File
RelativePath="..\sim_ether.c"
>
</File>
<File
RelativePath="..\sim_fio.c"
>
</File>
<File
RelativePath="..\sim_serial.c"
>
</File>
<File
RelativePath="..\sim_sock.c"
>
</File>
<File
RelativePath="..\sim_tape.c"
>
</File>
<File
RelativePath="..\sim_timer.c"
>
</File>
<File
RelativePath="..\sim_tmxr.c"
>
</File>
<File
RelativePath="..\sim_video.c"
>
</File>
<Filter
Name="slirp"
>
<File
RelativePath="..\slirp\arp_table.c"
>
</File>
<File
RelativePath="..\slirp\bootp.c"
>
</File>
<File
RelativePath="..\slirp\bootp.h"
>
</File>
<File
RelativePath="..\slirp\cksum.c"
>
</File>
<File
RelativePath="..\slirp\debug.h"
>
</File>
<File
RelativePath="..\slirp\dnssearch.c"
>
</File>
<File
RelativePath="..\slirp_glue\glib_qemu_stubs.c"
>
</File>
<File
RelativePath="..\slirp\if.c"
>
</File>
<File
RelativePath="..\slirp\if.h"
>
</File>
<File
RelativePath="..\slirp\ip.h"
>
</File>
<File
RelativePath="..\slirp\ip_icmp.c"
>
</File>
<File
RelativePath="..\slirp\ip_icmp.h"
>
</File>
<File
RelativePath="..\slirp\ip_input.c"
>
</File>
<File
RelativePath="..\slirp\ip_output.c"
>
</File>
<File
RelativePath="..\slirp\libslirp.h"
>
</File>
<File
RelativePath="..\slirp\main.h"
>
</File>
<File
RelativePath="..\slirp\mbuf.c"
>
</File>
<File
RelativePath="..\slirp\mbuf.h"
>
</File>
<File
RelativePath="..\slirp\misc.c"
>
</File>
<File
RelativePath="..\slirp\misc.h"
>
</File>
<File
RelativePath="..\slirp\sbuf.c"
>
</File>
<File
RelativePath="..\slirp\sbuf.h"
>
</File>
<File
RelativePath="..\slirp_glue\sim_slirp.c"
>
</File>
<File
RelativePath="..\slirp\slirp.c"
>
</File>
<File
RelativePath="..\slirp\slirp.h"
>
</File>
<File
RelativePath="..\slirp\slirp_config.h"
>
</File>
<File
RelativePath="..\slirp\socket.c"
>
</File>
<File
RelativePath="..\slirp\socket.h"
>
</File>
<File
RelativePath="..\slirp\tcp.h"
>
</File>
<File
RelativePath="..\slirp\tcp_input.c"
>
</File>
<File
RelativePath="..\slirp\tcp_output.c"
>
</File>
<File
RelativePath="..\slirp\tcp_subr.c"
>
</File>
<File
RelativePath="..\slirp\tcp_timer.c"
>
</File>
<File
RelativePath="..\slirp\tcp_timer.h"
>
</File>
<File
RelativePath="..\slirp\tcp_var.h"
>
</File>
<File
RelativePath="..\slirp\tcpip.h"
>
</File>
<File
RelativePath="..\slirp\tftp.c"
>
</File>
<File
RelativePath="..\slirp\tftp.h"
>
</File>
<File
RelativePath="..\slirp\udp.c"
>
</File>
<File
RelativePath="..\slirp\udp.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc"
>
<File
RelativePath="..\PDP10\kx10_defs.h"
>
</File>
<File
RelativePath="..\PDP10\kx10_disk.h"
>
</File>
<File
RelativePath="..\scp.h"
>
</File>
<File
RelativePath="..\sim_card.h"
>
</File>
<File
RelativePath="..\sim_console.h"
>
</File>
<File
RelativePath="..\sim_defs.h"
>
</File>
<File
RelativePath="..\sim_disk.h"
>
</File>
<File
RelativePath="..\sim_ether.h"
>
</File>
<File
RelativePath="..\sim_fio.h"
>
</File>
<File
RelativePath="..\sim_rev.h"
>
</File>
<File
RelativePath="..\sim_serial.h"
>
</File>
<File
RelativePath="..\sim_sock.h"
>
</File>
<File
RelativePath="..\sim_tape.h"
>
</File>
<File
RelativePath="..\sim_timer.h"
>
</File>
<File
RelativePath="..\sim_tmxr.h"
>
</File>
<File
RelativePath="..\sim_video.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -245,6 +245,10 @@
RelativePath="..\PDP10\pdp6_mtc.c" RelativePath="..\PDP10\pdp6_mtc.c"
> >
</File> </File>
<File
RelativePath="..\PDP10\pdp6_slave.c"
>
</File>
<File <File
RelativePath="..\..\windows-build\pthreads\pthread.c" RelativePath="..\..\windows-build\pthreads\pthread.c"
> >

View file

@ -398,6 +398,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imds-810", "imds-810.vcproj
{D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8} {D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PDP10-KL", "PDP10-KL.vcproj", "{DA2AA7A0-B679-456B-B152-DEF40FAE5A7A}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
@ -724,6 +726,10 @@ Global
{0720F164-692E-4C07-BE69-41C4302062E5}.Debug|Win32.Build.0 = Debug|Win32 {0720F164-692E-4C07-BE69-41C4302062E5}.Debug|Win32.Build.0 = Debug|Win32
{0720F164-692E-4C07-BE69-41C4302062E5}.Release|Win32.ActiveCfg = Release|Win32 {0720F164-692E-4C07-BE69-41C4302062E5}.Release|Win32.ActiveCfg = Release|Win32
{0720F164-692E-4C07-BE69-41C4302062E5}.Release|Win32.Build.0 = Release|Win32 {0720F164-692E-4C07-BE69-41C4302062E5}.Release|Win32.Build.0 = Release|Win32
{DA2AA7A0-B679-456B-B152-DEF40FAE5A7A}.Debug|Win32.ActiveCfg = Debug|Win32
{DA2AA7A0-B679-456B-B152-DEF40FAE5A7A}.Debug|Win32.Build.0 = Debug|Win32
{DA2AA7A0-B679-456B-B152-DEF40FAE5A7A}.Release|Win32.ActiveCfg = Release|Win32
{DA2AA7A0-B679-456B-B152-DEF40FAE5A7A}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

Binary file not shown.

Binary file not shown.

BIN
doc/kl10_doc.doc Normal file

Binary file not shown.

View file

@ -587,6 +587,7 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin)
DISPLAYVT = ${DISPLAYD}/vt11.c DISPLAYVT = ${DISPLAYD}/vt11.c
DISPLAY340 = ${DISPLAYD}/type340.c DISPLAY340 = ${DISPLAYD}/type340.c
DISPLAYNG = ${DISPLAYD}/ng.c DISPLAYNG = ${DISPLAYD}/ng.c
DISPLAYIII = ${DISPLAYD}/iii.c
DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS) DISPLAY_OPT += -DUSE_DISPLAY $(VIDEO_CCDEFS) $(VIDEO_LDFLAGS)
$(info using libSDL2: $(call find_include,SDL2/SDL)) $(info using libSDL2: $(call find_include,SDL2/SDL))
ifeq (Darwin,$(OSTYPE)) ifeq (Darwin,$(OSTYPE))
@ -1994,7 +1995,7 @@ PDP6 = ${PDP6D}/kx10_cpu.c ${PDP6D}/kx10_sys.c ${PDP6D}/kx10_cty.c \
${PDP6D}/kx10_lp.c ${PDP6D}/kx10_pt.c ${PDP6D}/kx10_cr.c \ ${PDP6D}/kx10_lp.c ${PDP6D}/kx10_pt.c ${PDP6D}/kx10_cr.c \
${PDP6D}/kx10_cp.c ${PDP6D}/pdp6_dct.c ${PDP6D}/pdp6_dtc.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}/pdp6_mtc.c ${PDP6D}/pdp6_dsk.c ${PDP6D}/pdp6_dcs.c \
${PDP6D}/kx10_dpy.c ${DISPLAYL} ${DISPLAY340} ${PDP6D}/kx10_dpy.c ${PDP6D}/pdp6_slave.c ${DISPLAYL} ${DISPLAY340}
PDP6_OPT = -DPDP6=1 -DUSE_INT64 -I ${PDP6D} -DUSE_SIM_CARD ${DISPLAY_OPT} ${PDP6_DISPLAY_OPT} PDP6_OPT = -DPDP6=1 -DUSE_INT64 -I ${PDP6D} -DUSE_SIM_CARD ${DISPLAY_OPT} ${PDP6_DISPLAY_OPT}
KA10D = ${SIMHD}/PDP10 KA10D = ${SIMHD}/PDP10
@ -2007,13 +2008,14 @@ KA10 = ${KA10D}/kx10_cpu.c ${KA10D}/kx10_sys.c ${KA10D}/kx10_df.c \
${KA10D}/kx10_rp.c ${KA10D}/kx10_rc.c ${KA10D}/kx10_dt.c \ ${KA10D}/kx10_rp.c ${KA10D}/kx10_rc.c ${KA10D}/kx10_dt.c \
${KA10D}/kx10_dk.c ${KA10D}/kx10_cr.c ${KA10D}/kx10_cp.c \ ${KA10D}/kx10_dk.c ${KA10D}/kx10_cr.c ${KA10D}/kx10_cp.c \
${KA10D}/kx10_tu.c ${KA10D}/kx10_rs.c ${KA10D}/ka10_pd.c \ ${KA10D}/kx10_tu.c ${KA10D}/kx10_rs.c ${KA10D}/ka10_pd.c \
${KA10D}/kx10_imp.c ${KA10D}/ka10_tk10.c ${KA10D}/ka10_mty.c \ ${KA10D}/kx10_rh.c ${KA10D}/kx10_imp.c ${KA10D}/ka10_tk10.c \
${KA10D}/ka10_imx.c ${KA10D}/ka10_ch10.c ${KA10D}/ka10_stk.c \ ${KA10D}/ka10_mty.c ${KA10D}/ka10_imx.c ${KA10D}/ka10_ch10.c \
${KA10D}/ka10_ten11.c ${KA10D}/ka10_auxcpu.c ${KA10D}/ka10_pmp.c \ ${KA10D}/ka10_stk.c ${KA10D}/ka10_ten11.c ${KA10D}/ka10_auxcpu.c \
${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c ${KA10D}/pdp6_dtc.c \ $(KA10D)/ka10_pmp.c ${KA10D}/ka10_dkb.c ${KA10D}/pdp6_dct.c \
${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c ${KA10D}/pdp6_dcs.c \ ${KA10D}/pdp6_dtc.c ${KA10D}/pdp6_mtc.c ${KA10D}/pdp6_dsk.c \
${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c ${PDP10D}/ka10_ai.c \ ${KA10D}/pdp6_dcs.c ${KA10D}/ka10_dpk.c ${KA10D}/kx10_dpy.c \
${DISPLAYL} ${DISPLAY340} ${PDP10D}/ka10_ai.c ${KA10D}/ka10_iii.c ${KA10D}/kx10_disk.c \
${DISPLAYL} ${DISPLAY340} ${DISPLAYIII}
KA10_OPT = -DKA=1 -DUSE_INT64 -I ${KA10D} -DUSE_SIM_CARD ${NETWORK_OPT} ${DISPLAY_OPT} ${KA10_DISPLAY_OPT} KA10_OPT = -DKA=1 -DUSE_INT64 -I ${KA10D} -DUSE_SIM_CARD ${NETWORK_OPT} ${DISPLAY_OPT} ${KA10_DISPLAY_OPT}
ifneq (${PANDA_LIGHTS},) ifneq (${PANDA_LIGHTS},)
# ONLY for Panda display. # ONLY for Panda display.
@ -2029,10 +2031,11 @@ endif
KI10 = ${KI10D}/kx10_cpu.c ${KI10D}/kx10_sys.c ${KI10D}/kx10_df.c \ KI10 = ${KI10D}/kx10_cpu.c ${KI10D}/kx10_sys.c ${KI10D}/kx10_df.c \
${KI10D}/kx10_dp.c ${KI10D}/kx10_mt.c ${KI10D}/kx10_cty.c \ ${KI10D}/kx10_dp.c ${KI10D}/kx10_mt.c ${KI10D}/kx10_cty.c \
${KI10D}/kx10_lp.c ${KI10D}/kx10_pt.c ${KI10D}/kx10_dc.c \ ${KI10D}/kx10_lp.c ${KI10D}/kx10_pt.c ${KI10D}/kx10_dc.c \
${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c ${KI10D}/kx10_dt.c \ ${KI10D}/kx10_rh.c ${KI10D}/kx10_rp.c ${KI10D}/kx10_rc.c \
${KI10D}/kx10_dk.c ${KI10D}/kx10_cr.c ${KI10D}/kx10_cp.c \ ${KI10D}/kx10_dt.c ${KI10D}/kx10_dk.c ${KI10D}/kx10_cr.c \
${KI10D}/kx10_tu.c ${KI10D}/kx10_rs.c ${KI10D}/kx10_imp.c \ ${KI10D}/kx10_cp.c ${KI10D}/kx10_tu.c ${KI10D}/kx10_rs.c \
${KI10D}/kx10_dpy.c ${DISPLAYL} ${DISPLAY340} ${KI10D}/kx10_imp.c ${KI10D}/kx10_dpy.c ${KI10D}/kx10_disk.c \
${DISPLAYL} ${DISPLAY340}
KI10_OPT = -DKI=1 -DUSE_INT64 -I ${KI10D} -DUSE_SIM_CARD ${NETWORK_OPT} ${DISPLAY_OPT} ${KI10_DISPLAY_OPT} KI10_OPT = -DKI=1 -DUSE_INT64 -I ${KI10D} -DUSE_SIM_CARD ${NETWORK_OPT} ${DISPLAY_OPT} ${KI10_DISPLAY_OPT}
ifneq (${PANDA_LIGHTS},) ifneq (${PANDA_LIGHTS},)
# ONLY for Panda display. # ONLY for Panda display.
@ -2041,12 +2044,13 @@ KI10 += ${KA10D}/ka10_lights.c
KI10_LDFLAGS = -lusb-1.0 KI10_LDFLAGS = -lusb-1.0
endif endif
KL10D = PDP10 KL10D = ${SIMHD}/PDP10
KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \ KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \
${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rh.c \ ${KL10D}/kx10_mt.c ${KL10D}/kx10_dc.c ${KL10D}/kx10_rh.c \
${KL10D}/kx10_rp.c ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c \ ${KL10D}/kx10_rp.c ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c \
${KL10D}/kx10_imp.c ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c \ ${KL10D}/kx10_imp.c ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c \
${KL10D}/ka10_ch10.c ${KL10D}/kx10_lp.c ${KL10D}/ka10_ch10.c ${KL10D}/kx10_lp.c ${KL10D}/kl10_nia.c \
${KL10D}/kx10_disk.c
KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT} KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) -DUSE_SIM_CARD ${NETWORK_OPT}
ATT3B2D = ${SIMHD}/3B2 ATT3B2D = ${SIMHD}/3B2
@ -2121,7 +2125,7 @@ ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \
swtp6800mp-a swtp6800mp-a2 tx-0 ssem b5500 isys8010 isys8020 \ swtp6800mp-a swtp6800mp-a2 tx-0 ssem b5500 isys8010 isys8020 \
isys8030 isys8024 imds-210 imds-220 imds-225 imds-230 imds-800 imds-810 \ isys8030 isys8024 imds-210 imds-220 imds-225 imds-230 imds-800 imds-810 \
scelbi 3b2 i701 i704 i7010 i7070 i7080 i7090 \ scelbi 3b2 i701 i704 i7010 i7070 i7080 i7090 \
sigma uc15 pdp10-ka pdp10-ki pdp6 sigma uc15 pdp10-ka pdp10-ki pdp10-kl pdp6
all : ${ALL} all : ${ALL}
@ -2921,7 +2925,6 @@ endif
pdp10-kl : ${BIN}pdp10-kl${EXE} pdp10-kl : ${BIN}pdp10-kl${EXE}
${BIN}pdp10-kl${EXE} : ${KL10} ${SIM} ${BIN}pdp10-kl${EXE} : ${KL10} ${SIM}
#cmake:ignore-target
${MKDIRBIN} ${MKDIRBIN}
${CC} ${KL10} ${SIM} ${KL10_OPT} ${CC_OUTSPEC} ${LDFLAGS} ${CC} ${KL10} ${SIM} ${KL10_OPT} ${CC_OUTSPEC} ${LDFLAGS}
ifneq (,$(call find_test,${PDP10D},kl10)) ifneq (,$(call find_test,${PDP10D},kl10))