KA10: Release 3 of PDP10 simulators. KS10 support added.
Added KS10 support. CPU Redid instruction decode to improve performance Triple-I display cleanup. Normalized end of line to DOS/Unix. KL10 FE, Cleanup issues with TTY devices hanging simulator.. Fixed errors in RH20 device. RP and TU drives more independent of RH controller.
This commit is contained in:
parent
10c7e50f1c
commit
91aee9b39f
38 changed files with 15110 additions and 2218 deletions
|
@ -54,7 +54,6 @@
|
||||||
|
|
||||||
t_stat dkb_devio(uint32 dev, uint64 *data);
|
t_stat dkb_devio(uint32 dev, uint64 *data);
|
||||||
int dkb_keyboard (SIM_KEY_EVENT *kev);
|
int dkb_keyboard (SIM_KEY_EVENT *kev);
|
||||||
t_stat dkb_svc(UNIT *uptr);
|
|
||||||
t_stat dkb_reset(DEVICE *dptr);
|
t_stat dkb_reset(DEVICE *dptr);
|
||||||
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);
|
||||||
const char *dkb_description (DEVICE *dptr);
|
const char *dkb_description (DEVICE *dptr);
|
||||||
|
@ -65,7 +64,7 @@ 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) },
|
{UDATA (NULL, UNIT_IDLE, 0) },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -417,11 +416,6 @@ int dkb_keyboard (SIM_KEY_EVENT *kev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
t_stat dkb_svc( UNIT *uptr)
|
|
||||||
{
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
t_stat dkb_reset( DEVICE *dptr)
|
t_stat dkb_reset( DEVICE *dptr)
|
||||||
{
|
{
|
||||||
if ((dkb_dev.flags & DEV_DIS) == 0)
|
if ((dkb_dev.flags & DEV_DIS) == 0)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* ka10_iii.c: Triple III display processor.
|
/* ka10_iii.c: Triple-I display processor.
|
||||||
|
|
||||||
Copyright (c) 2019-2020, Richard Cornwell
|
Copyright (c) 2019-2020, Richard Cornwell
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@
|
||||||
|
|
||||||
#if NUM_DEVS_III > 0
|
#if NUM_DEVS_III > 0
|
||||||
#include "display/display.h"
|
#include "display/display.h"
|
||||||
#include "display/iii.h"
|
|
||||||
|
|
||||||
#define III_DEVNUM 0430
|
#define III_DEVNUM 0430
|
||||||
|
|
||||||
|
@ -98,6 +97,11 @@
|
||||||
#define CBRT_V 3
|
#define CBRT_V 3
|
||||||
#define CSIZE_V 0
|
#define CSIZE_V 0
|
||||||
|
|
||||||
|
#define MIN_X -512
|
||||||
|
#define MAX_X 512
|
||||||
|
#define MIN_Y -501
|
||||||
|
#define MAX_Y 522
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Character map.
|
* Character map.
|
||||||
* M(x,y) moves pointer to x,y.
|
* M(x,y) moves pointer to x,y.
|
||||||
|
@ -380,7 +384,8 @@ t_stat iii_devio(uint32 dev, uint64 *data) {
|
||||||
uptr->STATUS |= DATA_FLG;
|
uptr->STATUS |= DATA_FLG;
|
||||||
else {
|
else {
|
||||||
iii_instr = *data;
|
iii_instr = *data;
|
||||||
sim_activate(uptr, 10);
|
/* Process instruction right away to ensure MAR is updated. */
|
||||||
|
iii_svc(iii_unit);
|
||||||
}
|
}
|
||||||
sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAO %06o\n", dev, (uint32)*data);
|
sim_debug(DEBUG_DATAIO, &iii_dev, "III %03o DATAO %06o\n", dev, (uint32)*data);
|
||||||
break;
|
break;
|
||||||
|
@ -398,7 +403,7 @@ iii_svc (UNIT *uptr)
|
||||||
float ch_sz;
|
float ch_sz;
|
||||||
|
|
||||||
if (uptr->CYCLE > 20) {
|
if (uptr->CYCLE > 20) {
|
||||||
iii_cycle(300, 0);
|
display_age(300, 0);
|
||||||
uptr->CYCLE = 0;
|
uptr->CYCLE = 0;
|
||||||
} else {
|
} else {
|
||||||
uptr->CYCLE++;
|
uptr->CYCLE++;
|
||||||
|
@ -448,7 +453,7 @@ iii_svc (UNIT *uptr)
|
||||||
if (ch == '\t' || ch == 0)
|
if (ch == '\t' || ch == 0)
|
||||||
continue;
|
continue;
|
||||||
if (ch == '\r') {
|
if (ch == '\r') {
|
||||||
ox = -512;
|
ox = MIN_X;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (ch == '\n') {
|
if (ch == '\n') {
|
||||||
|
@ -493,7 +498,7 @@ iii_svc (UNIT *uptr)
|
||||||
nx, ny, sz, br);
|
nx, ny, sz, br);
|
||||||
nx += ox;
|
nx += ox;
|
||||||
ny += oy;
|
ny += oy;
|
||||||
if (nx < -512 || nx > 512 || ny < -512 || ny > 512)
|
if (nx < MIN_X || nx > MAX_X || ny < MIN_Y || ny > MAX_Y)
|
||||||
uptr->STATUS |= EDG_FBIT;
|
uptr->STATUS |= EDG_FBIT;
|
||||||
i = (int)((iii_instr >> 18) & 3);
|
i = (int)((iii_instr >> 18) & 3);
|
||||||
if ((i & 02) == 0 && (iii_sel & 04000) != 0) { /* Check if visible */
|
if ((i & 02) == 0 && (iii_sel & 04000) != 0) { /* Check if visible */
|
||||||
|
@ -516,7 +521,7 @@ iii_svc (UNIT *uptr)
|
||||||
/* Compute relative position. */
|
/* Compute relative position. */
|
||||||
nx += ox;
|
nx += ox;
|
||||||
ny += oy;
|
ny += oy;
|
||||||
if (nx < -512 || nx > 512 || ny < -512 || ny > 512)
|
if (nx < MIN_X || nx > MAX_X || ny < MIN_Y || ny > MAX_Y)
|
||||||
uptr->STATUS |= EDG_FBIT;
|
uptr->STATUS |= EDG_FBIT;
|
||||||
/* Check if visible */
|
/* Check if visible */
|
||||||
if ((iii_instr & 040) == 0 && (iii_sel & 04000) != 0) {
|
if ((iii_instr & 040) == 0 && (iii_sel & 04000) != 0) {
|
||||||
|
@ -561,7 +566,7 @@ iii_svc (UNIT *uptr)
|
||||||
if ((iii_instr & 0100) == 0) { /* Relative mode */
|
if ((iii_instr & 0100) == 0) { /* Relative mode */
|
||||||
nx += ox;
|
nx += ox;
|
||||||
ny += oy;
|
ny += oy;
|
||||||
if (nx < -512 || nx > 512 || ny < -512 || ny > 512)
|
if (nx < MIN_X || nx > MAX_X || ny < MIN_Y || ny > MAX_Y)
|
||||||
uptr->STATUS |= EDG_FBIT;
|
uptr->STATUS |= EDG_FBIT;
|
||||||
}
|
}
|
||||||
/* Check if visible */
|
/* Check if visible */
|
||||||
|
@ -637,7 +642,7 @@ t_stat iii_reset (DEVICE *dptr)
|
||||||
} else {
|
} else {
|
||||||
display_reset();
|
display_reset();
|
||||||
dptr->units[0].POS = 0;
|
dptr->units[0].POS = 0;
|
||||||
iii_init(dptr, 1);
|
display_init(DIS_III, 1, dptr);
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -647,20 +652,20 @@ t_stat iii_reset (DEVICE *dptr)
|
||||||
static void
|
static void
|
||||||
draw_point(int x, int y, int b, UNIT *uptr)
|
draw_point(int x, int y, int b, UNIT *uptr)
|
||||||
{
|
{
|
||||||
if (x < -512 || x > 512 || y < -512 || y > 512)
|
if (x < MIN_X || x > MAX_X || y < MIN_Y || y > MAX_X)
|
||||||
uptr->STATUS |= WRP_FBIT;
|
uptr->STATUS |= WRP_FBIT;
|
||||||
iii_point(x, y, b);
|
display_point(x - MIN_X, y - MIN_Y, b, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw a line between two points */
|
/* Draw a line between two points */
|
||||||
static void
|
static void
|
||||||
draw_line(int x1, int y1, int x2, int y2, int b, UNIT *uptr)
|
draw_line(int x1, int y1, int x2, int y2, int b, UNIT *uptr)
|
||||||
{
|
{
|
||||||
if (x1 < -512 || x1 > 512 || y1 < -512 || y1 > 512)
|
if (x1 < MIN_X || x1 > MAX_X || y1 < MIN_Y || y1 > MAX_Y)
|
||||||
uptr->STATUS |= WRP_FBIT;
|
uptr->STATUS |= WRP_FBIT;
|
||||||
if (x2 < -512 || x2 > 512 || y2 < -512 || y2 > 512)
|
if (x2 < MIN_X || x2 > MAX_X || y2 < MIN_Y || y2 > MAX_Y)
|
||||||
uptr->STATUS |= WRP_FBIT;
|
uptr->STATUS |= WRP_FBIT;
|
||||||
iii_draw_line(x1, y1, x2, y2, b);
|
display_line(x1 - MIN_X, y1 - MIN_Y, x2 - MIN_X, y2 - MIN_Y, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
t_stat iii_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||||
|
@ -670,6 +675,6 @@ return SCPE_OK;
|
||||||
|
|
||||||
const char *iii_description (DEVICE *dptr)
|
const char *iii_description (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
return "Triple III Display";
|
return "Triple-I Display";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -291,7 +291,7 @@ t_stat imx_set_channel (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (*tptr != 0) {
|
if (*tptr != 0) {
|
||||||
if (strcasecmp (tptr, "negate") != 0)
|
if (MATCH_CMD (tptr, "NEGATE"))
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
negate = 1;
|
negate = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,6 +171,9 @@ static t_stat mty_input_svc (UNIT *uptr)
|
||||||
|
|
||||||
tmxr_poll_rx (&mty_desc);
|
tmxr_poll_rx (&mty_desc);
|
||||||
|
|
||||||
|
if (status & MTY_DONE)
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
for (i = 0; i < MTY_LINES; i++) {
|
for (i = 0; i < MTY_LINES; i++) {
|
||||||
/* Round robin scan 32 lines. */
|
/* Round robin scan 32 lines. */
|
||||||
scan = (scan + 1) & 037;
|
scan = (scan + 1) & 037;
|
||||||
|
@ -200,6 +203,9 @@ static t_stat mty_output_svc (UNIT *uptr)
|
||||||
int i, ch;
|
int i, ch;
|
||||||
int32 txdone;
|
int32 txdone;
|
||||||
|
|
||||||
|
if (status & MTY_DONE)
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
for (i = 0; i < MTY_LINES; i++) {
|
for (i = 0; i < MTY_LINES; i++) {
|
||||||
/* Round robin scan 32 lines. */
|
/* Round robin scan 32 lines. */
|
||||||
scan = (scan + 1) & 037;
|
scan = (scan + 1) & 037;
|
||||||
|
@ -232,9 +238,11 @@ static t_stat mty_output_svc (UNIT *uptr)
|
||||||
|
|
||||||
tmxr_poll_tx (&mty_desc);
|
tmxr_poll_tx (&mty_desc);
|
||||||
|
|
||||||
/* SIMH will actually schedule this UNIT when output is due
|
if ((status & MTY_ODONE) == 0) {
|
||||||
according to the line speed. */
|
/* SIMH will actually schedule this UNIT when output is due
|
||||||
sim_activate_after (uptr, 1000000);
|
according to the line speed. */
|
||||||
|
sim_activate_after (uptr, 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -245,7 +253,7 @@ static t_stat mty_reset (DEVICE *dptr)
|
||||||
|
|
||||||
sim_debug(DEBUG_CMD, &mty_dev, "Reset\n");
|
sim_debug(DEBUG_CMD, &mty_dev, "Reset\n");
|
||||||
if (mty_unit->flags & UNIT_ATT) {
|
if (mty_unit->flags & UNIT_ATT) {
|
||||||
sim_activate (mty_unit, tmxr_poll);
|
sim_activate (&mty_unit[0], tmxr_poll);
|
||||||
sim_activate_after (&mty_unit[1], 100);
|
sim_activate_after (&mty_unit[1], 100);
|
||||||
} else {
|
} else {
|
||||||
sim_cancel (&mty_unit[0]);
|
sim_cancel (&mty_unit[0]);
|
||||||
|
|
|
@ -409,7 +409,7 @@ DEVICE pmp_dev = {
|
||||||
"PMP", pmp_unit, NULL, pmp_mod,
|
"PMP", pmp_unit, NULL, pmp_mod,
|
||||||
NUM_UNITS_PMP, 8, 15, 1, 8, 8,
|
NUM_UNITS_PMP, 8, 15, 1, 8, 8,
|
||||||
NULL, NULL, &pmp_reset, NULL, &pmp_attach, &pmp_detach,
|
NULL, NULL, &pmp_reset, NULL, &pmp_attach, &pmp_detach,
|
||||||
&pmp_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_DISK, 0, dev_debug,
|
&pmp_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, dev_debug,
|
||||||
NULL, NULL, &pmp_help, NULL, NULL, &pmp_description
|
NULL, NULL, &pmp_help, NULL, NULL, &pmp_description
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2212,8 +2212,8 @@ pmp_format(UNIT * uptr, int flag) {
|
||||||
uptr->CMD |= DK_ATTN;
|
uptr->CMD |= DK_ATTN;
|
||||||
pmp_statusb |= REQ_CH;
|
pmp_statusb |= REQ_CH;
|
||||||
sim_activate(uptr, 100);
|
sim_activate(uptr, 100);
|
||||||
fputc('\n', stderr);
|
|
||||||
fputc('\r', stderr);
|
fputc('\r', stderr);
|
||||||
|
fputc('\n', stderr);
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
} else
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2243,7 +2243,7 @@ pmp_attach(UNIT * uptr, CONST char *file)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
sim_messagef(SCPE_OK, "Drive %03x=%d %d %02x %d\n\r", addr,
|
sim_messagef(SCPE_OK, "Drive %03x=%d %d %02x %d\r\n", addr,
|
||||||
hdr.heads, hdr.tracksize, hdr.devtype, hdr.highcyl);
|
hdr.heads, hdr.tracksize, hdr.devtype, hdr.highcyl);
|
||||||
for (i = 0; disk_type[i].name != 0; i++) {
|
for (i = 0; disk_type[i].name != 0; i++) {
|
||||||
tsize = (uint32)((disk_type[i].bpt | 0x1ff) + 1);
|
tsize = (uint32)((disk_type[i].bpt | 0x1ff) + 1);
|
||||||
|
@ -2251,7 +2251,7 @@ pmp_attach(UNIT * uptr, CONST char *file)
|
||||||
hdr.heads == disk_type[i].heads && hdr.highcyl == disk_type[i].cyl) {
|
hdr.heads == disk_type[i].heads && hdr.highcyl == disk_type[i].cyl) {
|
||||||
if (GET_TYPE(uptr->flags) != i) {
|
if (GET_TYPE(uptr->flags) != i) {
|
||||||
/* Ask if we should change */
|
/* Ask if we should change */
|
||||||
fprintf(stderr, "Wrong type %s\n\r", disk_type[i].name);
|
fprintf(stderr, "Wrong type %s\r\n", disk_type[i].name);
|
||||||
if (!get_yn("Update dasd type? [N] ", FALSE)) {
|
if (!get_yn("Update dasd type? [N] ", FALSE)) {
|
||||||
detach_unit(uptr);
|
detach_unit(uptr);
|
||||||
return SCPE_FMT;
|
return SCPE_FMT;
|
||||||
|
@ -2367,7 +2367,7 @@ pmp_set_dev_addr(UNIT * uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
/* Update device entry */
|
/* Update device entry */
|
||||||
uptr->flags &= ~UNIT_ADDR(0xff);
|
uptr->flags &= ~UNIT_ADDR(0xff);
|
||||||
uptr->flags |= UNIT_ADDR(newdev);
|
uptr->flags |= UNIT_ADDR(newdev);
|
||||||
fprintf(stderr, "Set dev %x\n\r", GET_UADDR(uptr->flags));
|
fprintf(stderr, "Set dev %x\r\n", GET_UADDR(uptr->flags));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,6 +148,11 @@ static int stk_modifiers (SIM_KEY_EVENT *kev)
|
||||||
|
|
||||||
static int stk_keys (SIM_KEY_EVENT *kev)
|
static int stk_keys (SIM_KEY_EVENT *kev)
|
||||||
{
|
{
|
||||||
|
if (kev->state == SIM_KEYPRESS_UP && kev->key == SIM_KEY_F11) {
|
||||||
|
vid_set_fullscreen (!vid_is_fullscreen ());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (kev->state == SIM_KEYPRESS_UP)
|
if (kev->state == SIM_KEYPRESS_UP)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,12 @@
|
||||||
/* Rubin 10-11 pager. */
|
/* Rubin 10-11 pager. */
|
||||||
static uint64 ten11_pager[256];
|
static uint64 ten11_pager[256];
|
||||||
|
|
||||||
|
/* Physical address range of TEN11 moby. */
|
||||||
|
t_addr ten11_base = 03000000;
|
||||||
|
t_addr ten11_end = 04000000;
|
||||||
|
|
||||||
/* Physical address of 10-11 control page. */
|
/* Physical address of 10-11 control page. */
|
||||||
#define T11CPA 03776000
|
#define T11CPA 0776000 //Offset inside TEN11 moby.
|
||||||
|
|
||||||
/* Bits in a 10-11 page table entry. */
|
/* Bits in a 10-11 page table entry. */
|
||||||
#define T11VALID (0400000000000LL)
|
#define T11VALID (0400000000000LL)
|
||||||
|
@ -64,6 +68,8 @@ static t_stat ten11_svc (UNIT *uptr);
|
||||||
static t_stat ten11_reset (DEVICE *dptr);
|
static t_stat ten11_reset (DEVICE *dptr);
|
||||||
static t_stat ten11_attach (UNIT *uptr, CONST char *ptr);
|
static t_stat ten11_attach (UNIT *uptr, CONST char *ptr);
|
||||||
static t_stat ten11_detach (UNIT *uptr);
|
static t_stat ten11_detach (UNIT *uptr);
|
||||||
|
static t_stat ten11_set_base (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
static t_stat ten11_show_base (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||||
static t_stat ten11_attach_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
static t_stat ten11_attach_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
||||||
static const char *ten11_description (DEVICE *dptr);
|
static const char *ten11_description (DEVICE *dptr);
|
||||||
|
|
||||||
|
@ -77,6 +83,8 @@ static REG ten11_reg[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static MTAB ten11_mod[] = {
|
static MTAB ten11_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "base address", "BASE",
|
||||||
|
&ten11_set_base, &ten11_show_base },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -290,6 +298,8 @@ int ten11_read (t_addr addr, uint64 *data)
|
||||||
int offset = addr & 01777;
|
int offset = addr & 01777;
|
||||||
int word1, word2;
|
int word1, word2;
|
||||||
|
|
||||||
|
addr &= RMASK; //Address offset inside moby.
|
||||||
|
|
||||||
if (addr >= T11CPA) {
|
if (addr >= T11CPA) {
|
||||||
/* Accessing the control page. */
|
/* Accessing the control page. */
|
||||||
if (offset >= 0400) {
|
if (offset >= 0400) {
|
||||||
|
@ -370,6 +380,8 @@ int ten11_write (t_addr addr, uint64 data)
|
||||||
{
|
{
|
||||||
int offset = addr & 01777;
|
int offset = addr & 01777;
|
||||||
|
|
||||||
|
addr &= RMASK; //Address offset inside moby.
|
||||||
|
|
||||||
if (addr >= T11CPA) {
|
if (addr >= T11CPA) {
|
||||||
/* Accessing the control page. */
|
/* Accessing the control page. */
|
||||||
if (offset >= 0400) {
|
if (offset >= 0400) {
|
||||||
|
@ -413,4 +425,28 @@ int ten11_write (t_addr addr, uint64 data)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static t_stat ten11_set_base (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
t_stat r;
|
||||||
|
t_value x;
|
||||||
|
|
||||||
|
if (cptr == NULL || *cptr == 0)
|
||||||
|
return SCPE_ARG;
|
||||||
|
|
||||||
|
x = get_uint (cptr, 8, 03777777, &r);
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return SCPE_ARG;
|
||||||
|
|
||||||
|
ten11_base = (t_addr)(x&03777777);
|
||||||
|
/* The end of the TEN11 range is the start of the next moby. */
|
||||||
|
ten11_end = (ten11_base + 01000000) & LMASK;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static t_stat ten11_show_base (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||||
|
{
|
||||||
|
fprintf (st, "Base: %011o", ten11_base);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
130
PDP10/ka10_tv.c
Normal file
130
PDP10/ka10_tv.c
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
/* ka10_tv.c: Stanford TV camera and Spacewar buttons.
|
||||||
|
|
||||||
|
Copyright (c) 2021, Lars Brinkhoff
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
LARS BRINKHOFF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kx10_defs.h"
|
||||||
|
#include "sim_video.h"
|
||||||
|
|
||||||
|
#if NUM_DEVS_TV > 0
|
||||||
|
|
||||||
|
#define TV_DEVNUM 0404
|
||||||
|
|
||||||
|
#define JOY_MAX_UNITS 5
|
||||||
|
#define JOY_MAX_AXES 4
|
||||||
|
#define JOY_MAX_BUTTONS 4
|
||||||
|
|
||||||
|
#define JOY_TRIG 5000
|
||||||
|
|
||||||
|
#define ROTATE_AXIS 0
|
||||||
|
#define THRUSTER_AXIS 1
|
||||||
|
#define TORPEDO_BUTTON 0
|
||||||
|
#define HYPER_BUTTON 1
|
||||||
|
|
||||||
|
/* CONI bits. */
|
||||||
|
#define TPBIT 001LL /* Fire torpedo. */
|
||||||
|
#define THRUBT 002LL /* Thruster. */
|
||||||
|
#define ROTRBT 004LL /* Rotate right. */
|
||||||
|
#define ROTLBT 010LL /* Rotate left. */
|
||||||
|
#define HYPRBT 014LL /* Hyperspace = right + left. */
|
||||||
|
|
||||||
|
static t_stat tv_devio(uint32 dev, uint64 *data);
|
||||||
|
static t_stat tv_reset (DEVICE *dptr);
|
||||||
|
static const char *tv_description (DEVICE *dptr);
|
||||||
|
|
||||||
|
static int joy_axes[JOY_MAX_UNITS][JOY_MAX_AXES];
|
||||||
|
static int joy_buttons[JOY_MAX_UNITS][JOY_MAX_BUTTONS];
|
||||||
|
|
||||||
|
DIB tv_dib = { TV_DEVNUM, 1, &tv_devio, NULL };
|
||||||
|
|
||||||
|
DEVICE tv_dev = {
|
||||||
|
"TV", NULL, NULL, NULL,
|
||||||
|
0, 8, 0, 1, 8, 36,
|
||||||
|
NULL, NULL, &tv_reset, NULL, NULL, NULL,
|
||||||
|
&tv_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, dev_debug,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, &tv_description
|
||||||
|
};
|
||||||
|
|
||||||
|
static void tv_joy_motion(int which, int axis, int value)
|
||||||
|
{
|
||||||
|
if (which < JOY_MAX_UNITS && axis < JOY_MAX_AXES) {
|
||||||
|
joy_axes[which][axis] = value;
|
||||||
|
sim_debug (DEBUG_DETAIL, &tv_dev, "Joystick %d axid %d: value %d\n",
|
||||||
|
which, axis, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tv_joy_button(int which, int button, int state)
|
||||||
|
{
|
||||||
|
if (which < JOY_MAX_UNITS && button < JOY_MAX_BUTTONS) {
|
||||||
|
joy_buttons[which][button] = state;
|
||||||
|
sim_debug (DEBUG_DETAIL, &tv_dev, "Joystick %d button %d: state %d\n",
|
||||||
|
which, button, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64 tv_buttons (void)
|
||||||
|
{
|
||||||
|
uint64 buttons = 2; /* Needed for unknown reason! */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < JOY_MAX_UNITS; i++) {
|
||||||
|
if (joy_axes[i][ROTATE_AXIS] > JOY_TRIG)
|
||||||
|
buttons ^= ROTRBT << (4 * i);
|
||||||
|
else if (joy_axes[i][ROTATE_AXIS] < -JOY_TRIG)
|
||||||
|
buttons ^= ROTLBT << (4 * i);
|
||||||
|
if (joy_axes[i][THRUSTER_AXIS] < -JOY_TRIG)
|
||||||
|
buttons ^= THRUBT << (4 * i);
|
||||||
|
if (joy_buttons[i][TORPEDO_BUTTON])
|
||||||
|
buttons ^= TPBIT << (4 * i);
|
||||||
|
if (joy_buttons[i][HYPER_BUTTON])
|
||||||
|
buttons ^= HYPRBT << (4 * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat tv_devio(uint32 dev, uint64 *data)
|
||||||
|
{
|
||||||
|
switch(dev & 07) {
|
||||||
|
case CONI|4:
|
||||||
|
*data = tv_buttons ();
|
||||||
|
sim_debug (DEBUG_CONI, &tv_dev, "%07llo\n", *data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static t_stat tv_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
memset (joy_axes, 0, sizeof joy_axes);
|
||||||
|
memset (joy_buttons, 0, sizeof joy_buttons);
|
||||||
|
vid_register_gamepad_motion_callback (tv_joy_motion);
|
||||||
|
vid_register_gamepad_button_callback (tv_joy_button);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *tv_description (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
return "Stanford TV camera and Spacewar buttons";
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -236,7 +236,7 @@ struct _dte_queue {
|
||||||
uint16 data[258]; /* Data packet */
|
uint16 data[258]; /* Data packet */
|
||||||
uint16 sdev; /* Secondary device code */
|
uint16 sdev; /* Secondary device code */
|
||||||
uint16 sz; /* Byte size */
|
uint16 sz; /* Byte size */
|
||||||
} dte_in[32], dte_out[32];
|
} dte_in[16], dte_out[16];
|
||||||
|
|
||||||
int32 dte_in_ptr;
|
int32 dte_in_ptr;
|
||||||
int32 dte_in_cmd;
|
int32 dte_in_cmd;
|
||||||
|
@ -589,7 +589,7 @@ t_stat dte_devio(uint32 dev, uint64 *data) {
|
||||||
if (res & DTE_CO11DB) {
|
if (res & DTE_CO11DB) {
|
||||||
sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n");
|
sim_debug(DEBUG_CONO, &dte_dev, "CTY Ring 11 DB\n");
|
||||||
dte_unit[0].STATUS |= DTE_11DB;
|
dte_unit[0].STATUS |= DTE_11DB;
|
||||||
sim_activate(&dte_unit[0], 200);
|
sim_activate(&dte_unit[0], 100);
|
||||||
}
|
}
|
||||||
if (dte_unit[0].STATUS & (DTE_10DB|DTE_11DN|DTE_10DN|DTE_11ER|DTE_10ER))
|
if (dte_unit[0].STATUS & (DTE_10DB|DTE_11DN|DTE_10DN|DTE_11ER|DTE_10ER))
|
||||||
set_interrupt(dev, dte_unit[0].STATUS);
|
set_interrupt(dev, dte_unit[0].STATUS);
|
||||||
|
@ -660,6 +660,7 @@ void dte_second(UNIT *uptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Do it */
|
/* Do it */
|
||||||
sim_debug(DEBUG_DETAIL, &dte_dev, "CTY secondary %012llo\n", word);
|
sim_debug(DEBUG_DETAIL, &dte_dev, "CTY secondary %012llo\n", word);
|
||||||
switch(word & SEC_CMDMSK) {
|
switch(word & SEC_CMDMSK) {
|
||||||
|
@ -673,7 +674,8 @@ void dte_second(UNIT *uptr) {
|
||||||
if (ch != 0) {
|
if (ch != 0) {
|
||||||
cty_out.buff[cty_out.in_ptr] = ch & 0x7f;
|
cty_out.buff[cty_out.in_ptr] = ch & 0x7f;
|
||||||
inci(&cty_out);
|
inci(&cty_out);
|
||||||
sim_activate(&dte_unit[1], 200);
|
if (!sim_is_active(&dte_unit[1]))
|
||||||
|
sim_activate(&dte_unit[1], 200);
|
||||||
}
|
}
|
||||||
M[SEC_DTCHR + base] = ch;
|
M[SEC_DTCHR + base] = ch;
|
||||||
M[SEC_DTMTD + base] = FMASK;
|
M[SEC_DTMTD + base] = FMASK;
|
||||||
|
@ -683,6 +685,7 @@ void dte_second(UNIT *uptr) {
|
||||||
enter_pri:
|
enter_pri:
|
||||||
if (Mem_examine_word(0, 0, &word))
|
if (Mem_examine_word(0, 0, &word))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
dte_proc_num = (word >> 24) & 037;
|
dte_proc_num = (word >> 24) & 037;
|
||||||
dte_base = dte_proc_num + 1;
|
dte_base = dte_proc_num + 1;
|
||||||
dte_off = dte_base + (word & 0177777);
|
dte_off = dte_base + (word & 0177777);
|
||||||
|
@ -697,6 +700,7 @@ enter_pri:
|
||||||
M[SEC_DTCMD + base] = 0;
|
M[SEC_DTCMD + base] = 0;
|
||||||
M[SEC_DTFLG + base] = FMASK;
|
M[SEC_DTFLG + base] = FMASK;
|
||||||
uptr->STATUS &= ~DTE_11DB;
|
uptr->STATUS &= ~DTE_11DB;
|
||||||
|
tty_reset(&tty_dev);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case SEC_SETDDT: /* Read character from console */
|
case SEC_SETDDT: /* Read character from console */
|
||||||
|
@ -857,7 +861,7 @@ void dte_primary(UNIT *uptr) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Check if there is room for another packet */
|
/* Check if there is room for another packet */
|
||||||
if (((dte_in_ptr + 1) & 0x1f) == dte_in_cmd) {
|
if (((dte_in_ptr + 1) & 0xf) == dte_in_cmd) {
|
||||||
/* If not reschedule ourselves */
|
/* If not reschedule ourselves */
|
||||||
sim_activate(uptr, 100);
|
sim_activate(uptr, 100);
|
||||||
return;
|
return;
|
||||||
|
@ -886,6 +890,7 @@ error:
|
||||||
sim_debug(DEBUG_DETAIL, &dte_dev, "DTE: error %012llo\n", word);
|
sim_debug(DEBUG_DETAIL, &dte_dev, "DTE: error %012llo\n", word);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, &dte_dev, "DTE: status word %012llo\n", word);
|
||||||
|
|
||||||
if ((word & PRI_CMT_QP) == 0) {
|
if ((word & PRI_CMT_QP) == 0) {
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -895,7 +900,7 @@ error:
|
||||||
if ((word & PRI_CMT_IP) != 0) {
|
if ((word & PRI_CMT_IP) != 0) {
|
||||||
/* Transfer from 10 */
|
/* Transfer from 10 */
|
||||||
if ((uptr->STATUS & DTE_IND) == 0) {
|
if ((uptr->STATUS & DTE_IND) == 0) {
|
||||||
fprintf(stderr, "DTE out of sync\n\r");
|
fprintf(stderr, "DTE out of sync\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Get size of transfer */
|
/* Get size of transfer */
|
||||||
|
@ -920,7 +925,7 @@ error:
|
||||||
cnt--;
|
cnt--;
|
||||||
}
|
}
|
||||||
uptr->STATUS &= ~DTE_IND;
|
uptr->STATUS &= ~DTE_IND;
|
||||||
dte_in_ptr = (dte_in_ptr + 1) & 0x1f;
|
dte_in_ptr = (dte_in_ptr + 1) & 0xf;
|
||||||
} else {
|
} else {
|
||||||
/* Transfer from 10 */
|
/* Transfer from 10 */
|
||||||
in->dptr = 0;
|
in->dptr = 0;
|
||||||
|
@ -965,7 +970,7 @@ error:
|
||||||
if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word))
|
if (Mem_deposit_word(0, dte_dt10_off + PRI_CMTW_STS, &word))
|
||||||
goto error;
|
goto error;
|
||||||
} else {
|
} else {
|
||||||
dte_in_ptr = (dte_in_ptr + 1) & 0x1f;
|
dte_in_ptr = (dte_in_ptr + 1) & 0xf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
word &= ~PRI_CMT_TOT;
|
word &= ~PRI_CMT_TOT;
|
||||||
|
@ -988,7 +993,7 @@ dte_function(UNIT *uptr)
|
||||||
|
|
||||||
/* Check if queue is empty */
|
/* Check if queue is empty */
|
||||||
while (dte_in_cmd != dte_in_ptr) {
|
while (dte_in_cmd != dte_in_ptr) {
|
||||||
if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) {
|
if (((dte_out_res + 1) & 0xf) == dte_out_ptr) {
|
||||||
sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n",
|
sim_debug(DEBUG_DATA, &dte_dev, "DTE: func out full %d %d\n",
|
||||||
dte_out_res, dte_out_ptr);
|
dte_out_res, dte_out_ptr);
|
||||||
return;
|
return;
|
||||||
|
@ -1016,10 +1021,15 @@ dte_function(UNIT *uptr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRI_EM2TI: /* Replay to initial message. */
|
case PRI_EM2TI: /* Replay to initial message. */
|
||||||
case PRI_EMLBE: /* Acknowledge line */
|
|
||||||
/* Should never get these */
|
/* Should never get these */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PRI_EMLBE: /* Acknowledge line */
|
||||||
|
data1[0] = 0;
|
||||||
|
if (dte_queue(PRI_EMLBE, dev, 1, data1) == 0)
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
case PRI_EMHDR: /* Here is date and time */
|
case PRI_EMHDR: /* Here is date and time */
|
||||||
/* Ignore this function */
|
/* Ignore this function */
|
||||||
break;
|
break;
|
||||||
|
@ -1109,8 +1119,10 @@ cty:
|
||||||
data1[0] = 0;
|
data1[0] = 0;
|
||||||
if (cmd->sz > 8)
|
if (cmd->sz > 8)
|
||||||
cmd->dcnt += cmd->dcnt;
|
cmd->dcnt += cmd->dcnt;
|
||||||
|
|
||||||
while (cmd->dptr < cmd->dcnt) {
|
while (cmd->dptr < cmd->dcnt) {
|
||||||
ch = (int32)(cmd->data[cmd->dptr >> 1]);
|
ch = (int32)(cmd->data[cmd->dptr >> 1]);
|
||||||
|
sim_debug(DEBUG_DATA, &dte_dev,"CTY data %o\n", ch);
|
||||||
if ((cmd->dptr & 1) == 0)
|
if ((cmd->dptr & 1) == 0)
|
||||||
ch >>= 8;
|
ch >>= 8;
|
||||||
ch &= 0177;
|
ch &= 0177;
|
||||||
|
@ -1127,6 +1139,7 @@ cty:
|
||||||
if (cmd->dptr != cmd->dcnt)
|
if (cmd->dptr != cmd->dcnt)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRI_EMSNA: /* Send all (ttys) */
|
case PRI_EMSNA: /* Send all (ttys) */
|
||||||
|
@ -1398,7 +1411,7 @@ cty:
|
||||||
}
|
}
|
||||||
/* Mark command as finished */
|
/* Mark command as finished */
|
||||||
cmd->cnt = 0;
|
cmd->cnt = 0;
|
||||||
dte_in_cmd = (dte_in_cmd + 1) & 0x1F;
|
dte_in_cmd = (dte_in_cmd + 1) & 0xf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1482,7 +1495,7 @@ void dte_transfer(UNIT *uptr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out->cnt = 0;
|
out->cnt = 0;
|
||||||
dte_out_ptr = (dte_out_ptr + 1) & 0x1f;
|
dte_out_ptr = (dte_out_ptr + 1) & 0xf;
|
||||||
done:
|
done:
|
||||||
uptr->STATUS |= DTE_10DN;
|
uptr->STATUS |= DTE_10DN;
|
||||||
set_interrupt(DTE_DEVNUM, uptr->STATUS);
|
set_interrupt(DTE_DEVNUM, uptr->STATUS);
|
||||||
|
@ -1623,7 +1636,7 @@ dte_input()
|
||||||
/* While we have room for one more packet,
|
/* While we have room for one more packet,
|
||||||
* grab as much input as we can */
|
* grab as much input as we can */
|
||||||
for (ln = 0; ln < tty_desc.lines &&
|
for (ln = 0; ln < tty_desc.lines &&
|
||||||
((dte_out_res + 1) & 0x1f) != dte_out_ptr; ln++) {
|
((dte_out_res + 1) & 0xf) != dte_out_ptr; ln++) {
|
||||||
struct _buffer *itty = &tty_in[ln];
|
struct _buffer *itty = &tty_in[ln];
|
||||||
while (not_empty(itty)) {
|
while (not_empty(itty)) {
|
||||||
ch = itty->buff[itty->out_ptr];
|
ch = itty->buff[itty->out_ptr];
|
||||||
|
@ -1671,7 +1684,7 @@ dte_queue(int func, int dev, int dcnt, uint16 *data)
|
||||||
struct _dte_queue *out;
|
struct _dte_queue *out;
|
||||||
|
|
||||||
/* Check if room in queue for this packet. */
|
/* Check if room in queue for this packet. */
|
||||||
if (((dte_out_res + 1) & 0x1f) == dte_out_ptr) {
|
if (((dte_out_res + 1) & 0xf) == dte_out_ptr) {
|
||||||
sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d out full\n", dte_out_res, dte_out_ptr);
|
sim_debug(DEBUG_DATA, &dte_dev, "DTE: %d %d out full\n", dte_out_res, dte_out_ptr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1688,7 +1701,7 @@ dte_queue(int func, int dev, int dcnt, uint16 *data)
|
||||||
*dp++ = *data++;
|
*dp++ = *data++;
|
||||||
}
|
}
|
||||||
/* Advance pointer to next function */
|
/* Advance pointer to next function */
|
||||||
dte_out_res = (dte_out_res + 1) & 0x1f;
|
dte_out_res = (dte_out_res + 1) & 0xf;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1965,7 +1978,7 @@ lp20_printline(UNIT *uptr, int nl) {
|
||||||
int trim = 0;
|
int trim = 0;
|
||||||
|
|
||||||
/* Trim off trailing blanks */
|
/* Trim off trailing blanks */
|
||||||
while (uptr->COL >= 0 && lp20_buffer[uptr->COL - 1] == ' ') {
|
while (uptr->COL > 0 && lp20_buffer[uptr->COL - 1] == ' ') {
|
||||||
uptr->COL--;
|
uptr->COL--;
|
||||||
trim = 1;
|
trim = 1;
|
||||||
}
|
}
|
||||||
|
@ -2197,15 +2210,11 @@ lp20_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc)
|
||||||
t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||||
const char *cptr)
|
const char *cptr)
|
||||||
{
|
{
|
||||||
fprintf (st, "Line Printer (LPT)\n\n");
|
fprintf (st, "Line Printer (LP20)\n\n");
|
||||||
fprintf (st, "The line printer (LPT) writes data to a disk file. The POS register specifies\n");
|
fprintf (st, "The line printer (LP20) writes data to a disk file.\n");
|
||||||
fprintf (st, "the number of the next data item to be written. Thus, by changing POS, the\n");
|
|
||||||
fprintf (st, "user can backspace or advance the printer.\n");
|
|
||||||
fprintf (st, "The Line printer can be configured to any number of lines per page with the:\n");
|
fprintf (st, "The Line printer can be configured to any number of lines per page with the:\n");
|
||||||
fprintf (st, " sim> SET %s0 LINESPERPAGE=n\n\n", dptr->name);
|
fprintf (st, " sim> SET %s LINESPERPAGE=n\n\n", dptr->name);
|
||||||
fprintf (st, "The default is 66 lines per page.\n\n");
|
fprintf (st, "The default is 66 lines per page.\n\n");
|
||||||
fprintf (st, "The device address of the Line printer can be changed\n");
|
|
||||||
fprintf (st, " sim> SET %s0 DEV=n\n\n", dptr->name);
|
|
||||||
fprint_set_help (st, dptr);
|
fprint_set_help (st, dptr);
|
||||||
fprint_show_help (st, dptr);
|
fprint_show_help (st, dptr);
|
||||||
fprint_reg_help (st, dptr);
|
fprint_reg_help (st, dptr);
|
||||||
|
@ -2274,16 +2283,15 @@ t_stat ttyo_svc (UNIT *uptr)
|
||||||
t_stat r;
|
t_stat r;
|
||||||
int32 ln;
|
int32 ln;
|
||||||
TMLN *lp;
|
TMLN *lp;
|
||||||
|
int f;
|
||||||
|
|
||||||
if ((tty_unit[0].flags & UNIT_ATT) == 0) /* attached? */
|
|
||||||
return SCPE_OK;
|
|
||||||
|
|
||||||
sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */
|
sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */
|
||||||
|
|
||||||
for (ln = 0; ln < tty_desc.lines; ln++) {
|
for (ln = 0; ln < tty_desc.lines; ln++) {
|
||||||
struct _buffer *optr = &tty_out[ln];
|
struct _buffer *optr = &tty_out[ln];
|
||||||
lp = &tty_ldsc[ln];
|
lp = &tty_ldsc[ln];
|
||||||
if (lp->conn == 0) {
|
if (lp->conn == 0 || (tty_unit[0].flags & UNIT_ATT) == 0) {
|
||||||
if (not_empty(optr)) {
|
if (not_empty(optr)) {
|
||||||
optr->out_ptr = optr->in_ptr = 0;
|
optr->out_ptr = optr->in_ptr = 0;
|
||||||
tty_done[ln] = 1;
|
tty_done[ln] = 1;
|
||||||
|
@ -2292,7 +2300,8 @@ t_stat ttyo_svc (UNIT *uptr)
|
||||||
}
|
}
|
||||||
if (empty(optr))
|
if (empty(optr))
|
||||||
continue;
|
continue;
|
||||||
while (not_empty(optr)) {
|
f = 1;
|
||||||
|
while (f && not_empty(optr)) {
|
||||||
int32 ch = optr->buff[optr->out_ptr];
|
int32 ch = optr->buff[optr->out_ptr];
|
||||||
ch = sim_tt_outcvt(ch, TT_GET_MODE (tty_unit[0].flags) | TTUF_KSR);
|
ch = sim_tt_outcvt(ch, TT_GET_MODE (tty_unit[0].flags) | TTUF_KSR);
|
||||||
sim_debug(DEBUG_DATA, &tty_dev, "TTY: %d output %o\n", ln, ch);
|
sim_debug(DEBUG_DATA, &tty_dev, "TTY: %d output %o\n", ln, ch);
|
||||||
|
@ -2301,11 +2310,16 @@ t_stat ttyo_svc (UNIT *uptr)
|
||||||
inco(optr);
|
inco(optr);
|
||||||
else if (r == SCPE_LOST) {
|
else if (r == SCPE_LOST) {
|
||||||
optr->out_ptr = optr->in_ptr = 0;
|
optr->out_ptr = optr->in_ptr = 0;
|
||||||
continue;
|
f = 0;
|
||||||
} else
|
} else if (r == SCPE_STALL) {
|
||||||
continue;
|
f = 0;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (empty(optr)) {
|
||||||
|
tty_done[ln] = 1;
|
||||||
}
|
}
|
||||||
tty_done[ln] = 1;
|
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -2314,6 +2328,12 @@ t_stat ttyo_svc (UNIT *uptr)
|
||||||
|
|
||||||
t_stat tty_reset (DEVICE *dptr)
|
t_stat tty_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < tty_desc.lines; i++) {
|
||||||
|
tty_done[i] = 0;
|
||||||
|
tty_out[i].out_ptr = tty_out[i].in_ptr = 0;
|
||||||
|
tty_in[i].out_ptr = tty_in[i].in_ptr = 0;
|
||||||
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -874,7 +874,7 @@ void nia_load_ptt()
|
||||||
nia_error(EBSERR);
|
nia_error(EBSERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %012llo %012llo\n\r",
|
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %012llo %012llo\n",
|
||||||
n, word1, word2);
|
n, word1, word2);
|
||||||
if (word1 & SMASK) {
|
if (word1 & SMASK) {
|
||||||
uint16 type;
|
uint16 type;
|
||||||
|
@ -887,7 +887,7 @@ void nia_load_ptt()
|
||||||
addr++;
|
addr++;
|
||||||
}
|
}
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %04x %010o\n\r",
|
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %04x %010o\n",
|
||||||
n, nia_data.ptt_proto[i], nia_data.ptt_head[i]);
|
n, nia_data.ptt_proto[i], nia_data.ptt_head[i]);
|
||||||
nia_data.ptt_n = n;
|
nia_data.ptt_n = n;
|
||||||
}
|
}
|
||||||
|
@ -925,7 +925,7 @@ void nia_load_mcast()
|
||||||
}
|
}
|
||||||
for(i = 0; i< n; i++) {
|
for(i = 0; i< n; i++) {
|
||||||
eth_mac_fmt(&nia_data.macs[i], buffer);
|
eth_mac_fmt(&nia_data.macs[i], buffer);
|
||||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load mcast%d: %s\n\r",i,buffer);
|
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load mcast%d: %s\n",i,buffer);
|
||||||
}
|
}
|
||||||
nia_data.macs_n = n - 2;
|
nia_data.macs_n = n - 2;
|
||||||
if (nia_recv_uptr->flags & UNIT_ATT)
|
if (nia_recv_uptr->flags & UNIT_ATT)
|
||||||
|
|
562
PDP10/ks10_ch11.c
Normal file
562
PDP10/ks10_ch11.c
Normal file
|
@ -0,0 +1,562 @@
|
||||||
|
/* ks10_ch11.c: CH11 Chaosnet interface.
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2022, Richard Cornwell, original by 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
|
||||||
|
THE AUTHOR 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 the author shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from the author.
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kx10_defs.h"
|
||||||
|
#include "sim_tmxr.h"
|
||||||
|
|
||||||
|
#ifndef NUM_DEVS_CH11
|
||||||
|
#define NUM_DEVS_CH11 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NUM_DEVS_CH11 > 0)
|
||||||
|
|
||||||
|
/* CSR 076410 */
|
||||||
|
|
||||||
|
#define CSR_BSY 0000001 /* Xmit busy RO */
|
||||||
|
#define CSR_LUP 0000002 /* Loop back R/W */
|
||||||
|
#define CSR_SPY 0000004 /* Receive msgs from any destination R/W */
|
||||||
|
#define CSR_RCL 0000010 /* Clear receiver WO */
|
||||||
|
#define CSR_REN 0000020 /* Receiver int enable R/W */
|
||||||
|
#define CSR_TEN 0000040 /* Transmitter int enable R/W */
|
||||||
|
#define CSR_TAB 0000100 /* Transmit abort by conflict RO */
|
||||||
|
#define CSR_TDN 0000200 /* Transmit Done */
|
||||||
|
#define CSR_TCL 0000400 /* Clear transmitter WO */
|
||||||
|
#define CSR_LOS 0017000 /* Lost count RO */
|
||||||
|
#define CSR_RST 0020000 /* I/O Reset WO */
|
||||||
|
#define CSR_ERR 0040000 /* CRC Error RO */
|
||||||
|
#define CSR_RDN 0100000 /* Receive done */
|
||||||
|
|
||||||
|
|
||||||
|
/* MY # 764142 Host number RO */
|
||||||
|
|
||||||
|
/* WBF 764142 Write bufffer WO */
|
||||||
|
|
||||||
|
/* RBF 764144 Read buffer RO */
|
||||||
|
|
||||||
|
/* RBC 764146 Receive bit counter RO */
|
||||||
|
|
||||||
|
/* XMT 764152 Read initiates transmission */
|
||||||
|
|
||||||
|
|
||||||
|
#define CHUDP_HEADER 4
|
||||||
|
#define IOLN_CH 020
|
||||||
|
#define DBG_TRC 0x0001
|
||||||
|
#define DBG_REG 0x0002
|
||||||
|
#define DBG_PKT 0x0004
|
||||||
|
#define DBG_DAT 0x0008
|
||||||
|
#define DBG_INT 0x0010
|
||||||
|
#define DBG_ERR 0x0020
|
||||||
|
|
||||||
|
int ch11_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access);
|
||||||
|
int ch11_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access);
|
||||||
|
uint16 ch11_checksum (const uint8 *p, int count);
|
||||||
|
void ch11_validate (const uint8 *p, int count);
|
||||||
|
t_stat ch11_transmit (struct pdp_dib *dibp);
|
||||||
|
void ch11_receive (struct pdp_dib *dibp);
|
||||||
|
void ch11_clear (struct pdp_dib *dibp);
|
||||||
|
t_stat ch11_svc(UNIT *);
|
||||||
|
t_stat ch11_reset (DEVICE *);
|
||||||
|
t_stat ch11_attach (UNIT *, CONST char *);
|
||||||
|
t_stat ch11_detach (UNIT *);
|
||||||
|
t_stat ch11_show_peer (FILE* st, UNIT* uptr, int32 val, CONST void* desc);
|
||||||
|
t_stat ch11_set_peer (UNIT* uptr, int32 val, CONST char* cptr, void* desc);
|
||||||
|
t_stat ch11_show_node (FILE* st, UNIT* uptr, int32 val, CONST void* desc);
|
||||||
|
t_stat ch11_set_node (UNIT* uptr, int32 val, CONST char* cptr, void* desc);
|
||||||
|
t_stat ch11_help (FILE *, DEVICE *, UNIT *, int32, const char *);
|
||||||
|
t_stat ch11_help_attach (FILE *, DEVICE *, UNIT *, int32, const char *);
|
||||||
|
const char *ch11_description (DEVICE *);
|
||||||
|
|
||||||
|
static char peer[256];
|
||||||
|
static int address;
|
||||||
|
static uint16 ch11_csr;
|
||||||
|
static int rx_count;
|
||||||
|
static int tx_count;
|
||||||
|
static uint8 rx_buffer[512+100];
|
||||||
|
static uint8 tx_buffer[512+100];
|
||||||
|
|
||||||
|
TMLN ch11_lines[1] = { {0} };
|
||||||
|
TMXR ch11_tmxr = { 1, NULL, 0, ch11_lines};
|
||||||
|
|
||||||
|
UNIT ch11_unit[] = {
|
||||||
|
{UDATA (&ch11_svc, UNIT_IDLE|UNIT_ATTABLE, 0) },
|
||||||
|
};
|
||||||
|
|
||||||
|
REG ch11_reg[] = {
|
||||||
|
{ ORDATA(CSR, ch11_csr, 16)},
|
||||||
|
{ GRDATAD(RXCNT, rx_count, 16, 16, 0, "Receive word count"), REG_FIT|REG_RO},
|
||||||
|
{ GRDATAD(TXCNT, tx_count, 16, 16, 0, "Transmit word count"), REG_FIT|REG_RO},
|
||||||
|
{ BRDATAD(RXBUF, rx_buffer, 16, 8, sizeof rx_buffer, "Receive packet buffer"), REG_FIT},
|
||||||
|
{ BRDATAD(TXBUF, tx_buffer, 16, 8, sizeof tx_buffer, "Transmit packet buffer"), REG_FIT},
|
||||||
|
{ BRDATAD(PEER, peer, 16, 8, sizeof peer, "Network peer"), REG_HRO},
|
||||||
|
{ GRDATAD(NODE, address, 16, 16, 0, "Node address"), REG_HRO},
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB ch11_mod[] = {
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "addr", "addr", &uba_set_addr, uba_show_addr,
|
||||||
|
NULL, "Sets address of CH11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "vect", "vect", &uba_set_vect, uba_show_vect,
|
||||||
|
NULL, "Sets vect of CH11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "br", "br", &uba_set_br, uba_show_br,
|
||||||
|
NULL, "Sets br of CH11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "ctl", "ctl", &uba_set_ctl, uba_show_ctl,
|
||||||
|
NULL, "Sets uba of CH11" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "PEER", "PEER",
|
||||||
|
&ch11_set_peer, &ch11_show_peer, NULL, "Remote host name and port" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "NODE", "NODE",
|
||||||
|
&ch11_set_node, &ch11_show_node, NULL, "Chaosnet node address" },
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
DIB ch11_dib = { 0764140, 017, 0270, 6, 3, &ch11_read, &ch11_write, NULL, 0, 0 };
|
||||||
|
|
||||||
|
DEBTAB ch11_debug[] = {
|
||||||
|
{ "DETAIL", DEBUG_DETAIL,"I/O operations"},
|
||||||
|
{ "TRC", DBG_TRC, "Detailed trace" },
|
||||||
|
{ "REG", DBG_REG, "Hardware registers" },
|
||||||
|
{ "PKT", DBG_PKT, "Packets" },
|
||||||
|
{ "DAT", DBG_DAT, "Packet data" },
|
||||||
|
{ "INT", DBG_INT, "Interrupts" },
|
||||||
|
{ "ERR", DBG_ERR, "Error conditions" },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
DEVICE ch11_dev = {
|
||||||
|
"CH", ch11_unit, ch11_reg, ch11_mod,
|
||||||
|
1, 8, 16, 1, 8, 16,
|
||||||
|
NULL, NULL, &ch11_reset,
|
||||||
|
NULL, &ch11_attach, &ch11_detach,
|
||||||
|
&ch11_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_MUX,
|
||||||
|
0, ch11_debug, NULL, NULL, &ch11_help, &ch11_help_attach, NULL,
|
||||||
|
&ch11_description
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
ch11_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||||
|
{
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
addr &= dibp->uba_mask;
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "CH11 write %06o %06o %o\n",
|
||||||
|
addr, data, access);
|
||||||
|
|
||||||
|
switch (addr & 016) {
|
||||||
|
case 000: /* CSR */
|
||||||
|
if (data & CSR_RST) {
|
||||||
|
sim_debug (DBG_REG, &ch11_dev, "Reset\n");
|
||||||
|
ch11_clear (dibp);
|
||||||
|
}
|
||||||
|
ch11_csr &= ~(CSR_REN|CSR_TEN|CSR_SPY);
|
||||||
|
ch11_csr |= data & (CSR_REN|CSR_TEN|CSR_SPY);
|
||||||
|
if (data & CSR_RCL) {
|
||||||
|
sim_debug (DBG_REG, &ch11_dev, "Clear RX\n");
|
||||||
|
ch11_csr &= ~CSR_RDN;
|
||||||
|
rx_count = 0;
|
||||||
|
ch11_lines[0].rcve = TRUE;
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
if (data & CSR_TCL) {
|
||||||
|
sim_debug (DBG_REG, &ch11_dev, "Clear TX\n");
|
||||||
|
tx_count = 0;
|
||||||
|
ch11_csr |= CSR_TDN;
|
||||||
|
if (ch11_csr & CSR_TEN)
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 002: /* Write buffer */
|
||||||
|
ch11_csr &= ~CSR_TDN;
|
||||||
|
if (tx_count < 512) {
|
||||||
|
i = CHUDP_HEADER + tx_count;
|
||||||
|
tx_buffer[i] = (data >> 8) & 0xff;
|
||||||
|
tx_buffer[i+1] = data & 0xff;
|
||||||
|
tx_count+=2;
|
||||||
|
sim_debug (DBG_DAT, &ch11_dev, "Write buffer word %d:%02x %02x %06o %06o\n",
|
||||||
|
tx_count, tx_buffer[i], tx_buffer[i+1], data, ch11_csr);
|
||||||
|
} else {
|
||||||
|
sim_debug (DBG_ERR, &ch11_dev, "Write buffer overflow\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 004: /* Read buffer */
|
||||||
|
case 006: /* Bit count */
|
||||||
|
case 012: /* Start transmission */
|
||||||
|
case 010: /* Empty */
|
||||||
|
case 014: /* Empty */
|
||||||
|
case 016: /* Empty */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ch11_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||||
|
{
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
addr &= dibp->uba_mask;
|
||||||
|
*data = 0;
|
||||||
|
switch (addr & 016) {
|
||||||
|
case 000: /* CSR */
|
||||||
|
*data = ch11_csr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 002: /* Host number */
|
||||||
|
*data = address;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 004: /* Read buffer */
|
||||||
|
if (rx_count == 0) {
|
||||||
|
*data = 0;
|
||||||
|
sim_debug (DBG_ERR, &ch11_dev, "Read empty buffer\n");
|
||||||
|
} else {
|
||||||
|
i = 512-rx_count;
|
||||||
|
ch11_csr &= ~CSR_RDN;
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect);
|
||||||
|
*data = ((uint64)(rx_buffer[i]) & 0xff) << 8;
|
||||||
|
*data |= ((uint64)(rx_buffer[i+1]) & 0xff);
|
||||||
|
rx_count-=2;
|
||||||
|
sim_debug (DBG_DAT, &ch11_dev, "Read buffer word %d:%02x %02x %06o %06o\n",
|
||||||
|
rx_count, rx_buffer[i], rx_buffer[i+1], *data, ch11_csr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 006: /* Bit count */
|
||||||
|
*data = ((512 - rx_count) - 1) & 07777;
|
||||||
|
break;
|
||||||
|
case 012: /* Start transmission */
|
||||||
|
sim_debug (DBG_REG, &ch11_dev, "XMIT TX\n");
|
||||||
|
ch11_transmit(dibp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 010: /* Empty */
|
||||||
|
case 014: /* Empty */
|
||||||
|
case 016: /* Empty */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "CH11 read %06o %06o %o\n",
|
||||||
|
addr, *data, access);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16
|
||||||
|
ch11_checksum (const uint8 *p, int count)
|
||||||
|
{
|
||||||
|
int32 sum = 0;
|
||||||
|
|
||||||
|
while (count > 1) {
|
||||||
|
sum += (p[0]<<8) | p[1];
|
||||||
|
p += 2;
|
||||||
|
count -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( count > 0)
|
||||||
|
sum += p[0];
|
||||||
|
|
||||||
|
while (sum >> 16)
|
||||||
|
sum = (sum & 0xffff) + (sum >> 16);
|
||||||
|
|
||||||
|
return (~sum) & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ch11_validate (const uint8 *p, int count)
|
||||||
|
{
|
||||||
|
uint16 chksum;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Packet opcode: %02x\n", p[0]);
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "MBZ: %02x\n", p[1]);
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Forwarding count: %02x\n", p[2] >> 4);
|
||||||
|
size = ((p[2] & 0xF) << 8) + p[3];
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Packet size: %03x\n", size);
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Destination address: %o\n", (p[4] << 8) + p[5]);
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Destination index: %02x\n", (p[6] << 8) + p[7]);
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Source address: %o\n", (p[8] << 8) + p[9]);
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Source index: %02x\n", (p[10] << 8) + p[11]);
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Packet number: %02x\n", (p[12] << 8) + p[13]);
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Acknowledgement: %02x\n", (p[14] << 8) + p[15]);
|
||||||
|
|
||||||
|
if (p[1] != 0)
|
||||||
|
sim_debug (DBG_ERR, &ch11_dev, "Bad packet\n");
|
||||||
|
|
||||||
|
chksum = ch11_checksum (p, count);
|
||||||
|
if (chksum != 0) {
|
||||||
|
sim_debug (DBG_ERR, &ch11_dev, "Checksum error: %04x\n", chksum);
|
||||||
|
ch11_csr |= CSR_ERR;
|
||||||
|
} else
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Checksum: %05o\n", chksum);
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
ch11_transmit (struct pdp_dib *dibp)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
t_stat r;
|
||||||
|
int i = CHUDP_HEADER + tx_count;
|
||||||
|
uint16 chk;
|
||||||
|
|
||||||
|
if (tx_count > (512 - CHUDP_HEADER)) {
|
||||||
|
sim_debug (DBG_PKT, &ch11_dev, "Pack size failed, %d bytes.\n", (int)tx_count);
|
||||||
|
ch11_csr |= CSR_ERR;
|
||||||
|
return SCPE_INCOMP;
|
||||||
|
}
|
||||||
|
tx_buffer[i] = tx_buffer[8+CHUDP_HEADER];
|
||||||
|
tx_buffer[i+1] = tx_buffer[9+CHUDP_HEADER];
|
||||||
|
tx_count += 2;
|
||||||
|
chk = ch11_checksum(tx_buffer + CHUDP_HEADER, tx_count);
|
||||||
|
tx_buffer[i+2] = (chk >> 8) & 0xff;
|
||||||
|
tx_buffer[i+3] = chk & 0xff;
|
||||||
|
tx_count += 2;
|
||||||
|
|
||||||
|
tmxr_poll_tx (&ch11_tmxr);
|
||||||
|
len = CHUDP_HEADER + (size_t)tx_count;
|
||||||
|
r = tmxr_put_packet_ln (&ch11_lines[0], (const uint8 *)&tx_buffer, len);
|
||||||
|
if (r == SCPE_OK) {
|
||||||
|
sim_debug (DBG_PKT, &ch11_dev, "Sent UDP packet, %d bytes.\n", (int)len);
|
||||||
|
tmxr_poll_tx (&ch11_tmxr);
|
||||||
|
} else {
|
||||||
|
sim_debug (DBG_ERR, &ch11_dev, "Sending UDP failed: %d.\n", r);
|
||||||
|
ch11_csr |= CSR_TAB;
|
||||||
|
}
|
||||||
|
tx_count = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ch11_receive (struct pdp_dib *dibp)
|
||||||
|
{
|
||||||
|
size_t count;
|
||||||
|
const uint8 *p;
|
||||||
|
uint16 dest;
|
||||||
|
|
||||||
|
tmxr_poll_rx (&ch11_tmxr);
|
||||||
|
if (tmxr_get_packet_ln (&ch11_lines[0], &p, &count) != SCPE_OK) {
|
||||||
|
sim_debug (DBG_ERR, &ch11_dev, "TMXR error receiving packet\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (p == NULL)
|
||||||
|
return;
|
||||||
|
dest = ((p[4+CHUDP_HEADER] & 0xff) << 8) + (p[5+CHUDP_HEADER] & 0xff);
|
||||||
|
|
||||||
|
sim_debug (DBG_PKT, &ch11_dev, "Received UDP packet, %d bytes for: %o\n", (int)count, dest);
|
||||||
|
/* Check if packet for us. */
|
||||||
|
if (dest != address && dest != 0 && (ch11_csr & CSR_SPY) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((CSR_RDN & ch11_csr) == 0) {
|
||||||
|
count = (count + 1) & 0776;
|
||||||
|
memcpy (rx_buffer + (512 - count), p, count);
|
||||||
|
rx_count = count;
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Rx count, %d\n", rx_count);
|
||||||
|
ch11_validate (p + CHUDP_HEADER, count - CHUDP_HEADER);
|
||||||
|
ch11_csr |= CSR_RDN;
|
||||||
|
if (ch11_csr & CSR_REN) {
|
||||||
|
sim_debug (DBG_INT, &ch11_dev, "RX Interrupt\n");
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
ch11_lines[0].rcve = FALSE;
|
||||||
|
sim_debug (DBG_TRC, &ch11_dev, "Rx off\n");
|
||||||
|
} else {
|
||||||
|
sim_debug (DBG_ERR, &ch11_dev, "Lost packet\n");
|
||||||
|
if ((ch11_csr & CSR_LOS) != CSR_LOS)
|
||||||
|
ch11_csr = (ch11_csr & ~CSR_LOS) | (CSR_LOS & (ch11_csr + 01000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ch11_clear (struct pdp_dib *dibp)
|
||||||
|
{
|
||||||
|
ch11_csr = CSR_TDN;
|
||||||
|
rx_count = 0;
|
||||||
|
tx_count = 0;
|
||||||
|
|
||||||
|
tx_buffer[0] = 1; /* CHUDP header */
|
||||||
|
tx_buffer[1] = 1;
|
||||||
|
tx_buffer[2] = 0;
|
||||||
|
tx_buffer[3] = 0;
|
||||||
|
ch11_lines[0].rcve = TRUE;
|
||||||
|
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
ch11_svc(UNIT *uptr)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
|
||||||
|
sim_clock_coschedule (uptr, 1000);
|
||||||
|
(void)tmxr_poll_conn (&ch11_tmxr);
|
||||||
|
if (ch11_lines[0].conn) {
|
||||||
|
ch11_receive (dibp);
|
||||||
|
}
|
||||||
|
if (tx_count == 0) {
|
||||||
|
ch11_csr |= CSR_TDN;
|
||||||
|
if (ch11_csr & CSR_TEN) {
|
||||||
|
sim_debug (DBG_INT, &ch11_dev, "RX Interrupt\n");
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat ch11_attach (UNIT *uptr, CONST char *cptr)
|
||||||
|
{
|
||||||
|
char linkinfo[256];
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
ch11_dev.dctrl |= 0xF77F0000;
|
||||||
|
if (address == -1)
|
||||||
|
return sim_messagef (SCPE_2FARG, "Must set Chaosnet NODE address first \"SET CH NODE=val\"\n");
|
||||||
|
if (peer[0] == '\0')
|
||||||
|
return sim_messagef (SCPE_2FARG, "Must set Chaosnet PEER \"SET CH PEER=host:port\"\n");
|
||||||
|
|
||||||
|
snprintf (linkinfo, sizeof(linkinfo), "Buffer=%d,UDP,%s,PACKET,Connect=%.*s,Line=0",
|
||||||
|
(int)sizeof tx_buffer, cptr, (int)(sizeof(linkinfo) - (45 + strlen(cptr))), peer);
|
||||||
|
r = tmxr_attach (&ch11_tmxr, uptr, linkinfo);
|
||||||
|
if (r != SCPE_OK) {
|
||||||
|
sim_debug (DBG_ERR, &ch11_dev, "TMXR error opening master\n");
|
||||||
|
return sim_messagef (r, "Error Opening: %s\n", peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr->filename = (char *)realloc (uptr->filename, 1 + strlen (cptr));
|
||||||
|
strcpy (uptr->filename, cptr);
|
||||||
|
sim_activate (uptr, 1000);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat ch11_detach (UNIT *uptr)
|
||||||
|
{
|
||||||
|
sim_cancel (uptr);
|
||||||
|
tmxr_detach (&ch11_tmxr, uptr);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat ch11_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
|
||||||
|
ch11_clear (dibp);
|
||||||
|
if (ch11_unit[0].flags & UNIT_ATT)
|
||||||
|
sim_activate (&ch11_unit[0], 100);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat ch11_show_peer (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
|
||||||
|
{
|
||||||
|
fprintf (st, "peer=%s", peer[0] ? peer : "unspecified");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat ch11_set_peer (UNIT* uptr, int32 val, CONST char* cptr, void* desc)
|
||||||
|
{
|
||||||
|
char host[256], port[256];
|
||||||
|
|
||||||
|
if ((cptr == NULL) || (*cptr == 0))
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (uptr->flags & UNIT_ATT)
|
||||||
|
return SCPE_ALATT;
|
||||||
|
if (sim_parse_addr (cptr, host, sizeof host, NULL, port, sizeof port, NULL, NULL))
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (host[0] == '\0')
|
||||||
|
return SCPE_ARG;
|
||||||
|
|
||||||
|
strncpy (peer, cptr, sizeof(peer) - 1);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat ch11_show_node (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
|
||||||
|
{
|
||||||
|
if (address == -1)
|
||||||
|
fprintf (st, "node=unspecified");
|
||||||
|
else
|
||||||
|
fprintf (st, "node=%o", address);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat ch11_set_node (UNIT* uptr, int32 val, CONST char* cptr, void* desc)
|
||||||
|
{
|
||||||
|
t_stat r;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
if ((cptr == NULL) || (*cptr == 0))
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (uptr->flags & UNIT_ATT)
|
||||||
|
return SCPE_ALATT;
|
||||||
|
|
||||||
|
x = (int)get_uint (cptr, 8, 0177777, &r);
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return SCPE_ARG;
|
||||||
|
|
||||||
|
address = x;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *ch11_description (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
return "CH11 Chaosnet interface";
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat ch11_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||||
|
{
|
||||||
|
fprintf (st, "CH11 Chaosnet interface\n\n");
|
||||||
|
fprintf (st, "It's a network interface for MIT's Chaosnet. Options allow\n");
|
||||||
|
fprintf (st, "control of the node address and network peer. The node address must\n");
|
||||||
|
fprintf (st, "be a 16-bit octal number.\n");
|
||||||
|
fprint_set_help (st, dptr);
|
||||||
|
fprintf (st, "\nConfigured options and controller state can be displayed with:\n");
|
||||||
|
fprint_show_help (st, dptr);
|
||||||
|
fprintf (st, "\nThe CH11 simulation will encapsulate Chaosnet packets in UDP or TCP.\n");
|
||||||
|
fprintf (st, "To access the network, the simulated Chaosnet interface must be attached\n");
|
||||||
|
fprintf (st, "to a network peer.\n\n");
|
||||||
|
ch11_help_attach (st, dptr, uptr, flag, cptr);
|
||||||
|
fprintf (st, "Software that runs on SIMH that supports this device include:\n");
|
||||||
|
fprintf (st, " - ITS, the PDP-10 Incompatible Timesharing System\n");
|
||||||
|
fprintf (st, "Outside SIMH, there's KLH10 and Lisp machine simulators. Various\n");
|
||||||
|
fprintf (st, "encapsulating transport mechanisms exist: UDP, IP, Ethernet.\n\n");
|
||||||
|
fprintf (st, "Documentation:\n");
|
||||||
|
fprintf (st, "https://lm-3.github.io/amber.html#Hardware-Programming-Documentation\n\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat ch11_help_attach (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||||
|
{
|
||||||
|
fprintf (st, "To configure CH11, first set the local Chaosnet node address, and\n");
|
||||||
|
fprintf (st, "the peer:\n\n");
|
||||||
|
fprintf (st, " sim> SET CH NODE=<octal address>\n");
|
||||||
|
fprintf (st, " sim> SET CH PEER=<remote host>:<remote port>\n\n");
|
||||||
|
fprintf (st, "Then, attach a local port. By default UDP is used:\n\n");
|
||||||
|
fprintf (st, " sim> ATTACH CH <local port>\n\n");
|
||||||
|
fprintf (st, "If TCP is desired, add \"TCP\":\n\n");
|
||||||
|
fprintf (st, " sim> ATTACH CH <local port>,TCP\n\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
#endif
|
282
PDP10/ks10_cty.c
Normal file
282
PDP10/ks10_cty.c
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
/* ks10_cty.c: KS-10 front end (console terminal) simulator
|
||||||
|
|
||||||
|
Copyright (c) 2021, Richard Cornwell
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Richard Cornwell shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from Richard Cornwell
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kx10_defs.h"
|
||||||
|
#include "sim_sock.h"
|
||||||
|
#include "sim_tmxr.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
#define UNIT_DUMMY (1 << UNIT_V_UF)
|
||||||
|
|
||||||
|
#define STATUS 031
|
||||||
|
#define CTY_IN 032
|
||||||
|
#define CTY_OUT 033
|
||||||
|
#define KLINK_IN 034
|
||||||
|
#define KLINK_OUT 035
|
||||||
|
#define BOOT_ADDR 036
|
||||||
|
#define BOOT_DRIVE 037
|
||||||
|
#define MAG_FMT 040
|
||||||
|
|
||||||
|
#define KA_FAIL 0000000000001LL /* Keep Alive failed to change */
|
||||||
|
#define FORCE_RELOAD 0000000000002LL /* Force reload */
|
||||||
|
#define PWR_FAIL1 0000000000004LL /* Power failure */
|
||||||
|
#define BOOT_SW 0000000000010LL /* Boot switch */
|
||||||
|
#define KEEP_ALIVE 0000000177400LL /* Keep alive */
|
||||||
|
#define TRAPS_ENB 0000040000000LL /* Traps enabled */
|
||||||
|
#define ONE_MS 0000100000000LL /* 1ms enabled */
|
||||||
|
#define CACHE_ENB 0000200000000LL /* Cache enable */
|
||||||
|
#define DP_PAR_ENB 0000400000000LL /* DP parity error enable */
|
||||||
|
#define CRAM_PAR_ENB 0001000000000LL /* CRAM parity error enable */
|
||||||
|
#define PAR_ENB 0002000000000LL /* Parity error detect enable */
|
||||||
|
#define KLINK_ENB 0004000000000LL /* Klink active */
|
||||||
|
#define EX_KEEP_ALV 0010000000000LL /* Examine Keep Alive */
|
||||||
|
#define RELOAD 0020000000000LL /* Reload */
|
||||||
|
|
||||||
|
#define CTY_CHAR 0000000000400LL /* Character pending */
|
||||||
|
#define KLINK_CHAR 0000000000400LL /* Character pending */
|
||||||
|
#define KLINK_ACT 0000000001000LL /* KLINK ACTIVE */
|
||||||
|
#define KLINK_HANG 0000000001400LL /* KLINK HANGUP */
|
||||||
|
|
||||||
|
extern int32 tmxr_poll;
|
||||||
|
t_stat ctyi_svc (UNIT *uptr);
|
||||||
|
t_stat ctyo_svc (UNIT *uptr);
|
||||||
|
t_stat ctyrtc_srv(UNIT * uptr);
|
||||||
|
t_stat cty_reset (DEVICE *dptr);
|
||||||
|
t_stat cty_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
t_stat cty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
||||||
|
const char *cty_description (DEVICE *dptr);
|
||||||
|
uint64 keep_alive = 0;
|
||||||
|
int keep_num = 0;
|
||||||
|
|
||||||
|
extern DEVICE *rh_boot_dev;
|
||||||
|
extern int rh_boot_unit;
|
||||||
|
|
||||||
|
static int32 rtc_tps = 1;
|
||||||
|
|
||||||
|
MTAB cty_mod[] = {
|
||||||
|
{ UNIT_DUMMY, 0, NULL, "STOP", &cty_stop_os },
|
||||||
|
{ TT_MODE, TT_MODE_UC, "UC", "UC", &tty_set_mode },
|
||||||
|
{ TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },
|
||||||
|
{ TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },
|
||||||
|
{ TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
UNIT cty_unit[] = {
|
||||||
|
{ UDATA (&ctyo_svc, TT_MODE_7B, 0), 20000},
|
||||||
|
{ UDATA (&ctyi_svc, TT_MODE_7B|UNIT_DIS, 0), 4000 },
|
||||||
|
{ UDATA (&ctyrtc_srv, UNIT_IDLE|UNIT_DIS, 0), 1000 }
|
||||||
|
};
|
||||||
|
|
||||||
|
REG cty_reg[] = {
|
||||||
|
{HRDATAD(WRU, sim_int_char, 8, "interrupt character") },
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
DEVICE cty_dev = {
|
||||||
|
"CTY", cty_unit, cty_reg, cty_mod,
|
||||||
|
3, 10, 31, 1, 8, 8,
|
||||||
|
NULL, NULL, &cty_reset,
|
||||||
|
NULL, NULL, NULL, NULL, DEV_DEBUG, 0, dev_debug,
|
||||||
|
NULL, NULL, &cty_help, NULL, NULL, &cty_description
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
cty_wakeup()
|
||||||
|
{
|
||||||
|
sim_debug(DEBUG_EXP, &cty_dev, "CTY wakeup\n");
|
||||||
|
sim_activate(&cty_unit[0], cty_unit[0].wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Check for input from CTY and put on queue. */
|
||||||
|
t_stat ctyi_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
uint64 buffer;
|
||||||
|
int32 ch;
|
||||||
|
|
||||||
|
sim_clock_coschedule (uptr, tmxr_poll * 3);
|
||||||
|
|
||||||
|
if (Mem_read_word(CTY_IN, &buffer, 0))
|
||||||
|
return SCPE_OK;
|
||||||
|
sim_debug(DEBUG_DETAIL, &cty_dev, "CTY Read %012llo\n", buffer);
|
||||||
|
if (buffer & CTY_CHAR)
|
||||||
|
return SCPE_OK;
|
||||||
|
ch = sim_poll_kbd ();
|
||||||
|
if (ch & SCPE_KFLAG) {
|
||||||
|
ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (cty_unit[0].flags));
|
||||||
|
sim_debug(DEBUG_DETAIL, &cty_dev, "CTY char %o '%c'\n", ch,
|
||||||
|
((ch > 040 && ch < 0177)? ch: '.'));
|
||||||
|
buffer = (uint64)(ch) | CTY_CHAR;
|
||||||
|
if (Mem_write_word(CTY_IN, &buffer, 0) == 0) {
|
||||||
|
cty_interrupt();
|
||||||
|
} else {
|
||||||
|
sim_debug(DEBUG_DETAIL, &cty_dev, "CTY write failed %o '%c'\n", ch,
|
||||||
|
((ch > 040 && ch < 0177)? ch: '.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle output of characters to CTY. Started whenever there is output pending */
|
||||||
|
t_stat ctyo_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
uint64 buffer;
|
||||||
|
/* Check if any input pending? */
|
||||||
|
if (Mem_read_word(CTY_OUT, &buffer, 0))
|
||||||
|
return SCPE_OK;
|
||||||
|
sim_debug(DEBUG_DETAIL, &cty_dev, "CTY Write %012llo\n", buffer);
|
||||||
|
if (buffer & CTY_CHAR) {
|
||||||
|
int32 ch;
|
||||||
|
ch = buffer & 0377;
|
||||||
|
ch = sim_tt_outcvt ( ch, TT_GET_MODE (uptr->flags));
|
||||||
|
if (sim_putchar_s(ch) != SCPE_OK) {
|
||||||
|
sim_activate(uptr, 2000);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, &cty_dev, "CTY write %o '%c'\n", ch,
|
||||||
|
((ch > 040 && ch < 0177)? ch: '.'));
|
||||||
|
|
||||||
|
buffer = 0;
|
||||||
|
if (Mem_write_word(CTY_OUT, &buffer, 0) == 0) {
|
||||||
|
cty_interrupt();
|
||||||
|
} else {
|
||||||
|
sim_debug(DEBUG_DETAIL, &cty_dev, "CTY write failed %o '%c'\n", ch,
|
||||||
|
((ch > 040 && ch < 0177)? ch: '.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mem_read_word(KLINK_OUT, &buffer, 0))
|
||||||
|
return SCPE_OK;
|
||||||
|
if (buffer != 0) {
|
||||||
|
buffer = 0;
|
||||||
|
if (Mem_write_word(CTY_OUT, &buffer, 0) == 0) {
|
||||||
|
cty_interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Handle FE timer interrupts. And keepalive counts */
|
||||||
|
t_stat
|
||||||
|
ctyrtc_srv(UNIT * uptr)
|
||||||
|
{
|
||||||
|
uint64 buffer;
|
||||||
|
|
||||||
|
sim_activate_after(uptr, 1000000/rtc_tps);
|
||||||
|
if (Mem_read_word(STATUS, &buffer, 0))
|
||||||
|
return SCPE_OK;
|
||||||
|
if (buffer & ONE_MS) {
|
||||||
|
fprintf(stderr, "1MS\n\r");
|
||||||
|
}
|
||||||
|
if (buffer & RELOAD && rh_boot_dev != NULL) {
|
||||||
|
reset_all(1); /* Reset everybody */
|
||||||
|
if (rh_boot_dev->boot(rh_boot_unit, rh_boot_dev) != SCPE_OK)
|
||||||
|
return SCPE_STOP;
|
||||||
|
}
|
||||||
|
/* Check if clock requested */
|
||||||
|
if (buffer & EX_KEEP_ALV) {
|
||||||
|
if (keep_alive != (buffer & KEEP_ALIVE)) {
|
||||||
|
keep_alive = buffer;
|
||||||
|
keep_num = 0;
|
||||||
|
} else {
|
||||||
|
if (++keep_num >= 15) {
|
||||||
|
keep_num = 0;
|
||||||
|
buffer &= ~0377LL;
|
||||||
|
buffer |= 1;
|
||||||
|
cty_execute(071);
|
||||||
|
M[STATUS] = buffer;
|
||||||
|
M[CTY_IN] = 0;
|
||||||
|
M[CTY_OUT] = 0;
|
||||||
|
M[KLINK_IN] = 0;
|
||||||
|
M[KLINK_OUT] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
t_stat cty_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
sim_activate(&cty_unit[1], cty_unit[1].wait);
|
||||||
|
sim_activate(&cty_unit[2], cty_unit[2].wait);
|
||||||
|
M[STATUS] = 0;
|
||||||
|
M[CTY_IN] = 0;
|
||||||
|
M[CTY_OUT] = 0;
|
||||||
|
M[KLINK_IN] = 0;
|
||||||
|
M[KLINK_OUT] = 0;
|
||||||
|
M[CTY_SWITCH] = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat tty_set_mode (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
cty_unit[0].flags = (cty_unit[0].flags & ~TT_MODE) | val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop operating system */
|
||||||
|
|
||||||
|
t_stat cty_stop_os (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
M[CTY_SWITCH] = 1; /* tell OS to stop */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
t_stat cty_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||||
|
{
|
||||||
|
fprintf (st, "To stop the cpu use the command:\n\n");
|
||||||
|
fprintf (st, " sim> SET CTY STOP\n\n");
|
||||||
|
fprintf (st, "This will write a 1 to location %03o, causing TOPS10 to stop\n\n", CTY_SWITCH);
|
||||||
|
fprintf (st, "The additional terminals can be set to one of four modes: UC, 7P, 7B, or 8B.\n\n");
|
||||||
|
fprintf (st, " mode input characters output characters\n\n");
|
||||||
|
fprintf (st, " UC lower case converted lower case converted to upper case,\n");
|
||||||
|
fprintf (st, " to upper case, high-order bit cleared,\n");
|
||||||
|
fprintf (st, " high-order bit cleared non-printing characters suppressed\n");
|
||||||
|
fprintf (st, " 7P high-order bit cleared high-order bit cleared,\n");
|
||||||
|
fprintf (st, " non-printing characters suppressed\n");
|
||||||
|
fprintf (st, " 7B high-order bit cleared high-order bit cleared\n");
|
||||||
|
fprintf (st, " 8B no changes no changes\n\n");
|
||||||
|
fprintf (st, "The default mode is 7P. In addition, each line can be configured to\n");
|
||||||
|
fprintf (st, "behave as though it was attached to a dataset, or hardwired to a terminal:\n\n");
|
||||||
|
fprint_reg_help (st, &cty_dev);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cty_description (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
return "Console TTY Line";
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
1604
PDP10/ks10_dup.c
Normal file
1604
PDP10/ks10_dup.c
Normal file
File diff suppressed because it is too large
Load diff
64
PDP10/ks10_dup.h
Normal file
64
PDP10/ks10_dup.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/* ks10_dup.h: PDP-11 DUP11 bit synchronous shared device packet interface interface
|
||||||
|
|
||||||
|
Copyright (c) 2013, Mark Pizzolato
|
||||||
|
Modified for KA10 simulator by Richard Cornwell, 2022
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
dup DUP11 Unibus/DPV11 Qbus bit synchronous interface
|
||||||
|
|
||||||
|
This module describes the interfaces exposed by the dup device for use by
|
||||||
|
a packet delivery devices (i.e. KMC11).
|
||||||
|
|
||||||
|
31-May-13 MP Initial implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PDP11_DUP_H_
|
||||||
|
#define PDP11_DUP_H_ 0
|
||||||
|
|
||||||
|
typedef void (*PACKET_DATA_AVAILABLE_CALLBACK)(int32 dup, int len);
|
||||||
|
typedef void (*PACKET_TRANSMIT_COMPLETE_CALLBACK)(int32 dup, int status);
|
||||||
|
typedef void (*MODEM_CHANGE_CALLBACK)(int32 dup);
|
||||||
|
|
||||||
|
int32 dup_get_DSR (int32 dup);
|
||||||
|
int32 dup_get_DCD (int32 dup);
|
||||||
|
int32 dup_get_CTS (int32 dup);
|
||||||
|
int32 dup_get_RING (int32 dup);
|
||||||
|
int32 dup_get_RCVEN (int32 dup);
|
||||||
|
t_stat dup_set_DTR (int32 dup, t_bool state);
|
||||||
|
t_stat dup_set_RTS (int32 dup, t_bool state);
|
||||||
|
t_stat dup_set_W3_option (int32 dup, t_bool state);
|
||||||
|
t_stat dup_set_W5_option (int32 dup, t_bool state);
|
||||||
|
t_stat dup_set_W6_option (int32 dup, t_bool state);
|
||||||
|
t_stat dup_set_RCVEN (int32 dup, t_bool state);
|
||||||
|
t_stat dup_setup_dup (int32 dup, t_bool enable, t_bool protocol_DDCMP, t_bool crc_inhibit, t_bool halfduplex, uint8 station);
|
||||||
|
t_stat dup_reset_dup (int32 dup);
|
||||||
|
|
||||||
|
int32 dup_csr_to_linenum (int32 CSRPA);
|
||||||
|
|
||||||
|
void dup_set_callback_mode (int32 dup, PACKET_DATA_AVAILABLE_CALLBACK receive, PACKET_TRANSMIT_COMPLETE_CALLBACK transmit, MODEM_CHANGE_CALLBACK modem);
|
||||||
|
|
||||||
|
t_bool dup_put_msg_bytes (int32 dup, uint8 *bytes, size_t len, t_bool start, t_bool end);
|
||||||
|
|
||||||
|
t_stat dup_get_packet (int32 dup, const uint8 **pbuf, uint16 *psize);
|
||||||
|
|
||||||
|
#endif /* PDP11_DUP_H_ */
|
667
PDP10/ks10_dz.c
Normal file
667
PDP10/ks10_dz.c
Normal file
|
@ -0,0 +1,667 @@
|
||||||
|
/* ks10_dz.c: PDP-10 DZ11 communication server simulator
|
||||||
|
|
||||||
|
Copyright (c) 2021, Richard Cornwell
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Richard Cornwell shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from Richard Cornwell.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kx10_defs.h"
|
||||||
|
#include "sim_sock.h"
|
||||||
|
#include "sim_tmxr.h"
|
||||||
|
|
||||||
|
#ifndef NUM_DEVS_DZ
|
||||||
|
#define NUM_DEVS_DZ 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NUM_DEVS_DZ > 0)
|
||||||
|
|
||||||
|
|
||||||
|
#define DZ11_LINES (8 * NUM_DEVS_DZ)
|
||||||
|
|
||||||
|
/* 0 CSR */
|
||||||
|
|
||||||
|
#define MAINT 0000010 /* Maintance mode */
|
||||||
|
#define CLR 0000020
|
||||||
|
#define MSE 0000040
|
||||||
|
#define RIE 0000100
|
||||||
|
#define RDONE 0000200
|
||||||
|
#define TLINE 0003400
|
||||||
|
#define TLINE_V 8
|
||||||
|
#define SAE 0010000
|
||||||
|
#define SA 0020000
|
||||||
|
#define TIE 0040000
|
||||||
|
#define TRDY 0100000
|
||||||
|
|
||||||
|
/* 2 RBUF */
|
||||||
|
#define RBUF 0000377
|
||||||
|
#define RXLINE 0003400
|
||||||
|
#define RXLINE_V 8
|
||||||
|
#define PAR_ERR 0010000
|
||||||
|
#define FRM_ERR 0020000
|
||||||
|
#define OVRN 0040000
|
||||||
|
#define VALID 0100000
|
||||||
|
|
||||||
|
/* 2 LPR */
|
||||||
|
#define LINE 0000007
|
||||||
|
#define CHAR_LEN 0000030
|
||||||
|
#define STOP 0000040
|
||||||
|
#define PAR_ENB 0000100
|
||||||
|
#define ODD_PAR 0000200
|
||||||
|
#define FREQ 0007400
|
||||||
|
#define RXON 0010000
|
||||||
|
|
||||||
|
/* 4 TCR */
|
||||||
|
#define LINE_ENB 0000001
|
||||||
|
#define DTR 0000400
|
||||||
|
|
||||||
|
/* 6 MSR */
|
||||||
|
#define RO 0000001
|
||||||
|
#define CO 0000400
|
||||||
|
|
||||||
|
/* 6 TDR */
|
||||||
|
#define TBUF 0000377
|
||||||
|
#define BRK 0000400
|
||||||
|
|
||||||
|
struct _buffer {
|
||||||
|
int in_ptr; /* Insert pointer */
|
||||||
|
int out_ptr; /* Remove pointer */
|
||||||
|
uint16 buff[64]; /* Buffer */
|
||||||
|
int len; /* Length */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define full(q) ((((q)->in_ptr + 1) & 0x3f) == (q)->out_ptr)
|
||||||
|
#define empty(q) ((q)->in_ptr == (q)->out_ptr)
|
||||||
|
#define not_empty(q) ((q)->in_ptr != (q)->out_ptr)
|
||||||
|
#define inco(q) (q)->out_ptr = ((q)->out_ptr + 1) & 0x3f
|
||||||
|
#define inci(q) (q)->in_ptr = ((q)->in_ptr + 1) & 0x3f
|
||||||
|
|
||||||
|
#define LINE_EN 01
|
||||||
|
#define DTR_FLAG 02
|
||||||
|
|
||||||
|
uint16 dz_csr[NUM_DEVS_DZ];
|
||||||
|
uint16 dz_xmit[DZ11_LINES];
|
||||||
|
uint8 dz_flags[DZ11_LINES];
|
||||||
|
uint8 dz_ring[NUM_DEVS_DZ];
|
||||||
|
struct _buffer dz_recv[NUM_DEVS_DZ];
|
||||||
|
TMLN dz_ldsc[DZ11_LINES] = { 0 }; /* Line descriptors */
|
||||||
|
TMXR dz_desc = { DZ11_LINES, 0, 0, dz_ldsc };
|
||||||
|
extern int32 tmxr_poll;
|
||||||
|
|
||||||
|
int dz_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access);
|
||||||
|
int dz_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access);
|
||||||
|
t_stat dz_svc (UNIT *uptr);
|
||||||
|
t_stat dz_reset (DEVICE *dptr);
|
||||||
|
void dz_checkirq(struct pdp_dib *dibp);
|
||||||
|
uint16 dz_vect(struct pdp_dib *dibp);
|
||||||
|
t_stat dz_set_modem (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
t_stat dz_show_modem (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||||
|
t_stat dz_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
t_stat dz_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
t_stat dz_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
t_stat dz_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||||
|
t_stat dz_attach (UNIT *uptr, CONST char *cptr);
|
||||||
|
t_stat dz_detach (UNIT *uptr);
|
||||||
|
t_stat dz_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||||
|
const char *cptr);
|
||||||
|
const char *dz_description (DEVICE *dptr);
|
||||||
|
DIB dz_dib = { 0760000, 077, 0340, 5, 3, &dz_read, &dz_write, 0, 0, 0 };
|
||||||
|
|
||||||
|
UNIT dz_unit = {
|
||||||
|
UDATA (&dz_svc, TT_MODE_7B+UNIT_IDLE+UNIT_DISABLE+UNIT_ATTABLE, 0), KBD_POLL_WAIT
|
||||||
|
};
|
||||||
|
|
||||||
|
REG dz_reg[] = {
|
||||||
|
{ DRDATA (TIME, dz_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
MTAB dz_mod[] = {
|
||||||
|
{ TT_MODE, TT_MODE_KSR, "KSR", "KSR", NULL },
|
||||||
|
{ TT_MODE, TT_MODE_7B, "7b", "7B", NULL },
|
||||||
|
{ TT_MODE, TT_MODE_8B, "8b", "8B", NULL },
|
||||||
|
{ TT_MODE, TT_MODE_7P, "7p", "7P", NULL },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "addr", "addr", &uba_set_addr, uba_show_addr,
|
||||||
|
NULL, "Sets address of DZ11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "vect", "vect", &uba_set_vect, uba_show_vect,
|
||||||
|
NULL, "Sets vect of DZ11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "br", "br", &uba_set_br, uba_show_br,
|
||||||
|
NULL, "Sets br of DZ11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "ctl", "ctl", &uba_set_ctl, uba_show_ctl,
|
||||||
|
NULL, "Sets uba of DZ11" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 1, NULL, "DISCONNECT",
|
||||||
|
&tmxr_dscln, NULL, &dz_desc, "Disconnect a specific line" },
|
||||||
|
{ UNIT_ATT, UNIT_ATT, "SUMMARY", NULL,
|
||||||
|
NULL, &tmxr_show_summ, (void *) &dz_desc, "Display a summary of line states" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||||
|
NULL, &tmxr_show_cstat, (void *) &dz_desc, "Display current connections" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "STATISTICS", NULL,
|
||||||
|
NULL, &tmxr_show_cstat, (void *) &dz_desc, "Display multiplexer statistics" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "LINES", "LINES=n",
|
||||||
|
&dz_setnl, &tmxr_show_lines, (void *) &dz_desc, "Set number of lines" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NC, 0, NULL, "LOG=n=file",
|
||||||
|
&dz_set_log, NULL, (void *)&dz_desc },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, NULL, "NOLOG",
|
||||||
|
&dz_set_nolog, NULL, (void *)&dz_desc, "Disable logging on designated line" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "LOG", NULL,
|
||||||
|
NULL, &dz_show_log, (void *)&dz_desc, "Display logging for all lines" },
|
||||||
|
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
DEVICE dz_dev = {
|
||||||
|
"DZ", &dz_unit, dz_reg, dz_mod,
|
||||||
|
1, 10, 31, 1, 8, 8,
|
||||||
|
&tmxr_ex, &tmxr_dep, &dz_reset,
|
||||||
|
NULL, &dz_attach, &dz_detach,
|
||||||
|
&dz_dib, DEV_MUX | DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
|
||||||
|
NULL, NULL, &dz_help, NULL, NULL, &dz_description
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
dz_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||||
|
{
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
int base;
|
||||||
|
uint16 temp;
|
||||||
|
int ln;
|
||||||
|
TMLN *lp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((dptr->flags & DEV_DIS) != 0)
|
||||||
|
return 1;
|
||||||
|
if ((dptr->units[0].flags & UNIT_DIS) != 0)
|
||||||
|
return 1;
|
||||||
|
addr &= dibp->uba_mask;
|
||||||
|
if (addr < 010 || addr > 047)
|
||||||
|
return 1;
|
||||||
|
base = ((addr & 070) - 010) >> 3;
|
||||||
|
if (((base + 1) * 8) > dz_desc.lines)
|
||||||
|
return 1;
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "DZ%o write %06o %06o %o\n", base,
|
||||||
|
addr, data, access);
|
||||||
|
|
||||||
|
switch (addr & 06) {
|
||||||
|
case 0:
|
||||||
|
if (access == BYTE) {
|
||||||
|
temp = dz_csr[base];
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (temp & 0377);
|
||||||
|
else
|
||||||
|
data = (temp & 0177400) | data;
|
||||||
|
}
|
||||||
|
if (data & CLR) {
|
||||||
|
dz_csr[base] = 0;
|
||||||
|
dz_recv[base].in_ptr = dz_recv[base].out_ptr = 0;
|
||||||
|
dz_recv[base].len = 0;
|
||||||
|
/* Set up the current status */
|
||||||
|
ln = base << 3;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
dz_flags[ln + i] &= ~LINE_EN;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dz_csr[base] &= ~(TIE|SAE|RIE|MSE|CLR|MAINT);
|
||||||
|
dz_csr[base] |= data & (TIE|SAE|RIE|MSE|MAINT);
|
||||||
|
if (((dz_csr[base] & (RDONE|RIE)) == (RDONE|RIE)) ||
|
||||||
|
(dz_csr[base] & (SA|SAE)) == (SA|SAE))
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect + (010 * base));
|
||||||
|
else
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect + (010 * base));
|
||||||
|
if ((dz_csr[base] & (TRDY|TIE)) == (TRDY|TIE))
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect + 4 + (010 * base));
|
||||||
|
else
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect + 4 + (010 * base));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
ln = (data & 07) + (base << 3);
|
||||||
|
dz_ldsc[ln].rcve = (data & RXON) != 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
temp = 0;
|
||||||
|
ln = base << 3;
|
||||||
|
/* Set up the current status */
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
if (dz_flags[ln + i] & LINE_EN)
|
||||||
|
temp |= LINE_ENB << i;
|
||||||
|
if (dz_flags[ln + i] & DTR_FLAG)
|
||||||
|
temp |= DTR << i;
|
||||||
|
dz_flags[ln + i] = 0;
|
||||||
|
}
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (temp & 0377);
|
||||||
|
else
|
||||||
|
data = (temp & 0177400) | data;
|
||||||
|
}
|
||||||
|
dz_csr[base] &= ~(TRDY);
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
lp = &dz_ldsc[ln + i];
|
||||||
|
if ((data & (LINE_ENB << i)) != 0)
|
||||||
|
dz_flags[ln + i] |= LINE_EN;
|
||||||
|
if ((data & (DTR << i)) != 0)
|
||||||
|
dz_flags[ln + i] |= DTR_FLAG;
|
||||||
|
if (dz_flags[ln + i] & DTR_FLAG)
|
||||||
|
tmxr_set_get_modem_bits(lp, TMXR_MDM_OUTGOING, 0, NULL);
|
||||||
|
else
|
||||||
|
tmxr_set_get_modem_bits(lp, 0, TMXR_MDM_OUTGOING, NULL);
|
||||||
|
sim_debug(DEBUG_EXP, dptr, "DZ%o sstatus %07o %o %o\n", base, data, i, dz_flags[ln+i]);
|
||||||
|
}
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect + 4 + (010 * base));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
if (access == BYTE && (addr & 1) != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dz_csr[base] & TRDY) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ln = ((dz_csr[base] & TLINE) >> TLINE_V) + (base << 3);
|
||||||
|
lp = &dz_ldsc[ln];
|
||||||
|
|
||||||
|
if ((dz_flags[ln] & LINE_EN) != 0 && lp->conn) {
|
||||||
|
int32 ch = data & 0377;
|
||||||
|
t_stat r;
|
||||||
|
ch = sim_tt_outcvt(ch, TT_GET_MODE (dz_unit.flags) | TTUF_KSR);
|
||||||
|
/* Try and send character */
|
||||||
|
r = tmxr_putc_ln(lp, ch);
|
||||||
|
/* If character did not send, queue it */
|
||||||
|
if (r == SCPE_STALL)
|
||||||
|
dz_xmit[ln] = TRDY | ch;
|
||||||
|
}
|
||||||
|
dz_csr[base] &= ~TRDY;
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect + 4 + (010 * base));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dz_checkirq(dibp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dz_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||||
|
{
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
int base;
|
||||||
|
uint16 temp;
|
||||||
|
int ln;
|
||||||
|
TMLN *lp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((dptr->flags & DEV_DIS) != 0)
|
||||||
|
return 1;
|
||||||
|
if ((dptr->units[0].flags & UNIT_DIS) != 0)
|
||||||
|
return 1;
|
||||||
|
addr &= dibp->uba_mask;
|
||||||
|
if (addr < 010 || addr > 047)
|
||||||
|
return 1;
|
||||||
|
base = ((addr & 070) - 010) >> 3;
|
||||||
|
if (((base + 1) * 8) > dz_desc.lines)
|
||||||
|
return 1;
|
||||||
|
switch (addr & 06) {
|
||||||
|
case 0:
|
||||||
|
*data = dz_csr[base];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
*data = 0;
|
||||||
|
if ((dz_csr[base] & MSE) == 0)
|
||||||
|
return 0;
|
||||||
|
dz_csr[base] &= ~(SA|RDONE);
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect + (010 * base));
|
||||||
|
if (!empty(&dz_recv[base])) {
|
||||||
|
*data = dz_recv[base].buff[dz_recv[base].out_ptr];
|
||||||
|
inco(&dz_recv[base]);
|
||||||
|
dz_recv[base].len = 0;
|
||||||
|
}
|
||||||
|
if (!empty(&dz_recv[base])) {
|
||||||
|
dz_csr[base] |= RDONE;
|
||||||
|
if (dz_csr[base] & RIE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect + (010 * base));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
temp = 0;
|
||||||
|
base <<= 3;
|
||||||
|
/* Set up the current status */
|
||||||
|
for (ln = 0; ln < 8; ln++) {
|
||||||
|
if (dz_flags[base + ln] & LINE_EN)
|
||||||
|
temp |= LINE_ENB << ln;
|
||||||
|
if (dz_flags[base + ln] & DTR_FLAG)
|
||||||
|
temp |= DTR << ln;
|
||||||
|
}
|
||||||
|
*data = temp;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
temp = (uint16)dz_ring[base];
|
||||||
|
ln = base << 3;
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
lp = &dz_ldsc[ln + i];
|
||||||
|
if (lp->conn)
|
||||||
|
temp |= CO << i;
|
||||||
|
}
|
||||||
|
dz_ring[base] = 0;
|
||||||
|
*data = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "DZ%o read %06o %06o %o\n", base,
|
||||||
|
addr, *data, access);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unit service */
|
||||||
|
t_stat dz_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
int32 ln;
|
||||||
|
int base;
|
||||||
|
uint16 temp;
|
||||||
|
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
TMLN *lp;
|
||||||
|
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||||
|
return SCPE_OK;
|
||||||
|
ln = tmxr_poll_conn (&dz_desc); /* look for connect */
|
||||||
|
if (ln >= 0) { /* got one? rcv enb*/
|
||||||
|
dz_ring[(ln & 030) >> 3] |= (1 << (ln & 7));
|
||||||
|
sim_debug(DEBUG_DETAIL, &dz_dev, "DZ line connect %d\n", ln);
|
||||||
|
dz_xmit[ln] = 0;
|
||||||
|
}
|
||||||
|
tmxr_poll_tx(&dz_desc);
|
||||||
|
tmxr_poll_rx(&dz_desc);
|
||||||
|
for (ln = 0; ln < dz_desc.lines; ln++) {
|
||||||
|
lp = &dz_ldsc[ln];
|
||||||
|
base = (ln >> 3) & 03;
|
||||||
|
if (dz_xmit[ln] != 0) {
|
||||||
|
/* Try and send character */
|
||||||
|
t_stat r = tmxr_putc_ln(lp, dz_xmit[ln] & 0377);
|
||||||
|
/* If character did not send, queue it */
|
||||||
|
if (r == SCPE_OK)
|
||||||
|
dz_xmit[ln] = 0;
|
||||||
|
}
|
||||||
|
/* If silo full, skip to next */
|
||||||
|
while (!full(&dz_recv[base])) {
|
||||||
|
int32 ch = tmxr_getc_ln(lp);
|
||||||
|
if ((ch & TMXR_VALID) != 0) {
|
||||||
|
if (ch & SCPE_BREAK) { /* break? */
|
||||||
|
temp = FRM_ERR;
|
||||||
|
} else {
|
||||||
|
ch = sim_tt_inpcvt (ch, TT_GET_MODE(dz_unit.flags) | TTUF_KSR);
|
||||||
|
temp = VALID | ((ln & 07) << RXLINE_V) | (uint16)(ch & RBUF);
|
||||||
|
}
|
||||||
|
dz_recv[base].buff[dz_recv[base].in_ptr] = temp;
|
||||||
|
inci(&dz_recv[base]);
|
||||||
|
dz_recv[base].len++;
|
||||||
|
dz_csr[base] |= RDONE;
|
||||||
|
if (dz_csr[base] & RIE)
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect + (010 * base));
|
||||||
|
if (dz_recv[base].len > 16) {
|
||||||
|
dz_csr[base] |= SA;
|
||||||
|
if (dz_csr[base] & SAE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect + (010 * base));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "TTY recieve %d: %o\n", ln, ch);
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dz_checkirq(dibp);
|
||||||
|
sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if a device has an IRQ event ready */
|
||||||
|
void
|
||||||
|
dz_checkirq(struct pdp_dib *dibp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int ln;
|
||||||
|
int stop;
|
||||||
|
TMLN *lp;
|
||||||
|
int irq = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_DEVS_DZ; i++) {
|
||||||
|
if ((dz_csr[i] & MSE) == 0)
|
||||||
|
continue;
|
||||||
|
ln = ((dz_csr[i] & TLINE) >> TLINE_V) + (i << 3);
|
||||||
|
stop = ln;
|
||||||
|
if ((dz_csr[i] & TRDY) == 0) {
|
||||||
|
/* See if there is another line ready */
|
||||||
|
do {
|
||||||
|
ln = (ln & 070) | ((ln + 1) & 07);
|
||||||
|
lp = &dz_ldsc[ln];
|
||||||
|
/* Connected and empty xmit_buffer */
|
||||||
|
if ((dz_flags[ln] & LINE_EN) != 0 && dz_xmit[ln] == 0) {
|
||||||
|
sim_debug(DEBUG_DETAIL, &dz_dev, "DZ line ready %o\n", ln);
|
||||||
|
|
||||||
|
dz_csr[i] &= ~(TRDY|TLINE);
|
||||||
|
dz_csr[i] |= TRDY | ((ln & 07) << TLINE_V);
|
||||||
|
if (dz_csr[i] & TIE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect + 4 + (010 * i));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (ln != stop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset routine */
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
dz_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (dz_unit.flags & UNIT_ATT) /* if attached, */
|
||||||
|
sim_activate (&dz_unit, tmxr_poll); /* activate */
|
||||||
|
else
|
||||||
|
sim_cancel (&dz_unit); /* else stop */
|
||||||
|
for (i = 0; i < NUM_DEVS_DZ; i++) {
|
||||||
|
dz_csr[i] = 0;
|
||||||
|
dz_recv[i].in_ptr = dz_recv[i].out_ptr = 0;
|
||||||
|
dz_recv[i].len = 0;
|
||||||
|
dz_ring[i] = 0;
|
||||||
|
dz_xmit[i] = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < DZ11_LINES; i++) {
|
||||||
|
dz_flags[i] = 0;
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* SET LINES processor */
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
dz_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
int32 newln, i, t;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL)
|
||||||
|
return SCPE_ARG;
|
||||||
|
newln = (int32) get_uint (cptr, 10, DZ11_LINES, &r);
|
||||||
|
if ((r != SCPE_OK) || (newln == dz_desc.lines))
|
||||||
|
return r;
|
||||||
|
if ((newln == 0) || (newln > DZ11_LINES) || (newln % 8) != 0)
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (newln < dz_desc.lines) {
|
||||||
|
for (i = newln - 1, t = 0; i < dz_desc.lines; i++)
|
||||||
|
t = t | dz_ldsc[i].conn;
|
||||||
|
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
|
||||||
|
return SCPE_OK;
|
||||||
|
for (i = newln - 1; i < dz_desc.lines; i++) {
|
||||||
|
if (dz_ldsc[i].conn) {
|
||||||
|
tmxr_linemsg (&dz_ldsc[i], "\r\nOperator disconnected line\r\n");
|
||||||
|
tmxr_send_buffered_data (&dz_ldsc[i]);
|
||||||
|
}
|
||||||
|
tmxr_detach_ln (&dz_ldsc[i]); /* completely reset line */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dz_desc.lines < newln)
|
||||||
|
memset (dz_ldsc + dz_desc.lines, 0, sizeof(*dz_ldsc)*(newln-dz_desc.lines));
|
||||||
|
dz_desc.lines = newln;
|
||||||
|
return dz_reset (&dz_dev); /* setup lines and auto config */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SET LOG processor */
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
dz_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
t_stat r;
|
||||||
|
char gbuf[CBUFSIZE];
|
||||||
|
int32 ln;
|
||||||
|
|
||||||
|
if (cptr == NULL)
|
||||||
|
return SCPE_ARG;
|
||||||
|
cptr = get_glyph (cptr, gbuf, '=');
|
||||||
|
if ((cptr == NULL) || (*cptr == 0) || (gbuf[0] == 0))
|
||||||
|
return SCPE_ARG;
|
||||||
|
ln = (int32) get_uint (gbuf, 10, dz_desc.lines, &r);
|
||||||
|
if ((r != SCPE_OK) || (ln > dz_desc.lines))
|
||||||
|
return SCPE_ARG;
|
||||||
|
return tmxr_set_log (NULL, ln, cptr, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SET NOLOG processor */
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
dz_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
t_stat r;
|
||||||
|
int32 ln;
|
||||||
|
|
||||||
|
if (cptr == NULL)
|
||||||
|
return SCPE_ARG;
|
||||||
|
ln = (int32) get_uint (cptr, 10, dz_desc.lines, &r);
|
||||||
|
if ((r != SCPE_OK) || (ln > dz_desc.lines))
|
||||||
|
return SCPE_ARG;
|
||||||
|
return tmxr_set_nolog (NULL, ln, NULL, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SHOW LOG processor */
|
||||||
|
|
||||||
|
t_stat dz_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < dz_desc.lines; i++) {
|
||||||
|
fprintf (st, "line %d: ", i);
|
||||||
|
tmxr_show_log (st, NULL, i, desc);
|
||||||
|
fprintf (st, "\n");
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Attach routine */
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
dz_attach (UNIT *uptr, CONST char *cptr)
|
||||||
|
{
|
||||||
|
t_stat reason;
|
||||||
|
|
||||||
|
reason = tmxr_attach (&dz_desc, uptr, cptr);
|
||||||
|
if (reason != SCPE_OK)
|
||||||
|
return reason;
|
||||||
|
sim_activate (uptr, tmxr_poll);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detach routine */
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
dz_detach (UNIT *uptr)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
t_stat reason;
|
||||||
|
reason = tmxr_detach (&dz_desc, uptr);
|
||||||
|
for (i = 0; i < dz_desc.lines; i++)
|
||||||
|
dz_ldsc[i].rcve = 0;
|
||||||
|
sim_cancel (uptr);
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat dz_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||||
|
{
|
||||||
|
fprintf (st, "DZ11 Terminal Interfaces\n\n");
|
||||||
|
fprintf (st, "Each DZ11 supports 8 serial lines. Up to 32 can be configured\n");
|
||||||
|
fprintf (st, " sim> SET DZ LINES=n set number of additional lines to n [8-32]\n\n");
|
||||||
|
fprintf (st, "Lines must be set in multiples of 8.\n");
|
||||||
|
fprintf (st, "The ATTACH command specifies the port to be used:\n\n");
|
||||||
|
tmxr_attach_help (st, dptr, uptr, flag, cptr);
|
||||||
|
fprintf (st, "The additional terminals can be set to one of four modes: UC, 7P, 7B, or 8B.\n\n");
|
||||||
|
fprintf (st, " mode input characters output characters\n\n");
|
||||||
|
fprintf (st, " UC lower case converted lower case converted to upper case,\n");
|
||||||
|
fprintf (st, " to upper case, high-order bit cleared,\n");
|
||||||
|
fprintf (st, " high-order bit cleared non-printing characters suppressed\n");
|
||||||
|
fprintf (st, " 7P high-order bit cleared high-order bit cleared,\n");
|
||||||
|
fprintf (st, " non-printing characters suppressed\n");
|
||||||
|
fprintf (st, " 7B high-order bit cleared high-order bit cleared\n");
|
||||||
|
fprintf (st, " 8B no changes no changes\n\n");
|
||||||
|
fprintf (st, "The default mode is 7P.\n");
|
||||||
|
fprintf (st, "Finally, each line supports output logging. The SET DZn LOG command enables\n");
|
||||||
|
fprintf (st, "logging on a line:\n\n");
|
||||||
|
fprintf (st, " sim> SET DZn LOG=filename log output of line n to filename\n\n");
|
||||||
|
fprintf (st, "The SET DZn NOLOG command disables logging and closes the open log file,\n");
|
||||||
|
fprintf (st, "if any.\n\n");
|
||||||
|
fprintf (st, "Once DZ is attached and the simulator is running, the terminals listen for\n");
|
||||||
|
fprintf (st, "connections on the specified port. They assume that the incoming connections\n");
|
||||||
|
fprintf (st, "are Telnet connections. The connections remain open until disconnected either\n");
|
||||||
|
fprintf (st, "by the Telnet client, a SET DZ DISCONNECT command, or a DETACH DC command.\n\n");
|
||||||
|
fprintf (st, "Other special commands:\n\n");
|
||||||
|
fprintf (st, " sim> SHOW DZ CONNECTIONS show current connections\n");
|
||||||
|
fprintf (st, " sim> SHOW DZ STATISTICS show statistics for active connections\n");
|
||||||
|
fprintf (st, " sim> SET DZn DISCONNECT disconnects the specified line.\n\n");
|
||||||
|
fprintf (st, "The DZ11 is a unibus device, various parameters can be changed on these devices\n");
|
||||||
|
fprintf (st, "\n The address of the device can be set with: \n");
|
||||||
|
fprintf (st, " sim> SET DZ ADDR=octal default address= 760000\n");
|
||||||
|
fprintf (st, "\n The interrupt vector can be set with: \n");
|
||||||
|
fprintf (st, " sim> SET DZ VECT=octal default 340\n");
|
||||||
|
fprintf (st, "\n The interrupt level can be set with: \n");
|
||||||
|
fprintf (st, " sim> SET DZ BR=# # should be between 4 and 7.\n");
|
||||||
|
fprintf (st, "\n The unibus addaptor that the DZ is on can be set with:\n");
|
||||||
|
fprintf (st, " sim> SET DZ CTL=# # can be either 1 or 3\n");
|
||||||
|
fprint_reg_help (st, &dz_dev);
|
||||||
|
fprintf (st, "\nThe additional terminals do not support save and restore. All open connections\n");
|
||||||
|
fprintf (st, "are lost when the simulator shuts down or DZ is detached.\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *dz_description (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
return "DZ11 asynchronous line interface";
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
3080
PDP10/ks10_kmc.c
Normal file
3080
PDP10/ks10_kmc.c
Normal file
File diff suppressed because it is too large
Load diff
896
PDP10/ks10_lp.c
Normal file
896
PDP10/ks10_lp.c
Normal file
|
@ -0,0 +1,896 @@
|
||||||
|
/* ks10_lp.c: PDP-10 LP20 printer.
|
||||||
|
|
||||||
|
Copyright (c) 2021, Richard Cornwell
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Richard Cornwell shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from Richard Cornwell.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kx10_defs.h"
|
||||||
|
#include "sim_sock.h"
|
||||||
|
#include "sim_tmxr.h"
|
||||||
|
|
||||||
|
#ifndef NUM_DEVS_LP20
|
||||||
|
#define NUM_DEVS_LP20 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NUM_DEVS_LP20 > 0)
|
||||||
|
|
||||||
|
#define UNIT_V_CT (UNIT_V_UF + 0)
|
||||||
|
#define UNIT_UC (1 << UNIT_V_CT)
|
||||||
|
#define UNIT_CT (1 << UNIT_V_CT)
|
||||||
|
#define UNIT_V_VFU (UNIT_V_CT + 1)
|
||||||
|
#define UNIT_OPT (1 << UNIT_V_VFU)
|
||||||
|
|
||||||
|
|
||||||
|
#define LINE u6
|
||||||
|
|
||||||
|
/* LPCSRA (765400) */
|
||||||
|
#define CS1_GO 0000001 /* Go command */
|
||||||
|
#define CS1_PAR 0000002 /* Enable Parity interrupt */
|
||||||
|
#define CS1_V_FNC 2 /* Function shift */
|
||||||
|
#define CS1_M_FNC 03 /* Function mask */
|
||||||
|
#define FNC_PRINT 0 /* Print */
|
||||||
|
#define FNC_TEST 1 /* Test */
|
||||||
|
#define FNC_DVU 2 /* Load DAVFU */
|
||||||
|
#define FNC_RAM 3 /* Load translation RAM */
|
||||||
|
#define CS1_UBA 0000060 /* Upper Unibus address */
|
||||||
|
#define CS1_IE 0000100 /* Interrupt enable */
|
||||||
|
#define CS1_DONE 0000200 /* Done flag */
|
||||||
|
#define CS1_INIT 0000400 /* Init */
|
||||||
|
#define CS1_ECLR 0001000 /* Clear errors */
|
||||||
|
#define CS1_DHOLD 0002000 /* Delimiter hold */
|
||||||
|
#define CS1_ONL 0004000 /* Online */
|
||||||
|
#define CS1_DVON 0010000 /* DAVFU online */
|
||||||
|
#define CS1_UND 0020000 /* Undefined Character */
|
||||||
|
#define CS1_PZERO 0040000 /* Page counter zero */
|
||||||
|
#define CS1_ERR 0100000 /* Errors */
|
||||||
|
#define CS1_MOD (CS1_DHOLD|CS1_IE|(CS1_M_FNC << CS1_V_FNC)|CS1_PAR|CS1_GO)
|
||||||
|
|
||||||
|
/* LPCSRB (765402) */
|
||||||
|
#define CS2_GOE 0000001 /* Go error */
|
||||||
|
#define CS2_DTE 0000002 /* DEM timing error */
|
||||||
|
#define CS2_MTE 0000004 /* MSYN error */
|
||||||
|
#define CS2_RPE 0000010 /* RAM parity error */
|
||||||
|
#define CS2_MPE 0000020 /* Memory parity error */
|
||||||
|
#define CS2_LPE 0000040 /* LPT parity error */
|
||||||
|
#define CS2_DVOF 0000100 /* DAVFU not ready */
|
||||||
|
#define CS2_OFFL 0000200 /* Offline */
|
||||||
|
#define CS2_TEST 0003400 /* Test mode */
|
||||||
|
#define CS2_OVFU 0004000 /* Optical VFU */
|
||||||
|
#define CS2_PBIT 0010000 /* data parity bit */
|
||||||
|
#define CS2_NRDY 0020000 /* Printer error */
|
||||||
|
#define CS2_LA180 0040000 /* LA180 printer */
|
||||||
|
#define CS2_VLD 0100000 /* Valid data */
|
||||||
|
#define CS2_ECLR (CS2_GOE|CS2_DTE|CS2_MTE|CS2_RPE|CS2_LPE)
|
||||||
|
#define CS2_ERR (CS2_ECLR|CS2_OFFL|CS2_DVOF)
|
||||||
|
|
||||||
|
/* LPBA (765404) */
|
||||||
|
/* Unibus address */
|
||||||
|
|
||||||
|
/* LPBC (765406) */
|
||||||
|
/* byte count */
|
||||||
|
|
||||||
|
/* LPPAGC (765410) */
|
||||||
|
/* Page count */
|
||||||
|
|
||||||
|
/* LPRDAT (765412) */
|
||||||
|
/* RAM Data register */
|
||||||
|
|
||||||
|
/* LPCOLC/LPCBUF (765414) */
|
||||||
|
/* Column counter / Character buffer */
|
||||||
|
|
||||||
|
/* LPCSUM/LPPDAT (765416) */
|
||||||
|
/* Checksum / Printer data */
|
||||||
|
|
||||||
|
|
||||||
|
#define EOFFLG 001 /* Tops 20 wants EOF */
|
||||||
|
#define HDSFLG 002 /* Tell Tops 20 The current device status */
|
||||||
|
#define ACKFLG 004 /* Post an acknowwledge message */
|
||||||
|
#define INTFLG 010 /* Send interrupt */
|
||||||
|
#define DELFLG 020 /* Previous character was delimiter */
|
||||||
|
|
||||||
|
#define MARGIN 6
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int lp20_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access);
|
||||||
|
int lp20_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access);
|
||||||
|
void lp20_printline(UNIT *uptr, int nl);
|
||||||
|
void lp20_output(UNIT *uptr, uint8 c);
|
||||||
|
void lp20_update_chkirq (UNIT *uptr, int done, int irq);
|
||||||
|
void lp20_update_ready(UNIT *uptr, uint16 setrdy, uint16 clrrdy);
|
||||||
|
t_stat lp20_svc (UNIT *uptr);
|
||||||
|
t_stat lp20_init (UNIT *uptr);
|
||||||
|
t_stat lp20_reset (DEVICE *dptr);
|
||||||
|
t_stat lp20_attach (UNIT *uptr, CONST char *cptr);
|
||||||
|
t_stat lp20_detach (UNIT *uptr);
|
||||||
|
t_stat lp20_setlpp(UNIT *, int32, CONST char *, void *);
|
||||||
|
t_stat lp20_getlpp(FILE *, UNIT *, int32, CONST void *);
|
||||||
|
t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||||
|
const char *cptr);
|
||||||
|
const char *lp20_description (DEVICE *dptr);
|
||||||
|
|
||||||
|
char lp20_buffer[134 * 3];
|
||||||
|
uint16 lp20_cs1;
|
||||||
|
uint16 lp20_cs2;
|
||||||
|
uint16 lp20_pagcnt;
|
||||||
|
uint32 lp20_ba;
|
||||||
|
uint16 lp20_wcnt;
|
||||||
|
uint8 lp20_col;
|
||||||
|
uint8 lp20_chksum;
|
||||||
|
uint8 lp20_buf;
|
||||||
|
uint8 lp20_data;
|
||||||
|
int lp20_odd = 0;
|
||||||
|
int lp20_duvfa_state = 0;
|
||||||
|
int lp20_index = 0;
|
||||||
|
|
||||||
|
#define LP20_RAM_RAP 010000 /* RAM Parity */
|
||||||
|
#define LP20_RAM_INT 04000 /* Interrrupt bit */
|
||||||
|
#define LP20_RAM_DEL 02000 /* Delimiter bit */
|
||||||
|
#define LP20_RAM_TRN 01000 /* Translation bite */
|
||||||
|
#define LP20_RAM_PI 00400 /* Paper Instruction */
|
||||||
|
#define LP20_RAM_CHR 00377 /* Character translation */
|
||||||
|
|
||||||
|
uint16 lp20_vfu[256];
|
||||||
|
uint16 lp20_ram[256];
|
||||||
|
uint16 lp20_dvfu[] = { /* Default VFU */
|
||||||
|
/* 66 line page with 6 line margin */
|
||||||
|
00377, /* Line 0 8 7 6 5 4 3 2 1 */
|
||||||
|
00220, /* Line 1 8 5 */
|
||||||
|
00224, /* Line 2 8 5 3 */
|
||||||
|
00230, /* Line 3 8 5 4 */
|
||||||
|
00224, /* Line 4 8 5 3 */
|
||||||
|
00220, /* Line 5 8 5 */
|
||||||
|
00234, /* Line 6 8 5 4 3 */
|
||||||
|
00220, /* Line 7 8 5 */
|
||||||
|
00224, /* Line 8 8 5 3 */
|
||||||
|
00230, /* Line 9 8 5 4 */
|
||||||
|
00264, /* Line 10 8 6 5 3 */
|
||||||
|
00220, /* Line 11 8 5 */
|
||||||
|
00234, /* Line 12 8 5 4 3 */
|
||||||
|
00220, /* Line 13 8 5 */
|
||||||
|
00224, /* Line 14 8 5 3 */
|
||||||
|
00230, /* Line 15 8 5 4 */
|
||||||
|
00224, /* Line 16 8 5 3 */
|
||||||
|
00220, /* Line 17 8 5 */
|
||||||
|
00234, /* Line 18 8 5 4 3 */
|
||||||
|
00220, /* Line 19 8 5 */
|
||||||
|
00364, /* Line 20 8 7 6 5 3 */
|
||||||
|
00230, /* Line 21 8 5 4 */
|
||||||
|
00224, /* Line 22 8 5 3 */
|
||||||
|
00220, /* Line 23 8 5 */
|
||||||
|
00234, /* Line 24 8 5 4 3 */
|
||||||
|
00220, /* Line 25 8 5 */
|
||||||
|
00224, /* Line 26 8 5 3 */
|
||||||
|
00230, /* Line 27 8 5 4 */
|
||||||
|
00224, /* Line 28 8 5 3 */
|
||||||
|
00220, /* Line 29 8 5 */
|
||||||
|
00276, /* Line 30 8 6 5 4 3 2 */
|
||||||
|
00220, /* Line 31 8 5 */
|
||||||
|
00224, /* Line 32 8 5 3 */
|
||||||
|
00230, /* Line 33 8 5 4 */
|
||||||
|
00224, /* Line 34 8 5 3 */
|
||||||
|
00220, /* Line 35 8 5 */
|
||||||
|
00234, /* Line 36 8 5 4 3 */
|
||||||
|
00220, /* Line 37 8 5 */
|
||||||
|
00224, /* Line 38 8 5 3 */
|
||||||
|
00230, /* Line 39 8 5 4 */
|
||||||
|
00364, /* Line 40 8 7 6 5 3 */
|
||||||
|
00220, /* Line 41 8 5 */
|
||||||
|
00234, /* Line 42 8 5 4 3 */
|
||||||
|
00220, /* Line 43 8 5 */
|
||||||
|
00224, /* Line 44 8 5 3 */
|
||||||
|
00230, /* Line 45 8 5 4 */
|
||||||
|
00224, /* Line 46 8 5 3 */
|
||||||
|
00220, /* Line 47 8 5 */
|
||||||
|
00234, /* Line 48 8 5 4 3 */
|
||||||
|
00220, /* Line 49 8 5 */
|
||||||
|
00264, /* Line 50 8 6 5 3 */
|
||||||
|
00230, /* Line 51 8 5 4 */
|
||||||
|
00224, /* Line 52 8 5 3 */
|
||||||
|
00220, /* Line 53 8 5 */
|
||||||
|
00234, /* Line 54 8 5 4 3 */
|
||||||
|
00220, /* Line 55 8 5 */
|
||||||
|
00224, /* Line 56 8 5 3 */
|
||||||
|
00230, /* Line 57 8 5 4 */
|
||||||
|
00224, /* Line 58 8 5 3 */
|
||||||
|
00220, /* Line 59 8 5 */
|
||||||
|
00020, /* Line 60 5 */
|
||||||
|
00020, /* Line 61 5 */
|
||||||
|
00020, /* Line 62 5 */
|
||||||
|
00020, /* Line 63 5 */
|
||||||
|
00020, /* Line 64 5 */
|
||||||
|
04020, /* Line 65 12 5 */
|
||||||
|
010000, /* End of form */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* LPT data structures
|
||||||
|
|
||||||
|
lp20_dev LPT device descriptor
|
||||||
|
lp20_unit LPT unit descriptor
|
||||||
|
lp20_reg LPT register list
|
||||||
|
*/
|
||||||
|
|
||||||
|
DIB lp20_dib = { 0775400, 017, 0754, 5, 3, &lp20_read, &lp20_write, NULL, 0, 0 };
|
||||||
|
|
||||||
|
|
||||||
|
UNIT lp20_unit = {
|
||||||
|
UDATA (&lp20_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 66), 100
|
||||||
|
};
|
||||||
|
|
||||||
|
REG lp20_reg[] = {
|
||||||
|
{BRDATA(BUFFER, lp20_buffer, 16, 8, sizeof(lp20_buffer)), REG_HRO},
|
||||||
|
{BRDATA(VFU, lp20_vfu, 16, 16, (sizeof(lp20_vfu)/sizeof(uint16))), REG_HRO},
|
||||||
|
{BRDATA(RAM, lp20_ram, 16, 16, (sizeof(lp20_ram)/sizeof(uint16))), REG_HRO},
|
||||||
|
{ORDATA(CS1, lp20_cs1, 16)},
|
||||||
|
{ORDATA(CS2, lp20_cs2, 16)},
|
||||||
|
{ORDATA(PAGCNT, lp20_pagcnt, 12)},
|
||||||
|
{ORDATA(BA, lp20_ba, 18)},
|
||||||
|
{ORDATA(BC, lp20_wcnt, 16)},
|
||||||
|
{ORDATA(COL, lp20_col, 8)},
|
||||||
|
{ORDATA(CHKSUM, lp20_chksum, 8)},
|
||||||
|
{ORDATA(BUF, lp20_buf, 8)},
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
MTAB lp20_mod[] = {
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "addr", "addr", &uba_set_addr, uba_show_addr,
|
||||||
|
NULL, "Sets address of LP20" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "vect", "vect", &uba_set_vect, uba_show_vect,
|
||||||
|
NULL, "Sets vect of LP20" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "br", "br", &uba_set_br, uba_show_br,
|
||||||
|
NULL, "Sets br of LP20" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "ctl", "ctl", &uba_set_ctl, uba_show_ctl,
|
||||||
|
NULL, "Sets uba of LP20" },
|
||||||
|
{UNIT_CT, 0, "Lower case", "LC", NULL},
|
||||||
|
{UNIT_CT, UNIT_UC, "Upper case", "UC", NULL},
|
||||||
|
{UNIT_OPT, 0, "Normal VFU", "NORMAL", NULL},
|
||||||
|
{UNIT_OPT, UNIT_OPT, "Optical VFU", "OPTICAL", NULL},
|
||||||
|
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LINESPERPAGE", "LINESPERPAGE",
|
||||||
|
&lp20_setlpp, &lp20_getlpp, NULL, "Number of lines per page"},
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
DEVICE lp20_dev = {
|
||||||
|
"LP20", &lp20_unit, lp20_reg, lp20_mod,
|
||||||
|
1, 10, 31, 1, 8, 8,
|
||||||
|
NULL, NULL, &lp20_reset,
|
||||||
|
NULL, &lp20_attach, &lp20_detach,
|
||||||
|
&lp20_dib, DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
|
||||||
|
NULL, NULL, &lp20_help, NULL, NULL, &lp20_description
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
lp20_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||||
|
{
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
uint16 temp;
|
||||||
|
|
||||||
|
addr &= dibp->uba_mask;
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "LP20 write %06o %06o %o\n",
|
||||||
|
addr, data, access);
|
||||||
|
|
||||||
|
switch (addr & 016) {
|
||||||
|
case 000: /* LPCSA */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (lp20_cs1 & 0377);
|
||||||
|
else
|
||||||
|
data = (lp20_cs1 & 0177400) | data;
|
||||||
|
}
|
||||||
|
lp20_ba = ((data & CS1_UBA) << 9) | (lp20_ba & 0177777);
|
||||||
|
if (data & CS1_INIT) {
|
||||||
|
/* Reset controller */
|
||||||
|
lp20_init (&lp20_unit);
|
||||||
|
}
|
||||||
|
if (data & CS1_ECLR) {
|
||||||
|
/* Clear errors */
|
||||||
|
lp20_cs2 &= ~(CS2_ECLR);
|
||||||
|
lp20_cs1 &= ~(CS1_GO);
|
||||||
|
lp20_cs1 |= CS1_DONE;
|
||||||
|
}
|
||||||
|
if (data & CS1_GO) {
|
||||||
|
if ((lp20_cs1 & CS1_GO) == 0) {
|
||||||
|
lp20_chksum = 0;
|
||||||
|
lp20_odd = 0;
|
||||||
|
lp20_duvfa_state = 0;
|
||||||
|
lp20_index = 0;
|
||||||
|
sim_activate(&lp20_unit, 100);
|
||||||
|
lp20_cs1 |= CS1_GO;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lp20_cs1 &= ~CS1_GO;
|
||||||
|
sim_cancel(&lp20_unit);
|
||||||
|
}
|
||||||
|
lp20_cs1 &= ~(CS1_MOD);
|
||||||
|
lp20_cs1 |= data & CS1_MOD;
|
||||||
|
if (lp20_duvfa_state && ((lp20_cs1 >> CS1_V_FNC) & CS1_M_FNC) != FNC_DVU) {
|
||||||
|
lp20_update_ready(&lp20_unit, 0, CS1_DVON);
|
||||||
|
lp20_duvfa_state = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 002: /* LPCSB */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1) {
|
||||||
|
lp20_cs2 &= ~(CS2_TEST);
|
||||||
|
lp20_cs2 |= data & CS2_TEST;
|
||||||
|
} else {
|
||||||
|
lp20_cs2 &= ~(CS2_GOE);
|
||||||
|
lp20_cs2 |= data & CS2_GOE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lp20_cs2 &= ~(CS2_TEST|CS2_GOE);
|
||||||
|
lp20_cs2 |= data & (CS2_TEST|CS2_GOE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 004: /* LPBA */
|
||||||
|
lp20_ba = (lp20_ba & 060000) | (data & 0177777);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 006: /* LPBC */
|
||||||
|
lp20_wcnt = (data & 0177777);
|
||||||
|
lp20_cs1 &= ~CS1_DONE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 010: /* LPPAGC */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (lp20_pagcnt & 0377);
|
||||||
|
else
|
||||||
|
data = (lp20_pagcnt & 0177400) | data;
|
||||||
|
}
|
||||||
|
lp20_pagcnt = (data & 0177777);
|
||||||
|
lp20_cs1 &= ~CS1_PZERO;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 012: /* LPRDAT */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 014: /* LPCOL/LPCBUF */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
lp20_col = (data >> 8) & 0377;
|
||||||
|
else
|
||||||
|
lp20_buf = data & 0377;
|
||||||
|
} else {
|
||||||
|
lp20_buf = data & 0377;
|
||||||
|
lp20_col = (data >> 8) & 0377;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 016: /* LPCSUM/LPPDAT */
|
||||||
|
if (access == BYTE) {
|
||||||
|
temp = lp20_ram[(int)lp20_buf];
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (temp & 0377);
|
||||||
|
else
|
||||||
|
data = (temp & 0177400) | data;
|
||||||
|
}
|
||||||
|
lp20_ram[(int)lp20_buf] = data & 07777;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lp20_update_chkirq(&lp20_unit, 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lp20_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||||
|
{
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
uint16 temp;
|
||||||
|
int par;
|
||||||
|
|
||||||
|
addr &= dibp->uba_mask;
|
||||||
|
switch (addr & 016) {
|
||||||
|
case 000: /* LPCSA */
|
||||||
|
*data = lp20_cs1;
|
||||||
|
*data &= ~CS1_UBA;
|
||||||
|
*data |= (lp20_ba >> 9) & CS1_UBA;
|
||||||
|
if ((lp20_cs2 & CS2_ERR) != 0)
|
||||||
|
*data |= CS1_ERR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 002: /* LPCSB */
|
||||||
|
*data = lp20_cs2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 004: /* LPBA */
|
||||||
|
*data = lp20_ba & 0177777;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 006: /* LPBC */
|
||||||
|
*data = lp20_wcnt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 010: /* LPPAGC */
|
||||||
|
*data = lp20_pagcnt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 012: /* LPRDAT */
|
||||||
|
temp = lp20_ram[(int)lp20_buf] & 07777;
|
||||||
|
par = (temp >> 8) ^ (temp >> 4) ^ temp;
|
||||||
|
par = (par >> 2) ^ par;
|
||||||
|
par ^= par >> 1;
|
||||||
|
if ((par & 1) != 0)
|
||||||
|
temp |= LP20_RAM_RAP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 014: /* LPCOL/LPCBUF */
|
||||||
|
*data = ((uint16)lp20_col) << 8;
|
||||||
|
*data |= (uint16)lp20_buf;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 016: /* LPCSUM/LPPDAT */
|
||||||
|
*data = ((uint16)lp20_chksum) << 8;
|
||||||
|
*data |= (uint16)lp20_data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "LP20 read %06o %06o %o\n",
|
||||||
|
addr, *data, access);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lp20_printline(UNIT *uptr, int nl) {
|
||||||
|
int trim = 0;
|
||||||
|
|
||||||
|
/* Trim off trailing blanks */
|
||||||
|
while (lp20_col != 0 && lp20_buffer[lp20_col - 1] == ' ') {
|
||||||
|
lp20_col--;
|
||||||
|
trim = 1;
|
||||||
|
}
|
||||||
|
lp20_buffer[lp20_col] = '\0';
|
||||||
|
sim_debug(DEBUG_DETAIL, &lp20_dev, "LP output %d %d [%s]\n", lp20_col, nl,
|
||||||
|
lp20_buffer);
|
||||||
|
/* Stick a carraige return and linefeed as needed */
|
||||||
|
if (lp20_col != 0 || trim)
|
||||||
|
lp20_buffer[lp20_col++] = '\r';
|
||||||
|
if (nl != 0) {
|
||||||
|
lp20_buffer[lp20_col++] = '\n';
|
||||||
|
uptr->LINE++;
|
||||||
|
}
|
||||||
|
if (nl > 0 && lp20_vfu[uptr->LINE] == 010000) {
|
||||||
|
lp20_buffer[lp20_col++] = '\f';
|
||||||
|
uptr->LINE = 0;
|
||||||
|
lp20_pagcnt = (lp20_pagcnt - 1) & 07777;
|
||||||
|
if (lp20_pagcnt == 0)
|
||||||
|
lp20_cs1 |= CS1_PZERO;
|
||||||
|
} else if (nl < 0 && uptr->LINE >= (int32)uptr->capac) {
|
||||||
|
uptr->LINE = 0;
|
||||||
|
lp20_pagcnt = (lp20_pagcnt - 1) & 07777;
|
||||||
|
if (lp20_pagcnt == 0)
|
||||||
|
lp20_cs1 |= CS1_PZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
sim_fwrite(&lp20_buffer, 1, lp20_col, uptr->fileref);
|
||||||
|
uptr->pos += lp20_col;
|
||||||
|
lp20_col = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Unit service */
|
||||||
|
void
|
||||||
|
lp20_output(UNIT *uptr, uint8 c) {
|
||||||
|
|
||||||
|
if (c == 0)
|
||||||
|
return;
|
||||||
|
lp20_data = c & 0377;
|
||||||
|
if (lp20_col == 132)
|
||||||
|
lp20_printline(uptr, 1);
|
||||||
|
/* Map lower to upper case if uppercase only */
|
||||||
|
if ((uptr->flags & UNIT_UC) && (c & 0140) == 0140)
|
||||||
|
c &= 0137;
|
||||||
|
if (c >= 040 && c < 0177) { /* If printable */
|
||||||
|
lp20_buffer[lp20_col++] = c;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (c == 012) { /* Line feed? */
|
||||||
|
lp20_printline(uptr, 1);
|
||||||
|
} else if (c == 014) { /* Form feed, advance to top of form */
|
||||||
|
if (lp20_col != 0)
|
||||||
|
lp20_printline(uptr, 1);
|
||||||
|
sim_fwrite("\f", 1, 1, uptr->fileref);
|
||||||
|
uptr->pos += 1;
|
||||||
|
lp20_col = 0;
|
||||||
|
uptr->LINE = 0;
|
||||||
|
} else if (c == 015) { /* Carrage return */
|
||||||
|
lp20_col = 0;
|
||||||
|
}
|
||||||
|
if (c == 011) { /* Tab */
|
||||||
|
lp20_buffer[lp20_col++] = ' ';
|
||||||
|
while ((lp20_col & 07) != 0)
|
||||||
|
lp20_buffer[lp20_col++] = ' ';
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if interrupt should be sent.
|
||||||
|
* Done set CS1_DONE.
|
||||||
|
* Irq set interrupt
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
lp20_update_chkirq (UNIT *uptr, int done, int irq)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
if (done)
|
||||||
|
lp20_cs1 |= CS1_DONE;
|
||||||
|
|
||||||
|
if (uptr->flags & UNIT_ATT) {
|
||||||
|
lp20_cs1 |= CS1_ONL;
|
||||||
|
lp20_cs2 &= ~(CS2_OFFL|CS2_NRDY);
|
||||||
|
} else {
|
||||||
|
lp20_cs1 &= ~(CS1_ONL|CS1_DONE);
|
||||||
|
lp20_cs2 |= CS2_NRDY|CS2_OFFL;
|
||||||
|
}
|
||||||
|
if ((lp20_cs1 & CS1_IE) && (irq || (lp20_cs1 & CS1_DONE)))
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
else
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update ready status of printer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
lp20_update_ready(UNIT *uptr, uint16 setrdy, uint16 clrrdy)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
uint16 new_cs1 = (lp20_cs1 | setrdy) & ~clrrdy;
|
||||||
|
|
||||||
|
if ((new_cs1 ^ lp20_cs1) & (CS1_ONL|CS1_DVON) && !sim_is_active(uptr)) {
|
||||||
|
if (new_cs1 & CS1_IE)
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
if (new_cs1 & CS1_DVON)
|
||||||
|
lp20_cs2 &= ~CS2_DVOF;
|
||||||
|
if (new_cs1 & CS1_ONL)
|
||||||
|
lp20_cs2 &= ~CS2_OFFL;
|
||||||
|
else
|
||||||
|
lp20_cs2 |= CS2_OFFL;
|
||||||
|
lp20_cs1 = new_cs1;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
lp20_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
char ch;
|
||||||
|
int fnc = (lp20_cs1 >> CS1_V_FNC) & CS1_M_FNC;
|
||||||
|
uint16 ram_ch;
|
||||||
|
uint8 data;
|
||||||
|
|
||||||
|
if (fnc == FNC_PRINT && (uptr->flags & UNIT_ATT) == 0) {
|
||||||
|
lp20_cs1 |= CS1_ERR;
|
||||||
|
/* Set error */
|
||||||
|
lp20_cs1 &= ~CS1_GO;
|
||||||
|
lp20_update_chkirq (uptr, 0, 1);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uba_read_npr_byte(lp20_ba, dibp->uba_ctl, &data) == 0) {
|
||||||
|
lp20_cs2 |= CS2_MTE;
|
||||||
|
lp20_cs1 &= ~CS1_GO;
|
||||||
|
lp20_update_chkirq (uptr, 0, 1);
|
||||||
|
sim_debug(DEBUG_DETAIL, &lp20_dev, "LP npr failed\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
lp20_buf = data;
|
||||||
|
lp20_ba = (lp20_ba + 1) & 0777777;
|
||||||
|
lp20_wcnt = (lp20_wcnt + 1) & 07777;
|
||||||
|
if (lp20_wcnt == 0) {
|
||||||
|
lp20_cs1 &= ~CS1_GO;
|
||||||
|
}
|
||||||
|
lp20_chksum += lp20_buf;
|
||||||
|
sim_debug(DEBUG_DETAIL, &lp20_dev, "LP npr %08o %06o %03o %d\n", lp20_ba, lp20_wcnt,
|
||||||
|
lp20_buf, fnc);
|
||||||
|
switch(fnc) {
|
||||||
|
case FNC_PRINT:
|
||||||
|
ram_ch = lp20_ram[(int)lp20_buf];
|
||||||
|
/* If previous was delimiter or translation do it */
|
||||||
|
if (lp20_cs1 & CS1_DHOLD || (ram_ch &(LP20_RAM_DEL|LP20_RAM_TRN)) != 0) {
|
||||||
|
ch = ram_ch & LP20_RAM_CHR;
|
||||||
|
lp20_cs1 &= ~CS1_DHOLD;
|
||||||
|
if (ram_ch & LP20_RAM_DEL)
|
||||||
|
lp20_cs1 |= CS1_DHOLD;
|
||||||
|
}
|
||||||
|
/* Flag if interrupt set */
|
||||||
|
if (ram_ch & LP20_RAM_INT) {
|
||||||
|
lp20_cs1 &= ~CS1_GO;
|
||||||
|
lp20_cs1 |= CS1_UND;
|
||||||
|
}
|
||||||
|
/* Check if translate flag set */
|
||||||
|
if (ram_ch & LP20_RAM_TRN) {
|
||||||
|
lp20_buf = (uint8)(ram_ch & 0377);
|
||||||
|
}
|
||||||
|
/* Check if paper motion */
|
||||||
|
if (ram_ch & LP20_RAM_PI) {
|
||||||
|
int lines = 0; /* Number of new lines to output */
|
||||||
|
/* Print any buffered line */
|
||||||
|
if (lp20_col != 0)
|
||||||
|
lp20_printline(uptr, 1);
|
||||||
|
sim_debug(DEBUG_DETAIL, &lp20_dev, "LP Page Index %02x %04x\n",
|
||||||
|
lp20_buf, ram_ch);
|
||||||
|
if ((ram_ch & 020) == 0) { /* Find channel mark in output */
|
||||||
|
while ((lp20_vfu[uptr->LINE] & (1 << (ram_ch & 017))) == 0) {
|
||||||
|
sim_debug(DEBUG_DETAIL, &lp20_dev,
|
||||||
|
"LP skip chan %04x %04x %d\n",
|
||||||
|
lp20_vfu[uptr->LINE], ram_ch, uptr->LINE);
|
||||||
|
if (lp20_vfu[uptr->LINE] & 010000) { /* Hit bottom of form */
|
||||||
|
sim_fwrite("\014", 1, 1, uptr->fileref);
|
||||||
|
uptr->pos++;
|
||||||
|
lines = 0;
|
||||||
|
uptr->LINE = 0;
|
||||||
|
lp20_pagcnt = (lp20_pagcnt - 1) & 07777;
|
||||||
|
if (lp20_pagcnt == 0)
|
||||||
|
lp20_cs1 |= CS1_PZERO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lines++;
|
||||||
|
uptr->LINE++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while ((ram_ch & 017) != 0) {
|
||||||
|
sim_debug(DEBUG_DETAIL, &lp20_dev,
|
||||||
|
"LP skip line %04x %04x %d\n",
|
||||||
|
lp20_vfu[uptr->LINE], ram_ch, uptr->LINE);
|
||||||
|
if (lp20_vfu[uptr->LINE] & 010000) { /* Hit bottom of form */
|
||||||
|
sim_fwrite("\014", 1, 1, uptr->fileref);
|
||||||
|
uptr->pos++;
|
||||||
|
lines = 0;
|
||||||
|
uptr->LINE = 0;
|
||||||
|
lp20_pagcnt = (lp20_pagcnt - 1) & 07777;
|
||||||
|
if (lp20_pagcnt == 0)
|
||||||
|
lp20_cs1 |= CS1_PZERO;
|
||||||
|
}
|
||||||
|
lines++;
|
||||||
|
uptr->LINE++;
|
||||||
|
ram_ch--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(;lines > 0; lines--) {
|
||||||
|
sim_fwrite("\r\n", 1, 2, uptr->fileref);
|
||||||
|
uptr->pos+=2;
|
||||||
|
}
|
||||||
|
} else if (lp20_buf != 0) {
|
||||||
|
sim_debug(DEBUG_DETAIL, &lp20_dev, "LP print %03o '%c' %04o\n",
|
||||||
|
lp20_buf, lp20_buf, ram_ch);
|
||||||
|
lp20_output(uptr, lp20_buf);
|
||||||
|
}
|
||||||
|
if (lp20_cs1 & CS1_GO)
|
||||||
|
sim_activate(uptr, 600);
|
||||||
|
else
|
||||||
|
lp20_update_chkirq (uptr, lp20_wcnt == 0, 1);
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
|
case FNC_TEST:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FNC_DVU:
|
||||||
|
if ((uptr->flags & UNIT_OPT) != 0) {
|
||||||
|
lp20_output(uptr, lp20_buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (lp20_buf >= 0354 && lp20_buf <= 0356) { /* Start of DVU load */
|
||||||
|
lp20_duvfa_state = 1;
|
||||||
|
lp20_index = 0;
|
||||||
|
lp20_odd = 0;
|
||||||
|
lp20_cs2 &= ~CS2_DVOF;
|
||||||
|
} else if (lp20_buf == 0357) { /* Stop DVU load */
|
||||||
|
lp20_duvfa_state = 0;
|
||||||
|
lp20_vfu[lp20_index] = 010000;
|
||||||
|
if (lp20_odd || lp20_index < 12) {
|
||||||
|
lp20_cs1 &= ~CS1_DVON;
|
||||||
|
} else {
|
||||||
|
lp20_cs1 |= CS1_DVON;
|
||||||
|
}
|
||||||
|
} else if (lp20_duvfa_state) {
|
||||||
|
if (lp20_odd) {
|
||||||
|
lp20_vfu[lp20_index] = (lp20_vfu[lp20_index] & 077) | ((lp20_buf & 077) << 6);
|
||||||
|
sim_debug(DEBUG_DETAIL, &lp20_dev,
|
||||||
|
"LP load DFU %d %04x\n", lp20_index, lp20_vfu[lp20_index]);
|
||||||
|
lp20_index++;
|
||||||
|
} else {
|
||||||
|
lp20_vfu[lp20_index] = (lp20_vfu[lp20_index] & 0007700) | (lp20_buf & 077);
|
||||||
|
}
|
||||||
|
lp20_odd = !lp20_odd;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FNC_RAM:
|
||||||
|
if (lp20_odd) {
|
||||||
|
lp20_ram[lp20_index] = (lp20_ram[lp20_index] & 0377) | ((lp20_buf & 017) << 8);
|
||||||
|
lp20_index++;
|
||||||
|
} else {
|
||||||
|
lp20_ram[lp20_index] = (lp20_ram[lp20_index] & 07400) | (lp20_buf & 0377);
|
||||||
|
}
|
||||||
|
lp20_odd = !lp20_odd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (lp20_cs1 & CS1_GO) {
|
||||||
|
sim_activate(uptr, 10);
|
||||||
|
} else {
|
||||||
|
lp20_update_chkirq (uptr, 1, 1);
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init routine */
|
||||||
|
t_stat lp20_init (UNIT *uptr)
|
||||||
|
{
|
||||||
|
lp20_cs1 = (lp20_cs1 & CS1_DVON) | CS1_DONE;
|
||||||
|
lp20_cs2 = lp20_cs2 & (CS2_OFFL|CS2_DVOF);
|
||||||
|
lp20_col = 0;
|
||||||
|
lp20_ba = 0;
|
||||||
|
lp20_wcnt = 0;
|
||||||
|
lp20_chksum = 0;
|
||||||
|
sim_cancel (uptr); /* deactivate unit */
|
||||||
|
lp20_update_chkirq (uptr, 1, 0);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Reset routine */
|
||||||
|
t_stat lp20_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
UNIT *uptr = &lp20_unit;
|
||||||
|
int i;
|
||||||
|
int par;
|
||||||
|
lp20_col = 0;
|
||||||
|
uptr->LINE = 0;
|
||||||
|
lp20_cs1 = 0;
|
||||||
|
lp20_cs2 = CS2_OFFL|CS2_DVOF;
|
||||||
|
lp20_ba = 0;
|
||||||
|
lp20_wcnt = 0;
|
||||||
|
/* Clear RAM & VFU */
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
lp20_ram[i] = 0;
|
||||||
|
lp20_vfu[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((uptr->flags & UNIT_OPT) != 0) {
|
||||||
|
/* Load default VFU into VFU */
|
||||||
|
memcpy(&lp20_vfu, lp20_dvfu, sizeof(lp20_dvfu));
|
||||||
|
lp20_cs2 |= CS2_OVFU;
|
||||||
|
lp20_cs2 &= CS2_DVOF;
|
||||||
|
lp20_cs1 |= CS1_DVON;
|
||||||
|
}
|
||||||
|
lp20_ram[012] = LP20_RAM_TRN|LP20_RAM_PI|7; /* Line feed, print line, space one line */
|
||||||
|
lp20_ram[013] = LP20_RAM_TRN|LP20_RAM_PI|6; /* Vertical tab, Skip mod 20 */
|
||||||
|
lp20_ram[014] = LP20_RAM_TRN|LP20_RAM_PI|0; /* Form feed, skip to top of page */
|
||||||
|
lp20_ram[015] = LP20_RAM_TRN|LP20_RAM_PI|020; /* Carrage return */
|
||||||
|
lp20_ram[020] = LP20_RAM_TRN|LP20_RAM_PI|1; /* Skip half page */
|
||||||
|
lp20_ram[021] = LP20_RAM_TRN|LP20_RAM_PI|2; /* Skip even lines */
|
||||||
|
lp20_ram[022] = LP20_RAM_TRN|LP20_RAM_PI|3; /* Skip triple lines */
|
||||||
|
lp20_ram[023] = LP20_RAM_TRN|LP20_RAM_PI|4; /* Skip one line */
|
||||||
|
lp20_ram[024] = LP20_RAM_TRN|LP20_RAM_PI|5;
|
||||||
|
/* Set parity of default RAM */
|
||||||
|
for (i = 0; i < 256; i++) {
|
||||||
|
lp20_ram[i] &= ~(LP20_RAM_RAP);
|
||||||
|
par = (lp20_ram[i] >> 8) ^ (lp20_ram[i] >> 4) ^ (lp20_ram[i]);
|
||||||
|
par = (par >> 2) ^ par;
|
||||||
|
par ^= par >> 1;
|
||||||
|
if ((par & 1) == 0)
|
||||||
|
lp20_ram[i] |= LP20_RAM_RAP;
|
||||||
|
}
|
||||||
|
sim_cancel (uptr); /* deactivate unit */
|
||||||
|
if (uptr->flags & UNIT_ATT) {
|
||||||
|
lp20_update_ready(uptr, CS1_ONL, 0);
|
||||||
|
lp20_update_chkirq (uptr, 1, 0);
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach routine */
|
||||||
|
|
||||||
|
t_stat lp20_attach (UNIT *uptr, CONST char *cptr)
|
||||||
|
{
|
||||||
|
t_stat r;
|
||||||
|
sim_switches |= SWMASK ('A'); /* Position to EOF */
|
||||||
|
r = attach_unit (uptr, cptr);
|
||||||
|
if (r == SCPE_OK) {
|
||||||
|
lp20_update_ready(uptr, CS1_ONL, 0);
|
||||||
|
lp20_update_chkirq (uptr, 1, 1);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detach routine */
|
||||||
|
|
||||||
|
t_stat lp20_detach (UNIT *uptr)
|
||||||
|
{
|
||||||
|
sim_cancel (uptr); /* deactivate unit */
|
||||||
|
lp20_update_ready(uptr, 0, CS1_ONL);
|
||||||
|
lp20_update_chkirq (uptr, 1, 1);
|
||||||
|
return detach_unit (uptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Line printer routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
lp20_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
t_value i;
|
||||||
|
t_stat r;
|
||||||
|
if (cptr == NULL)
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (uptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
i = get_uint (cptr, 10, 100, &r);
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return SCPE_ARG;
|
||||||
|
uptr->capac = (t_addr)i;
|
||||||
|
uptr->LINE = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
lp20_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc)
|
||||||
|
{
|
||||||
|
if (uptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
fprintf(st, "linesperpage=%d", uptr->capac);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||||
|
const char *cptr)
|
||||||
|
{
|
||||||
|
fprintf (st, "Line Printer (LPT)\n\n");
|
||||||
|
fprintf (st, "The line printer (LPT) writes data to a disk file. \n");
|
||||||
|
fprintf (st, "The Line printer can be configured to any number of lines per page with the:\n");
|
||||||
|
fprintf (st, " sim> SET %s LINESPERPAGE=n\n\n", dptr->name);
|
||||||
|
fprintf (st, "The default is 66 lines per page.\n\n");
|
||||||
|
fprintf (st, "The LP20 is a unibus device, various parameters can be changed on these devices\n");
|
||||||
|
fprintf (st, "\n The address of the device can be set with: \n");
|
||||||
|
fprintf (st, " sim> SET LP20 ADDR=octal default address= 775400\n");
|
||||||
|
fprintf (st, "\n The interrupt vector can be set with: \n");
|
||||||
|
fprintf (st, " sim> SET LP20 VECT=octal default 754\n");
|
||||||
|
fprintf (st, "\n The interrupt level can be set with: \n");
|
||||||
|
fprintf (st, " sim> SET LP20 BR=# # should be between 4 and 7.\n");
|
||||||
|
fprintf (st, "\n The unibus addaptor that the DZ is on can be set with:\n");
|
||||||
|
fprintf (st, " sim> SET LP20 CTL=# # can be either 1 or 3\n");
|
||||||
|
|
||||||
|
fprint_set_help (st, dptr);
|
||||||
|
fprint_show_help (st, dptr);
|
||||||
|
fprint_reg_help (st, dptr);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *lp20_description (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
return "LP20 line printer" ;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
137
PDP10/ks10_tcu.c
Normal file
137
PDP10/ks10_tcu.c
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/* ks10_tcu.c: PDP-10
|
||||||
|
|
||||||
|
Copyright (c) 2021, Richard Cornwell
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Richard Cornwell shall not be
|
||||||
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from Richard Cornwell.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kx10_defs.h"
|
||||||
|
#include "sim_sock.h"
|
||||||
|
#include "sim_tmxr.h"
|
||||||
|
|
||||||
|
#ifndef NUM_DEVS_TCU
|
||||||
|
#define NUM_DEVS_TCU 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NUM_DEVS_TCU > 0)
|
||||||
|
|
||||||
|
#define UNIT_V_Y2K (UNIT_V_UF + 0) /* Y2K compliant OS */
|
||||||
|
#define UNIT_Y2K (1u << UNIT_V_Y2K)
|
||||||
|
|
||||||
|
|
||||||
|
int tcu_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access);
|
||||||
|
int tcu_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access);
|
||||||
|
t_stat tcu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||||
|
const char *cptr);
|
||||||
|
const char *tcu_description (DEVICE *dptr);
|
||||||
|
DIB tcu_dib = { 0760770, 07, 0, 0, 3, &tcu_read, &tcu_write, NULL, 0, 0 };
|
||||||
|
|
||||||
|
UNIT tcu_unit = {UDATA (NULL, UNIT_IDLE+UNIT_DISABLE, 0)};
|
||||||
|
|
||||||
|
MTAB tcu_mod[] = {
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "addr", "addr", &uba_set_addr, uba_show_addr,
|
||||||
|
NULL, "Sets address of TCU" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "ctl", "ctl", &uba_set_ctl, uba_show_ctl,
|
||||||
|
NULL, "Sets uba of TCU" },
|
||||||
|
{ UNIT_Y2K, 0, "non Y2K OS", "NOY2K", NULL },
|
||||||
|
{ UNIT_Y2K, UNIT_Y2K, "Y2K OS", "Y2K", NULL },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
DEVICE tcu_dev = {
|
||||||
|
"TIM", &tcu_unit, NULL, tcu_mod,
|
||||||
|
1, 10, 31, 1, 8, 8,
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
&tcu_dib, DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
|
||||||
|
NULL, NULL, &tcu_help, NULL, NULL, &tcu_description
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Time can't be set in device */
|
||||||
|
int
|
||||||
|
tcu_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||||
|
{
|
||||||
|
if ((dptr->units[0].flags & UNIT_DIS) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read current time of day */
|
||||||
|
int
|
||||||
|
tcu_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||||
|
{
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
time_t curtim;
|
||||||
|
struct tm *tptr;
|
||||||
|
|
||||||
|
if ((dptr->units[0].flags & UNIT_DIS) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Get time */
|
||||||
|
curtim = sim_get_time (NULL);
|
||||||
|
tptr = localtime (&curtim);
|
||||||
|
if (tptr == NULL)
|
||||||
|
return 0;
|
||||||
|
if ((tptr->tm_year > 99) && !(dptr->units[0].flags & UNIT_Y2K))
|
||||||
|
tptr->tm_year = 99; /* Y2K prob? */
|
||||||
|
|
||||||
|
switch (addr & 06) {
|
||||||
|
|
||||||
|
case 0: /* year/month/day */
|
||||||
|
*data = (((tptr->tm_year) & 0177) << 9) |
|
||||||
|
(((tptr->tm_mon + 1) & 017) << 5) |
|
||||||
|
((tptr->tm_mday) & 037);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: /* hour/minute */
|
||||||
|
*data = (((tptr->tm_hour) & 037) << 8) |
|
||||||
|
((tptr->tm_min) & 077);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: /* second */
|
||||||
|
*data = (tptr->tm_sec) & 077;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: /* status */
|
||||||
|
*data = 0200;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "TCU read %06o %06o %o\n",
|
||||||
|
addr, *data, access);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
t_stat tcu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||||
|
{
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *tcu_description (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
return "TCU150 Time of day clock";
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
586
PDP10/ks10_uba.c
Normal file
586
PDP10/ks10_uba.c
Normal file
|
@ -0,0 +1,586 @@
|
||||||
|
/* ks10_uba.c: KS10 Unibus interface
|
||||||
|
|
||||||
|
Copyright (c) 2021, Richard Cornwell
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kx10_defs.h"
|
||||||
|
|
||||||
|
/* UBA Map as stored */
|
||||||
|
#define PAGE_MASK 000003777000 /* Page mask bits, bits 25-36 on load */
|
||||||
|
#define MAP_RPV 000400000000 /* Ram parity valid bit */
|
||||||
|
#define MAP_VALID 001000000000 /* Page valid */
|
||||||
|
#define MAP_FME 002000000000 /* Fast Mode enable */
|
||||||
|
#define MAP_EN16 004000000000 /* Disable upper 2 bits UBA */
|
||||||
|
#define MAP_RPW 010000000000 /* For Read Pause Write */
|
||||||
|
#define MAP_RAMP 020000000000 /* Parity error in RAM */
|
||||||
|
|
||||||
|
/* UBA Stats register */
|
||||||
|
#define UBST_PIL 000000000007 /* Low level PIA */
|
||||||
|
#define UBST_PIH 000000000070 /* High level PIA */
|
||||||
|
#define UBST_INIT 000000000100 /* Initialize UBA */
|
||||||
|
#define UBST_DXFR 000000000200 /* Disable transfer on uncorrectable */
|
||||||
|
#define UBST_PWRL 000000001000 /* Power low */
|
||||||
|
#define UBST_INTL 000000002000 /* Interrupt on Br5 or Br4 */
|
||||||
|
#define UBST_INTH 000000004000 /* INterrupt on Br7 or Br6 */
|
||||||
|
#define UBST_NED 000000040000 /* Non-existant device */
|
||||||
|
#define UBST_PAR 000000100000 /* Parity error */
|
||||||
|
#define UBST_BAD 000000200000 /* Bad mem transfer */
|
||||||
|
#define UBST_TIM 000000400000 /* UBA Timout */
|
||||||
|
|
||||||
|
#define VECT_L 0x10
|
||||||
|
#define VECT_H 0x20
|
||||||
|
#define VECT_CTR 0x0F
|
||||||
|
|
||||||
|
uint32 uba_map[2][64];
|
||||||
|
uint32 uba_status[2];
|
||||||
|
int uba_device[16] = { -1, 0, -1, 1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1 };
|
||||||
|
|
||||||
|
int uba_irq_ctlr[128];
|
||||||
|
|
||||||
|
int
|
||||||
|
uba_read(t_addr addr, int ctl, uint64 *data, int access)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
int i;
|
||||||
|
int ubm = uba_device[ctl];
|
||||||
|
|
||||||
|
if (ctl == 0 && addr == 0100000) {
|
||||||
|
*data = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ubm == -1) {
|
||||||
|
sim_debug(DEBUG_EXP, &cpu_dev, "No UBA adaptor %02o %08o\n", ctl, addr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if in UBA map */
|
||||||
|
if ((addr & 0777600) == 0763000) {
|
||||||
|
if ((addr & 0100) == 0) {
|
||||||
|
*data = (uint64)uba_map[ubm][addr & 077];
|
||||||
|
return 0;
|
||||||
|
} else if ((addr & 077) == 0) {
|
||||||
|
int pih, pil;
|
||||||
|
int irqf = 0;
|
||||||
|
*data = (uint64)uba_status[ubm];
|
||||||
|
pih = 0200 >> ((uba_status[ubm] >> 3) & 07);
|
||||||
|
pil = 0200 >> (uba_status[ubm] & 07);
|
||||||
|
for (i = 0; i < 128; i++) {
|
||||||
|
if ((uba_irq_ctlr[i] & VECT_CTR) == ctl)
|
||||||
|
irqf |= uba_irq_ctlr[i];
|
||||||
|
}
|
||||||
|
*data |= (irqf & (VECT_L|VECT_H)) << 6;
|
||||||
|
return 0;
|
||||||
|
} else if ((addr & 077) == 1) {
|
||||||
|
*data = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*data = 0;
|
||||||
|
uba_status[ubm] |= UBST_TIM | UBST_NED;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for device */
|
||||||
|
for(i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||||
|
DIB *dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
continue;
|
||||||
|
if (ctl == dibp->uba_ctl &&
|
||||||
|
dibp->uba_addr == (addr & (~dibp->uba_mask))) {
|
||||||
|
uint16 buf;
|
||||||
|
int r = dibp->rd_io(dptr, addr, &buf, access);
|
||||||
|
if (r)
|
||||||
|
break;
|
||||||
|
if (access == BYTE) {
|
||||||
|
if ((addr & 1) != 0)
|
||||||
|
buf >>= 8;
|
||||||
|
buf &= 0377;
|
||||||
|
}
|
||||||
|
*data = (uint64)buf;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_EXP, &cpu_dev, "No UBA device %02o %08o\n", ctl, addr);
|
||||||
|
*data = 0;
|
||||||
|
uba_status[ubm] |= UBST_TIM | UBST_NED;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uba_write(t_addr addr, int ctl, uint64 data, int access)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
int i;
|
||||||
|
int ubm = uba_device[ctl];
|
||||||
|
|
||||||
|
if (ctl == 0 && addr == 0100000) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (ubm == -1) {
|
||||||
|
sim_debug(DEBUG_EXP, &cpu_dev, "No UBA adaptor %02o %08o %012llo\n", ctl, addr, data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sim_debug(DEBUG_EXP, &cpu_dev, "UBA device write %02o %08o %012llo %d\n", ctl, addr, data, access);
|
||||||
|
if (access == BYTE) {
|
||||||
|
if ((addr & 1) != 0)
|
||||||
|
data = (data & 0377) << 8;
|
||||||
|
else
|
||||||
|
data = (data & 0377);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if in UBA map */
|
||||||
|
if ((addr & 0777400) == 0763000) {
|
||||||
|
if ((addr & 0100) == 0) {
|
||||||
|
uint32 map = (uint32)(data & 03777) << 9;
|
||||||
|
map |= (uint32)(data & 0740000) << 13;
|
||||||
|
uba_map[ubm][addr & 077] = map;
|
||||||
|
sim_debug(DEBUG_EXP, &cpu_dev, "Wr MAP %02o %012llo %06o\n",
|
||||||
|
addr & 077, data, map);
|
||||||
|
return 0;
|
||||||
|
} else if ((addr & 077) == 0) {
|
||||||
|
uba_status[ubm] &= (uint32)(074000 ^ data) | 0746000;
|
||||||
|
if (data & 0100) {
|
||||||
|
uba_status[ubm] = 0;
|
||||||
|
for(i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||||
|
DIB *dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
continue;
|
||||||
|
if (ctl == dibp->uba_ctl && dptr->reset != NULL)
|
||||||
|
(void)(dptr->reset)(dptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < 128; i++) {
|
||||||
|
if ((uba_irq_ctlr[i] & VECT_CTR) == ctl) {
|
||||||
|
uba_irq_ctlr[i] = 0;
|
||||||
|
clr_interrupt(i << 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uba_status[ubm] |= (uint32)(0277 & data);
|
||||||
|
return 0;
|
||||||
|
} else if ((addr & 077) == 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uba_status[ubm] |= UBST_TIM | UBST_NED;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for device */
|
||||||
|
for(i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||||
|
DIB *dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
continue;
|
||||||
|
if (ctl == dibp->uba_ctl && dibp->uba_addr == (addr & (~dibp->uba_mask))) {
|
||||||
|
uint16 buf = (uint16)(data & 0177777);
|
||||||
|
int r = dibp->wr_io(dptr, addr, buf, access);
|
||||||
|
sim_debug(DEBUG_EXP, &cpu_dev, "UBA device write %02o %08o %012llo %06o\n", ctl, addr, data, buf);
|
||||||
|
if (r)
|
||||||
|
break;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_EXP, &cpu_dev, "No UBA device write %02o %08o %012llo\n", ctl, addr, data);
|
||||||
|
uba_status[ubm] |= UBST_TIM | UBST_NED;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uba_read_npr(t_addr addr, uint16 ctl, uint64 *data)
|
||||||
|
{
|
||||||
|
int ubm = uba_device[ctl];
|
||||||
|
uint32 map = uba_map[ubm][(077) & (addr >> 11)];
|
||||||
|
if ((addr & 0400000) != 0)
|
||||||
|
return 0;
|
||||||
|
if ((map & MAP_VALID) == 0)
|
||||||
|
return 0;
|
||||||
|
addr = (map & PAGE_MASK) | (addr >> 2) & 0777;
|
||||||
|
*data = M[addr];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uba_write_npr(t_addr addr, uint16 ctl, uint64 data)
|
||||||
|
{
|
||||||
|
int ubm = uba_device[ctl];
|
||||||
|
uint32 map = uba_map[ubm][(077) & (addr >> 11)];
|
||||||
|
t_addr oaddr = addr;
|
||||||
|
if ((addr & 0400000) != 0)
|
||||||
|
return 0;
|
||||||
|
if ((map & MAP_VALID) == 0)
|
||||||
|
return 0;
|
||||||
|
addr = (map & PAGE_MASK) | (addr >> 2) & 0777;
|
||||||
|
sim_debug(DEBUG_DATA, &cpu_dev, "Wr NPR %08o %08o %012llo\n", oaddr, addr, data);
|
||||||
|
M[addr] = data;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uba_read_npr_byte(t_addr addr, uint16 ctl, uint8 *data)
|
||||||
|
{
|
||||||
|
int ubm = uba_device[ctl];
|
||||||
|
uint32 map = uba_map[ubm][(077) & (addr >> 11)];
|
||||||
|
t_addr oaddr = addr;
|
||||||
|
uint64 wd;
|
||||||
|
if ((addr & 0400000) != 0)
|
||||||
|
return 0;
|
||||||
|
if ((map & MAP_VALID) == 0)
|
||||||
|
return 0;
|
||||||
|
addr = (map & PAGE_MASK) | (addr >> 2) & 0777;
|
||||||
|
wd = M[addr];
|
||||||
|
sim_debug(DEBUG_DATA, &kmc_dev, "RD NPR B %08o %08o %012llo ", oaddr, addr, wd);
|
||||||
|
if ((oaddr & 02) == 0)
|
||||||
|
wd >>= 18;
|
||||||
|
if ((oaddr & 01))
|
||||||
|
wd >>= 8;
|
||||||
|
sim_debug(DEBUG_DATA, &kmc_dev, "%03llo\n", wd & 0377);
|
||||||
|
*data = (uint8)(wd & 0377);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uba_write_npr_byte(t_addr addr, uint16 ctl, uint8 data)
|
||||||
|
{
|
||||||
|
int ubm = uba_device[ctl];
|
||||||
|
uint32 map = uba_map[ubm][(077) & (addr >> 11)];
|
||||||
|
t_addr oaddr = addr;
|
||||||
|
uint64 wd;
|
||||||
|
uint64 msk;
|
||||||
|
uint64 buf;
|
||||||
|
if ((addr & 0400000) != 0)
|
||||||
|
return 0;
|
||||||
|
if ((map & MAP_VALID) == 0)
|
||||||
|
return 0;
|
||||||
|
addr = (map & PAGE_MASK) | (addr >> 2) & 0777;
|
||||||
|
msk = 0377;
|
||||||
|
buf = (uint64)(data & msk);
|
||||||
|
wd = M[addr];
|
||||||
|
sim_debug(DEBUG_DATA, &kmc_dev, "WR NPR B %08o %08o %012llo ", oaddr, addr, wd);
|
||||||
|
if ((oaddr & 02) == 0) {
|
||||||
|
buf <<= 18;
|
||||||
|
msk <<= 18;
|
||||||
|
}
|
||||||
|
if ((oaddr & 01)) {
|
||||||
|
buf <<= 8;
|
||||||
|
msk <<= 8;
|
||||||
|
}
|
||||||
|
wd &= ~msk;
|
||||||
|
wd |= buf;
|
||||||
|
M[addr] = wd;
|
||||||
|
sim_debug(DEBUG_DATA, &kmc_dev, "%012llo\n", wd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uba_read_npr_word(t_addr addr, uint16 ctl, uint16 *data)
|
||||||
|
{
|
||||||
|
int ubm = uba_device[ctl];
|
||||||
|
uint32 map = uba_map[ubm][(077) & (addr >> 11)];
|
||||||
|
t_addr oaddr = addr;
|
||||||
|
uint64 wd;
|
||||||
|
if ((addr & 0400000) != 0)
|
||||||
|
return 0;
|
||||||
|
if ((map & MAP_VALID) == 0)
|
||||||
|
return 0;
|
||||||
|
addr = (map & PAGE_MASK) | (addr >> 2) & 0777;
|
||||||
|
wd = M[addr];
|
||||||
|
sim_debug(DEBUG_EXP, &cpu_dev, "RD NPR W %08o %08o %012llo m=%o\n", oaddr, addr, wd, map);
|
||||||
|
if ((oaddr & 02) == 0)
|
||||||
|
wd >>= 18;
|
||||||
|
*data = (uint16)(wd & 0177777);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uba_write_npr_word(t_addr addr, uint16 ctl, uint16 data)
|
||||||
|
{
|
||||||
|
int ubm = uba_device[ctl];
|
||||||
|
uint32 map = uba_map[ubm][(077) & (addr >> 11)];
|
||||||
|
t_addr oaddr = addr;
|
||||||
|
uint64 wd;
|
||||||
|
uint64 msk;
|
||||||
|
uint64 buf;
|
||||||
|
if ((addr & 0400000) != 0)
|
||||||
|
return 0;
|
||||||
|
if ((map & MAP_VALID) == 0)
|
||||||
|
return 0;
|
||||||
|
addr = (map & PAGE_MASK) | (addr >> 2) & 0777;
|
||||||
|
msk = 0177777;
|
||||||
|
buf = (uint64)(data & msk);
|
||||||
|
wd = M[addr];
|
||||||
|
sim_debug(DEBUG_EXP, &cpu_dev, "WR NPR W %08o %08o %012llo m=%o\n", oaddr, addr, wd, map);
|
||||||
|
if ((oaddr & 02) == 0) {
|
||||||
|
buf <<= 18;
|
||||||
|
msk <<= 18;
|
||||||
|
}
|
||||||
|
wd &= ~msk;
|
||||||
|
wd |= buf;
|
||||||
|
M[addr] = wd;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uba_set_irq(DIB *dibp, int vect)
|
||||||
|
{
|
||||||
|
int ubm = uba_device[dibp->uba_ctl];
|
||||||
|
int pi;
|
||||||
|
int flg;
|
||||||
|
|
||||||
|
if (ubm < 0)
|
||||||
|
return;
|
||||||
|
/* Figure out what channel device should IRQ on */
|
||||||
|
if (dibp->uba_br > 5) {
|
||||||
|
pi = uba_status[ubm] >> 3;
|
||||||
|
flg = VECT_H;
|
||||||
|
} else {
|
||||||
|
pi = uba_status[ubm];
|
||||||
|
flg = VECT_L;
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_IRQ, &cpu_dev, "set uba irq %06o %03o %o pi=%o\n",
|
||||||
|
dibp->uba_addr, vect, dibp->uba_br, pi);
|
||||||
|
/* Save in device temp the irq value */
|
||||||
|
set_interrupt(vect, pi);
|
||||||
|
uba_irq_ctlr[vect >> 2] = flg | dibp->uba_ctl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uba_clr_irq(DIB *idev, int vect)
|
||||||
|
{
|
||||||
|
int ubm = uba_device[idev->uba_ctl];
|
||||||
|
|
||||||
|
if (ubm < 0)
|
||||||
|
return;
|
||||||
|
sim_debug(DEBUG_IRQ, &cpu_dev, "clr uba irq %06o %03o %o\n",
|
||||||
|
idev->uba_addr, vect, idev->uba_br);
|
||||||
|
clr_interrupt(vect);
|
||||||
|
uba_irq_ctlr[vect >> 2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uba_reset()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Clear the Unibus map */
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
uba_map[0][i] = 0;
|
||||||
|
uba_map[1][i] = 0;
|
||||||
|
}
|
||||||
|
uba_status[0] = 0;
|
||||||
|
uba_status[1] = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 128; i++)
|
||||||
|
uba_irq_ctlr[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_addr
|
||||||
|
uba_get_vect(t_addr addr, int lvl, int dev)
|
||||||
|
{
|
||||||
|
uint64 buffer;
|
||||||
|
int ubm;
|
||||||
|
|
||||||
|
ubm = uba_irq_ctlr[dev];
|
||||||
|
if (ubm != 0) {
|
||||||
|
/* Fetch vector base */
|
||||||
|
ubm &= VECT_CTR;
|
||||||
|
if (Mem_read_word(0100 | ubm, &buffer, 1))
|
||||||
|
return addr;
|
||||||
|
/* Compute unibus vector */
|
||||||
|
addr = (buffer + dev) & RMASK;
|
||||||
|
sim_debug(DEBUG_IRQ, &cpu_dev, "get_vect d=%03o l=%03o ir=%02o v=%012llo\n",
|
||||||
|
dev << 2, lvl, uba_irq_ctlr[dev], buffer);
|
||||||
|
uba_irq_ctlr[dev] = 0;
|
||||||
|
}
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
uba_set_parity(uint16 ctl)
|
||||||
|
{
|
||||||
|
int ubm = uba_device[ctl];
|
||||||
|
if (ubm >= 0)
|
||||||
|
uba_status[ubm] |= UBST_PAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
uba_set_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
DIB *dibp;
|
||||||
|
t_value newaddr;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL)
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (uptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
dptr = find_dev_from_unit(uptr);
|
||||||
|
if (dptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
|
||||||
|
newaddr = get_uint (cptr, 18, 0777777, &r);
|
||||||
|
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return r;
|
||||||
|
dibp->uba_addr = (uint32)(newaddr & RMASK);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
uba_show_addr (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit(uptr);
|
||||||
|
DIB *dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
fprintf(st, "addr=%07o", dibp->uba_addr);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
uba_set_br(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
DIB *dibp;
|
||||||
|
t_value br;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL)
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (uptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
dptr = find_dev_from_unit(uptr);
|
||||||
|
if (dptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
|
||||||
|
br = get_uint (cptr, 3, 07, &r);
|
||||||
|
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (br < 4 || br > 7)
|
||||||
|
return SCPE_ARG;
|
||||||
|
dibp->uba_br = (uint16)br;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
uba_show_br (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit(uptr);
|
||||||
|
DIB *dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
fprintf(st, "br=%o", dibp->uba_br);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
uba_set_vect(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
DIB *dibp;
|
||||||
|
t_value vect;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL)
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (uptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
dptr = find_dev_from_unit(uptr);
|
||||||
|
if (dptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
|
||||||
|
vect = get_uint (cptr, 8, 0377, &r);
|
||||||
|
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
dibp->uba_vect = (uint16)vect;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
uba_show_vect (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit(uptr);
|
||||||
|
DIB *dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
fprintf(st, "vect=%03o", dibp->uba_vect);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
uba_set_ctl(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
DIB *dibp;
|
||||||
|
t_value ctl;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL)
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (uptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
dptr = find_dev_from_unit(uptr);
|
||||||
|
if (dptr == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
|
||||||
|
ctl = get_uint (cptr, 4, 017, &r);
|
||||||
|
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (ctl != 1 && ctl != 3)
|
||||||
|
return SCPE_ARG;
|
||||||
|
dibp->uba_ctl = (uint16)ctl;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
uba_show_ctl (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit(uptr);
|
||||||
|
DIB *dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL)
|
||||||
|
return SCPE_IERR;
|
||||||
|
fprintf(st, "uba%o", dibp->uba_ctl);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
6379
PDP10/kx10_cpu.c
6379
PDP10/kx10_cpu.c
File diff suppressed because it is too large
Load diff
|
@ -50,11 +50,15 @@
|
||||||
#define KL 0
|
#define KL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef KS
|
||||||
|
#define KS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#if KL
|
#if KL
|
||||||
#define EPT440 0 /* Force KL10 to use as 440 section address */
|
#define EPT440 0 /* Force KL10 to use as 440 section address */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (PDP6 + KA + KI + KL) != 1
|
#if (PDP6 + KA + KI + KL + KS) != 1
|
||||||
#error "Please define only one type of CPU"
|
#error "Please define only one type of CPU"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -82,6 +86,11 @@
|
||||||
#define KL_ITS KL
|
#define KL_ITS KL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Support for ITS on KS */
|
||||||
|
#ifndef KS_ITS
|
||||||
|
#define KS_ITS KS
|
||||||
|
#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
|
||||||
|
@ -195,6 +204,30 @@ extern DEBTAB crd_debug[];
|
||||||
#define FPMMASK 00000000000077777777777LL
|
#define FPMMASK 00000000000077777777777LL
|
||||||
#define FPRBIT2 00000000000100000000000LL
|
#define FPRBIT2 00000000000100000000000LL
|
||||||
#define FPRBIT1 00000000000200000000000LL
|
#define FPRBIT1 00000000000200000000000LL
|
||||||
|
#if KS
|
||||||
|
#define IOCTL 00000017000000LL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* IRQ Flags in APR */
|
||||||
|
#if KL
|
||||||
|
#define SWP_DONE 0000020 /* Cache sweep done */
|
||||||
|
#define PFAIL 0000040 /* Power failure */
|
||||||
|
#define ADDR_PAR 0000100 /* Address Parity error */
|
||||||
|
#define CACHE_DIR 0000200 /* Cache Parity error */
|
||||||
|
#define MB_PAR 0000400 /* Memory parity error */
|
||||||
|
#define INOUT_FAIL 0001000 /* Fault during IRQ */
|
||||||
|
#define NXM_MEM 0002000 /* Non-existent memory */
|
||||||
|
#define SBUS_ERR 0004000 /* SBus Error */
|
||||||
|
#endif
|
||||||
|
#if KS
|
||||||
|
#define CON_IRQ 0000020 /* Interrupt from Console */
|
||||||
|
#define INT_DONE 0000040 /* Interval timer complete */
|
||||||
|
#define COR_MEM 0000100 /* Corrected memory error */
|
||||||
|
#define MB_ERR 0000200 /* Uncorrectable memory error */
|
||||||
|
#define NXM_MEM 0000400 /* No memory */
|
||||||
|
#define PFAIL 0001000 /* Power Failure */
|
||||||
|
#define FLAG_24 0004000 /* Spare */
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CM(x) (FMASK ^ (x))
|
#define CM(x) (FMASK ^ (x))
|
||||||
#define CCM(x) ((CMASK ^ (x)) & CMASK)
|
#define CCM(x) ((CMASK ^ (x)) & CMASK)
|
||||||
|
@ -231,12 +264,16 @@ extern DEBTAB crd_debug[];
|
||||||
#define NODIV 000001 /* 000040 */
|
#define NODIV 000001 /* 000040 */
|
||||||
#define FLTUND 000002 /* 000100 */
|
#define FLTUND 000002 /* 000100 */
|
||||||
#endif
|
#endif
|
||||||
#if KI|KL
|
#if KI|KL|KS
|
||||||
#define TRP1 000004 /* 000200 */
|
#define TRP1 000004 /* 000200 */
|
||||||
#define TRP2 000010 /* 000400 */
|
#define TRP2 000010 /* 000400 */
|
||||||
#define ADRFLT 000020 /* 001000 */
|
#define ADRFLT 000020 /* 001000 */
|
||||||
|
#if KI | KL
|
||||||
#define PUBLIC 000040 /* 002000 */
|
#define PUBLIC 000040 /* 002000 */
|
||||||
#else
|
#else
|
||||||
|
#define PUBLIC 000000 /* 000000 */
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
#define TRP1 000000
|
#define TRP1 000000
|
||||||
#define TRP2 000000
|
#define TRP2 000000
|
||||||
#define ADRFLT 000000
|
#define ADRFLT 000000
|
||||||
|
@ -261,7 +298,7 @@ extern DEBTAB crd_debug[];
|
||||||
#if KI|KL
|
#if KI|KL
|
||||||
#define PRV_PUB 020000 /* Overflow in excutive mode */
|
#define PRV_PUB 020000 /* Overflow in excutive mode */
|
||||||
#else
|
#else
|
||||||
#define PRV_PUB 000000 /* Not on KA or PDP6 */
|
#define PRV_PUB 000000 /* Not on KA, KS or PDP6 */
|
||||||
#endif
|
#endif
|
||||||
#ifdef ITS
|
#ifdef ITS
|
||||||
#ifdef PURE
|
#ifdef PURE
|
||||||
|
@ -280,13 +317,13 @@ extern DEBTAB crd_debug[];
|
||||||
|
|
||||||
#if KI_22BIT|KI
|
#if KI_22BIT|KI
|
||||||
#define MAXMEMSIZE 4096 * 1024
|
#define MAXMEMSIZE 4096 * 1024
|
||||||
#else
|
#elif PDP6
|
||||||
#if PDP6
|
|
||||||
#define MAXMEMSIZE 256 * 1024
|
#define MAXMEMSIZE 256 * 1024
|
||||||
|
#elif KS
|
||||||
|
#define MAXMEMSIZE 1024 * 1024
|
||||||
#else
|
#else
|
||||||
#define MAXMEMSIZE 1024 * 1024
|
#define MAXMEMSIZE 1024 * 1024
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#define MEMSIZE (cpu_unit[0].capac)
|
#define MEMSIZE (cpu_unit[0].capac)
|
||||||
|
|
||||||
#define ICWA 0000000000776
|
#define ICWA 0000000000776
|
||||||
|
@ -323,6 +360,10 @@ extern DEBTAB crd_debug[];
|
||||||
#define DEF_SERIAL 1025 /* Default DEC test machine */
|
#define DEF_SERIAL 1025 /* Default DEC test machine */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
#define DEF_SERIAL 4097 /* 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
|
||||||
|
@ -339,7 +380,7 @@ extern DEBTAB crd_debug[];
|
||||||
#define BBN_MERGE 0161740000000LL
|
#define BBN_MERGE 0161740000000LL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if KL
|
#if KL|KS
|
||||||
/* KL10 TLB paging bits */
|
/* KL10 TLB paging bits */
|
||||||
#define KL_PAG_A 0400000 /* Access */
|
#define KL_PAG_A 0400000 /* Access */
|
||||||
#define KL_PAG_P 0200000 /* Public */
|
#define KL_PAG_P 0200000 /* Public */
|
||||||
|
@ -367,7 +408,11 @@ extern DEBTAB crd_debug[];
|
||||||
#define UNIT_KL10B (1 << UNIT_V_PAGE)
|
#define UNIT_KL10B (1 << UNIT_V_PAGE)
|
||||||
#define UNIT_TWOSEG (0)
|
#define UNIT_TWOSEG (0)
|
||||||
#else
|
#else
|
||||||
|
#if KA
|
||||||
#define UNIT_TWOSEG (1 << UNIT_V_PAGE)
|
#define UNIT_TWOSEG (1 << UNIT_V_PAGE)
|
||||||
|
#else
|
||||||
|
#define UNIT_TWOSEG (0)
|
||||||
|
#endif
|
||||||
#endif
|
#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)
|
||||||
|
@ -415,6 +460,10 @@ 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[];
|
||||||
|
#if KS
|
||||||
|
extern DEVICE lp20_dev;
|
||||||
|
extern DEVICE ch11_dev;
|
||||||
|
#endif
|
||||||
#if KL
|
#if KL
|
||||||
extern DEVICE dte_dev;
|
extern DEVICE dte_dev;
|
||||||
extern DEVICE lp20_dev;
|
extern DEVICE lp20_dev;
|
||||||
|
@ -462,15 +511,104 @@ extern DEVICE dkb_dev;
|
||||||
extern DEVICE auxcpu_dev;
|
extern DEVICE auxcpu_dev;
|
||||||
extern DEVICE slave_dev;
|
extern DEVICE slave_dev;
|
||||||
extern DEVICE dpk_dev;
|
extern DEVICE dpk_dev;
|
||||||
|
extern DEVICE tv_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 ocnsls_dev; /* Old MIT Spacewar Consoles */
|
||||||
extern DEVICE ai_dev;
|
extern DEVICE ai_dev;
|
||||||
|
extern DEVICE dn_dev;
|
||||||
extern DEVICE dct_dev; /* PDP6 devices. */
|
extern DEVICE dct_dev; /* PDP6 devices. */
|
||||||
extern DEVICE dtc_dev;
|
extern DEVICE dtc_dev;
|
||||||
extern DEVICE mtc_dev;
|
extern DEVICE mtc_dev;
|
||||||
extern DEVICE dsk_dev;
|
extern DEVICE dsk_dev;
|
||||||
extern DEVICE dcs_dev;
|
extern DEVICE dcs_dev;
|
||||||
|
extern DEVICE dz_dev;
|
||||||
|
extern DEVICE kmc_dev;
|
||||||
|
extern DEVICE dup_dev;
|
||||||
|
extern DEVICE tcu_dev;
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
|
||||||
|
struct rh_if {
|
||||||
|
int (*dev_write)(DEVICE *dptr, struct rh_if *rh, int reg, uint32 data);
|
||||||
|
int (*dev_read)(DEVICE *dptr, struct rh_if *rh, int reg, uint32 *data);
|
||||||
|
void (*dev_reset)(DEVICE *dptr);
|
||||||
|
struct pdp_dib *dib; /* Pointer back to DIB */
|
||||||
|
int drive; /* Last drive selected */
|
||||||
|
t_uint64 buf; /* Data buffer */
|
||||||
|
uint32 status; /* Status word */
|
||||||
|
uint16 cs1; /* Control register 1 */
|
||||||
|
uint16 cs2; /* Control register 1 */
|
||||||
|
uint16 error; /* Controller Error register */
|
||||||
|
uint32 wcr; /* Current word count */
|
||||||
|
uint32 cda; /* Current bus address */
|
||||||
|
uint16 dba; /* Input data buffer */
|
||||||
|
uint16 dbb; /* Output data buffer*/
|
||||||
|
int rae; /* Access register error */
|
||||||
|
int attn; /* Attention bits */
|
||||||
|
int xfer_drive; /* Current transfering drive */
|
||||||
|
uint16 regs[16]; /* Space for TM03 formater */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Device context block */
|
||||||
|
struct pdp_dib {
|
||||||
|
uint32 uba_addr; /* device address, includes adaptor */
|
||||||
|
uint32 uba_mask; /* Compare mask */
|
||||||
|
uint16 uba_vect; /* Floating IRQ vector */
|
||||||
|
uint16 uba_br; /* Unibus IRQ level */
|
||||||
|
uint16 uba_ctl; /* Unibus controller number */
|
||||||
|
t_stat (*rd_io)(DEVICE *dptr, t_addr addr, uint16 *data, int32 access);
|
||||||
|
t_stat (*wr_io)(DEVICE *dptr, t_addr addr, uint16 data, int32 access);
|
||||||
|
uint16 (*irqv)(struct pdp_dib *dibp);
|
||||||
|
uint8 uba_irq_pend; /* Device has pending */
|
||||||
|
struct rh_if *rh11_if;
|
||||||
|
};
|
||||||
|
typedef struct pdp_dib DIB;
|
||||||
|
|
||||||
|
void cty_wakeup();
|
||||||
|
void cty_interrupt();
|
||||||
|
void cty_execute(int addr);
|
||||||
|
t_stat cty_reset (DEVICE *dptr);
|
||||||
|
|
||||||
|
|
||||||
|
#define WORD 0
|
||||||
|
#define BYTE 1
|
||||||
|
int uba_read(t_addr addr, int ctl, uint64 *data, int access);
|
||||||
|
int uba_write(t_addr addr, int ctl, uint64 data, int access);
|
||||||
|
int uba_read_npr(t_addr addr, uint16 ctl, uint64 *data);
|
||||||
|
int uba_write_npr(t_addr addr, uint16 ctl, uint64 data);
|
||||||
|
int uba_read_npr_byte(t_addr addr, uint16 ctl, uint8 *data);
|
||||||
|
int uba_write_npr_byte(t_addr addr, uint16 ctl, uint8 data);
|
||||||
|
int uba_read_npr_word(t_addr addr, uint16 ctl, uint16 *data);
|
||||||
|
int uba_write_npr_word(t_addr addr, uint16 ctl, uint16 data);
|
||||||
|
void uba_set_irq(DIB *dibp, int vect);
|
||||||
|
void uba_clr_irq(DIB *dibp, int vect);
|
||||||
|
t_addr uba_get_vect(t_addr addr, int lvl, int dev);
|
||||||
|
void uba_set_parity(uint16 ctl);
|
||||||
|
uint16 uba_rh_vect(struct pdp_dib *dibp);
|
||||||
|
int uba_rh_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access);
|
||||||
|
int uba_rh_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access);
|
||||||
|
void uba_reset();
|
||||||
|
|
||||||
|
t_stat uba_set_addr(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
t_stat uba_show_addr (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||||
|
t_stat uba_set_br(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
t_stat uba_show_br (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||||
|
t_stat uba_set_vect(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
t_stat uba_show_vect (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||||
|
t_stat uba_set_ctl(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
t_stat uba_show_ctl (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||||
|
|
||||||
|
void rh_reset(DEVICE *dptr, struct rh_if *rh);
|
||||||
|
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);
|
||||||
|
#else
|
||||||
extern t_stat (*dev_tab[128])(uint32 dev, t_uint64 *data);
|
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 */
|
||||||
|
@ -512,6 +650,7 @@ struct rh_if {
|
||||||
int rae; /* Access register error */
|
int rae; /* Access register error */
|
||||||
int attn; /* Attention bits */
|
int attn; /* Attention bits */
|
||||||
int xfer_drive; /* Current transfering drive */
|
int xfer_drive; /* Current transfering drive */
|
||||||
|
uint16 regs[16]; /* Space for TM03 formater */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Device context block */
|
/* Device context block */
|
||||||
|
@ -551,6 +690,7 @@ 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_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||||
t_stat rh_devio(uint32 dev, t_uint64 *data);
|
t_stat rh_devio(uint32 dev, t_uint64 *data);
|
||||||
t_addr rh_devirq(uint32 dev, t_addr addr);
|
t_addr rh_devirq(uint32 dev, t_addr addr);
|
||||||
|
void rh_reset(DEVICE *dptr, struct rh_if *rh);
|
||||||
#if KL
|
#if KL
|
||||||
void rh20_setup(struct rh_if *rhc);
|
void rh20_setup(struct rh_if *rhc);
|
||||||
#endif
|
#endif
|
||||||
|
@ -565,23 +705,18 @@ int rh_read(struct rh_if *rh);
|
||||||
int rh_write(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);
|
||||||
extern void ka10_lights_main (t_uint64);
|
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);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* I/O system parameters */
|
/* I/O system parameters */
|
||||||
|
#if !(PDP6 | KS)
|
||||||
#define NUM_DEVS_LP 1
|
#define NUM_DEVS_LP 1
|
||||||
#if KL
|
#endif
|
||||||
#define NUM_DEVS_PT 0
|
#if !(KL | KS)
|
||||||
#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
|
||||||
|
@ -597,34 +732,48 @@ extern void ka10_lights_clear_aux (int);
|
||||||
#define NUM_DEVS_DCS 1
|
#define NUM_DEVS_DCS 1
|
||||||
#define NUM_DEVS_SLAVE PDP6
|
#define NUM_DEVS_SLAVE PDP6
|
||||||
#endif
|
#endif
|
||||||
#if !PDP6
|
#if !(PDP6 | KS)
|
||||||
#define NUM_DEVS_DC 1
|
#define NUM_DEVS_DC 1
|
||||||
#define NUM_DEVS_MT 1
|
#define NUM_DEVS_MT 1
|
||||||
|
#endif
|
||||||
#if KL
|
#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_LP20 1
|
||||||
#define NUM_DEVS_TTY 1
|
#define NUM_DEVS_TTY 1
|
||||||
#define NUM_LINES_TTY 64
|
#define NUM_LINES_TTY 64
|
||||||
#define NUM_DEVS_NIA 1
|
#define NUM_DEVS_NIA 1
|
||||||
#else
|
#define NUM_DEVS_DN 0
|
||||||
|
#elif KS
|
||||||
|
#define NUM_DEVS_LP20 1
|
||||||
|
#define NUM_DEVS_DZ 4
|
||||||
|
#define NUM_DEVS_TCU 1
|
||||||
|
#define NUM_DEVS_DUP 2
|
||||||
|
#define NUM_DEVS_KMC 2
|
||||||
|
#if KS_ITS
|
||||||
|
#define NUM_DEVS_IMP KS_ITS
|
||||||
|
#define NUM_DEVS_CH11 KS_ITS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if KA | KI
|
||||||
#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
|
#endif
|
||||||
|
#if KS
|
||||||
|
#define NUM_DEVS_RP 1
|
||||||
|
#elif KA | KI | KL
|
||||||
#define NUM_DEVS_RP 4
|
#define NUM_DEVS_RP 4
|
||||||
#define NUM_DEVS_RS 1
|
#define NUM_DEVS_RS 1
|
||||||
|
#endif
|
||||||
|
#if !(PDP6)
|
||||||
#define NUM_DEVS_TU 1
|
#define NUM_DEVS_TU 1
|
||||||
|
#endif
|
||||||
|
#if KA
|
||||||
#define NUM_DEVS_PMP WAITS
|
#define NUM_DEVS_PMP WAITS
|
||||||
#define NUM_DEVS_DKB (WAITS * USE_DISPLAY)
|
#define NUM_DEVS_DKB (WAITS * USE_DISPLAY)
|
||||||
#define NUM_DEVS_III (WAITS * USE_DISPLAY)
|
#define NUM_DEVS_III (WAITS * USE_DISPLAY)
|
||||||
#define NUM_DEVS_PD ITS | KL_ITS
|
#define NUM_DEVS_TV (WAITS * USE_DISPLAY)
|
||||||
|
#define NUM_DEVS_PD ITS
|
||||||
#define NUM_DEVS_PCLK WAITS
|
#define NUM_DEVS_PCLK WAITS
|
||||||
#define NUM_DEVS_IMX ITS
|
#define NUM_DEVS_IMX ITS
|
||||||
#define NUM_DEVS_STK ITS
|
#define NUM_DEVS_STK ITS
|
||||||
|
@ -632,11 +781,16 @@ extern void ka10_lights_clear_aux (int);
|
||||||
#define NUM_DEVS_MTY ITS
|
#define NUM_DEVS_MTY ITS
|
||||||
#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 ITS
|
||||||
#define NUM_DEVS_CH10 ITS | KL_ITS
|
#define NUM_DEVS_CH10 ITS
|
||||||
#define NUM_DEVS_DPK ITS
|
#define NUM_DEVS_DPK ITS
|
||||||
#define NUM_DEVS_AI ITS
|
#define NUM_DEVS_AI ITS
|
||||||
#endif
|
#endif
|
||||||
|
#if KL_ITS
|
||||||
|
#define NUM_DEVS_PD KL_ITS
|
||||||
|
#define NUM_DEVS_IMP KL_ITS
|
||||||
|
#define NUM_DEVS_CH10 KL_ITS
|
||||||
|
#endif
|
||||||
#if MAGIC_SWITCH && !KA && !ITS
|
#if MAGIC_SWITCH && !KA && !ITS
|
||||||
#error "Magic switch only valid on KA10 with ITS mods"
|
#error "Magic switch only valid on KA10 with ITS mods"
|
||||||
#endif
|
#endif
|
||||||
|
@ -645,12 +799,20 @@ extern void ka10_lights_clear_aux (int);
|
||||||
|
|
||||||
|
|
||||||
extern t_bool sim_idle_enab;
|
extern t_bool sim_idle_enab;
|
||||||
|
#if !KS
|
||||||
extern struct rh_dev rh[];
|
extern struct rh_dev rh[];
|
||||||
|
#endif
|
||||||
extern t_uint64 M[MAXMEMSIZE];
|
extern t_uint64 M[MAXMEMSIZE];
|
||||||
extern t_uint64 FM[];
|
extern t_uint64 FM[];
|
||||||
extern uint32 PC;
|
extern uint32 PC;
|
||||||
extern uint32 FLAGS;
|
extern uint32 FLAGS;
|
||||||
|
|
||||||
|
#if NUM_DEVS_TEN11
|
||||||
|
int ten11_read (t_addr addr, t_uint64 *data);
|
||||||
|
int ten11_write (t_addr addr, t_uint64 data);
|
||||||
|
extern t_addr ten11_base;
|
||||||
|
extern t_addr ten11_end;
|
||||||
|
#endif
|
||||||
#if NUM_DEVS_AUXCPU
|
#if NUM_DEVS_AUXCPU
|
||||||
extern t_addr auxcpu_base;
|
extern t_addr auxcpu_base;
|
||||||
int auxcpu_read (t_addr addr, uint64 *);
|
int auxcpu_read (t_addr addr, uint64 *);
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
/* Flags in the unit flags word */
|
/* Flags in the unit flags word */
|
||||||
|
|
||||||
#define UNIT_V_FMT (UNIT_V_UF + 8)
|
#define UNIT_V_FMT (UNIT_V_UF + 7)
|
||||||
#define UNIT_M_FMT 7
|
#define UNIT_M_FMT 7
|
||||||
#define GET_FMT(x) (((x) >> UNIT_V_FMT) & UNIT_M_FMT)
|
#define GET_FMT(x) (((x) >> UNIT_V_FMT) & UNIT_M_FMT)
|
||||||
#define SET_FMT(x) (((x) & UNIT_M_FMT) << UNIT_V_FMT)
|
#define SET_FMT(x) (((x) & UNIT_M_FMT) << UNIT_V_FMT)
|
||||||
|
|
|
@ -717,7 +717,7 @@ t_stat dp_svc (UNIT *uptr)
|
||||||
CLR_BUF(uptr);
|
CLR_BUF(uptr);
|
||||||
}
|
}
|
||||||
if (r)
|
if (r)
|
||||||
sim_activate(uptr, 40);
|
sim_activate(uptr, 25);
|
||||||
else {
|
else {
|
||||||
uptr->STATUS &= ~(SRC_DONE|END_CYL|BUSY);
|
uptr->STATUS &= ~(SRC_DONE|END_CYL|BUSY);
|
||||||
uptr->UFLAGS |= DONE;
|
uptr->UFLAGS |= DONE;
|
||||||
|
|
305
PDP10/kx10_dpy.c
305
PDP10/kx10_dpy.c
|
@ -109,6 +109,7 @@
|
||||||
|
|
||||||
#include "kx10_defs.h"
|
#include "kx10_defs.h"
|
||||||
#include "sim_video.h"
|
#include "sim_video.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#ifndef NUM_DEVS_DPY
|
#ifndef NUM_DEVS_DPY
|
||||||
#define NUM_DEVS_DPY 0
|
#define NUM_DEVS_DPY 0
|
||||||
|
@ -120,6 +121,8 @@
|
||||||
|
|
||||||
#define DPY_DEVNUM 0130
|
#define DPY_DEVNUM 0130
|
||||||
|
|
||||||
|
#define FULLSCREEN (1 << (UNIT_V_UF))
|
||||||
|
|
||||||
#define RRZ(W) ((W) & RMASK)
|
#define RRZ(W) ((W) & RMASK)
|
||||||
#define XWD(L,R) ((((uint64)(L))<<18)|((uint64)(R)))
|
#define XWD(L,R) ((((uint64)(L))<<18)|((uint64)(R)))
|
||||||
|
|
||||||
|
@ -187,12 +190,20 @@ UNIT dpy_unit[] = {
|
||||||
|
|
||||||
#define UPTR(UNIT) (dpy_unit+(UNIT))
|
#define UPTR(UNIT) (dpy_unit+(UNIT))
|
||||||
|
|
||||||
|
MTAB dpy_mod[] = {
|
||||||
|
{ FULLSCREEN, FULLSCREEN, "FULLSCREEN", "FULLSCREEN", NULL, NULL, NULL,
|
||||||
|
"Display in fullscreen"},
|
||||||
|
{ FULLSCREEN, 0, NULL, "WINDOW", NULL, NULL, NULL,
|
||||||
|
"Display in window"},
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
DEVICE dpy_dev = {
|
DEVICE dpy_dev = {
|
||||||
"DPY", dpy_unit, NULL, NULL,
|
"DPY", dpy_unit, NULL, dpy_mod,
|
||||||
NUM_DEVS_DPY, 0, 0, 0, 0, 0,
|
NUM_DEVS_DPY, 0, 0, 0, 0, 0,
|
||||||
NULL, NULL, dpy_reset,
|
NULL, NULL, dpy_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
&dpy_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_DISPLAY, 0, NULL,
|
&dpy_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_DISPLAY, 0, dev_debug,
|
||||||
NULL, NULL, NULL, NULL, NULL, &dpy_description
|
NULL, NULL, NULL, NULL, NULL, &dpy_description
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -348,10 +359,21 @@ static void dpy_joy_motion(int which, int axis, int value)
|
||||||
static void dpy_joy_button(int which, int button, int state)
|
static void dpy_joy_button(int which, int button, int state)
|
||||||
{
|
{
|
||||||
if (which < JOY_MAX_UNITS && button < JOY_MAX_BUTTONS) {
|
if (which < JOY_MAX_UNITS && button < JOY_MAX_BUTTONS) {
|
||||||
joy_buttons[which * JOY_MAX_UNITS + button] = state;
|
joy_buttons[which * JOY_MAX_BUTTONS + button] = state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dpy_keyboard (SIM_KEY_EVENT *ev)
|
||||||
|
{
|
||||||
|
sim_debug(DEBUG_DATA, &dpy_dev, "Key %d %s\n",
|
||||||
|
ev->key, ev->state == SIM_KEYPRESS_DOWN ? "down" : "up");
|
||||||
|
if (ev->state == SIM_KEYPRESS_UP && ev->key == SIM_KEY_F11) {
|
||||||
|
vid_set_fullscreen (!vid_is_fullscreen ());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
||||||
t_stat dpy_reset (DEVICE *dptr)
|
t_stat dpy_reset (DEVICE *dptr)
|
||||||
|
@ -359,8 +381,15 @@ t_stat dpy_reset (DEVICE *dptr)
|
||||||
if (dptr->flags & DEV_DIS) {
|
if (dptr->flags & DEV_DIS) {
|
||||||
display_close(dptr);
|
display_close(dptr);
|
||||||
} else {
|
} else {
|
||||||
|
#if ITS
|
||||||
|
if (stk_dev.flags & DEV_DIS) {
|
||||||
|
sim_debug(DEBUG_DETAIL, &dpy_dev, "Grabbing keyboard\n");
|
||||||
|
vid_display_kb_event_process = dpy_keyboard;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
display_reset();
|
display_reset();
|
||||||
ty340_reset(dptr);
|
ty340_reset(dptr);
|
||||||
|
vid_set_fullscreen (dpy_unit[0].flags & FULLSCREEN);
|
||||||
vid_register_gamepad_motion_callback (dpy_joy_motion);
|
vid_register_gamepad_motion_callback (dpy_joy_motion);
|
||||||
vid_register_gamepad_button_callback (dpy_joy_button);
|
vid_register_gamepad_button_callback (dpy_joy_button);
|
||||||
}
|
}
|
||||||
|
@ -427,37 +456,63 @@ 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)
|
#define UNIT_JOY (1 << DEV_V_UF) /* Use USB gaming devices. */
|
||||||
|
#define UNIT_CSCOPE (1 << (DEV_V_UF+1)) /* Enable color scope. */
|
||||||
|
|
||||||
t_stat wcnsls_devio(uint32 dev, uint64 *data);
|
t_stat wcnsls_devio(uint32 dev, uint64 *data);
|
||||||
|
t_stat wcnsls_svc (UNIT *uptr);
|
||||||
|
t_stat wcnsls_reset (DEVICE *dptr);
|
||||||
const char *wcnsls_description (DEVICE *dptr);
|
const char *wcnsls_description (DEVICE *dptr);
|
||||||
|
|
||||||
|
static uint64 dev420_cono = 0;
|
||||||
|
static uint8 cscope_r = 0;
|
||||||
|
static uint8 cscope_g = 0;
|
||||||
|
static uint8 cscope_b = 0;
|
||||||
|
static VID_DISPLAY *cscope_display = NULL;
|
||||||
|
static uint32 fade[512 * 512];
|
||||||
|
static uint32 dot[7 * 7];
|
||||||
|
|
||||||
DIB wcnsls_dib[] = {
|
DIB wcnsls_dib[] = {
|
||||||
{ WCNSLS_DEVNUM, 1, &wcnsls_devio, NULL }};
|
{ WCNSLS_DEVNUM, 1, &wcnsls_devio, NULL }};
|
||||||
|
|
||||||
MTAB wcnsls_mod[] = {
|
MTAB wcnsls_mod[] = {
|
||||||
{ UNIT_JOY, UNIT_JOY, "JOYSTICK", "JOYSTICK", NULL, NULL, NULL,
|
{ UNIT_JOY, UNIT_JOY, "JOYSTICK", "JOYSTICK", NULL, NULL, NULL,
|
||||||
"Use USB joysticks"},
|
"Use USB joysticks"},
|
||||||
|
{ UNIT_CSCOPE, UNIT_CSCOPE, "CSCOPE", "CSCOPE", NULL, NULL, NULL,
|
||||||
|
"Enable color scope"},
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
UNIT wcnsls_unit[] = {
|
UNIT wcnsls_unit[] = {
|
||||||
{ UDATA (NULL, UNIT_IDLE, 0) }};
|
{ UDATA (wcnsls_svc, UNIT_IDLE, 0) }};
|
||||||
|
|
||||||
|
REG wcnsls_reg[] = {
|
||||||
|
{ORDATA(CONO, dev420_cono, 18)},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
DEVICE wcnsls_dev = {
|
DEVICE wcnsls_dev = {
|
||||||
"WCNSLS", wcnsls_unit, NULL, wcnsls_mod,
|
"WCNSLS", wcnsls_unit, wcnsls_reg, wcnsls_mod,
|
||||||
NUM_DEVS_WCNSLS, 0, 0, 0, 0, 0,
|
NUM_DEVS_WCNSLS, 0, 0, 0, 0, 0,
|
||||||
|
NULL, NULL, wcnsls_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL,
|
&wcnsls_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, dev_debug,
|
||||||
&wcnsls_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, NULL,
|
|
||||||
NULL, NULL, NULL, NULL, NULL, &wcnsls_description
|
NULL, NULL, NULL, NULL, NULL, &wcnsls_description
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *wcnsls_description (DEVICE *dptr)
|
const char *wcnsls_description (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
return "MIT Spacewar Consoles";
|
return "MIT Spacewar Consoles, and DEC color scope";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Device 420 CONO bits. */
|
||||||
|
#define CONO_BLUE 0000020 /* Color scope blue enable */
|
||||||
|
#define CONO_SPCWAR 0000040 /* Spacewar consoles */
|
||||||
|
#define CONO_GREEN 0002000 /* Color scope green enable */
|
||||||
|
#define CONO_RANDOM 0004000 /* Random switches */
|
||||||
|
#define CONO_RED 0200000 /* Color scope red enable */
|
||||||
|
#define CONO_KNIGHT 0400000 /* Switches in TK's office */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
|
@ -485,55 +540,86 @@ const char *wcnsls_description (DEVICE *dptr)
|
||||||
#define BUT2 (JOY_MAX_BUTTONS*2)
|
#define BUT2 (JOY_MAX_BUTTONS*2)
|
||||||
#define BUT3 (JOY_MAX_BUTTONS*3)
|
#define BUT3 (JOY_MAX_BUTTONS*3)
|
||||||
|
|
||||||
|
static void
|
||||||
|
cscope_init (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
fade[0] = vid_map_rgba_window (cscope_display, 0, 0, 0, 240);
|
||||||
|
for (i = 1; i < 512 * 512; i++)
|
||||||
|
fade[i] = fade[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cscope_plot(int x, int y)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < 7; i++) {
|
||||||
|
for (j = 0; j < 7; j++) {
|
||||||
|
int dx = i - 3, dy = j - 3;
|
||||||
|
int r2 = dx*dx + dy*dy;
|
||||||
|
double focus = 0.2;
|
||||||
|
double intensity = 0xFF/15.0;
|
||||||
|
double alpha = 0xFF*exp(-focus*r2);
|
||||||
|
dot[i + 7*j] = vid_map_rgba_window (cscope_display,
|
||||||
|
(uint8)(intensity*(cscope_r << 4)),
|
||||||
|
(uint8)(intensity*(cscope_g << 4)),
|
||||||
|
(uint8)(intensity*(cscope_b << 4)),
|
||||||
|
(uint8)alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vid_draw_window (cscope_display, x - 3, 511 - y - 3, 7, 7, dot);
|
||||||
|
}
|
||||||
|
|
||||||
static uint64 joystick_switches (void)
|
static uint64 joystick_switches (void)
|
||||||
{
|
{
|
||||||
uint64 switches = 0777777777777LL;
|
uint64 switches = 0777777777777LL;
|
||||||
|
|
||||||
if (joy_axes[JOY0] > JOY_TRIG)
|
if (joy_axes[JOY0] > JOY_TRIG)
|
||||||
switches &= ~(CCW << UR);
|
switches &= ~(CCW << UR);
|
||||||
else if (joy_axes[JOY0] < -JOY_TRIG)
|
else if (joy_axes[JOY0] < -JOY_TRIG)
|
||||||
switches &= ~(CW << UR);
|
switches &= ~(CW << UR);
|
||||||
if (joy_axes[JOY0+1] < -JOY_TRIG)
|
if (joy_axes[JOY0+1] < -JOY_TRIG)
|
||||||
switches &= ~(THRUST << UR);
|
switches &= ~(THRUST << UR);
|
||||||
if (joy_buttons[BUT0])
|
if (joy_buttons[BUT0])
|
||||||
switches &= ~(FIRE << UR);
|
switches &= ~(FIRE << UR);
|
||||||
if (joy_buttons[BUT0+1])
|
if (joy_buttons[BUT0+1])
|
||||||
switches &= ~(HYPER << UR);
|
switches &= ~(HYPER << UR);
|
||||||
|
|
||||||
if (joy_axes[JOY1] > JOY_TRIG)
|
if (joy_axes[JOY1] > JOY_TRIG)
|
||||||
switches &= ~(CCW << LR);
|
switches &= ~(CCW << LR);
|
||||||
else if (joy_axes[JOY1] < -JOY_TRIG)
|
else if (joy_axes[JOY1] < -JOY_TRIG)
|
||||||
switches &= ~(CW << LR);
|
switches &= ~(CW << LR);
|
||||||
if (joy_axes[JOY1+1] < -JOY_TRIG)
|
if (joy_axes[JOY1+1] < -JOY_TRIG)
|
||||||
switches &= ~(THRUST << LR);
|
switches &= ~(THRUST << LR);
|
||||||
if (joy_buttons[BUT1])
|
if (joy_buttons[BUT1])
|
||||||
switches &= ~(FIRE << LR);
|
switches &= ~(FIRE << LR);
|
||||||
if (joy_buttons[BUT1+1])
|
if (joy_buttons[BUT1+1])
|
||||||
switches &= ~(HYPER << LR);
|
switches &= ~(HYPER << LR);
|
||||||
|
|
||||||
if (joy_axes[JOY2] > JOY_TRIG)
|
if (joy_axes[JOY2] > JOY_TRIG)
|
||||||
switches &= ~(CCW << LL);
|
switches &= ~(CCW << LL);
|
||||||
else if (joy_axes[JOY2] < -JOY_TRIG)
|
else if (joy_axes[JOY2] < -JOY_TRIG)
|
||||||
switches &= ~(CW << LL);
|
switches &= ~(CW << LL);
|
||||||
if (joy_axes[JOY2+1] < -JOY_TRIG)
|
if (joy_axes[JOY2+1] < -JOY_TRIG)
|
||||||
switches &= ~(THRUST << LL);
|
switches &= ~(THRUST << LL);
|
||||||
if (joy_buttons[BUT2])
|
if (joy_buttons[BUT2])
|
||||||
switches &= ~(FIRE << LL);
|
switches &= ~(FIRE << LL);
|
||||||
if (joy_buttons[BUT2+1])
|
if (joy_buttons[BUT2+1])
|
||||||
switches &= ~(HYPER << LL);
|
switches &= ~(HYPER << LL);
|
||||||
|
|
||||||
if (joy_axes[JOY3] > JOY_TRIG)
|
if (joy_axes[JOY3] > JOY_TRIG)
|
||||||
switches &= ~((uint64)CCW << UL);
|
switches &= ~((uint64)CCW << UL);
|
||||||
else if (joy_axes[JOY3] < -JOY_TRIG)
|
else if (joy_axes[JOY3] < -JOY_TRIG)
|
||||||
switches &= ~((uint64)CW << UL);
|
switches &= ~((uint64)CW << UL);
|
||||||
if (joy_axes[JOY3+1] < -JOY_TRIG)
|
if (joy_axes[JOY3+1] < -JOY_TRIG)
|
||||||
switches &= ~((uint64)THRUST << UL);
|
switches &= ~((uint64)THRUST << UL);
|
||||||
if (joy_buttons[BUT3])
|
if (joy_buttons[BUT3])
|
||||||
switches &= ~((uint64)FIRE << UL);
|
switches &= ~((uint64)FIRE << UL);
|
||||||
if (joy_buttons[BUT3+1])
|
if (joy_buttons[BUT3+1])
|
||||||
switches &= ~(HYPER << UL);
|
switches &= ~(HYPER << UL);
|
||||||
|
|
||||||
return switches;
|
return switches;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64 keyboard_switches (void)
|
static uint64 keyboard_switches (void)
|
||||||
|
@ -562,17 +648,66 @@ static uint64 keyboard_switches (void)
|
||||||
return switches;
|
return switches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_stat wcnsls_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
vid_refresh_window (cscope_display);
|
||||||
|
vid_draw_window (cscope_display, 0, 0, 512, 512, fade);
|
||||||
|
sim_activate_after (uptr, 33333);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat
|
||||||
|
wcnsls_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
t_stat r;
|
||||||
|
if (sim_switches & SWMASK('P') || dptr->flags & DEV_DIS ||
|
||||||
|
(wcnsls_unit->flags & UNIT_CSCOPE) == 0) {
|
||||||
|
sim_cancel (wcnsls_unit);
|
||||||
|
if (cscope_display != NULL)
|
||||||
|
vid_close_window (cscope_display);
|
||||||
|
cscope_display = NULL;
|
||||||
|
} else if (cscope_display == NULL) {
|
||||||
|
r = vid_open_window (&cscope_display, dptr, "Color scope", 512, 512, 0);
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return r;
|
||||||
|
/* Allow time for window to open and data structures to settle. */
|
||||||
|
sim_os_sleep (1);
|
||||||
|
r = vid_set_alpha_mode (cscope_display, SIM_ALPHA_BLEND);
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return r;
|
||||||
|
sim_activate_abs (wcnsls_unit, 0);
|
||||||
|
cscope_init ();
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
t_stat wcnsls_devio(uint32 dev, uint64 *data) {
|
t_stat wcnsls_devio(uint32 dev, uint64 *data) {
|
||||||
switch (dev & 3) {
|
switch (dev & 3) {
|
||||||
case CONO:
|
case CONO:
|
||||||
/* CONO WCNSLS,40 ;enable spacewar consoles */
|
/* CONO WCNSLS,40 ;enable spacewar consoles */
|
||||||
|
sim_debug (DEBUG_CONO, &wcnsls_dev, "%06llo\n", *data);
|
||||||
|
dev420_cono = *data;
|
||||||
|
if (dev420_cono & CONO_RED)
|
||||||
|
cscope_r = (dev420_cono >> 12) & 017;
|
||||||
|
if (dev420_cono & CONO_GREEN)
|
||||||
|
cscope_g = (dev420_cono >> 6) & 017;
|
||||||
|
if (dev420_cono & CONO_BLUE)
|
||||||
|
cscope_b = dev420_cono & 017;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DATAO:
|
||||||
|
sim_debug (DEBUG_DATAIO, &wcnsls_dev, "DATAO %012llo\n", *data);
|
||||||
|
if (wcnsls_unit->flags & UNIT_CSCOPE)
|
||||||
|
cscope_plot((*data >> 9) & 0777, *data & 0777);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATAI:
|
case DATAI:
|
||||||
if (wcnsls_unit->flags & UNIT_JOY) {
|
if (dev420_cono & CONO_SPCWAR) {
|
||||||
*data = joystick_switches ();
|
if (wcnsls_unit->flags & UNIT_JOY) {
|
||||||
} else {
|
*data = joystick_switches ();
|
||||||
*data = keyboard_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",
|
||||||
|
@ -621,39 +756,39 @@ const char *ocnsls_description (DEVICE *dptr)
|
||||||
|
|
||||||
static uint64 old_switches (void)
|
static uint64 old_switches (void)
|
||||||
{
|
{
|
||||||
uint64 switches = 0;
|
uint64 switches = 0;
|
||||||
|
|
||||||
if (joy_axes[JOY0] > JOY_TRIG)
|
if (joy_axes[JOY0] > JOY_TRIG)
|
||||||
switches |= OCCW;
|
switches |= OCCW;
|
||||||
else if (joy_axes[JOY0] < -JOY_TRIG)
|
else if (joy_axes[JOY0] < -JOY_TRIG)
|
||||||
switches |= OCW;
|
switches |= OCW;
|
||||||
if (joy_axes[JOY0+1] < -JOY_TRIG)
|
if (joy_axes[JOY0+1] < -JOY_TRIG)
|
||||||
switches |= FAST;
|
switches |= FAST;
|
||||||
if (joy_axes[JOY0+1] > JOY_TRIG)
|
if (joy_axes[JOY0+1] > JOY_TRIG)
|
||||||
switches |= SLOW;
|
switches |= SLOW;
|
||||||
if (joy_buttons[BUT0])
|
if (joy_buttons[BUT0])
|
||||||
switches |= OFIRE;
|
switches |= OFIRE;
|
||||||
if (joy_buttons[BUT0+1])
|
if (joy_buttons[BUT0+1])
|
||||||
switches |= OHYPER;
|
switches |= OHYPER;
|
||||||
if (joy_buttons[BUT0+2])
|
if (joy_buttons[BUT0+2])
|
||||||
switches |= BEACON;
|
switches |= BEACON;
|
||||||
|
|
||||||
if (joy_axes[JOY1] > JOY_TRIG)
|
if (joy_axes[JOY1] > JOY_TRIG)
|
||||||
switches |= OCCW << 18;
|
switches |= OCCW << 18;
|
||||||
else if (joy_axes[JOY1] < -JOY_TRIG)
|
else if (joy_axes[JOY1] < -JOY_TRIG)
|
||||||
switches |= OCW << 18;
|
switches |= OCW << 18;
|
||||||
if (joy_axes[JOY1+1] < -JOY_TRIG)
|
if (joy_axes[JOY1+1] < -JOY_TRIG)
|
||||||
switches |= FAST << 18;
|
switches |= FAST << 18;
|
||||||
if (joy_axes[JOY1+1] > JOY_TRIG)
|
if (joy_axes[JOY1+1] > JOY_TRIG)
|
||||||
switches |= SLOW << 18;
|
switches |= SLOW << 18;
|
||||||
if (joy_buttons[BUT1])
|
if (joy_buttons[BUT1])
|
||||||
switches |= OFIRE << 18;
|
switches |= OFIRE << 18;
|
||||||
if (joy_buttons[BUT1+1])
|
if (joy_buttons[BUT1+1])
|
||||||
switches |= OHYPER << 18;
|
switches |= OHYPER << 18;
|
||||||
if (joy_buttons[BUT1+2])
|
if (joy_buttons[BUT1+2])
|
||||||
switches |= BEACON << 18;
|
switches |= BEACON << 18;
|
||||||
|
|
||||||
return switches;
|
return switches;
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat ocnsls_devio(uint32 dev, uint64 *data) {
|
t_stat ocnsls_devio(uint32 dev, uint64 *data) {
|
||||||
|
|
|
@ -1233,7 +1233,6 @@ void dt_flush (UNIT* uptr)
|
||||||
uint32 ba, k, *fbuf;
|
uint32 ba, k, *fbuf;
|
||||||
|
|
||||||
if (uptr->WRITTEN && uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
if (uptr->WRITTEN && uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||||
sim_printf ("%s: writing buffer to file: %s\n", sim_uname (uptr), uptr->filename);
|
|
||||||
rewind (uptr->fileref); /* start of file */
|
rewind (uptr->fileref); /* start of file */
|
||||||
fbuf = (uint32 *) uptr->filebuf; /* file buffer */
|
fbuf = (uint32 *) uptr->filebuf; /* file buffer */
|
||||||
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||||
|
@ -1285,8 +1284,10 @@ t_stat dt_detach (UNIT* uptr)
|
||||||
sim_cancel (uptr);
|
sim_cancel (uptr);
|
||||||
uptr->CMD = uptr->pos = 0;
|
uptr->CMD = uptr->pos = 0;
|
||||||
}
|
}
|
||||||
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) /* any data? */
|
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||||
dt_flush(uptr); /* end if hwmark */
|
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 */
|
free (uptr->filebuf); /* release buf */
|
||||||
uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */
|
uptr->flags = uptr->flags & ~UNIT_BUF; /* clear buf flag */
|
||||||
uptr->filebuf = NULL; /* clear buf ptr */
|
uptr->filebuf = NULL; /* clear buf ptr */
|
||||||
|
|
531
PDP10/kx10_imp.c
531
PDP10/kx10_imp.c
|
@ -44,6 +44,59 @@
|
||||||
#define TYPE_BBN 1 /* BBN style interface TENEX */
|
#define TYPE_BBN 1 /* BBN style interface TENEX */
|
||||||
#define TYPE_WAITS 2 /* IMP connected to waits system. */
|
#define TYPE_WAITS 2 /* IMP connected to waits system. */
|
||||||
|
|
||||||
|
#define TYPE_UNI 0 /* Unibus byte order */
|
||||||
|
#define TYPE_SIMP 1 /* PDP10 string byte order */
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
/* IMP11 interface */
|
||||||
|
|
||||||
|
/* CSR values */
|
||||||
|
#define CSR_GO 0000001 /* Go transfer */
|
||||||
|
#define CSR_RST 0000002 /* Reset interface */
|
||||||
|
#define CSR_UBA 0000060 /* Unibus upper address */
|
||||||
|
#define CSR_IE 0000100 /* Interrupt enable */
|
||||||
|
#define CSR_RDY 0000200 /* Device ready */
|
||||||
|
#define CSR_MRE 0001000 /* Master error */
|
||||||
|
#define CSR_NXM 0040000 /* Non existant memory */
|
||||||
|
#define CSR_ERR 0100000 /* Error present */
|
||||||
|
|
||||||
|
/* Input CSR 0767600 */
|
||||||
|
#define CSR_HRC 0000004 /* Host Ready Relay Control */
|
||||||
|
#define CSR_SE 0000010 /* Store enable */
|
||||||
|
#define CSR_IBF 0000400 /* Input Buffer full */
|
||||||
|
#define CSR_INR 0002000 /* IMP not ready */
|
||||||
|
#define CSR_HR 0004000 /* Host Ready */
|
||||||
|
#define CSR_EOM 0020000 /* End of Message */
|
||||||
|
|
||||||
|
/* Input data buffer 0767602 */
|
||||||
|
/* Input Bus Address 0767604 */
|
||||||
|
/* Input Word Count 0767606 */
|
||||||
|
|
||||||
|
/* Output CSR 07676010 */
|
||||||
|
#define CSR_ELB 0000004 /* Send EOM indication to IMP */
|
||||||
|
#define CSR_BB 0000010 /* Bus Back */
|
||||||
|
#define CSR_OBE 0000400 /* OUtput Buffer Empty */
|
||||||
|
#define CSR_WC0 0020000 /* Output Word Count 0 */
|
||||||
|
|
||||||
|
/* Output data buffer 0767612 */
|
||||||
|
/* Output Bus Address 0767614 */
|
||||||
|
/* Output Word Count 0767616 */
|
||||||
|
|
||||||
|
/* Bits in STATUS */
|
||||||
|
#define IMPID 010 /* Input done. */
|
||||||
|
#define IMPIB 040 /* Input busy. */
|
||||||
|
#define IMPOD 0100 /* Output done. */
|
||||||
|
#define IMPOB 0400 /* Output busy. */
|
||||||
|
#define IMPERR 01000 /* IMP error. */
|
||||||
|
#define IMPR 02000 /* IMP ready. */
|
||||||
|
#define IMPIC 04000 /* IMP interrupt condition. */
|
||||||
|
#define IMPHER 010000 /* Host error. */
|
||||||
|
#define IMPHR 020000 /* Host ready. */
|
||||||
|
#define IMPIHE 040000 /* Inhibit interrupt on host error. */
|
||||||
|
#define IMPLW 0100000 /* Last IMP word. */
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
/* ITS IMP Bits */
|
/* ITS IMP Bits */
|
||||||
|
|
||||||
/* CONI */
|
/* CONI */
|
||||||
|
@ -123,6 +176,7 @@
|
||||||
/* CONI timeout. If no CONI instruction is executed for 3-5 seconds,
|
/* CONI timeout. If no CONI instruction is executed for 3-5 seconds,
|
||||||
the interface will raise the host error signal. */
|
the interface will raise the host error signal. */
|
||||||
#define CONI_TIMEOUT 3000000
|
#define CONI_TIMEOUT 3000000
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STATUS u3
|
#define STATUS u3
|
||||||
#define OPOS u4 /* Output bit position */
|
#define OPOS u4 /* Output bit position */
|
||||||
|
@ -435,8 +489,14 @@ 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};
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
int imp_wr(DEVICE *dptr, t_addr addr, uint16 data, int32 access);
|
||||||
|
int imp_rd(DEVICE *dptr, t_addr addr, uint16 *data, int32 access);
|
||||||
|
uint16 imp_vect(struct pdp_dib *dibp);
|
||||||
|
#else
|
||||||
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_addr imp_devirq(uint32 dev, t_addr addr);
|
||||||
|
#endif
|
||||||
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 *);
|
||||||
|
@ -480,22 +540,38 @@ const char *imp_description (DEVICE *dptr);
|
||||||
static char *ipv4_inet_ntoa(struct in_addr ip);
|
static char *ipv4_inet_ntoa(struct in_addr ip);
|
||||||
static int ipv4_inet_aton(const char *str, struct in_addr *inp);
|
static int ipv4_inet_aton(const char *str, struct in_addr *inp);
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
uint16 imp_icsr;
|
||||||
|
uint16 imp_idb;
|
||||||
|
uint32 imp_iba;
|
||||||
|
uint16 imp_iwcnt;
|
||||||
|
uint16 imp_ocsr;
|
||||||
|
uint16 imp_odb;
|
||||||
|
uint32 imp_oba;
|
||||||
|
uint16 imp_owcnt;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int imp_mpx_lvl = 0;
|
int imp_mpx_lvl = 0;
|
||||||
double last_coni;
|
double last_coni;
|
||||||
|
|
||||||
UNIT imp_unit[] = {
|
UNIT imp_unit[] = {
|
||||||
{UDATA(imp_srv, UNIT_IDLE+UNIT_ATTABLE+UNIT_DHCP, 0)}, /* 0 */
|
{UDATA(imp_srv, UNIT_IDLE+UNIT_ATTABLE+UNIT_DHCP, 0)}, /* 0 */
|
||||||
{UDATA(imp_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */
|
{UDATA(imp_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 1 */
|
||||||
{UDATA(imp_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */
|
{UDATA(imp_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 2 */
|
||||||
};
|
};
|
||||||
DIB imp_dib = {IMP_DEVNUM, 1, &imp_devio,
|
|
||||||
|
#if KS
|
||||||
|
DIB imp_dib = {0767600, 017, 0250, 6, 3, &imp_rd, &imp_wr, 0, 0, 0};
|
||||||
|
#else
|
||||||
|
DIB imp_dib = {IMP_DEVNUM, 1, &imp_devio,
|
||||||
#if KL
|
#if KL
|
||||||
&imp_devirq,
|
&imp_devirq,
|
||||||
#else
|
#else
|
||||||
NULL
|
NULL
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
#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",
|
||||||
|
@ -516,16 +592,33 @@ MTAB imp_mod[] = {
|
||||||
"Use DHCP to set IP address"},
|
"Use DHCP to set IP address"},
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DHCPIP", NULL,
|
{ MTAB_XTD|MTAB_VDV, 0, "DHCPIP", NULL,
|
||||||
NULL, &imp_show_dhcpip, NULL, "DHCP info" },
|
NULL, &imp_show_dhcpip, NULL, "DHCP info" },
|
||||||
|
#if KS
|
||||||
|
{ UNIT_DTYPE, (TYPE_UNI << UNIT_V_DTYPE), "UNI", "UNI", NULL, NULL, NULL,
|
||||||
|
"Standard Unibus transfers"},
|
||||||
|
{ UNIT_DTYPE, (TYPE_SIMP << UNIT_V_DTYPE), "SIMP", "SIMP", NULL, NULL, NULL,
|
||||||
|
"PDP10 byte order transfers"},
|
||||||
|
#else
|
||||||
{ UNIT_DTYPE, (TYPE_MIT << UNIT_V_DTYPE), "MIT", "MIT", NULL, NULL, NULL,
|
{ UNIT_DTYPE, (TYPE_MIT << UNIT_V_DTYPE), "MIT", "MIT", NULL, NULL, NULL,
|
||||||
"ITS/MIT style interface"},
|
"ITS/MIT style interface"},
|
||||||
{ UNIT_DTYPE, (TYPE_BBN << UNIT_V_DTYPE), "BBN", "BBN", NULL, NULL, NULL,
|
{ UNIT_DTYPE, (TYPE_BBN << UNIT_V_DTYPE), "BBN", "BBN", NULL, NULL, NULL,
|
||||||
"Tenex/BBN style interface"},
|
"Tenex/BBN style interface"},
|
||||||
{ UNIT_DTYPE, (TYPE_WAITS << UNIT_V_DTYPE), "WAITS", "WAITS", NULL, NULL, NULL,
|
{ UNIT_DTYPE, (TYPE_WAITS << UNIT_V_DTYPE), "WAITS", "WAITS", NULL, NULL, NULL,
|
||||||
"WAITS style interface"},
|
"WAITS style interface"},
|
||||||
|
#endif
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "ARP", NULL,
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "ARP", NULL,
|
||||||
NULL, &imp_show_arp, NULL, "ARP IP address->MAC address table" },
|
NULL, &imp_show_arp, NULL, "ARP IP address->MAC address table" },
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, NULL, "ARP=ddd.ddd.ddd.ddd=XX:XX:XX:XX:XX:XX",
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, NULL, "ARP=ddd.ddd.ddd.ddd=XX:XX:XX:XX:XX:XX",
|
||||||
&imp_set_arp, NULL, NULL, "Create a static ARP Entry" },
|
&imp_set_arp, NULL, NULL, "Create a static ARP Entry" },
|
||||||
|
#if KS
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "addr", "addr", &uba_set_addr, uba_show_addr,
|
||||||
|
NULL, "Sets address of CH11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "vect", "vect", &uba_set_vect, uba_show_vect,
|
||||||
|
NULL, "Sets vect of CH11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "br", "br", &uba_set_br, uba_show_br,
|
||||||
|
NULL, "Sets br of CH11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "ctl", "ctl", &uba_set_ctl, uba_show_ctl,
|
||||||
|
NULL, "Sets uba of CH11" },
|
||||||
|
#endif
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -570,6 +663,180 @@ DEVICE imp_dev = {
|
||||||
#define IMP_ICHN 0000070
|
#define IMP_ICHN 0000070
|
||||||
#define IMP_ECHN 0000700
|
#define IMP_ECHN 0000700
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
static void check_interrupts (UNIT *uptr)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = &imp_dev;
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
|
||||||
|
if ((uptr->STATUS & IMPID) != 0 && imp_icsr & CSR_IE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
imp_wr(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||||
|
{
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
UNIT *uptr = imp_unit;
|
||||||
|
|
||||||
|
addr &= dibp->uba_mask;
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "IMP11 write %06o %06o %o\n",
|
||||||
|
addr, data, access);
|
||||||
|
|
||||||
|
switch (addr & 016) {
|
||||||
|
case 000: /* Input CSR */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (imp_icsr & 0377);
|
||||||
|
else
|
||||||
|
data = (imp_icsr & 0177400) | data;
|
||||||
|
}
|
||||||
|
if (data & CSR_RST) {
|
||||||
|
imp_icsr = CSR_INR|CSR_RDY;
|
||||||
|
imp_iba = 0;
|
||||||
|
imp_iwcnt = 0;
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
data &= (CSR_GO|CSR_RST|CSR_UBA|CSR_IE|CSR_HRC|CSR_SE);
|
||||||
|
imp_icsr &= ~(CSR_GO|CSR_RST|CSR_UBA|CSR_IE|CSR_HRC|CSR_SE|CSR_ERR
|
||||||
|
|CSR_NXM|CSR_MRE);
|
||||||
|
imp_icsr |= data;
|
||||||
|
if (data & CSR_HRC) {
|
||||||
|
imp_icsr |= CSR_HR;
|
||||||
|
} else {
|
||||||
|
imp_icsr &= ~CSR_HR;
|
||||||
|
imp_icsr |= CSR_INR;
|
||||||
|
}
|
||||||
|
if (data & CSR_GO) {
|
||||||
|
imp_icsr &= ~CSR_RDY;
|
||||||
|
uptr->STATUS &= ~(IMPID|IMPLW);
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "IMP11 icsr %06o\n", imp_icsr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 002: /* Input Data Buffer */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (imp_idb & 0377);
|
||||||
|
else
|
||||||
|
data = (imp_idb & 0177400) | data;
|
||||||
|
}
|
||||||
|
imp_idb = data;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 004: /* Input Bus Address */
|
||||||
|
imp_iba = (data & 0177777);
|
||||||
|
imp_icsr &= ~(CSR_ERR);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 006: /* Input Word Count */
|
||||||
|
imp_iwcnt = (data & 0177777);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 010: /* Output CSR */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (imp_ocsr & 0377);
|
||||||
|
else
|
||||||
|
data = (imp_ocsr & 0177400) | data;
|
||||||
|
}
|
||||||
|
if (data & CSR_RST) {
|
||||||
|
imp_ocsr |= CSR_RDY;
|
||||||
|
imp_oba = 0;
|
||||||
|
imp_owcnt = 0;
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect + 4);
|
||||||
|
}
|
||||||
|
data &= (CSR_GO|CSR_RST|CSR_UBA|CSR_IE|CSR_BB|CSR_ELB);
|
||||||
|
imp_ocsr &= ~(CSR_GO|CSR_RST|CSR_UBA|CSR_IE|CSR_BB|CSR_ELB|CSR_ERR
|
||||||
|
|CSR_NXM|CSR_MRE);
|
||||||
|
imp_ocsr |= data;
|
||||||
|
if (data & CSR_GO) {
|
||||||
|
imp_ocsr &= ~CSR_RDY;
|
||||||
|
uptr->STATUS &= ~(IMPOD);
|
||||||
|
uba_clr_irq(dibp, dibp->uba_vect + 4);
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "IMP11 ocsr %06o\n", imp_ocsr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 012: /* Output Data Buffer */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (imp_odb & 0377);
|
||||||
|
else
|
||||||
|
data = (imp_odb & 0177400) | data;
|
||||||
|
}
|
||||||
|
imp_odb = data;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 014: /* Output Bus Address */
|
||||||
|
imp_oba = (data & 0177777);
|
||||||
|
imp_ocsr &= ~(CSR_ERR);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 016: /* Output Word Count */
|
||||||
|
imp_owcnt = (data & 0177777);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (imp_ocsr & CSR_GO || imp_icsr & CSR_GO)
|
||||||
|
sim_activate(uptr, 100);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
imp_rd(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||||
|
{
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
UNIT *uptr = imp_unit;
|
||||||
|
|
||||||
|
addr &= dibp->uba_mask;
|
||||||
|
|
||||||
|
switch (addr & 016) {
|
||||||
|
case 000: /* Input CSR */
|
||||||
|
*data = imp_icsr;
|
||||||
|
if ((uptr->STATUS & (IMPID)) != 0)
|
||||||
|
*data |= CSR_IBF;
|
||||||
|
if ((uptr->STATUS & (IMPLW)) != 0)
|
||||||
|
*data |= CSR_EOM;
|
||||||
|
break;
|
||||||
|
case 002: /* Input Data Buffer */
|
||||||
|
*data = imp_idb;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 004: /* Input Bus Address */
|
||||||
|
*data = imp_iba;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 006: /* Input Word Count */
|
||||||
|
*data = imp_iwcnt;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 010: /* Output CSR */
|
||||||
|
*data = imp_ocsr;
|
||||||
|
if ((uptr->STATUS & (IMPOD)) != 0)
|
||||||
|
*data |= CSR_OBE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 012: /* Output Data Buffer */
|
||||||
|
*data = imp_odb;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 014: /* Output Bus Address */
|
||||||
|
*data = imp_oba;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 016: /* Output Word Count */
|
||||||
|
*data = imp_owcnt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "IMP11 read %06o %06o %o\n",
|
||||||
|
addr, *data, access);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
static void check_interrupts (UNIT *uptr)
|
static void check_interrupts (UNIT *uptr)
|
||||||
{
|
{
|
||||||
clr_interrupt (DEVNUM);
|
clr_interrupt (DEVNUM);
|
||||||
|
@ -660,7 +927,7 @@ t_stat imp_devio(uint32 dev, uint64 *data)
|
||||||
memset(imp_data.sbuffer, 0, ETH_FRAME_SIZE);
|
memset(imp_data.sbuffer, 0, ETH_FRAME_SIZE);
|
||||||
uptr->OPOS = 0;
|
uptr->OPOS = 0;
|
||||||
uptr->STATUS &= ~(IMPLHW);
|
uptr->STATUS &= ~(IMPLHW);
|
||||||
} else
|
} else
|
||||||
uptr->STATUS |= IMPLHW;
|
uptr->STATUS |= IMPLHW;
|
||||||
}
|
}
|
||||||
if (*data & IMP_STROUT)
|
if (*data & IMP_STROUT)
|
||||||
|
@ -740,9 +1007,171 @@ imp_devirq(uint32 dev, t_addr addr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
t_stat imp_srv(UNIT * uptr)
|
t_stat imp_srv(UNIT * uptr)
|
||||||
{
|
{
|
||||||
|
#if KS
|
||||||
|
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||||
|
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||||
|
t_addr pa;
|
||||||
|
uint64 wd64;
|
||||||
|
uint16 wd;
|
||||||
|
|
||||||
|
if (imp_ocsr & CSR_GO && imp_data.sendq == NULL) {
|
||||||
|
pa = ((imp_ocsr & CSR_UBA) << 12) | imp_oba;
|
||||||
|
switch (GET_DTYPE(uptr->flags)) {
|
||||||
|
case TYPE_UNI:
|
||||||
|
if (uba_read_npr_word(pa, dibp->uba_ctl, &wd) == 0) {
|
||||||
|
imp_ocsr |= CSR_NXM;
|
||||||
|
imp_ocsr &= ~CSR_GO;
|
||||||
|
uptr->STATUS |= IMPOD;
|
||||||
|
if (imp_ocsr & CSR_IE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect + 4);
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP out npr failed\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
imp_data.sbuffer[uptr->OPOS >> 3] = (wd & 0377);
|
||||||
|
uptr->OPOS += 8;
|
||||||
|
imp_data.sbuffer[uptr->OPOS >> 3] = ((wd >> 8) & 0377);
|
||||||
|
uptr->OPOS += 8;
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP send %04x %07o %06o %06o\n",
|
||||||
|
wd, pa, imp_owcnt, imp_ocsr);
|
||||||
|
break;
|
||||||
|
case TYPE_SIMP:
|
||||||
|
if (uba_read_npr(pa, dibp->uba_ctl, &wd64) == 0) {
|
||||||
|
imp_ocsr |= CSR_NXM;
|
||||||
|
imp_ocsr &= ~CSR_GO;
|
||||||
|
uptr->STATUS |= IMPOD;
|
||||||
|
if (imp_ocsr & CSR_IE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect + 4);
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP out npr failed\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
imp_data.sbuffer[uptr->OPOS >> 3] = (wd64 >> 28) & 0377;
|
||||||
|
uptr->OPOS += 8;
|
||||||
|
imp_data.sbuffer[uptr->OPOS >> 3] = (wd64 >> 20) & 0377;
|
||||||
|
uptr->OPOS += 8;
|
||||||
|
imp_data.sbuffer[uptr->OPOS >> 3] = (wd64 >> 12) & 0377;
|
||||||
|
uptr->OPOS += 8;
|
||||||
|
imp_data.sbuffer[uptr->OPOS >> 3] = (wd64 >> 4) & 0377;
|
||||||
|
uptr->OPOS += 8;
|
||||||
|
imp_oba += 2;
|
||||||
|
imp_owcnt++;
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP send %08llx %07o %06o %06o\n",
|
||||||
|
(wd64 >> 4), pa, imp_owcnt, imp_ocsr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
imp_oba += 2;
|
||||||
|
imp_owcnt++;
|
||||||
|
if (imp_oba == 0) {
|
||||||
|
imp_ocsr |= CSR_ERR;
|
||||||
|
imp_ocsr &= ~CSR_GO;
|
||||||
|
uptr->STATUS |= IMPOD;
|
||||||
|
if (imp_ocsr & CSR_IE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect + 4);
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP oba overflow\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if (imp_owcnt == 0) {
|
||||||
|
imp_ocsr |= CSR_RDY;
|
||||||
|
imp_ocsr &= ~CSR_GO;
|
||||||
|
uptr->STATUS |= IMPOD;
|
||||||
|
if (imp_ocsr & CSR_IE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect + 4);
|
||||||
|
}
|
||||||
|
if (imp_ocsr & CSR_ELB) {
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP send\n");
|
||||||
|
|
||||||
|
imp_send_packet (&imp_data, uptr->OPOS >> 3);
|
||||||
|
memset(imp_data.sbuffer, 0, ETH_FRAME_SIZE);
|
||||||
|
uptr->OPOS = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (uptr->STATUS & IMPIB && imp_icsr & CSR_GO) {
|
||||||
|
pa = ((imp_icsr & CSR_UBA) << 12) | imp_iba;
|
||||||
|
if (imp_iba == 0) {
|
||||||
|
imp_icsr |= CSR_ERR;
|
||||||
|
imp_icsr &= ~CSR_GO;
|
||||||
|
uptr->STATUS |= IMPID;
|
||||||
|
if (imp_icsr & CSR_IE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP oba overflow\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
switch (GET_DTYPE(uptr->flags)) {
|
||||||
|
case TYPE_UNI:
|
||||||
|
wd = imp_data.rbuffer[uptr->IPOS >> 3] << 8;
|
||||||
|
uptr->IPOS += 8;
|
||||||
|
wd |= imp_data.rbuffer[uptr->IPOS >> 3];
|
||||||
|
uptr->IPOS += 8;
|
||||||
|
if (uba_write_npr_word(pa, dibp->uba_ctl, wd) == 0) {
|
||||||
|
imp_icsr |= CSR_NXM;
|
||||||
|
imp_icsr &= ~CSR_GO;
|
||||||
|
uptr->STATUS |= IMPID;
|
||||||
|
if (imp_icsr & CSR_IE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP in npr failed\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP rec %04x %07o %06o %06o\n",
|
||||||
|
wd, pa, imp_owcnt, imp_ocsr);
|
||||||
|
break;
|
||||||
|
case TYPE_SIMP:
|
||||||
|
wd64 = (uint64)imp_data.rbuffer[uptr->IPOS >> 3] << 28;
|
||||||
|
uptr->IPOS += 8;
|
||||||
|
wd64 |= (uint64)imp_data.rbuffer[uptr->IPOS >> 3] << 20;
|
||||||
|
uptr->IPOS += 8;
|
||||||
|
wd64 |= (uint64)imp_data.rbuffer[uptr->IPOS >> 3] << 12;
|
||||||
|
uptr->IPOS += 8;
|
||||||
|
wd64 |= (uint64)imp_data.rbuffer[uptr->IPOS >> 3] << 4;
|
||||||
|
uptr->IPOS += 8;
|
||||||
|
if (uba_write_npr(pa, dibp->uba_ctl, wd64) == 0) {
|
||||||
|
imp_ocsr |= CSR_NXM;
|
||||||
|
imp_ocsr &= ~CSR_GO;
|
||||||
|
uptr->STATUS |= IMPID;
|
||||||
|
if (imp_icsr & CSR_IE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP out npr failed\n");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
imp_iba += 2;
|
||||||
|
imp_iwcnt++;
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP rec %08llx %07o %06o %06o\n",
|
||||||
|
(wd64 >> 4), pa, imp_owcnt, imp_ocsr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
imp_iba += 2;
|
||||||
|
imp_iwcnt++;
|
||||||
|
if (uptr->IPOS > uptr->ILEN) {
|
||||||
|
imp_icsr |= CSR_EOM|CSR_RDY;
|
||||||
|
imp_icsr &= ~CSR_GO;
|
||||||
|
uptr->STATUS |= IMPID|IMPLW;
|
||||||
|
uptr->STATUS &= ~IMPIB;
|
||||||
|
if (imp_icsr & CSR_IE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
uptr->ILEN = 0;
|
||||||
|
}
|
||||||
|
if (imp_iwcnt == 0) {
|
||||||
|
imp_icsr |= CSR_RDY;
|
||||||
|
imp_icsr &= ~CSR_GO;
|
||||||
|
uptr->STATUS |= IMPID;
|
||||||
|
if (imp_icsr & CSR_IE) {
|
||||||
|
uba_set_irq(dibp, dibp->uba_vect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (imp_ocsr & CSR_GO || imp_icsr & CSR_GO)
|
||||||
|
sim_activate(uptr, 100);
|
||||||
|
#else
|
||||||
int i;
|
int i;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
|
@ -782,6 +1211,7 @@ t_stat imp_srv(UNIT * uptr)
|
||||||
uptr->STATUS |= IMPID;
|
uptr->STATUS |= IMPID;
|
||||||
check_interrupts (uptr);
|
check_interrupts (uptr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (uptr->ILEN == 0 && (uptr->STATUS & (IMPIB|IMPID)) == 0)
|
if (uptr->ILEN == 0 && (uptr->STATUS & (IMPIB|IMPID)) == 0)
|
||||||
imp_packet_in(&imp_data);
|
imp_packet_in(&imp_data);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -870,8 +1300,8 @@ t_stat imp_eth_srv(UNIT * uptr)
|
||||||
imp_packet_in(&imp_data);
|
imp_packet_in(&imp_data);
|
||||||
|
|
||||||
if (imp_data.init_state >= 3 && imp_data.init_state < 6) {
|
if (imp_data.init_state >= 3 && imp_data.init_state < 6) {
|
||||||
if (imp_unit[0].flags & UNIT_DHCP &&
|
if (imp_unit[0].flags & UNIT_DHCP &&
|
||||||
imp_data.dhcp_state != DHCP_STATE_BOUND &&
|
imp_data.dhcp_state != DHCP_STATE_BOUND &&
|
||||||
imp_data.dhcp_state != DHCP_STATE_REBINDING &&
|
imp_data.dhcp_state != DHCP_STATE_REBINDING &&
|
||||||
imp_data.dhcp_state != DHCP_STATE_RENEWING)
|
imp_data.dhcp_state != DHCP_STATE_RENEWING)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -879,11 +1309,16 @@ t_stat imp_eth_srv(UNIT * uptr)
|
||||||
imp_data.init_state);
|
imp_data.init_state);
|
||||||
if (imp_unit[0].ILEN == 0) {
|
if (imp_unit[0].ILEN == 0) {
|
||||||
/* Queue up a nop packet */
|
/* Queue up a nop packet */
|
||||||
imp_data.rbuffer[0] = 0x4;
|
#if KS
|
||||||
#if 0
|
|
||||||
imp_data.rbuffer[0] = 0xf;
|
imp_data.rbuffer[0] = 0xf;
|
||||||
imp_data.rbuffer[3] = 4;
|
imp_data.rbuffer[3] = 4;
|
||||||
|
#else
|
||||||
|
imp_data.rbuffer[0] = 0x4;
|
||||||
#endif
|
#endif
|
||||||
|
imp_data.rbuffer[1] = (ntohl(imp_data.ip) >> 24) & 0xff;
|
||||||
|
imp_data.rbuffer[5] = (ntohl(imp_data.ip) >> 16) & 0xff;
|
||||||
|
imp_data.rbuffer[6] = (ntohl(imp_data.ip) >> 8) & 0xff;
|
||||||
|
imp_data.rbuffer[7] = ntohl(imp_data.ip) & 0xff;
|
||||||
imp_unit[0].STATUS |= IMPIB;
|
imp_unit[0].STATUS |= IMPIB;
|
||||||
imp_unit[0].IPOS = 0;
|
imp_unit[0].IPOS = 0;
|
||||||
imp_unit[0].ILEN = 12*8;
|
imp_unit[0].ILEN = 12*8;
|
||||||
|
@ -938,6 +1373,9 @@ t_stat imp_tim_srv(UNIT * uptr)
|
||||||
|
|
||||||
imp_dhcp_timer(&imp_data);
|
imp_dhcp_timer(&imp_data);
|
||||||
imp_arp_age(&imp_data);
|
imp_arp_age(&imp_data);
|
||||||
|
#if KS
|
||||||
|
imp_icsr &= ~CSR_HR;
|
||||||
|
#endif
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -981,7 +1419,7 @@ imp_packet_in(struct imp_device *imp)
|
||||||
(ip_hdr->ip_v_hl & 0xf) * 4]);
|
(ip_hdr->ip_v_hl & 0xf) * 4]);
|
||||||
struct udp *udp_hdr = (struct udp *)payload;
|
struct udp *udp_hdr = (struct udp *)payload;
|
||||||
/* Check for DHCP traffic */
|
/* Check for DHCP traffic */
|
||||||
if (ip_hdr->ip_p == UDP_PROTO &&
|
if (ip_hdr->ip_p == UDP_PROTO &&
|
||||||
ntohs(udp_hdr->udp_dport) == DHCP_UDP_PORT_CLIENT &&
|
ntohs(udp_hdr->udp_dport) == DHCP_UDP_PORT_CLIENT &&
|
||||||
ntohs(udp_hdr->udp_sport) == DHCP_UDP_PORT_SERVER) {
|
ntohs(udp_hdr->udp_sport) == DHCP_UDP_PORT_SERVER) {
|
||||||
imp_do_dhcp_client(imp, &read_buffer);
|
imp_do_dhcp_client(imp, &read_buffer);
|
||||||
|
@ -996,12 +1434,20 @@ imp_packet_in(struct imp_device *imp)
|
||||||
memset(&imp->rbuffer[0], 0, 256);
|
memset(&imp->rbuffer[0], 0, 256);
|
||||||
imp->rbuffer[0] = 0xf;
|
imp->rbuffer[0] = 0xf;
|
||||||
imp->rbuffer[3] = 0;
|
imp->rbuffer[3] = 0;
|
||||||
|
#if KS
|
||||||
|
imp->rbuffer[1] = (ntohl(ip_hdr->ip_src) >> 24) & 0xff;
|
||||||
imp->rbuffer[5] = (ntohl(ip_hdr->ip_src) >> 16) & 0xff;
|
imp->rbuffer[5] = (ntohl(ip_hdr->ip_src) >> 16) & 0xff;
|
||||||
|
imp->rbuffer[6] = (ntohl(ip_hdr->ip_src) >> 8) & 0xff;
|
||||||
|
imp->rbuffer[7] = ntohl(ip_hdr->ip_src) & 0xff;
|
||||||
|
#else
|
||||||
imp->rbuffer[7] = 14;
|
imp->rbuffer[7] = 14;
|
||||||
|
#endif
|
||||||
imp->rbuffer[8] = 0233;
|
imp->rbuffer[8] = 0233;
|
||||||
|
#if !KS
|
||||||
imp->rbuffer[18] = 0;
|
imp->rbuffer[18] = 0;
|
||||||
imp->rbuffer[19] = 0x80;
|
imp->rbuffer[19] = 0x80;
|
||||||
imp->rbuffer[21] = 0x30;
|
imp->rbuffer[21] = 0x30;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Copy message over */
|
/* Copy message over */
|
||||||
pad = 12 + (imp->padding / 8);
|
pad = 12 + (imp->padding / 8);
|
||||||
|
@ -1144,6 +1590,12 @@ imp_packet_in(struct imp_device *imp)
|
||||||
imp_unit[0].STATUS |= IMPIB;
|
imp_unit[0].STATUS |= IMPIB;
|
||||||
imp_unit[0].IPOS = 0;
|
imp_unit[0].IPOS = 0;
|
||||||
imp_unit[0].ILEN = n*8;
|
imp_unit[0].ILEN = n*8;
|
||||||
|
imp->rbuffer[1] = (ntohl(ip_hdr->ip_src) >> 24) & 0xff;
|
||||||
|
imp->rbuffer[5] = (ntohl(ip_hdr->ip_src) >> 16) & 0xff;
|
||||||
|
imp->rbuffer[6] = (ntohl(ip_hdr->ip_src) >> 8) & 0xff;
|
||||||
|
imp->rbuffer[7] = ntohl(ip_hdr->ip_src) & 0xff;
|
||||||
|
imp->rbuffer[10] = (n >> 8) & 0xff;
|
||||||
|
imp->rbuffer[11] = n & 0xff;
|
||||||
}
|
}
|
||||||
if (!sim_is_active(&imp_unit[0]))
|
if (!sim_is_active(&imp_unit[0]))
|
||||||
sim_activate(&imp_unit[0], 100);
|
sim_activate(&imp_unit[0], 100);
|
||||||
|
@ -1187,10 +1639,11 @@ imp_send_packet (struct imp_device *imp, int len)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sim_debug(DEBUG_DETAIL, &imp_dev,
|
sim_debug(DEBUG_DETAIL, &imp_dev,
|
||||||
"IMP packet Type=%d ht=%d dh=%d imp=%d lk=%d %d st=%d Len=%d\n",
|
"IMP packet H=%x Type=%d ht=%d dh=%d imp=%d lk=%d %d st=%d Len=%d mt=%d\n",
|
||||||
|
imp->sbuffer[0],
|
||||||
imp->sbuffer[3], imp->sbuffer[4], imp->sbuffer[5],
|
imp->sbuffer[3], imp->sbuffer[4], imp->sbuffer[5],
|
||||||
(imp->sbuffer[6] * 256) + imp->sbuffer[7],
|
(imp->sbuffer[6] * 256) + imp->sbuffer[7],
|
||||||
lk, imp->sbuffer[9] >> 4, st, n);
|
lk, imp->sbuffer[9] >> 4, st, n, mt);
|
||||||
switch(mt) {
|
switch(mt) {
|
||||||
case 0: /* Regular packet */
|
case 0: /* Regular packet */
|
||||||
switch(st) {
|
switch(st) {
|
||||||
|
@ -1205,6 +1658,15 @@ imp_send_packet (struct imp_device *imp, int len)
|
||||||
imp_packet_out(imp, &write_buffer);
|
imp_packet_out(imp, &write_buffer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 4: /* Nop */
|
||||||
|
if (imp->init_state < 3)
|
||||||
|
imp->init_state++;
|
||||||
|
imp->padding = 0;
|
||||||
|
sim_debug(DEBUG_DETAIL, &imp_dev,
|
||||||
|
"IMP recieve Nop %d padding= %d\n",
|
||||||
|
imp->init_state, imp->padding);
|
||||||
|
sim_activate(uptr, tmxr_poll); /* Start reciever task */
|
||||||
|
break;
|
||||||
case 2: /* Getting ready */
|
case 2: /* Getting ready */
|
||||||
case 3: /* Uncontrolled */
|
case 3: /* Uncontrolled */
|
||||||
default:
|
default:
|
||||||
|
@ -1214,7 +1676,6 @@ imp_send_packet (struct imp_device *imp, int len)
|
||||||
case 1: /* Error */
|
case 1: /* Error */
|
||||||
break;
|
break;
|
||||||
case 2: /* Host going down */
|
case 2: /* Host going down */
|
||||||
fprintf(stderr, "IMP: Host shutdown\n\r");
|
|
||||||
break;
|
break;
|
||||||
case 4: /* Nop */
|
case 4: /* Nop */
|
||||||
if (imp->init_state < 3)
|
if (imp->init_state < 3)
|
||||||
|
@ -1499,7 +1960,7 @@ void imp_packet_debug(struct imp_device *imp, const char *action, ETH_PACK *pack
|
||||||
memcpy(&in_addr, &arp->dipaddr, sizeof(in_addr));
|
memcpy(&in_addr, &arp->dipaddr, sizeof(in_addr));
|
||||||
strlcpy(arp_dipaddr, ipv4_inet_ntoa(in_addr), sizeof(arp_dipaddr));
|
strlcpy(arp_dipaddr, ipv4_inet_ntoa(in_addr), sizeof(arp_dipaddr));
|
||||||
sim_debug(DEBUG_ARP, &imp_dev,
|
sim_debug(DEBUG_ARP, &imp_dev,
|
||||||
"%s %s EthDst=%s EthSrc=%s shwaddr=%s sipaddr=%s dhwaddr=%s dipaddr=%s\n",
|
"%s %s EthDst=%s EthSrc=%s shwaddr=%s sipaddr=%s dhwaddr=%s dipaddr=%s\n",
|
||||||
action, arp_op, eth_dst, eth_src, arp_shwaddr, arp_sipaddr, arp_dhwaddr, arp_dipaddr);
|
action, arp_op, eth_dst, eth_src, arp_shwaddr, arp_sipaddr, arp_dhwaddr, arp_dipaddr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1519,17 +1980,17 @@ void imp_packet_debug(struct imp_device *imp, const char *action, ETH_PACK *pack
|
||||||
snprintf(dst_port, sizeof(dst_port), "%d", ntohs(udp->udp_dport));
|
snprintf(dst_port, sizeof(dst_port), "%d", ntohs(udp->udp_dport));
|
||||||
sim_debug(DEBUG_UDP, &imp_dev, "%s %d byte packet from %s:%s to %s:%s\n", action,
|
sim_debug(DEBUG_UDP, &imp_dev, "%s %d byte packet from %s:%s to %s:%s\n", action,
|
||||||
ntohs(udp->len), src_ip, src_port, dst_ip, dst_port);
|
ntohs(udp->len), src_ip, src_port, dst_ip, dst_port);
|
||||||
if ((imp_dev.dctrl & DEBUG_DHCP) &&
|
if ((imp_dev.dctrl & DEBUG_DHCP) &&
|
||||||
(((ntohs(udp->udp_sport) == DHCP_UDP_PORT_CLIENT) &&
|
(((ntohs(udp->udp_sport) == DHCP_UDP_PORT_CLIENT) &&
|
||||||
(ntohs(udp->udp_dport) == DHCP_UDP_PORT_SERVER)) ||
|
(ntohs(udp->udp_dport) == DHCP_UDP_PORT_SERVER)) ||
|
||||||
((ntohs(udp->udp_dport) == DHCP_UDP_PORT_CLIENT) &&
|
((ntohs(udp->udp_dport) == DHCP_UDP_PORT_CLIENT) &&
|
||||||
(ntohs(udp->udp_sport) == DHCP_UDP_PORT_SERVER)))) {
|
(ntohs(udp->udp_sport) == DHCP_UDP_PORT_SERVER)))) {
|
||||||
struct dhcp *dhcp = (struct dhcp *)(payload + sizeof(struct udp));
|
struct dhcp *dhcp = (struct dhcp *)(payload + sizeof(struct udp));
|
||||||
uint8 *opt = &dhcp->options[0];
|
uint8 *opt = &dhcp->options[0];
|
||||||
|
|
||||||
sim_debug(DEBUG_DHCP, &imp_dev, "%s XID=%08X",
|
sim_debug(DEBUG_DHCP, &imp_dev, "%s XID=%08X",
|
||||||
(dhcp->op == DHCP_BOOTREQUEST) ? "REQUEST" :
|
(dhcp->op == DHCP_BOOTREQUEST) ? "REQUEST" :
|
||||||
(dhcp->op == DHCP_BOOTREPLY) ? "REPLY" :
|
(dhcp->op == DHCP_BOOTREPLY) ? "REPLY" :
|
||||||
"??????",
|
"??????",
|
||||||
dhcp->xid);
|
dhcp->xid);
|
||||||
if (dhcp->ciaddr) {
|
if (dhcp->ciaddr) {
|
||||||
|
@ -1619,7 +2080,7 @@ void imp_packet_debug(struct imp_device *imp, const char *action, ETH_PACK *pack
|
||||||
sim_debug(DEBUG_DHCP, &imp_dev, "\n");
|
sim_debug(DEBUG_DHCP, &imp_dev, "\n");
|
||||||
} else {
|
} else {
|
||||||
if (udp->len && (imp_dev.dctrl & DEBUG_UDP))
|
if (udp->len && (imp_dev.dctrl & DEBUG_UDP))
|
||||||
sim_data_trace(&imp_dev, imp_unit, payload + sizeof(struct udp), "",
|
sim_data_trace(&imp_dev, imp_unit, payload + sizeof(struct udp), "",
|
||||||
ntohs(udp->len), "", DEBUG_DATA);
|
ntohs(udp->len), "", DEBUG_DATA);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1678,7 +2139,7 @@ imp_arp_update(struct imp_device *imp, in_addr_T ipaddr, ETH_MAC *ethaddr, int a
|
||||||
memcpy(&tabptr->ethaddr, ethaddr, sizeof(ETH_MAC));
|
memcpy(&tabptr->ethaddr, ethaddr, sizeof(ETH_MAC));
|
||||||
eth_mac_fmt(ethaddr, mac_buf);
|
eth_mac_fmt(ethaddr, mac_buf);
|
||||||
sim_debug(DEBUG_ARP, &imp_dev,
|
sim_debug(DEBUG_ARP, &imp_dev,
|
||||||
"updating entry for IP %s to %s\n",
|
"updating entry for IP %s to %s\n",
|
||||||
ipv4_inet_ntoa(*((struct in_addr *)&ipaddr)), mac_buf);
|
ipv4_inet_ntoa(*((struct in_addr *)&ipaddr)), mac_buf);
|
||||||
}
|
}
|
||||||
if (tabptr->age != ARP_DONT_AGE)
|
if (tabptr->age != ARP_DONT_AGE)
|
||||||
|
@ -1716,7 +2177,7 @@ imp_arp_update(struct imp_device *imp, in_addr_T ipaddr, ETH_MAC *ethaddr, int a
|
||||||
tabptr->age = age;
|
tabptr->age = age;
|
||||||
eth_mac_fmt(ethaddr, mac_buf);
|
eth_mac_fmt(ethaddr, mac_buf);
|
||||||
sim_debug(DEBUG_ARP, &imp_dev,
|
sim_debug(DEBUG_ARP, &imp_dev,
|
||||||
"creating entry for IP %s to %s, initial age=%d\n",
|
"creating entry for IP %s to %s, initial age=%d\n",
|
||||||
ipv4_inet_ntoa(*((struct in_addr *)&ipaddr)), mac_buf, age);
|
ipv4_inet_ntoa(*((struct in_addr *)&ipaddr)), mac_buf, age);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1738,8 +2199,8 @@ void imp_arp_age(struct imp_device *imp)
|
||||||
char mac_buf[20];
|
char mac_buf[20];
|
||||||
|
|
||||||
eth_mac_fmt(&tabptr->ethaddr, mac_buf);
|
eth_mac_fmt(&tabptr->ethaddr, mac_buf);
|
||||||
sim_debug(DEBUG_ARP, &imp_dev,
|
sim_debug(DEBUG_ARP, &imp_dev,
|
||||||
"discarding ARP entry for IP %s %s after %d seconds\n",
|
"discarding ARP entry for IP %s %s after %d seconds\n",
|
||||||
ipv4_inet_ntoa(*((struct in_addr *)&tabptr->ipaddr)), mac_buf, IMP_ARP_MAX_AGE);
|
ipv4_inet_ntoa(*((struct in_addr *)&tabptr->ipaddr)), mac_buf, IMP_ARP_MAX_AGE);
|
||||||
memset(tabptr, 0, sizeof(*tabptr));
|
memset(tabptr, 0, sizeof(*tabptr));
|
||||||
}
|
}
|
||||||
|
@ -1993,7 +2454,7 @@ imp_do_send_dhcp(struct imp_device *imp,
|
||||||
eth_mac_fmt (&pkt->ethhdr.dest, mac_buf);
|
eth_mac_fmt (&pkt->ethhdr.dest, mac_buf);
|
||||||
memcpy(&in_addr, &udp_hdr.ip_dst, sizeof(in_addr));
|
memcpy(&in_addr, &udp_hdr.ip_dst, sizeof(in_addr));
|
||||||
sim_debug(DEBUG_DHCP, &imp_dev,
|
sim_debug(DEBUG_DHCP, &imp_dev,
|
||||||
"client sent %s packet to: %s:%d(%s)\n",
|
"client sent %s packet to: %s:%d(%s)\n",
|
||||||
op, ipv4_inet_ntoa(in_addr), ntohs(udp->udp_dport), mac_buf);
|
op, ipv4_inet_ntoa(in_addr), ntohs(udp->udp_dport), mac_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2027,7 +2488,7 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer)
|
||||||
|
|
||||||
ip_checksum((uint8 *)&sum, (uint8 *)ip_hdr, hl);
|
ip_checksum((uint8 *)&sum, (uint8 *)ip_hdr, hl);
|
||||||
if (sum != 0) {
|
if (sum != 0) {
|
||||||
sim_printf("IP checksum error %x\n\r", sum);
|
sim_printf("IP checksum error %x\r\n", sum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ip_checksum((uint8 *)(&sum), (uint8 *)(upkt), ntohs(upkt->len));
|
ip_checksum((uint8 *)(&sum), (uint8 *)(upkt), ntohs(upkt->len));
|
||||||
|
@ -2038,7 +2499,7 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer)
|
||||||
udp_hdr.hlen = upkt->len;
|
udp_hdr.hlen = upkt->len;
|
||||||
checksumadjust((uint8 *)&sum, 0, 0, (uint8 *)(&udp_hdr), sizeof(udp_hdr));
|
checksumadjust((uint8 *)&sum, 0, 0, (uint8 *)(&udp_hdr), sizeof(udp_hdr));
|
||||||
if (sum != 0) {
|
if (sum != 0) {
|
||||||
sim_printf("UDP checksum error %x\n\r", sum);
|
sim_printf("UDP checksum error %x\r\n", sum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2110,8 +2571,8 @@ imp_do_dhcp_client(struct imp_device *imp, ETH_PACK *read_buffer)
|
||||||
eth_mac_fmt(ð->src, mac_buf);
|
eth_mac_fmt(ð->src, mac_buf);
|
||||||
memcpy(&in_addr, &udp_hdr.ip_src, sizeof(in_addr));
|
memcpy(&in_addr, &udp_hdr.ip_src, sizeof(in_addr));
|
||||||
sim_debug(DEBUG_DHCP, &imp_dev,
|
sim_debug(DEBUG_DHCP, &imp_dev,
|
||||||
"client incoming %s packet: dhcp_state=%s - wait_time=%d from: %s:%d(%s)\n",
|
"client incoming %s packet: dhcp_state=%s - wait_time=%d from: %s:%d(%s)\n",
|
||||||
(opr == -1) ? "" : dhcp_opr_names[opr],
|
(opr == -1) ? "" : dhcp_opr_names[opr],
|
||||||
dhcp_state_names[imp->dhcp_state], imp->dhcp_wait_time,
|
dhcp_state_names[imp->dhcp_state], imp->dhcp_wait_time,
|
||||||
ipv4_inet_ntoa(in_addr), ntohs(upkt->udp_sport), mac_buf);
|
ipv4_inet_ntoa(in_addr), ntohs(upkt->udp_sport), mac_buf);
|
||||||
|
|
||||||
|
@ -2574,7 +3035,7 @@ t_stat imp_show_dhcpip (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||||
fprintf (st, ", Lease Expires in %d seconds", imp_data.dhcp_lease);
|
fprintf (st, ", Lease Expires in %d seconds", imp_data.dhcp_lease);
|
||||||
} else {
|
} else {
|
||||||
fprintf (st, ", State:%s, Waited %d seconds", dhcp_state_names[imp_data.dhcp_state],
|
fprintf (st, ", State:%s, Waited %d seconds", dhcp_state_names[imp_data.dhcp_state],
|
||||||
imp_data.dhcp_wait_time);
|
imp_data.dhcp_wait_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -2647,6 +3108,10 @@ t_stat imp_reset (DEVICE *dptr)
|
||||||
imp_data.freeq = p;
|
imp_data.freeq = p;
|
||||||
imp_data.init_state = 0;
|
imp_data.init_state = 0;
|
||||||
last_coni = sim_gtime();
|
last_coni = sim_gtime();
|
||||||
|
#if KS
|
||||||
|
imp_icsr = CSR_RDY;
|
||||||
|
imp_ocsr = CSR_RDY;
|
||||||
|
#endif
|
||||||
if (imp_unit[0].flags & UNIT_ATT)
|
if (imp_unit[0].flags & UNIT_ATT)
|
||||||
sim_activate_after(&imp_unit[2], 1000000); /* Start Timer service */
|
sim_activate_after(&imp_unit[2], 1000000); /* Start Timer service */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -2659,6 +3124,7 @@ t_stat imp_attach(UNIT* uptr, CONST char* cptr)
|
||||||
char* tptr;
|
char* tptr;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
|
#if !KS
|
||||||
/* Set to correct device number */
|
/* Set to correct device number */
|
||||||
switch(GET_DTYPE(imp_unit[0].flags)) {
|
switch(GET_DTYPE(imp_unit[0].flags)) {
|
||||||
case TYPE_MIT:
|
case TYPE_MIT:
|
||||||
|
@ -2669,8 +3135,9 @@ t_stat imp_attach(UNIT* uptr, CONST char* cptr)
|
||||||
imp_dib.dev_num = WA_IMP_DEVNUM;
|
imp_dib.dev_num = WA_IMP_DEVNUM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (!(uptr->flags & UNIT_DHCP) && imp_data.ip == 0)
|
if (!(uptr->flags & UNIT_DHCP) && imp_data.ip == 0)
|
||||||
return sim_messagef (SCPE_NOATT, "%s: An IP Address must be specified when DHCP is disabled\n",
|
return sim_messagef (SCPE_NOATT, "%s: An IP Address must be specified when DHCP is disabled\n",
|
||||||
imp_dev.name);
|
imp_dev.name);
|
||||||
|
|
||||||
tptr = (char *) malloc(strlen(cptr) + 1);
|
tptr = (char *) malloc(strlen(cptr) + 1);
|
||||||
|
@ -2710,7 +3177,7 @@ t_stat imp_attach(UNIT* uptr, CONST char* cptr)
|
||||||
return sim_messagef (status, "%s: Can't initialize receive queue\n", imp_dev.name);
|
return sim_messagef (status, "%s: Can't initialize receive queue\n", imp_dev.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pick a relatively unique starting xid, presuming that the
|
/* Pick a relatively unique starting xid, presuming that the
|
||||||
MAC address has been verified unique on the LAN by eth_open */
|
MAC address has been verified unique on the LAN by eth_open */
|
||||||
imp_data.dhcp_xid = (imp_data.mac[0] | (imp_data.mac[1] << 8) |
|
imp_data.dhcp_xid = (imp_data.mac[0] | (imp_data.mac[1] << 8) |
|
||||||
(imp_data.mac[2] << 16) | (imp_data.mac[3] << 24)) + (uint32)time(NULL);
|
(imp_data.mac[2] << 16) | (imp_data.mac[3] << 24)) + (uint32)time(NULL);
|
||||||
|
@ -2718,7 +3185,7 @@ t_stat imp_attach(UNIT* uptr, CONST char* cptr)
|
||||||
memset(imp_data.arp_table, 0, sizeof(imp_data.arp_table));
|
memset(imp_data.arp_table, 0, sizeof(imp_data.arp_table));
|
||||||
|
|
||||||
/* If we're not doing DHCP and a gateway is defined on the network
|
/* If we're not doing DHCP and a gateway is defined on the network
|
||||||
then define a static APR entry for the gateway to facilitate
|
then define a static APR entry for the gateway to facilitate
|
||||||
outbound routing */
|
outbound routing */
|
||||||
if (!(uptr->flags & UNIT_DHCP) && imp_data.gwip) {
|
if (!(uptr->flags & UNIT_DHCP) && imp_data.gwip) {
|
||||||
ETH_PACK read_buffer;
|
ETH_PACK read_buffer;
|
||||||
|
|
|
@ -178,10 +178,8 @@ UNIT mt_unit[] = {
|
||||||
DIB mt_dib = {MT_DEVNUM, 2, &mt_devio, NULL};
|
DIB mt_dib = {MT_DEVNUM, 2, &mt_devio, NULL};
|
||||||
|
|
||||||
MTAB mt_mod[] = {
|
MTAB mt_mod[] = {
|
||||||
{ MTAB_XTD|MTAB_VUN, 0, "write enabled", "WRITEENABLED",
|
{MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL},
|
||||||
&set_writelock, &show_writelock, NULL, "Write ring in place" },
|
{MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL},
|
||||||
{ MTAB_XTD|MTAB_VUN, 1, NULL, "LOCKED",
|
|
||||||
&set_writelock, NULL, NULL, "no Write ring in place" },
|
|
||||||
{MTAB_XTD|MTAB_VDV|MTAB_VALR, MTDF_TYPEB, "TYPE", "TYPE", &mt_set_mta, &mt_show_mta},
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, MTDF_TYPEB, "TYPE", "TYPE", &mt_set_mta, &mt_show_mta},
|
||||||
{MTUF_7TRK, 0, "9T", "9T", NULL, NULL},
|
{MTUF_7TRK, 0, "9T", "9T", NULL, NULL},
|
||||||
{MTUF_7TRK, MTUF_7TRK, "7T", "7T", NULL, NULL},
|
{MTUF_7TRK, MTUF_7TRK, "7T", "7T", NULL, NULL},
|
||||||
|
@ -297,7 +295,7 @@ t_stat mt_devio(uint32 dev, uint64 *data) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WRITE:
|
case WRITE:
|
||||||
if ((uptr->flags & MTUF_WRP) != 0) {
|
if ((uptr->flags & MTUF_WLK) != 0) {
|
||||||
mt_status |= IDLE_UNIT|ILL_OPR|EOF_FLAG;
|
mt_status |= IDLE_UNIT|ILL_OPR|EOF_FLAG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -372,7 +370,7 @@ t_stat mt_devio(uint32 dev, uint64 *data) {
|
||||||
res |= SEVEN_CHAN;
|
res |= SEVEN_CHAN;
|
||||||
if ((uptr->flags & UNIT_ATT) != 0 && (uptr->CNTRL & MT_MOTION) == 0)
|
if ((uptr->flags & UNIT_ATT) != 0 && (uptr->CNTRL & MT_MOTION) == 0)
|
||||||
res |= IDLE_UNIT;
|
res |= IDLE_UNIT;
|
||||||
if ((uptr->flags & MTUF_WRP) != 0)
|
if ((uptr->flags & MTUF_WLK) != 0)
|
||||||
res |= WRITE_LOCK;
|
res |= WRITE_LOCK;
|
||||||
if (sim_tape_bot(uptr))
|
if (sim_tape_bot(uptr))
|
||||||
res |= BOT_FLAG;
|
res |= BOT_FLAG;
|
||||||
|
@ -534,8 +532,8 @@ t_stat mt_error(UNIT * uptr, t_stat r, DEVICE * dptr)
|
||||||
/* Handle processing of tape requests. */
|
/* Handle processing of tape requests. */
|
||||||
t_stat mt_srv(UNIT * uptr)
|
t_stat mt_srv(UNIT * uptr)
|
||||||
{
|
{
|
||||||
DEVICE *dptr = find_dev_from_unit(uptr);
|
DEVICE *dptr = uptr->dptr;
|
||||||
int unit = (uptr - dptr->units) & 7;
|
int unit;
|
||||||
int cmd = (uptr->CNTRL & FUNCTION) >> 9;
|
int cmd = (uptr->CNTRL & FUNCTION) >> 9;
|
||||||
t_mtrlnt reclen;
|
t_mtrlnt reclen;
|
||||||
t_stat r = SCPE_ARG; /* Force error if not set */
|
t_stat r = SCPE_ARG; /* Force error if not set */
|
||||||
|
@ -559,6 +557,10 @@ t_stat mt_srv(UNIT * uptr)
|
||||||
cc_max = (4 + ((uptr->CNTRL & CORE_DUMP) != 0));
|
cc_max = (4 + ((uptr->CNTRL & CORE_DUMP) != 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dptr == NULL)
|
||||||
|
dptr = find_dev_from_unit(uptr);
|
||||||
|
|
||||||
|
unit = (uptr - dptr->units) & 7;
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case NOP_IDLE:
|
case NOP_IDLE:
|
||||||
sim_debug(DEBUG_DETAIL, dptr, "MT%o Idle\n", unit);
|
sim_debug(DEBUG_DETAIL, dptr, "MT%o Idle\n", unit);
|
||||||
|
@ -802,7 +804,7 @@ t_stat mt_srv(UNIT * uptr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WTM:
|
case WTM:
|
||||||
if ((uptr->flags & MTUF_WRP) != 0)
|
if ((uptr->flags & MTUF_WLK) != 0)
|
||||||
return mt_error(uptr, MTSE_WRP, dptr);
|
return mt_error(uptr, MTSE_WRP, dptr);
|
||||||
if (uptr->CPOS == 0) {
|
if (uptr->CPOS == 0) {
|
||||||
mt_status &= ~(IDLE_UNIT|BOT_FLAG|EOT_FLAG);
|
mt_status &= ~(IDLE_UNIT|BOT_FLAG|EOT_FLAG);
|
||||||
|
@ -821,7 +823,7 @@ t_stat mt_srv(UNIT * uptr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ERG:
|
case ERG:
|
||||||
if ((uptr->flags & MTUF_WRP) != 0)
|
if ((uptr->flags & MTUF_WLK) != 0)
|
||||||
return mt_error(uptr, MTSE_WRP, dptr);
|
return mt_error(uptr, MTSE_WRP, dptr);
|
||||||
uptr->CNTRL &= ~MT_MOTION;
|
uptr->CNTRL &= ~MT_MOTION;
|
||||||
mt_status &= ~(IDLE_UNIT|BOT_FLAG|EOT_FLAG);
|
mt_status &= ~(IDLE_UNIT|BOT_FLAG|EOT_FLAG);
|
||||||
|
|
|
@ -130,7 +130,7 @@ t_stat ptp_devio(uint32 dev, uint64 *data) {
|
||||||
if (cpu_unit[0].flags & UNIT_WAITS)
|
if (cpu_unit[0].flags & UNIT_WAITS)
|
||||||
*data |= 0200;
|
*data |= 0200;
|
||||||
#endif
|
#endif
|
||||||
sim_debug(DEBUG_CONI, &ptp_dev, "PP: CONI %012llo\n\r", *data);
|
sim_debug(DEBUG_CONI, &ptp_dev, "PP: CONI %012llo\n", *data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONO:
|
case CONO:
|
||||||
|
@ -144,7 +144,7 @@ t_stat ptp_devio(uint32 dev, uint64 *data) {
|
||||||
}
|
}
|
||||||
if (uptr->STATUS & DONE_FLG)
|
if (uptr->STATUS & DONE_FLG)
|
||||||
set_interrupt(dev, uptr->STATUS);
|
set_interrupt(dev, uptr->STATUS);
|
||||||
sim_debug(DEBUG_CONO, &ptp_dev, "PP: CONO %012llo\n\r", *data);
|
sim_debug(DEBUG_CONO, &ptp_dev, "PP: CONO %012llo\n", *data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATAO:
|
case DATAO:
|
||||||
|
@ -159,7 +159,7 @@ t_stat ptp_devio(uint32 dev, uint64 *data) {
|
||||||
clr_interrupt(dev);
|
clr_interrupt(dev);
|
||||||
sim_activate (&ptp_unit, ptp_unit.wait);
|
sim_activate (&ptp_unit, ptp_unit.wait);
|
||||||
}
|
}
|
||||||
sim_debug(DEBUG_DATAIO, &ptp_dev, "PP: DATAO %012llo\n\r", *data);
|
sim_debug(DEBUG_DATAIO, &ptp_dev, "PP: DATAO %012llo\n", *data);
|
||||||
break;
|
break;
|
||||||
case DATAI:
|
case DATAI:
|
||||||
*data = 0;
|
*data = 0;
|
||||||
|
@ -181,12 +181,12 @@ t_stat ptp_svc (UNIT *uptr)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
fputc (uptr->CHR, uptr->fileref); /* print char */
|
fputc (uptr->CHR, uptr->fileref); /* print char */
|
||||||
|
uptr->pos = ftell (uptr->fileref);
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
perror ("PTP I/O error");
|
perror ("PTP I/O error");
|
||||||
clearerr (uptr->fileref);
|
clearerr (uptr->fileref);
|
||||||
return SCPE_IOERR;
|
return SCPE_IOERR;
|
||||||
}
|
}
|
||||||
uptr->pos = uptr->pos + 1;
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ t_stat ptr_devio(uint32 dev, uint64 *data) {
|
||||||
switch(dev & 3) {
|
switch(dev & 3) {
|
||||||
case CONI:
|
case CONI:
|
||||||
*data = uptr->STATUS;
|
*data = uptr->STATUS;
|
||||||
sim_debug(DEBUG_CONI, &ptr_dev, "PT: CONI %012llo\n\r", *data);
|
sim_debug(DEBUG_CONI, &ptr_dev, "PT: CONI %012llo\n", *data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONO:
|
case CONO:
|
||||||
|
@ -245,7 +245,7 @@ t_stat ptr_devio(uint32 dev, uint64 *data) {
|
||||||
}
|
}
|
||||||
if (uptr->STATUS & DONE_FLG)
|
if (uptr->STATUS & DONE_FLG)
|
||||||
set_interrupt(dev, uptr->STATUS);
|
set_interrupt(dev, uptr->STATUS);
|
||||||
sim_debug(DEBUG_CONO, &ptr_dev, "PT: CONO %012llo\n\r", *data);
|
sim_debug(DEBUG_CONO, &ptr_dev, "PT: CONO %012llo\n", *data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATAI:
|
case DATAI:
|
||||||
|
@ -257,7 +257,7 @@ t_stat ptr_devio(uint32 dev, uint64 *data) {
|
||||||
sim_activate (&ptr_unit, ptr_unit.wait);
|
sim_activate (&ptr_unit, ptr_unit.wait);
|
||||||
}
|
}
|
||||||
uptr->STATUS |= BUSY_FLG;
|
uptr->STATUS |= BUSY_FLG;
|
||||||
sim_debug(DEBUG_DATAIO, &ptr_dev, "PT: DATAI %012llo\n\r", *data);
|
sim_debug(DEBUG_DATAIO, &ptr_dev, "PT: DATAI %012llo\n", *data);
|
||||||
break;
|
break;
|
||||||
case DATAO:
|
case DATAO:
|
||||||
break;
|
break;
|
||||||
|
|
423
PDP10/kx10_rh.c
423
PDP10/kx10_rh.c
|
@ -24,7 +24,66 @@
|
||||||
#include "kx10_defs.h"
|
#include "kx10_defs.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
#define CS1_GO 1 /* go */
|
||||||
|
#define CS1_V_FNC 1 /* function pos */
|
||||||
|
#define CS1_M_FNC 037 /* function mask */
|
||||||
|
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
|
||||||
|
#define CS1_IE 0000100 /* Enable interrupts */
|
||||||
|
#define CS1_RDY 0000200 /* Drive ready */
|
||||||
|
#define CS1_UBA 0001400 /* High order UBA bits */
|
||||||
|
#define CS1_PSEL 0002000 /* */
|
||||||
|
#define CS1_DVA 0004000 /* drive avail */
|
||||||
|
#define CS1_MCPE 0020000 /* */
|
||||||
|
#define CS1_TRE 0040000 /* Set if CS2 0177400 */
|
||||||
|
#define CS1_SC 0100000 /* Set if TRE or ATTN */
|
||||||
|
|
||||||
|
#define CS2_V_UNIT 0 /* unit pos */
|
||||||
|
#define CS2_M_UNIT 07 /* unit mask */
|
||||||
|
#define CS2_UNIT (CS2_M_UNIT << CS2_V_UNIT)
|
||||||
|
#define CS2_UAI 0000010 /* addr inhibit */
|
||||||
|
#define CS2_PAT 0000020 /* parity test NI */
|
||||||
|
#define CS2_CLR 0000040 /* controller clear */
|
||||||
|
#define CS2_IR 0000100 /* input ready */
|
||||||
|
#define CS2_OR 0000200 /* output ready */
|
||||||
|
#define CS2_MDPE 0000400 /* Mbus par err NI */
|
||||||
|
#define CS2_MXF 0001000 /* missed xfer NI */
|
||||||
|
#define CS2_PGE 0002000 /* program err */
|
||||||
|
#define CS2_NEM 0004000 /* nx mem err */
|
||||||
|
#define CS2_NED 0010000 /* nx drive err */
|
||||||
|
#define CS2_PE 0020000 /* parity err NI */
|
||||||
|
#define CS2_WCE 0040000 /* write check err */
|
||||||
|
#define CS2_DLT 0100000 /* data late NI */
|
||||||
|
|
||||||
|
/* Controller error bits, saved in error register */
|
||||||
|
#define ER1_ILF 0000001 /* illegal func */
|
||||||
|
#define ER1_ILR 0000002 /* illegal register */
|
||||||
|
#define ER1_RMR 0000004 /* reg mod refused */
|
||||||
|
#define ER1_PAR 0000010 /* parity err */
|
||||||
|
|
||||||
|
/* Map addresses into RH registers */
|
||||||
|
int rh_map[] = { 0, /* 776700 */
|
||||||
|
-1, /* 776702 */
|
||||||
|
-1, /* 776704 */
|
||||||
|
05, /* 776706 */
|
||||||
|
-1, /* 776710 */
|
||||||
|
01, /* 776712 */
|
||||||
|
02, /* 776714 */
|
||||||
|
04, /* 776716 */
|
||||||
|
07, /* 776720 */
|
||||||
|
-1, /* 776722 */
|
||||||
|
03, /* 776724 */
|
||||||
|
06, /* 776726 */
|
||||||
|
010, /* 776730 */
|
||||||
|
011, /* 776732 */
|
||||||
|
012, /* 776734 */
|
||||||
|
013, /* 776736 */
|
||||||
|
014, /* 776740 */
|
||||||
|
015, /* 776742 */
|
||||||
|
016, /* 776744 */
|
||||||
|
017 /* 776746 */
|
||||||
|
};
|
||||||
|
#else
|
||||||
/* CONI Flags */
|
/* CONI Flags */
|
||||||
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
|
#define IADR_ATTN 0000000000040LL /* Interrupt on attention */
|
||||||
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
|
#define IARD_RAE 0000000000100LL /* Interrupt on register access error */
|
||||||
|
@ -103,6 +162,19 @@
|
||||||
#define IRQ_VECT 0000000000777LL /* Interupt vector */
|
#define IRQ_VECT 0000000000777LL /* Interupt vector */
|
||||||
#define IRQ_KI10 0000002000000LL
|
#define IRQ_KI10 0000002000000LL
|
||||||
#define IRQ_KA10 0000001000000LL
|
#define IRQ_KA10 0000001000000LL
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
|
||||||
|
#endif
|
||||||
#define FNC_XFER 024 /* >=? data xfr */
|
#define FNC_XFER 024 /* >=? data xfr */
|
||||||
|
|
||||||
/* Status register settings */
|
/* Status register settings */
|
||||||
|
@ -118,17 +190,234 @@
|
||||||
#define DS_ERR 0040000 /* error */
|
#define DS_ERR 0040000 /* error */
|
||||||
#define DS_ATA 0100000 /* attention active */
|
#define DS_ATA 0100000 /* attention active */
|
||||||
|
|
||||||
/* RH20 channel status flags */
|
#if KS
|
||||||
#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 */
|
|
||||||
|
|
||||||
|
DEVICE *rh_boot_dev = NULL;
|
||||||
|
int rh_boot_unit = 0;
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
uba_rh_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access) {
|
||||||
|
int r = 0;
|
||||||
|
struct pdp_dib *dibp = (DIB *) dptr->ctxt;
|
||||||
|
struct rh_if *rhc;
|
||||||
|
int reg;
|
||||||
|
uint32 temp;
|
||||||
|
|
||||||
|
if (dibp == NULL)
|
||||||
|
return 1;
|
||||||
|
rhc = dibp->rh11_if;
|
||||||
|
/* Check for parity error during access */
|
||||||
|
if (rhc->cs2 & CS2_PAT) {
|
||||||
|
uba_set_parity(dibp->uba_ctl);
|
||||||
|
rhc->error |= ER1_PAR;
|
||||||
|
}
|
||||||
|
addr &= dibp->uba_mask;
|
||||||
|
reg = rh_map[addr >> 1];
|
||||||
|
|
||||||
|
switch(addr & 076) {
|
||||||
|
case 000: /* CS1 */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1) {
|
||||||
|
rhc->dev_read(dptr, rhc, 0, &temp);
|
||||||
|
data = data | (rhc->cs1 & 0300) | (temp & 076);
|
||||||
|
} else {
|
||||||
|
data = data | (rhc->cs1 & CS1_UBA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rhc->cs1 &= ~(CS1_IE);
|
||||||
|
rhc->cs1 |= data & (CS1_IE);
|
||||||
|
if ((rhc->status & BUSY) == 0)
|
||||||
|
rhc->cda = ((data << 8) & 0600000) | (rhc->cda & 0177777);
|
||||||
|
if ((data & CS1_GO) != 0 || (rhc->cs1 & CS1_IE) == 0)
|
||||||
|
uba_clr_irq(rhc->dib, rhc->dib->uba_vect);
|
||||||
|
if ((data & CS1_GO) != 0 && (rhc->status & BUSY) != 0 && GET_FNC(data) >= FNC_XFER) {
|
||||||
|
rhc->cs2 |= CS2_PGE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
r = rhc->dev_write(dptr, rhc, 0, data);
|
||||||
|
/* Check if we had a go with a data transfer command */
|
||||||
|
if (r == 0 && (data & CS1_GO) != 0 && GET_FNC(data) >= FNC_XFER) {
|
||||||
|
rhc->cs2 = ((CS2_UAI|CS2_OR|CS2_IR|CS2_PAT|CS2_UNIT) & rhc->cs2);
|
||||||
|
rhc->xfer_drive = rhc->drive;
|
||||||
|
rhc->status |= BUSY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 002: /* RPWC - 176702 - word count */ /* 1 */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (rhc->wcr & 0377);
|
||||||
|
else
|
||||||
|
data = (rhc->wcr & 0177400) | data;
|
||||||
|
}
|
||||||
|
rhc->wcr = data;
|
||||||
|
break;
|
||||||
|
case 004: /* RPBA - 176704 - base address */ /* 2 */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (rhc->cda & 0377);
|
||||||
|
else
|
||||||
|
data = (rhc->cda & 0177400) | data;
|
||||||
|
}
|
||||||
|
rhc->cda = (rhc->cda & 0600000) | (data & 0177776);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 010: /* RPCS2 - 176710 - Control and Status register 2 */ /* 4 */
|
||||||
|
if (access == BYTE) {
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (rhc->cs2 & 0377);
|
||||||
|
else
|
||||||
|
data = (rhc->cs2 & 0177400) | data;
|
||||||
|
}
|
||||||
|
if (data & CS2_CLR) {
|
||||||
|
rh_reset(dptr, rhc);
|
||||||
|
if (rhc->dev_reset != NULL)
|
||||||
|
rhc->dev_reset(dptr);
|
||||||
|
else
|
||||||
|
dptr->reset(dptr);
|
||||||
|
rhc->cs2 |= CS2_CLR; /* Hack for tops 10 7.04 */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Don't allow UAI to be set just after reset */
|
||||||
|
if (rhc->cs2 & CS2_CLR) {
|
||||||
|
data &= ~CS2_UAI;
|
||||||
|
rhc->cs2 &= ~CS2_CLR;
|
||||||
|
}
|
||||||
|
|
||||||
|
rhc->cs2 &= ~(CS2_PE|CS2_MXF|CS2_PAT|CS2_UNIT);
|
||||||
|
if ((rhc->status & BUSY) == 0) {
|
||||||
|
rhc->cs2 &= ~(CS2_UAI);
|
||||||
|
if( data & CS2_UAI)
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "RH%o set no UAI %06o\n", rhc->drive, PC);
|
||||||
|
rhc->cs2 |= CS2_UAI & data;
|
||||||
|
}
|
||||||
|
rhc->cs2 |= (CS2_PE|CS2_MXF|CS2_PAT|CS2_UNIT) & data;
|
||||||
|
rhc->cs2 |= CS2_IR;
|
||||||
|
rhc->drive = rhc->cs2 & CS2_UNIT;
|
||||||
|
/* Try reading the command register */
|
||||||
|
r = rhc->dev_read(dptr, rhc, 0, &temp);
|
||||||
|
if (r < 0)
|
||||||
|
rhc->cs2 |= CS2_NED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 022: /* RPDB - 176722 - data buffer */ /* 11 */
|
||||||
|
if ((rhc->cs2 & CS2_IR) == 0) {
|
||||||
|
rhc->cs2 |= CS2_DLT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rhc->dba = rhc->dbb;
|
||||||
|
rhc->dbb = data;
|
||||||
|
if (rhc->cs2 & CS2_IR)
|
||||||
|
rhc->dba = rhc->dbb;
|
||||||
|
rhc->cs2 |= CS2_OR;
|
||||||
|
rhc->cs2 &= ~CS2_IR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 014: /* RPER1 - 176714 - error status 1 */ /* 6 */
|
||||||
|
rhc->error = data;
|
||||||
|
/* Fall through */
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (access == BYTE) {
|
||||||
|
rhc->dev_read(dptr, rhc, reg, &temp);
|
||||||
|
if (addr & 1)
|
||||||
|
data = data | (temp & 0377);
|
||||||
|
else
|
||||||
|
data = (temp & 0177400) | data;
|
||||||
|
}
|
||||||
|
r = rhc->dev_write(dptr, rhc, reg, data);
|
||||||
|
}
|
||||||
|
if (r < 0) {
|
||||||
|
rhc->cs2 |= CS2_NED;
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "RH%o write %06o %06o %o\n", rhc->drive,
|
||||||
|
addr, data, access);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
uba_rh_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access) {
|
||||||
|
int r = 1;
|
||||||
|
struct pdp_dib *dibp = (DIB *) dptr->ctxt;
|
||||||
|
struct rh_if *rhc;
|
||||||
|
int reg;
|
||||||
|
uint32 temp = 0;
|
||||||
|
|
||||||
|
if (dibp == NULL)
|
||||||
|
return 1;
|
||||||
|
rhc = dibp->rh11_if;
|
||||||
|
addr &= dibp->uba_mask;
|
||||||
|
reg = rh_map[addr >> 1];
|
||||||
|
|
||||||
|
if (reg >= 0) {
|
||||||
|
r = rhc->dev_read(dptr, rhc, reg, &temp);
|
||||||
|
if (r < 0) {
|
||||||
|
rhc->cs2 |= CS2_NED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(addr & 076) {
|
||||||
|
case 000: /* RPC - 176700 - control */
|
||||||
|
temp |= (uint16)(rhc->cs1 & (CS1_IE));
|
||||||
|
temp |= (rhc->cda & 0600000) >> 8;
|
||||||
|
if ((rhc->status & BUSY) == 0)
|
||||||
|
temp |= CS1_RDY;
|
||||||
|
if (rhc->cs2 & (CS2_MDPE|CS2_MXF|CS2_PGE|CS2_NEM|CS2_NED|CS2_PE|CS2_WCE|CS2_DLT))
|
||||||
|
temp |= CS1_TRE;
|
||||||
|
if (rhc->attn || (temp & CS1_TRE) != 0)
|
||||||
|
temp |= CS1_SC;
|
||||||
|
r = 0;
|
||||||
|
break;
|
||||||
|
case 002: /* RPWC - 176702 - word count */
|
||||||
|
temp = rhc->wcr;
|
||||||
|
r = 0;
|
||||||
|
break;
|
||||||
|
case 004: /* RPBA - 176704 - base address */
|
||||||
|
temp = (uint16)(rhc->cda & 0177776);
|
||||||
|
r = 0;
|
||||||
|
break;
|
||||||
|
case 010: /* RPCS2 - 176710 - control/status 2 */
|
||||||
|
temp = rhc->cs2 & ~CS2_CLR;
|
||||||
|
r = 0;
|
||||||
|
break;
|
||||||
|
case 014: /* RPER1 - 176714 - error status 1 */
|
||||||
|
temp |= rhc->error;
|
||||||
|
r = 0;
|
||||||
|
break;
|
||||||
|
case 022: /* RPDB - 176722 - data buffer */
|
||||||
|
r = 0;
|
||||||
|
if ((rhc->cs2 & CS2_OR) == 0) {
|
||||||
|
rhc->cs2 |= CS2_DLT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
temp = rhc->dba;
|
||||||
|
rhc->dba = rhc->dbb;
|
||||||
|
rhc->cs2 &= ~CS2_OR;
|
||||||
|
rhc->cs2 |= CS2_IR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*data = temp;
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "RH%o read %o %d %06o %06o %06o\n", rhc->drive, r, reg,
|
||||||
|
addr, temp, PC);
|
||||||
|
/* Check for parity error during access */
|
||||||
|
if (rhc->cs2 & CS2_PAT) {
|
||||||
|
uba_set_parity(dibp->uba_ctl);
|
||||||
|
rhc->error |= ER1_PAR;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16
|
||||||
|
uba_rh_vect(struct pdp_dib *dibp)
|
||||||
|
{
|
||||||
|
return dibp->uba_vect;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
/* 0-37 mass bus register.
|
/* 0-37 mass bus register.
|
||||||
70 SBAR, block address.
|
70 SBAR, block address.
|
||||||
71 STCR, neg block count, func
|
71 STCR, neg block count, func
|
||||||
|
@ -446,14 +735,16 @@ t_stat rh_devio(uint32 dev, uint64 *data) {
|
||||||
dptr->name, dev, *data, rhc->drive, PC, rhc->status);
|
dptr->name, dev, *data, rhc->drive, PC, rhc->status);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
rhc->drive = (int)(*data >> 18) & 07;
|
||||||
/* Check if access error */
|
/* Check if access error */
|
||||||
if (rhc->rae & (1 << rhc->drive))
|
if (rhc->rae & (1 << rhc->drive))
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
/* Start command */
|
/* Start command */
|
||||||
rh_setup(rhc, (uint32)(*data >> 6));
|
|
||||||
rhc->xfer_drive = (int)(*data >> 18) & 07;
|
|
||||||
if (rhc->dev_write(dptr, rhc, 0, (uint32)(*data & 077))) {
|
if (rhc->dev_write(dptr, rhc, 0, (uint32)(*data & 077))) {
|
||||||
rhc->status |= CR_DRE;
|
rhc->status |= CR_DRE;
|
||||||
|
} else {
|
||||||
|
rh_setup(rhc, (uint32)(*data >> 6));
|
||||||
|
rhc->xfer_drive = rhc->drive;
|
||||||
}
|
}
|
||||||
sim_debug(DEBUG_DATAIO, dptr,
|
sim_debug(DEBUG_DATAIO, dptr,
|
||||||
"%s %03o command %012llo, %d PC=%06o %06o\n",
|
"%s %03o command %012llo, %d PC=%06o %06o\n",
|
||||||
|
@ -506,23 +797,51 @@ rh_devirq(uint32 dev, t_addr addr) {
|
||||||
else if (rhc->imode == 2) /* RH20 style */
|
else if (rhc->imode == 2) /* RH20 style */
|
||||||
addr = rhc->ivect;
|
addr = rhc->ivect;
|
||||||
} else {
|
} else {
|
||||||
sim_printf("Unable to find device %03o\n\r", dev);
|
sim_printf("Unable to find device %03o\r\n", dev);
|
||||||
}
|
}
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Reset the RH to a known clear condiguration */
|
||||||
|
void rh_reset(DEVICE *dptr, struct rh_if *rhc)
|
||||||
|
{
|
||||||
|
rhc->status = 0;
|
||||||
|
rhc->attn = 0;
|
||||||
|
rhc->rae = 0;
|
||||||
|
rhc->wcr = 0;
|
||||||
|
rhc->cda = 0;
|
||||||
|
rhc->drive = 0;
|
||||||
|
// rhc->xfer_drive = -1;
|
||||||
|
#if KS
|
||||||
|
rhc->dib = (DIB *)dptr->ctxt;
|
||||||
|
rhc->cs1 = 0;
|
||||||
|
rhc->cs2 = CS2_IR;
|
||||||
|
rhc->dba = 0;
|
||||||
|
rhc->dbb = 0;
|
||||||
|
rhc->error = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the attention flag for a unit */
|
/* Set the attention flag for a unit */
|
||||||
void rh_setattn(struct rh_if *rhc, int unit)
|
void rh_setattn(struct rh_if *rhc, int unit)
|
||||||
{
|
{
|
||||||
rhc->attn |= 1<<unit;
|
rhc->attn |= 1<<unit;
|
||||||
if ((rhc->status & BUSY) == 0 && (rhc->status & IADR_ATTN) != 0)
|
#if KS
|
||||||
|
if ((rhc->status & BUSY) == 0 && (rhc->cs1 & CS1_IE) != 0)
|
||||||
|
uba_set_irq(rhc->dib, rhc->dib->uba_vect);
|
||||||
|
#else
|
||||||
|
if ((rhc->status & BUSY) == 0 && (rhc->status & IADR_ATTN) != 0)
|
||||||
set_interrupt(rhc->devnum, rhc->status);
|
set_interrupt(rhc->devnum, rhc->status);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void rh_error(struct rh_if *rhc)
|
void rh_error(struct rh_if *rhc)
|
||||||
{
|
{
|
||||||
|
#if !KS
|
||||||
if (rhc->imode == 2)
|
if (rhc->imode == 2)
|
||||||
rhc->status |= RH20_DR_EXC;
|
rhc->status |= RH20_DR_EXC;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decrement block count for RH20, nop for RH10 */
|
/* Decrement block count for RH20, nop for RH10 */
|
||||||
|
@ -542,12 +861,18 @@ int rh_blkend(struct rh_if *rhc)
|
||||||
|
|
||||||
/* Set an IRQ for a DF10 device */
|
/* Set an IRQ for a DF10 device */
|
||||||
void rh_setirq(struct rh_if *rhc) {
|
void rh_setirq(struct rh_if *rhc) {
|
||||||
rhc->status |= PI_ENABLE;
|
rhc->status |= PI_ENABLE;
|
||||||
set_interrupt(rhc->devnum, rhc->status);
|
#if KS
|
||||||
|
if ((rhc->status & BUSY) == 0 && (rhc->cs1 & CS1_IE) != 0)
|
||||||
|
uba_set_irq(rhc->dib, rhc->dib->uba_vect);
|
||||||
|
#else
|
||||||
|
set_interrupt(rhc->devnum, rhc->status);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate the DF10 complete word */
|
/* Generate the DF10 complete word */
|
||||||
void rh_writecw(struct rh_if *rhc, int nxm) {
|
void rh_writecw(struct rh_if *rhc, int nxm) {
|
||||||
|
#if !KS
|
||||||
uint64 wrd1;
|
uint64 wrd1;
|
||||||
#if KL
|
#if KL
|
||||||
if (rhc->imode == 2) {
|
if (rhc->imode == 2) {
|
||||||
|
@ -564,7 +889,7 @@ void rh_writecw(struct rh_if *rhc, int nxm) {
|
||||||
if (nxm) {
|
if (nxm) {
|
||||||
wrd1 |= RH20_NXM_ERR;
|
wrd1 |= RH20_NXM_ERR;
|
||||||
rhc->status |= RH20_CHAN_ERR;
|
rhc->status |= RH20_CHAN_ERR;
|
||||||
}
|
}
|
||||||
if (wc != 0) {
|
if (wc != 0) {
|
||||||
wrd1 |= RH20_NOT_WC0;
|
wrd1 |= RH20_NOT_WC0;
|
||||||
if (rhc->status & RH20_XEND) {
|
if (rhc->status & RH20_XEND) {
|
||||||
|
@ -598,14 +923,16 @@ void rh_writecw(struct rh_if *rhc, int nxm) {
|
||||||
rhc->cda++;
|
rhc->cda++;
|
||||||
wrd1 = ((uint64)(rhc->ccw & WMASK) << CSHIFT) | ((uint64)(rhc->cda) & AMASK);
|
wrd1 = ((uint64)(rhc->ccw & WMASK) << CSHIFT) | ((uint64)(rhc->cda) & AMASK);
|
||||||
(void)Mem_write_word(rhc->cia|1, &wrd1, 0);
|
(void)Mem_write_word(rhc->cia|1, &wrd1, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finish off a DF10 transfer */
|
/* Finish off a DF10 transfer */
|
||||||
void rh_finish_op(struct rh_if *rhc, int nxm) {
|
void rh_finish_op(struct rh_if *rhc, int nxm) {
|
||||||
#if KL
|
#if KL
|
||||||
|
rhc->status &= ~(CC_CHAN_ACT);
|
||||||
if (rhc->imode != 2)
|
if (rhc->imode != 2)
|
||||||
#endif
|
#endif
|
||||||
rhc->status &= ~BUSY;
|
rhc->status &= ~(BUSY);
|
||||||
rh_writecw(rhc, nxm);
|
rh_writecw(rhc, nxm);
|
||||||
rh_setirq(rhc);
|
rh_setirq(rhc);
|
||||||
#if KL
|
#if KL
|
||||||
|
@ -621,7 +948,9 @@ void rh_finish_op(struct rh_if *rhc, int nxm) {
|
||||||
void rh20_setup(struct rh_if *rhc)
|
void rh20_setup(struct rh_if *rhc)
|
||||||
{
|
{
|
||||||
DEVICE *dptr = NULL;
|
DEVICE *dptr = NULL;
|
||||||
|
uint32 data;
|
||||||
int reg;
|
int reg;
|
||||||
|
int drv;
|
||||||
|
|
||||||
for (reg = 0; rh[reg].dev_num != 0; reg++) {
|
for (reg = 0; rh[reg].dev_num != 0; reg++) {
|
||||||
if (rh[reg].rh == rhc) {
|
if (rh[reg].rh == rhc) {
|
||||||
|
@ -631,15 +960,24 @@ void rh20_setup(struct rh_if *rhc)
|
||||||
}
|
}
|
||||||
if (dptr == 0)
|
if (dptr == 0)
|
||||||
return;
|
return;
|
||||||
rhc->pbar = rhc->sbar;
|
/* Check to see if drive currently doing something */
|
||||||
|
drv = rhc->drive;
|
||||||
|
rhc->drive = (rhc->stcr >> 18) & 07;
|
||||||
|
if (rhc->dev_read != NULL) {
|
||||||
|
(void)rhc->dev_read(dptr, rhc, 0, &data);
|
||||||
|
if (data & 1) {
|
||||||
|
rhc->drive = drv;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
rhc->ptcr = rhc->stcr;
|
rhc->ptcr = rhc->stcr;
|
||||||
/* Read drive status */
|
rhc->pbar = rhc->sbar;
|
||||||
rhc->drive = (rhc->ptcr >> 18) & 07;
|
rhc->drive = (rhc->ptcr >> 18) & 07;
|
||||||
|
/* Read drive status */
|
||||||
rhc->status &= ~(RH20_DATA_OVR|RH20_CHAN_RDY|RH20_DR_RESP|RH20_CHAN_ERR|RH20_SHRT_WC|\
|
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);
|
RH20_LONG_WC|RH20_DR_EXC|RH20_SCR_FULL|PI_ENABLE|RH20_XEND);
|
||||||
rhc->status |= RH20_PCR_FULL;
|
rhc->status |= RH20_PCR_FULL;
|
||||||
if (rhc->status & RH20_SBAR) {
|
if (rhc->status & RH20_SBAR) {
|
||||||
rhc->drive = (rhc->pbar >> 18) & 07;
|
|
||||||
if (rhc->dev_write != NULL)
|
if (rhc->dev_write != NULL)
|
||||||
(void)rhc->dev_write(dptr, rhc, 5, (rhc->pbar & 0177777));
|
(void)rhc->dev_write(dptr, rhc, 5, (rhc->pbar & 0177777));
|
||||||
rhc->status &= ~RH20_SBAR;
|
rhc->status &= ~RH20_SBAR;
|
||||||
|
@ -649,28 +987,33 @@ void rh20_setup(struct rh_if *rhc)
|
||||||
rhc->wcr = 0;
|
rhc->wcr = 0;
|
||||||
}
|
}
|
||||||
/* Hold block count in cia */
|
/* Hold block count in cia */
|
||||||
rhc->drive = (rhc->ptcr >> 18) & 07;
|
|
||||||
rhc->cia = (rhc->ptcr >> 6) & 01777;
|
rhc->cia = (rhc->ptcr >> 6) & 01777;
|
||||||
if (rhc->dev_write != NULL)
|
if (rhc->dev_write != NULL)
|
||||||
(void)rhc->dev_write(dptr, rhc, 0, (rhc->ptcr & 077));
|
(void)rhc->dev_write(dptr, rhc, 0, (rhc->ptcr & 077));
|
||||||
rhc->cop = 0;
|
rhc->cop = 0;
|
||||||
rhc->wcr = 0;
|
rhc->wcr = 0;
|
||||||
|
rhc->xfer_drive = rhc->drive;
|
||||||
rhc->status &= ~RH20_CHAN_RDY;
|
rhc->status &= ~RH20_CHAN_RDY;
|
||||||
|
rhc->status |= BUSY;
|
||||||
|
rhc->drive = drv;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Setup for a DF10 transfer */
|
/* Setup for a DF10 transfer */
|
||||||
void rh_setup(struct rh_if *rhc, uint32 addr)
|
void rh_setup(struct rh_if *rhc, uint32 addr)
|
||||||
{
|
{
|
||||||
|
#if !KS
|
||||||
rhc->cia = addr & ICWA;
|
rhc->cia = addr & ICWA;
|
||||||
rhc->ccw = rhc->cia;
|
rhc->ccw = rhc->cia;
|
||||||
rhc->wcr = 0;
|
rhc->wcr = 0;
|
||||||
|
#endif
|
||||||
rhc->status |= BUSY;
|
rhc->status |= BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Fetch the next IO control word */
|
/* Fetch the next IO control word */
|
||||||
int rh_fetch(struct rh_if *rhc) {
|
int rh_fetch(struct rh_if *rhc) {
|
||||||
|
#if !KS
|
||||||
uint64 data;
|
uint64 data;
|
||||||
int reg;
|
int reg;
|
||||||
DEVICE *dptr = NULL;
|
DEVICE *dptr = NULL;
|
||||||
|
@ -727,12 +1070,30 @@ int rh_fetch(struct rh_if *rhc) {
|
||||||
rhc->wcr = (uint32)((data >> CSHIFT) & WMASK);
|
rhc->wcr = (uint32)((data >> CSHIFT) & WMASK);
|
||||||
rhc->cda = (uint32)(data & AMASK);
|
rhc->cda = (uint32)(data & AMASK);
|
||||||
rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK);
|
rhc->ccw = (uint32)((rhc->ccw + 1) & AMASK);
|
||||||
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read next word */
|
/* Read next word */
|
||||||
int rh_read(struct rh_if *rhc) {
|
int rh_read(struct rh_if *rhc) {
|
||||||
|
#if KS
|
||||||
|
if ((rhc->status & BUSY) == 0)
|
||||||
|
return 0;
|
||||||
|
if (uba_read_npr(rhc->cda, rhc->dib->uba_ctl, &rhc->buf) == 0) {
|
||||||
|
rhc->cs2 |= CS2_NEM;
|
||||||
|
rhc->status &= ~BUSY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((rhc->cs2 & CS2_UAI) == 0)
|
||||||
|
rhc->cda += 4;
|
||||||
|
rhc->wcr = (rhc->wcr + 2) & 0177777;
|
||||||
|
if (rhc->wcr == 0) {
|
||||||
|
rhc->status &= ~BUSY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
uint64 data;
|
uint64 data;
|
||||||
|
|
||||||
if (rhc->wcr == 0) {
|
if (rhc->wcr == 0) {
|
||||||
if (!rh_fetch(rhc))
|
if (!rh_fetch(rhc))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -774,11 +1135,28 @@ int rh_read(struct rh_if *rhc) {
|
||||||
if (rhc->wcr == 0) {
|
if (rhc->wcr == 0) {
|
||||||
return rh_fetch(rhc);
|
return rh_fetch(rhc);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write next word */
|
/* Write next word */
|
||||||
int rh_write(struct rh_if *rhc) {
|
int rh_write(struct rh_if *rhc) {
|
||||||
|
#if KS
|
||||||
|
if ((rhc->status & BUSY) == 0)
|
||||||
|
return 0;
|
||||||
|
if (uba_write_npr(rhc->cda, rhc->dib->uba_ctl, rhc->buf) == 0) {
|
||||||
|
rhc->cs2 |= CS2_NEM;
|
||||||
|
rhc->status &= ~BUSY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((rhc->cs2 & CS2_UAI) == 0)
|
||||||
|
rhc->cda += 4;
|
||||||
|
rhc->wcr = (rhc->wcr + 2) & 0177777;
|
||||||
|
if (rhc->wcr == 0) {
|
||||||
|
rhc->status &= ~BUSY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (rhc->wcr == 0) {
|
if (rhc->wcr == 0) {
|
||||||
if (!rh_fetch(rhc))
|
if (!rh_fetch(rhc))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -817,6 +1195,7 @@ int rh_write(struct rh_if *rhc) {
|
||||||
if (rhc->wcr == 0) {
|
if (rhc->wcr == 0) {
|
||||||
return rh_fetch(rhc);
|
return rh_fetch(rhc);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
589
PDP10/kx10_rp.c
589
PDP10/kx10_rp.c
File diff suppressed because it is too large
Load diff
|
@ -42,6 +42,9 @@
|
||||||
sim_load binary loader
|
sim_load binary loader
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
char sim_name[] = "KS-10";
|
||||||
|
#endif
|
||||||
#if KL
|
#if KL
|
||||||
char sim_name[] = "KL-10";
|
char sim_name[] = "KL-10";
|
||||||
#endif
|
#endif
|
||||||
|
@ -62,7 +65,7 @@ int32 sim_emax = 1;
|
||||||
|
|
||||||
DEVICE *sim_devices[] = {
|
DEVICE *sim_devices[] = {
|
||||||
&cpu_dev,
|
&cpu_dev,
|
||||||
#if PDP6 | KA | KI
|
#if PDP6 | KA | KI | KS
|
||||||
&cty_dev,
|
&cty_dev,
|
||||||
#endif
|
#endif
|
||||||
#if KL
|
#if KL
|
||||||
|
@ -171,6 +174,9 @@ DEVICE *sim_devices[] = {
|
||||||
#if (NUM_DEVS_III > 0)
|
#if (NUM_DEVS_III > 0)
|
||||||
&iii_dev,
|
&iii_dev,
|
||||||
#endif
|
#endif
|
||||||
|
#if (NUM_DEVS_TV > 0)
|
||||||
|
&tv_dev,
|
||||||
|
#endif
|
||||||
#if NUM_DEVS_IMP > 0
|
#if NUM_DEVS_IMP > 0
|
||||||
&imp_dev,
|
&imp_dev,
|
||||||
#endif
|
#endif
|
||||||
|
@ -180,6 +186,9 @@ DEVICE *sim_devices[] = {
|
||||||
#if NUM_DEVS_CH10 > 0
|
#if NUM_DEVS_CH10 > 0
|
||||||
&ch10_dev,
|
&ch10_dev,
|
||||||
#endif
|
#endif
|
||||||
|
#if NUM_DEVS_CH11 > 0
|
||||||
|
&ch11_dev,
|
||||||
|
#endif
|
||||||
#if NUM_DEVS_IMX > 0
|
#if NUM_DEVS_IMX > 0
|
||||||
&imx_dev,
|
&imx_dev,
|
||||||
#endif
|
#endif
|
||||||
|
@ -211,6 +220,21 @@ DEVICE *sim_devices[] = {
|
||||||
#endif
|
#endif
|
||||||
#if NUM_DEVS_AI > 0
|
#if NUM_DEVS_AI > 0
|
||||||
&ai_dev,
|
&ai_dev,
|
||||||
|
#endif
|
||||||
|
#if NUM_DEVS_DZ > 0
|
||||||
|
&dz_dev,
|
||||||
|
#endif
|
||||||
|
#if NUM_DEVS_TCU > 0
|
||||||
|
&tcu_dev,
|
||||||
|
#endif
|
||||||
|
#if NUM_DEVS_KMC > 0
|
||||||
|
&kmc_dev,
|
||||||
|
#endif
|
||||||
|
#if NUM_DEVS_DUP > 0
|
||||||
|
&dup_dev,
|
||||||
|
#endif
|
||||||
|
#if NUM_DEVS_DN > 0
|
||||||
|
&dn_dev,
|
||||||
#endif
|
#endif
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -279,24 +303,20 @@ t_stat load_dmp (FILE *fileref)
|
||||||
uint64 data;
|
uint64 data;
|
||||||
uint32 high = 0;
|
uint32 high = 0;
|
||||||
|
|
||||||
while (fgets((char *)buffer, 80, fileref) != 0) {
|
while (fgets(&buffer[0], 80, fileref) != 0) {
|
||||||
p = (char *)buffer;
|
data = 0;
|
||||||
while (*p >= '0' && *p <= '7') {
|
p = &buffer[0];
|
||||||
data = 0;
|
if (*p >= '0' && *p <= '7') {
|
||||||
while (*p >= '0' && *p <= '7') {
|
for (; *p >= '0' && *p <= '7'; p++)
|
||||||
data = (data << 3) + *p - '0';
|
data = (data << 3) + *p - '0';
|
||||||
p++;
|
if (addr == 0135 && data != 0)
|
||||||
}
|
high = (uint32)(data & RMASK);
|
||||||
if (addr == 0135 && data != 0)
|
if (high != 0 && high == addr) {
|
||||||
high = (uint32)(data & RMASK);
|
addr = 0400000;
|
||||||
if (high != 0 && high == addr) {
|
high = 0;
|
||||||
addr = 0400000;
|
}
|
||||||
high = 0;
|
M[addr++] = data;
|
||||||
}
|
}
|
||||||
M[addr++] = data;
|
|
||||||
if (*p == ' ' || *p == '\t')
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -585,7 +605,7 @@ t_stat load_sav (FILE *fileref, int ftype)
|
||||||
wc = (int32)(data >> 18);
|
wc = (int32)(data >> 18);
|
||||||
pa = (uint32) (data & RMASK);
|
pa = (uint32) (data & RMASK);
|
||||||
if (wc == (OP_JRST << 9)) {
|
if (wc == (OP_JRST << 9)) {
|
||||||
printf("Start addr=%06o\n", pa);
|
sim_printf("Start addr=%06o\n", pa);
|
||||||
PC = pa;
|
PC = pa;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -769,6 +789,8 @@ t_stat load_exb (FILE *fileref, int ftype)
|
||||||
return SCPE_FMT;
|
return SCPE_FMT;
|
||||||
addr |= byt << 24;
|
addr |= byt << 24;
|
||||||
/* Empty record gives start address */
|
/* Empty record gives start address */
|
||||||
|
if (addr > MEMSIZE)
|
||||||
|
return SCPE_FMT;
|
||||||
if (wc == 0) {
|
if (wc == 0) {
|
||||||
PC = addr;
|
PC = addr;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -784,6 +806,8 @@ t_stat load_exb (FILE *fileref, int ftype)
|
||||||
case 2: word |= ((uint64)byt) << 16; break;
|
case 2: word |= ((uint64)byt) << 16; break;
|
||||||
case 3: word |= ((uint64)byt) << 24; break;
|
case 3: word |= ((uint64)byt) << 24; break;
|
||||||
case 4: word |= ((uint64)(byt & 017)) << 32;
|
case 4: word |= ((uint64)(byt & 017)) << 32;
|
||||||
|
if (addr > MEMSIZE)
|
||||||
|
return SCPE_FMT;
|
||||||
M[addr++] = word;
|
M[addr++] = word;
|
||||||
pos = -1;
|
pos = -1;
|
||||||
break;
|
break;
|
||||||
|
@ -902,7 +926,7 @@ static const char *opcode[] = {
|
||||||
"SETSTS", "STATO", "STATUS", "GETSTS", "INBUF", "OUTBUF", "INPUT", "OUTPUT",
|
"SETSTS", "STATO", "STATUS", "GETSTS", "INBUF", "OUTBUF", "INPUT", "OUTPUT",
|
||||||
"CLOSE", "RELEAS", "MTAPE", "UGETF", "USETI", "USETO", "LOOKUP", "ENTER",
|
"CLOSE", "RELEAS", "MTAPE", "UGETF", "USETI", "USETO", "LOOKUP", "ENTER",
|
||||||
|
|
||||||
#if KL
|
#if KL | KS
|
||||||
"UJEN", "GFAD", "GFSB", "JSYS", "ADJSP", "GFMP", "GFDV ",
|
"UJEN", "GFAD", "GFSB", "JSYS", "ADJSP", "GFMP", "GFDV ",
|
||||||
"DFAD", "DFSB", "DFMP", "DFDV", "DADD", "DSUB", "DMUL", "DDIV",
|
"DFAD", "DFSB", "DFMP", "DFDV", "DADD", "DSUB", "DMUL", "DDIV",
|
||||||
#else
|
#else
|
||||||
|
@ -961,6 +985,19 @@ static const char *opcode[] = {
|
||||||
"TRO", "TLO", "TROE", "TLOE", "TROA", "TLOA", "TRON", "TLON",
|
"TRO", "TLO", "TROE", "TLOE", "TROA", "TLOA", "TRON", "TLON",
|
||||||
"TDO", "TSO", "TDOE", "TSOE", "TDOA", "TSOA", "TDON", "TSON",
|
"TDO", "TSO", "TDOE", "TSOE", "TDOA", "TSOA", "TDON", "TSON",
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
"APRID", "CLRSCH", "RDUBR", "CLRPT",
|
||||||
|
"WRUBR", "WREBR", "RDEBR",
|
||||||
|
"RDSPB", "RDCSB", "RDPUR", "RDCSTM",
|
||||||
|
"RDTIME", "RDINT", "RDHSB", "SPM",
|
||||||
|
"WRSPB", "WRCSB", "WRPUR", "WRCSTM",
|
||||||
|
"WRTIME", "WRINT", "WRHSB", "LPMR",
|
||||||
|
"UMOVE", "UMOVEM",
|
||||||
|
"TIOE", "TION", "RDIO", "WRIO",
|
||||||
|
"BSIO", "BCIO",
|
||||||
|
"TIOEB", "TIONB", "RDIOB", "WRIOB",
|
||||||
|
"BSIOB", "BCIOB",
|
||||||
|
#endif
|
||||||
|
|
||||||
"BLKI", "DATAI", "BLKO", "DATAO", /* classic I/O */
|
"BLKI", "DATAI", "BLKO", "DATAO", /* classic I/O */
|
||||||
"CONO", "CONI", "CONSZ", "CONSO",
|
"CONO", "CONI", "CONSZ", "CONSO",
|
||||||
|
@ -1095,9 +1132,21 @@ static const t_int64 opc_val[] = {
|
||||||
0670000000000+I_AC, 0671000000000+I_AC, 0672000000000+I_AC, 0673000000000+I_AC,
|
0670000000000+I_AC, 0671000000000+I_AC, 0672000000000+I_AC, 0673000000000+I_AC,
|
||||||
0674000000000+I_AC, 0675000000000+I_AC, 0676000000000+I_AC, 0677000000000+I_AC,
|
0674000000000+I_AC, 0675000000000+I_AC, 0676000000000+I_AC, 0677000000000+I_AC,
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
0700000000000+I_OP, 0701000000000+I_OP, 0701040000000+I_OP, 0701100000000+I_OP,
|
||||||
|
0701140000000+I_OP, 0701200000000+I_OP, 0701240000000+I_OP,
|
||||||
|
0702000000000+I_OP, 0702040000000+I_OP, 0702100000000+I_OP, 0702140000000+I_OP,
|
||||||
|
0702200000000+I_OP, 0702240000000+I_OP, 0702300000000+I_OP, 0702340000000+I_OP,
|
||||||
|
0702400000000+I_OP, 0702440000000+I_OP, 0702500000000+I_OP, 0702540000000+I_OP,
|
||||||
|
0702600000000+I_OP, 0702640000000+I_OP, 0702700000000+I_OP, 0702740000000+I_OP,
|
||||||
|
0704000000000+I_AC, 0705000000000+I_AC,
|
||||||
|
0710000000000+I_AC, 0711000000000+I_AC, 0712000000000+I_AC, 0713000000000+I_AC,
|
||||||
|
0714000000000+I_AC, 0715000000000+I_AC,
|
||||||
|
0720000000000+I_AC, 0721000000000+I_AC, 0722000000000+I_AC, 0723000000000+I_AC,
|
||||||
|
0724000000000+I_AC, 0725000000000+I_AC,
|
||||||
|
#endif
|
||||||
0700000000000+I_IO, 0700040000000+I_IO, 0700100000000+I_IO, 0700140000000+I_IO,
|
0700000000000+I_IO, 0700040000000+I_IO, 0700100000000+I_IO, 0700140000000+I_IO,
|
||||||
0700200000000+I_IO, 0700240000000+I_IO, 0700300000000+I_IO, 0700340000000+I_IO,
|
0700200000000+I_IO, 0700240000000+I_IO, 0700300000000+I_IO, 0700340000000+I_IO,
|
||||||
|
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
531
PDP10/kx10_tu.c
531
PDP10/kx10_tu.c
|
@ -41,7 +41,6 @@
|
||||||
#define TU_UNIT UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE
|
#define TU_UNIT UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE
|
||||||
|
|
||||||
#define CMD u3
|
#define CMD u3
|
||||||
/* u3 low */
|
|
||||||
/* TUC - 00 - control */
|
/* TUC - 00 - control */
|
||||||
|
|
||||||
#define CS1_GO 1 /* go */
|
#define CS1_GO 1 /* go */
|
||||||
|
@ -64,15 +63,12 @@
|
||||||
#define FNC_READ 034 /* read */
|
#define FNC_READ 034 /* read */
|
||||||
#define FNC_READREV 037 /* read reverse */
|
#define FNC_READREV 037 /* read reverse */
|
||||||
#define CS1_DVA 0004000 /* drive avail NI */
|
#define CS1_DVA 0004000 /* drive avail NI */
|
||||||
|
#define CS1_TRE 0040000 /* Set if errors */
|
||||||
|
#define CS1_SC 0100000 /* Set if TRE or ATTN */
|
||||||
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
|
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
|
||||||
#define CS_TM 001000 /* Tape mark sensed */
|
|
||||||
#define CS_MOTION 002000 /* Tape moving */
|
|
||||||
#define CS_PIP 004000 /* Tape Position command */
|
|
||||||
#define CS_ATA 010000 /* Tape signals attention */
|
|
||||||
#define CS_CHANGE 020000 /* Status changed */
|
|
||||||
|
|
||||||
#define STATUS u5
|
#define TUDS 01
|
||||||
/* u5 low */
|
#define STATUS u4 /* Attentions status for device */
|
||||||
/* TUDS - 01 - drive status */
|
/* TUDS - 01 - drive status */
|
||||||
|
|
||||||
#define DS_SLA 0000001 /* Drive has become ready */
|
#define DS_SLA 0000001 /* Drive has become ready */
|
||||||
|
@ -92,7 +88,7 @@
|
||||||
#define DS_ERR 0040000 /* error */
|
#define DS_ERR 0040000 /* error */
|
||||||
#define DS_ATA 0100000 /* attention active */
|
#define DS_ATA 0100000 /* attention active */
|
||||||
|
|
||||||
/* u5 high */
|
#define TUER1 02
|
||||||
/* TUER1 - 02 - error status 1 */
|
/* TUER1 - 02 - error status 1 */
|
||||||
|
|
||||||
#define ER1_ILF 0000001 /* illegal func */
|
#define ER1_ILF 0000001 /* illegal func */
|
||||||
|
@ -112,20 +108,27 @@
|
||||||
#define ER1_UNS 0040000 /* drive unsafe */
|
#define ER1_UNS 0040000 /* drive unsafe */
|
||||||
#define ER1_DCK 0100000 /* data check NI */
|
#define ER1_DCK 0100000 /* data check NI */
|
||||||
|
|
||||||
|
#define TUMR 03
|
||||||
/* TUMR - 03 - maintenace register */
|
/* TUMR - 03 - maintenace register */
|
||||||
|
|
||||||
|
#define TUAS 04
|
||||||
/* TUAS - 04 - attention summary */
|
/* TUAS - 04 - attention summary */
|
||||||
|
|
||||||
#define AS_U0 0000001 /* unit 0 flag */
|
#define AS_U0 0000001 /* unit 0 flag */
|
||||||
|
|
||||||
|
#define TUDC 05
|
||||||
/* TUDC - 05 - frame count */
|
/* TUDC - 05 - frame count */
|
||||||
|
|
||||||
|
#define TUDT 06
|
||||||
/* TUDT - 06 - drive type */
|
/* TUDT - 06 - drive type */
|
||||||
|
|
||||||
|
#define TULA 07
|
||||||
/* TULA - 07 - Check Character */
|
/* TULA - 07 - Check Character */
|
||||||
|
|
||||||
|
#define TUSN 010
|
||||||
/* TUSN - 10 - serial number */
|
/* TUSN - 10 - serial number */
|
||||||
|
|
||||||
|
#define TUTC 011
|
||||||
/* TUTC - 11 - Tape control register */
|
/* TUTC - 11 - Tape control register */
|
||||||
#define TC_SS 0000007 /* Slave select mask */
|
#define TC_SS 0000007 /* Slave select mask */
|
||||||
#define TC_EVPAR 0000010 /* Even parity */
|
#define TC_EVPAR 0000010 /* Even parity */
|
||||||
|
@ -153,12 +156,10 @@
|
||||||
|
|
||||||
/* TUER3 - 15 - error status 3 - more unsafe conditions - unimplemented */
|
/* TUER3 - 15 - error status 3 - more unsafe conditions - unimplemented */
|
||||||
|
|
||||||
#define CPOS u4
|
#define CPOS u5
|
||||||
#define DATAPTR u6
|
#define DATAPTR u6
|
||||||
|
|
||||||
uint8 tu_buf[NUM_DEVS_TU][TU_NUMFR];
|
uint8 tu_buf[NUM_DEVS_TU][TU_NUMFR];
|
||||||
uint16 tu_frame[NUM_DEVS_TU];
|
|
||||||
uint16 tu_tcr[NUM_DEVS_TU];
|
|
||||||
static uint64 tu_boot_buffer;
|
static uint64 tu_boot_buffer;
|
||||||
|
|
||||||
int tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data);
|
int tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data);
|
||||||
|
@ -173,6 +174,10 @@ t_stat tu_detach(UNIT *);
|
||||||
t_stat tu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
t_stat tu_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||||
const char *cptr);
|
const char *cptr);
|
||||||
const char *tu_description (DEVICE *dptr);
|
const char *tu_description (DEVICE *dptr);
|
||||||
|
#if KS
|
||||||
|
extern DEVICE *rh_boot_dev;
|
||||||
|
extern int rh_boot_unit;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
UNIT tu_unit[] = {
|
UNIT tu_unit[] = {
|
||||||
|
@ -187,6 +192,15 @@ UNIT tu_unit[] = {
|
||||||
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
|
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if KS
|
||||||
|
struct rh_if tu_rh[NUM_DEVS_TU] = {
|
||||||
|
{ &tu_write, &tu_read},
|
||||||
|
};
|
||||||
|
|
||||||
|
DIB tu_dib[NUM_DEVS_TU] = {
|
||||||
|
{0772440, 037, 0224, 6, 3, &uba_rh_read, &uba_rh_write, 0, 0, &tu_rh[0]},
|
||||||
|
};
|
||||||
|
#else
|
||||||
struct rh_if tu_rh[NUM_DEVS_TU] = {
|
struct rh_if tu_rh[NUM_DEVS_TU] = {
|
||||||
{ &tu_write, &tu_read}
|
{ &tu_write, &tu_read}
|
||||||
};
|
};
|
||||||
|
@ -194,6 +208,7 @@ struct rh_if tu_rh[NUM_DEVS_TU] = {
|
||||||
DIB tu_dib[] = {
|
DIB tu_dib[] = {
|
||||||
{RH10_DEV, 1, &rh_devio, &rh_devirq, &tu_rh[0]}
|
{RH10_DEV, 1, &rh_devio, &rh_devirq, &tu_rh[0]}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
MTAB tu_mod[] = {
|
MTAB tu_mod[] = {
|
||||||
#if KL
|
#if KL
|
||||||
|
@ -202,35 +217,45 @@ MTAB tu_mod[] = {
|
||||||
{MTAB_XTD|MTAB_VDV, TYPE_RH20, "RH20", "RH20", &rh_set_type, &rh_show_type,
|
{MTAB_XTD|MTAB_VDV, TYPE_RH20, "RH20", "RH20", &rh_set_type, &rh_show_type,
|
||||||
NULL, "Sets controller to RH20"},
|
NULL, "Sets controller to RH20"},
|
||||||
#endif
|
#endif
|
||||||
{ MTAB_XTD|MTAB_VUN, 0, "write enabled", "WRITEENABLED",
|
{MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL},
|
||||||
&set_writelock, &show_writelock, NULL, "Write ring in place" },
|
{MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL},
|
||||||
{ MTAB_XTD|MTAB_VUN, 1, NULL, "LOCKED",
|
|
||||||
&set_writelock, NULL, NULL, "no Write ring in place" },
|
|
||||||
{MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
{MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||||
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL},
|
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL},
|
||||||
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LENGTH", "LENGTH",
|
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LENGTH", "LENGTH",
|
||||||
&sim_tape_set_capac, &sim_tape_show_capac, NULL},
|
&sim_tape_set_capac, &sim_tape_show_capac, NULL},
|
||||||
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "DENSITY", "DENSITY",
|
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "DENSITY", "DENSITY",
|
||||||
&sim_tape_set_dens, &sim_tape_show_dens, NULL},
|
&sim_tape_set_dens, &sim_tape_show_dens, NULL},
|
||||||
|
#if KS
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "addr", "addr", &uba_set_addr, uba_show_addr,
|
||||||
|
NULL, "Sets address of RH11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "vect", "vect", &uba_set_vect, uba_show_vect,
|
||||||
|
NULL, "Sets vect of RH11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "br", "br", &uba_set_br, uba_show_br,
|
||||||
|
NULL, "Sets br of RH11" },
|
||||||
|
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "ctl", "ctl", &uba_set_ctl, uba_show_ctl,
|
||||||
|
NULL, "Sets uba of RH11" },
|
||||||
|
#endif
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
REG tua_reg[] = {
|
REG tua_reg[] = {
|
||||||
|
#if !KS
|
||||||
{ORDATA(IVECT, tu_rh[0].ivect, 18)},
|
{ORDATA(IVECT, tu_rh[0].ivect, 18)},
|
||||||
{FLDATA(IMODE, tu_rh[0].imode, 0)},
|
{FLDATA(IMODE, tu_rh[0].imode, 0)},
|
||||||
{ORDATA(FRAME, tu_frame[0], 16)},
|
|
||||||
{ORDATA(TCR, tu_tcr[0], 16)},
|
|
||||||
{ORDATA(XFER, tu_rh[0].xfer_drive, 3), REG_HRO},
|
{ORDATA(XFER, tu_rh[0].xfer_drive, 3), REG_HRO},
|
||||||
{ORDATA(DRIVE, tu_rh[0].drive, 3), REG_HRO},
|
|
||||||
{ORDATA(REG, tu_rh[0].reg, 6), REG_RO},
|
{ORDATA(REG, tu_rh[0].reg, 6), REG_RO},
|
||||||
|
{ORDATA(CIA, tu_rh[0].cia, 18)},
|
||||||
|
{ORDATA(CCW, tu_rh[0].ccw, 18)},
|
||||||
|
{ORDATA(DEVNUM, tu_rh[0].devnum, 9), REG_HRO},
|
||||||
|
#endif
|
||||||
|
{ORDATA(FRAME, tu_rh[0].regs[TUDC], 16)},
|
||||||
|
{ORDATA(TCR, tu_rh[0].regs[TUTC], 16)},
|
||||||
|
{ORDATA(DRIVE, tu_rh[0].drive, 3), REG_HRO},
|
||||||
{ORDATA(RAE, tu_rh[0].rae, 8), REG_RO},
|
{ORDATA(RAE, tu_rh[0].rae, 8), REG_RO},
|
||||||
{ORDATA(ATTN, tu_rh[0].attn, 8), REG_RO},
|
{ORDATA(ATTN, tu_rh[0].attn, 8), REG_RO},
|
||||||
{ORDATA(STATUS, tu_rh[0].status, 18), REG_RO},
|
{ORDATA(STATUS, tu_rh[0].status, 18), REG_RO},
|
||||||
{ORDATA(CIA, tu_rh[0].cia, 18)},
|
|
||||||
{ORDATA(CCW, tu_rh[0].ccw, 18)},
|
|
||||||
{ORDATA(WCR, tu_rh[0].wcr, 18)},
|
{ORDATA(WCR, tu_rh[0].wcr, 18)},
|
||||||
{ORDATA(CDA, tu_rh[0].cda, 18)},
|
{ORDATA(CDA, tu_rh[0].cda, 18)},
|
||||||
{ORDATA(DEVNUM, tu_rh[0].devnum, 9), REG_HRO},
|
|
||||||
{ORDATA(BUF, tu_rh[0].buf, 36), REG_HRO},
|
{ORDATA(BUF, tu_rh[0].buf, 36), REG_HRO},
|
||||||
{BRDATA(BUFF, tu_buf[0], 16, 8, TU_NUMFR), REG_HRO},
|
{BRDATA(BUFF, tu_buf[0], 16, 8, TU_NUMFR), REG_HRO},
|
||||||
{0}
|
{0}
|
||||||
|
@ -252,15 +277,16 @@ DEVICE *tu_devs[] = {
|
||||||
int
|
int
|
||||||
tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) {
|
tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) {
|
||||||
int ctlr = GET_CNTRL_RH(dptr->units[0].flags);
|
int ctlr = GET_CNTRL_RH(dptr->units[0].flags);
|
||||||
int unit = tu_tcr[ctlr] & 07;
|
uint16 *regs = &rhc->regs[0];
|
||||||
|
int unit = regs[TUTC] & 07;
|
||||||
UNIT *uptr = &dptr->units[unit];
|
UNIT *uptr = &dptr->units[unit];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (rhc->drive != 0 && reg != 04) /* Only one unit at 0 */
|
if (rhc->drive != 0 && reg != 04) /* Only one unit at 0 */
|
||||||
return 1;
|
return -1;
|
||||||
|
|
||||||
if (uptr->CMD & CS1_GO) {
|
if ((uptr->CMD & CS1_GO) != 0 || (uptr->STATUS & DS_PIP) != 0) {
|
||||||
uptr->STATUS |= (ER1_RMR);
|
regs[TUER1] |= ER1_RMR;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,93 +294,122 @@ tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) {
|
||||||
case 000: /* control */
|
case 000: /* control */
|
||||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o %d Status=%06o\n",
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o %d Status=%06o\n",
|
||||||
dptr->name, unit, ctlr, uptr->STATUS);
|
dptr->name, unit, ctlr, uptr->STATUS);
|
||||||
if ((data & 01) != 0 && (uptr->flags & UNIT_ATT) != 0) {
|
uptr->CMD = data & 076;
|
||||||
uptr->CMD = data & 076;
|
if ((data & 01) == 0) {
|
||||||
switch (GET_FNC(data)) {
|
sim_debug(DEBUG_DETAIL, &tua_dev, "TU%o no go %06o\n", unit, data);
|
||||||
case FNC_NOP:
|
return 0; /* No, nop */
|
||||||
break;
|
|
||||||
|
|
||||||
case FNC_PRESET: /* read-in preset */
|
|
||||||
case FNC_READ: /* read */
|
|
||||||
case FNC_READREV: /* read w/ headers */
|
|
||||||
tu_frame[ctlr] = 0;
|
|
||||||
tu_tcr[ctlr] |= TC_FCS;
|
|
||||||
/* Fall through */
|
|
||||||
|
|
||||||
case FNC_WRITE: /* write */
|
|
||||||
case FNC_SPACEF: /* Space forward */
|
|
||||||
case FNC_SPACEB: /* Space backward */
|
|
||||||
if ((tu_tcr[ctlr] & TC_FCS) == 0) {
|
|
||||||
uptr->STATUS |= ER1_NEF;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Fall through */
|
|
||||||
|
|
||||||
case FNC_ERASE: /* Erase gap */
|
|
||||||
case FNC_WTM: /* Write tape mark */
|
|
||||||
case FNC_WCHK: /* write check */
|
|
||||||
case FNC_REWIND: /* rewind */
|
|
||||||
case FNC_UNLOAD: /* unload */
|
|
||||||
case FNC_WCHKREV: /* write w/ headers */
|
|
||||||
uptr->CMD |= CS_PIP|CS1_GO;
|
|
||||||
rhc->attn = 0;
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
if (dptr->units[i].CMD & CS_ATA)
|
|
||||||
rhc->attn = 1;
|
|
||||||
}
|
|
||||||
CLR_BUF(uptr);
|
|
||||||
uptr->DATAPTR = 0;
|
|
||||||
sim_activate(uptr, 100);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FNC_DCLR: /* drive clear */
|
|
||||||
uptr->CMD &= ~(CS_ATA|CS1_GO|CS_TM);
|
|
||||||
uptr->STATUS = 0;
|
|
||||||
rhc->status &= ~PI_ENABLE;
|
|
||||||
rhc->attn = 0;
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
if (dptr->units[i].CMD & CS_ATA)
|
|
||||||
rhc->attn = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
uptr->STATUS |= (ER1_ILF);
|
|
||||||
uptr->CMD |= CS_ATA;
|
|
||||||
rhc->attn = 1;
|
|
||||||
}
|
|
||||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o AStatus=%06o\n", dptr->name, unit,
|
|
||||||
uptr->CMD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) {
|
||||||
|
if (GET_FNC(data) == FNC_DCLR) {
|
||||||
|
uptr->STATUS = 0;
|
||||||
|
rhc->attn = 0;
|
||||||
|
for (i = 0; i < NUM_UNITS_TU; i++) {
|
||||||
|
if (dptr->units[i].STATUS & DS_ATA)
|
||||||
|
rhc->attn = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, &tua_dev, "TU%o unattached %06o\n", unit, data);
|
||||||
|
return 0; /* No, nop */
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (GET_FNC(data)) {
|
||||||
|
case FNC_NOP:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FNC_PRESET: /* read-in preset */
|
||||||
|
case FNC_READ: /* read */
|
||||||
|
case FNC_READREV: /* read w/ headers */
|
||||||
|
regs[TUDC] = 0;
|
||||||
|
regs[TUTC] |= TC_FCS;
|
||||||
|
/* Fall through */
|
||||||
|
|
||||||
|
case FNC_WRITE: /* write */
|
||||||
|
case FNC_SPACEF: /* Space forward */
|
||||||
|
case FNC_SPACEB: /* Space backward */
|
||||||
|
if ((regs[TUTC] & TC_FCS) == 0) {
|
||||||
|
regs[TUER1] |= ER1_NEF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Fall through */
|
||||||
|
|
||||||
|
case FNC_ERASE: /* Erase gap */
|
||||||
|
case FNC_WTM: /* Write tape mark */
|
||||||
|
case FNC_WCHK: /* write check */
|
||||||
|
case FNC_REWIND: /* rewind */
|
||||||
|
case FNC_UNLOAD: /* unload */
|
||||||
|
case FNC_WCHKREV: /* write w/ headers */
|
||||||
|
uptr->CMD |= CS1_GO;
|
||||||
|
uptr->STATUS = DS_PIP;
|
||||||
|
regs[TUTC] |= TC_ACCL;
|
||||||
|
regs[TUER1] = 0;
|
||||||
|
rhc->attn = 0;
|
||||||
|
for (i = 0; i < NUM_UNITS_TU; i++) {
|
||||||
|
if (dptr->units[i].STATUS & DS_ATA)
|
||||||
|
rhc->attn = 1;
|
||||||
|
}
|
||||||
|
CLR_BUF(uptr);
|
||||||
|
uptr->DATAPTR = 0;
|
||||||
|
sim_activate(uptr, 100);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FNC_DCLR: /* drive clear */
|
||||||
|
uptr->CMD &= ~(CS1_GO);
|
||||||
|
uptr->STATUS = 0;
|
||||||
|
regs[TUER1] = 0;
|
||||||
|
regs[TUTC] &= ~TC_FCS;
|
||||||
|
rhc->status &= ~PI_ENABLE;
|
||||||
|
rhc->attn = 0;
|
||||||
|
for (i = 0; i < NUM_UNITS_TU; i++) {
|
||||||
|
if (dptr->units[i].STATUS & DS_ATA)
|
||||||
|
rhc->attn = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
regs[TUER1] |= ER1_ILF;
|
||||||
|
uptr->STATUS = DS_ATA;
|
||||||
|
rhc->attn = 1;
|
||||||
|
rh_setattn(rhc, 0);
|
||||||
|
}
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o AStatus=%06o\n", dptr->name, unit,
|
||||||
|
uptr->CMD);
|
||||||
return 0;
|
return 0;
|
||||||
case 001: /* status */
|
case 001: /* status */
|
||||||
break;
|
break;
|
||||||
case 002: /* error register 1 */
|
case 002: /* error register 1 */
|
||||||
uptr->STATUS &= ~0177777;
|
regs[TUER1] = data;
|
||||||
uptr->STATUS |= data;
|
|
||||||
break;
|
break;
|
||||||
case 003: /* maintenance */
|
case 003: /* maintenance */
|
||||||
|
regs[TUMR] = data;
|
||||||
|
fprintf(stderr, "TU MR=%06o\r\n", data);
|
||||||
break;
|
break;
|
||||||
case 004: /* atten summary */
|
case 004: /* atten summary */
|
||||||
rhc->attn = 0;
|
rhc->attn = 0;
|
||||||
if (data & 1) {
|
if (data & 1) {
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < NUM_UNITS_TU; i++)
|
||||||
dptr->units[i].CMD &= ~CS_ATA;
|
dptr->units[i].STATUS &= ~DS_ATA;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 005: /* frame count */
|
case 005: /* frame count */
|
||||||
tu_frame[ctlr] = data & 0177777;
|
regs[TUDC] = data;
|
||||||
tu_tcr[ctlr] |= TC_FCS;
|
regs[TUTC] |= TC_FCS;
|
||||||
break;
|
break;
|
||||||
case 006: /* drive type */
|
case 006: /* drive type */
|
||||||
case 007: /* look ahead */
|
case 007: /* look ahead */
|
||||||
|
case 010: /* look ahead */
|
||||||
|
break;
|
||||||
case 011: /* tape control register */
|
case 011: /* tape control register */
|
||||||
tu_tcr[ctlr] = data & 0177777 ;
|
regs[TUTC] = data;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
uptr->STATUS |= ER1_ILR;
|
#if KS
|
||||||
uptr->CMD |= CS_ATA;
|
return 1;
|
||||||
|
#else
|
||||||
|
regs[TUER1] |= ER1_ILR;
|
||||||
|
uptr->STATUS = DS_ATA;
|
||||||
rhc->attn = 1;
|
rhc->attn = 1;
|
||||||
rhc->rae = 1;
|
rhc->rae = 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -362,77 +417,76 @@ tu_write(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 data) {
|
||||||
int
|
int
|
||||||
tu_read(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 *data) {
|
tu_read(DEVICE *dptr, struct rh_if *rhc, int reg, uint32 *data) {
|
||||||
int ctlr = GET_CNTRL_RH(dptr->units[0].flags);
|
int ctlr = GET_CNTRL_RH(dptr->units[0].flags);
|
||||||
int unit = tu_tcr[ctlr] & 07;
|
uint16 *regs = &rhc->regs[0];
|
||||||
|
int unit = regs[TUTC] & 07;
|
||||||
UNIT *uptr = &dptr->units[unit];
|
UNIT *uptr = &dptr->units[unit];
|
||||||
uint32 temp = 0;
|
uint32 temp = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (rhc->drive != 0 && reg != 4) /* Only one unit at 0 */
|
if (rhc->drive != 0 && reg != 4) /* Only one unit at 0 */
|
||||||
return 1;
|
return -1;
|
||||||
|
|
||||||
switch(reg) {
|
switch(reg) {
|
||||||
case 000: /* control */
|
case 000: /* control */
|
||||||
temp = uptr->CMD & 076;
|
temp = uptr->CMD & 077;
|
||||||
temp |= CS1_DVA;
|
temp |= CS1_DVA;
|
||||||
if (uptr->CMD & CS1_GO)
|
|
||||||
temp |= CS1_GO;
|
|
||||||
break;
|
break;
|
||||||
case 001: /* status */
|
case 001: /* status */
|
||||||
temp = DS_DPR;
|
temp = DS_DPR | uptr->STATUS;
|
||||||
if (uptr->CMD & CS_ATA)
|
if (regs[TUER1] != 0)
|
||||||
temp |= DS_ATA;
|
|
||||||
if (uptr->CMD & CS_CHANGE)
|
|
||||||
temp |= DS_SSC;
|
|
||||||
if ((uptr->STATUS & 0177777) != 0)
|
|
||||||
temp |= DS_ERR;
|
temp |= DS_ERR;
|
||||||
if ((uptr->flags & UNIT_ATT) != 0) {
|
if ((uptr->flags & UNIT_ATT) != 0) {
|
||||||
temp |= DS_MOL;
|
temp |= DS_MOL;
|
||||||
if (uptr->CMD & CS_TM)
|
if ((regs[TUTC] & TC_DENS) == TC_1600)
|
||||||
temp |= DS_TM;
|
temp |= DS_PES;
|
||||||
if (uptr->flags & MTUF_WRP)
|
if (uptr->flags & MTUF_WLK)
|
||||||
temp |= DS_WRL;
|
temp |= DS_WRL;
|
||||||
if ((uptr->CMD & (CS_MOTION|CS_PIP|CS1_GO)) == 0)
|
if ((uptr->CMD & (CS1_GO)) == 0 && (uptr->STATUS & (DS_PIP)) == 0)
|
||||||
temp |= DS_DRY;
|
temp |= DS_DRY;
|
||||||
if (sim_tape_bot(uptr))
|
if (sim_tape_bot(uptr))
|
||||||
temp |= DS_BOT;
|
temp |= DS_BOT;
|
||||||
if (sim_tape_eot(uptr))
|
if (sim_tape_eot(uptr))
|
||||||
temp |= DS_EOT;
|
temp |= DS_EOT;
|
||||||
if ((uptr->CMD & CS_MOTION) == 0)
|
if ((uptr->CMD & CS1_GO) == 0)
|
||||||
temp |= DS_SDWN;
|
temp |= DS_SDWN;
|
||||||
if (uptr->CMD & CS_PIP)
|
|
||||||
temp |= DS_PIP;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 002: /* error register 1 */
|
case 002: /* error register 1 */
|
||||||
temp = uptr->STATUS & 0177777;
|
temp = regs[TUER1];
|
||||||
break;
|
break;
|
||||||
case 004: /* atten summary */
|
case 004: /* atten summary */
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < NUM_UNITS_TU; i++) {
|
||||||
if (dptr->units[i].CMD & CS_ATA)
|
if (dptr->units[i].STATUS & DS_ATA)
|
||||||
temp |= 1;
|
temp |= 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 005: /* frame count */
|
case 005: /* frame count */
|
||||||
temp = tu_frame[ctlr];
|
temp = regs[TUDC];
|
||||||
break;
|
break;
|
||||||
case 006: /* drive type */
|
case 006: /* drive type */
|
||||||
if ((uptr->flags & UNIT_DIS) == 0)
|
if ((uptr->flags & UNIT_DIS) == 0)
|
||||||
temp = 042054;
|
temp = 0142054;
|
||||||
break;
|
|
||||||
case 011: /* tape control register */
|
|
||||||
temp = tu_tcr[ctlr];
|
|
||||||
break;
|
break;
|
||||||
case 010: /* serial no */
|
case 010: /* serial no */
|
||||||
temp = 020 + (unit + 1);
|
temp = 020 + (unit + 1);
|
||||||
break;
|
break;
|
||||||
|
case 011: /* tape control register */
|
||||||
|
temp = regs[TUTC];
|
||||||
|
break;
|
||||||
case 003: /* maintenance */
|
case 003: /* maintenance */
|
||||||
|
temp = regs[TUMR];
|
||||||
|
break;
|
||||||
case 007: /* look ahead */
|
case 007: /* look ahead */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
uptr->STATUS |= (ER1_ILR);
|
#if KS
|
||||||
uptr->CMD |= CS_ATA;
|
return 1;
|
||||||
|
#else
|
||||||
|
regs[TUER1] |= ER1_ILR;
|
||||||
|
uptr->STATUS |= DS_ATA;
|
||||||
rhc->attn = 1;
|
rhc->attn = 1;
|
||||||
rhc->rae = 1;
|
rhc->rae = 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
*data = temp;
|
*data = temp;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -445,18 +499,19 @@ void tu_error(UNIT * uptr, t_stat r)
|
||||||
int ctlr = GET_CNTRL_RH(uptr->flags);
|
int ctlr = GET_CNTRL_RH(uptr->flags);
|
||||||
DEVICE *dptr = tu_devs[ctlr];
|
DEVICE *dptr = tu_devs[ctlr];
|
||||||
struct rh_if *rhc = &tu_rh[ctlr];
|
struct rh_if *rhc = &tu_rh[ctlr];
|
||||||
|
uint16 *regs = &rhc->regs[0];
|
||||||
|
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case MTSE_OK: /* no error */
|
case MTSE_OK: /* no error */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTSE_TMK: /* tape mark */
|
case MTSE_TMK: /* tape mark */
|
||||||
uptr->CMD |= CS_TM;
|
uptr->STATUS |= DS_TM;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTSE_WRP: /* write protected */
|
case MTSE_WRP: /* write protected */
|
||||||
uptr->STATUS |= (ER1_NEF);
|
regs[TUER1] |= ER1_NEF;
|
||||||
uptr->CMD |= CS_ATA;
|
uptr->STATUS |= DS_ATA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTSE_UNATT: /* unattached */
|
case MTSE_UNATT: /* unattached */
|
||||||
|
@ -466,26 +521,27 @@ void tu_error(UNIT * uptr, t_stat r)
|
||||||
|
|
||||||
case MTSE_IOERR: /* IO error */
|
case MTSE_IOERR: /* IO error */
|
||||||
case MTSE_FMT: /* invalid format */
|
case MTSE_FMT: /* invalid format */
|
||||||
uptr->STATUS |= (ER1_PEF);
|
regs[TUER1] |= ER1_PEF;
|
||||||
uptr->CMD |= CS_ATA;
|
uptr->STATUS |= DS_ATA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTSE_RECE: /* error in record */
|
case MTSE_RECE: /* error in record */
|
||||||
uptr->STATUS |= (ER1_DPAR);
|
regs[TUER1] |= ER1_DPAR;
|
||||||
uptr->CMD |= CS_ATA;
|
uptr->STATUS |= DS_ATA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTSE_INVRL: /* invalid rec lnt */
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
uptr->STATUS |= (ER1_FCE);
|
regs[TUER1] |= ER1_FCE;
|
||||||
uptr->CMD |= CS_ATA;
|
uptr->STATUS |= DS_ATA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (uptr->CMD & CS_ATA)
|
if (uptr->STATUS & DS_ATA)
|
||||||
rh_setattn(rhc, 0);
|
rh_setattn(rhc, 0);
|
||||||
if (GET_FNC(uptr->CMD) >= FNC_XFER && uptr->CMD & (CS_ATA | CS_TM))
|
if (GET_FNC(uptr->CMD) >= FNC_XFER && uptr->STATUS & (DS_ATA | DS_TM))
|
||||||
rh_error(rhc);
|
rh_error(rhc);
|
||||||
uptr->CMD &= ~(CS_MOTION|CS_PIP|CS1_GO);
|
uptr->CMD &= ~(CS1_GO);
|
||||||
|
uptr->STATUS &= ~(DS_PIP);
|
||||||
sim_debug(DEBUG_EXP, dptr, "Setting status %d\n", r);
|
sim_debug(DEBUG_EXP, dptr, "Setting status %d\n", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,6 +551,7 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
int ctlr = GET_CNTRL_RH(uptr->flags);
|
int ctlr = GET_CNTRL_RH(uptr->flags);
|
||||||
int unit;
|
int unit;
|
||||||
struct rh_if *rhc;
|
struct rh_if *rhc;
|
||||||
|
uint16 *regs;
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
t_mtrlnt reclen;
|
t_mtrlnt reclen;
|
||||||
|
@ -505,8 +562,10 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
/* Find dptr, and df10 */
|
/* Find dptr, and df10 */
|
||||||
dptr = tu_devs[ctlr];
|
dptr = tu_devs[ctlr];
|
||||||
rhc = &tu_rh[ctlr];
|
rhc = &tu_rh[ctlr];
|
||||||
|
regs = &rhc->regs[0];
|
||||||
unit = uptr - dptr->units;
|
unit = uptr - dptr->units;
|
||||||
cc_max = (4 + ((tu_tcr[ctlr] & TC_FMTSEL) == 0));
|
cc_max = (4 + ((regs[TUTC] & TC_FMTSEL) == 0));
|
||||||
|
regs[TUTC] &= ~TC_ACCL;
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) {
|
if ((uptr->flags & UNIT_ATT) == 0) {
|
||||||
tu_error(uptr, MTSE_UNATT); /* attached? */
|
tu_error(uptr, MTSE_UNATT); /* attached? */
|
||||||
rh_setirq(rhc);
|
rh_setirq(rhc);
|
||||||
|
@ -522,38 +581,35 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
|
|
||||||
case FNC_REWIND:
|
case FNC_REWIND:
|
||||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o rewind\n", dptr->name, unit);
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o rewind\n", dptr->name, unit);
|
||||||
if (uptr->CMD & CS1_GO) {
|
if (uptr->STATUS & CS1_GO) {
|
||||||
sim_activate(uptr,40000);
|
sim_activate(uptr,40000);
|
||||||
uptr->CMD |= CS_MOTION;
|
|
||||||
uptr->CMD &= ~(CS1_GO);
|
uptr->CMD &= ~(CS1_GO);
|
||||||
} else {
|
} else {
|
||||||
uptr->CMD &= ~(CS_MOTION|CS_PIP);
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o rewind done\n", dptr->name, unit);
|
||||||
uptr->CMD |= CS_CHANGE|CS_ATA;
|
uptr->STATUS |= DS_SSC|DS_ATA;
|
||||||
rh_setattn(rhc, 0);
|
tu_error(uptr, sim_tape_rewind(uptr));
|
||||||
(void)sim_tape_rewind(uptr);
|
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
||||||
case FNC_UNLOAD:
|
case FNC_UNLOAD:
|
||||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o unload\n", dptr->name, unit);
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o unload\n", dptr->name, unit);
|
||||||
uptr->CMD |= CS_CHANGE|CS_ATA;
|
uptr->STATUS |= DS_SSC|DS_ATA;
|
||||||
tu_error(uptr, sim_tape_detach(uptr));
|
tu_error(uptr, sim_tape_detach(uptr));
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
||||||
case FNC_WCHKREV:
|
case FNC_WCHKREV:
|
||||||
case FNC_READREV:
|
case FNC_READREV:
|
||||||
if (BUF_EMPTY(uptr)) {
|
if (BUF_EMPTY(uptr)) {
|
||||||
uptr->CMD &= ~CS_PIP;
|
uptr->STATUS &= ~DS_PIP;
|
||||||
if ((r = sim_tape_rdrecr(uptr, &tu_buf[ctlr][0], &reclen,
|
if ((r = sim_tape_rdrecr(uptr, &tu_buf[ctlr][0], &reclen,
|
||||||
TU_NUMFR)) != MTSE_OK) {
|
TU_NUMFR)) != MTSE_OK) {
|
||||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r);
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r);
|
||||||
if (r == MTSE_BOT)
|
if (r == MTSE_BOT)
|
||||||
uptr->STATUS |= ER1_NEF;
|
regs[TUER1] |= ER1_NEF;
|
||||||
tu_error(uptr, r);
|
tu_error(uptr, r);
|
||||||
rh_finish_op(rhc, 0);
|
rh_finish_op(rhc, 0);
|
||||||
} else {
|
} else {
|
||||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o read %d\n", dptr->name, unit, reclen);
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o read %d\n", dptr->name, unit, reclen);
|
||||||
uptr->CMD |= CS_MOTION;
|
|
||||||
uptr->hwmark = reclen;
|
uptr->hwmark = reclen;
|
||||||
uptr->DATAPTR = uptr->hwmark-1;
|
uptr->DATAPTR = uptr->hwmark-1;
|
||||||
uptr->CPOS = cc_max;
|
uptr->CPOS = cc_max;
|
||||||
|
@ -563,7 +619,9 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
if (uptr->DATAPTR >= 0) {
|
if (uptr->DATAPTR >= 0) {
|
||||||
tu_frame[ctlr]++;
|
regs[TUDC]++;
|
||||||
|
if (regs[TUDC] == 0)
|
||||||
|
regs[TUTC] &= ~TC_FCS;
|
||||||
cc = (8 * (3 - uptr->CPOS)) + 4;
|
cc = (8 * (3 - uptr->CPOS)) + 4;
|
||||||
ch = tu_buf[ctlr][uptr->DATAPTR];
|
ch = tu_buf[ctlr][uptr->DATAPTR];
|
||||||
if (cc < 0)
|
if (cc < 0)
|
||||||
|
@ -596,13 +654,12 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
case FNC_WCHK:
|
case FNC_WCHK:
|
||||||
case FNC_READ:
|
case FNC_READ:
|
||||||
if (BUF_EMPTY(uptr)) {
|
if (BUF_EMPTY(uptr)) {
|
||||||
uptr->CMD &= ~CS_PIP;
|
uptr->STATUS &= ~DS_PIP;
|
||||||
uptr->CMD |= CS_MOTION;
|
|
||||||
if ((r = sim_tape_rdrecf(uptr, &tu_buf[ctlr][0], &reclen,
|
if ((r = sim_tape_rdrecf(uptr, &tu_buf[ctlr][0], &reclen,
|
||||||
TU_NUMFR)) != MTSE_OK) {
|
TU_NUMFR)) != MTSE_OK) {
|
||||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r);
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o read error %d\n", dptr->name, unit, r);
|
||||||
if (r == MTSE_TMK)
|
if (r == MTSE_TMK)
|
||||||
uptr->STATUS |= ER1_FCE;
|
regs[TUER1] |= ER1_FCE;
|
||||||
tu_error(uptr, r);
|
tu_error(uptr, r);
|
||||||
rh_finish_op(rhc, 0);
|
rh_finish_op(rhc, 0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -616,7 +673,9 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
if ((uint32)uptr->DATAPTR < uptr->hwmark) {
|
if ((uint32)uptr->DATAPTR < uptr->hwmark) {
|
||||||
tu_frame[ctlr]++;
|
regs[TUDC]++;
|
||||||
|
if (regs[TUDC] == 0)
|
||||||
|
regs[TUTC] &= ~TC_FCS;
|
||||||
cc = (8 * (3 - uptr->CPOS)) + 4;
|
cc = (8 * (3 - uptr->CPOS)) + 4;
|
||||||
ch = tu_buf[ctlr][uptr->DATAPTR];
|
ch = tu_buf[ctlr][uptr->DATAPTR];
|
||||||
if (cc < 0)
|
if (cc < 0)
|
||||||
|
@ -644,8 +703,8 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
dptr->name, unit, rhc->buf);
|
dptr->name, unit, rhc->buf);
|
||||||
rh_write(rhc);
|
rh_write(rhc);
|
||||||
}
|
}
|
||||||
if (tu_frame[ctlr] != 0)
|
if (regs[TUDC] != 0)
|
||||||
uptr->STATUS |= ER1_FCE;
|
regs[TUER1] |= ER1_FCE;
|
||||||
tu_error(uptr, MTSE_OK);
|
tu_error(uptr, MTSE_OK);
|
||||||
(void)rh_blkend(rhc);
|
(void)rh_blkend(rhc);
|
||||||
rh_finish_op(rhc, 0);
|
rh_finish_op(rhc, 0);
|
||||||
|
@ -655,52 +714,49 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
|
|
||||||
case FNC_WRITE:
|
case FNC_WRITE:
|
||||||
if (BUF_EMPTY(uptr)) {
|
if (BUF_EMPTY(uptr)) {
|
||||||
uptr->CMD &= ~CS_PIP;
|
uptr->STATUS &= ~DS_PIP;
|
||||||
if (tu_frame[ctlr] == 0) {
|
if (regs[TUDC] == 0) {
|
||||||
uptr->STATUS |= ER1_NEF;
|
regs[TUER1] |= ER1_NEF;
|
||||||
uptr->CMD |= CS_ATA;
|
uptr->STATUS |= DS_ATA;
|
||||||
rhc->attn = 1;
|
rhc->attn = 1;
|
||||||
tu_error(uptr, MTSE_OK);
|
tu_error(uptr, MTSE_OK);
|
||||||
rh_finish_op(rhc, 0);
|
rh_finish_op(rhc, 0);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
if ((uptr->flags & MTUF_WRP) != 0) {
|
if ((uptr->flags & MTUF_WLK) != 0) {
|
||||||
tu_error(uptr, MTSE_WRP);
|
tu_error(uptr, MTSE_WRP);
|
||||||
rh_finish_op(rhc, 0);
|
rh_finish_op(rhc, 0);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
uptr->CMD |= CS_MOTION;
|
|
||||||
sim_debug(DEBUG_EXP, dptr, "%s%o Init write\n", dptr->name, unit);
|
sim_debug(DEBUG_EXP, dptr, "%s%o Init write\n", dptr->name, unit);
|
||||||
uptr->hwmark = 0;
|
uptr->hwmark = 0;
|
||||||
uptr->CPOS = 0;
|
uptr->CPOS = 0;
|
||||||
uptr->DATAPTR = 0;
|
uptr->DATAPTR = 0;
|
||||||
rhc->buf = 0;
|
rhc->buf = 0;
|
||||||
}
|
}
|
||||||
if (tu_frame[ctlr] != 0 && uptr->CPOS == 0 && rh_read(rhc) == 0)
|
if (regs[TUDC] != 0 && uptr->CPOS == 0 && rh_read(rhc) == 0)
|
||||||
uptr->CPOS |= 010;
|
uptr->CPOS |= 010;
|
||||||
|
|
||||||
if ((uptr->CMD & CS_MOTION) != 0) {
|
if (uptr->CPOS == 0)
|
||||||
if (uptr->CPOS == 0)
|
sim_debug(DEBUG_DATA, dptr, "%s%o write %012llo\n",
|
||||||
sim_debug(DEBUG_DATA, dptr, "%s%o write %012llo\n",
|
dptr->name, unit, rhc->buf);
|
||||||
dptr->name, unit, rhc->buf);
|
/* Write next char out */
|
||||||
/* Write next char out */
|
cc = (8 * (3 - (uptr->CPOS & 07))) + 4;
|
||||||
cc = (8 * (3 - (uptr->CPOS & 07))) + 4;
|
if (cc < 0)
|
||||||
if (cc < 0)
|
ch = rhc->buf & 0x0f;
|
||||||
ch = rhc->buf & 0x0f;
|
else
|
||||||
else
|
ch = (rhc->buf >> cc) & 0xff;
|
||||||
ch = (rhc->buf >> cc) & 0xff;
|
tu_buf[ctlr][uptr->DATAPTR] = ch;
|
||||||
tu_buf[ctlr][uptr->DATAPTR] = ch;
|
uptr->DATAPTR++;
|
||||||
uptr->DATAPTR++;
|
uptr->hwmark = uptr->DATAPTR;
|
||||||
uptr->hwmark = uptr->DATAPTR;
|
uptr->CPOS = (uptr->CPOS & 010) | ((uptr->CPOS & 07) + 1);
|
||||||
uptr->CPOS = (uptr->CPOS & 010) | ((uptr->CPOS & 07) + 1);
|
if ((uptr->CPOS & 7) == cc_max) {
|
||||||
if ((uptr->CPOS & 7) == cc_max) {
|
uptr->CPOS &= 010;
|
||||||
uptr->CPOS &= 010;
|
}
|
||||||
}
|
regs[TUDC]++;
|
||||||
tu_frame[ctlr] = 0177777 & (tu_frame[ctlr] + 1);
|
if (regs[TUDC] == 0) {
|
||||||
if (tu_frame[ctlr] == 0) {
|
uptr->CPOS = 010;
|
||||||
uptr->CPOS = 010;
|
regs[TUTC] &= ~(TC_FCS);
|
||||||
tu_tcr[ctlr] &= ~(TC_FCS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (uptr->CPOS == 010) {
|
if (uptr->CPOS == 010) {
|
||||||
/* Write out the block */
|
/* Write out the block */
|
||||||
|
@ -718,9 +774,9 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_WTM:
|
case FNC_WTM:
|
||||||
uptr->CMD &= ~CS_PIP;
|
uptr->STATUS &= ~DS_PIP;
|
||||||
uptr->CMD |= CS_ATA;
|
uptr->STATUS |= DS_ATA;
|
||||||
if ((uptr->flags & MTUF_WRP) != 0) {
|
if ((uptr->flags & MTUF_WLK) != 0) {
|
||||||
tu_error(uptr, MTSE_WRP);
|
tu_error(uptr, MTSE_WRP);
|
||||||
} else {
|
} else {
|
||||||
tu_error(uptr, sim_tape_wrtmk(uptr));
|
tu_error(uptr, sim_tape_wrtmk(uptr));
|
||||||
|
@ -729,9 +785,10 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
||||||
case FNC_ERASE:
|
case FNC_ERASE:
|
||||||
uptr->CMD &= ~CS_PIP;
|
uptr->STATUS &= ~DS_PIP;
|
||||||
uptr->CMD |= CS_ATA;
|
uptr->STATUS |= DS_ATA;
|
||||||
if ((uptr->flags & MTUF_WRP) != 0) {
|
sim_tape_sprecf(uptr, &reclen);
|
||||||
|
if ((uptr->flags & MTUF_WLK) != 0) {
|
||||||
tu_error(uptr, MTSE_WRP);
|
tu_error(uptr, MTSE_WRP);
|
||||||
} else {
|
} else {
|
||||||
tu_error(uptr, sim_tape_wrgap(uptr, 35));
|
tu_error(uptr, sim_tape_wrgap(uptr, 35));
|
||||||
|
@ -741,47 +798,42 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
|
|
||||||
case FNC_SPACEF:
|
case FNC_SPACEF:
|
||||||
case FNC_SPACEB:
|
case FNC_SPACEB:
|
||||||
sim_debug(DEBUG_DETAIL, dptr, "%s%o space %o\n", dptr->name, unit, GET_FNC(uptr->CMD));
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o space %06o %o\n", dptr->name, unit, regs[TUDC], GET_FNC(uptr->CMD));
|
||||||
uptr->CMD &= ~CS_PIP;
|
uptr->STATUS &= ~DS_PIP;
|
||||||
if (tu_frame[ctlr] == 0) {
|
|
||||||
uptr->STATUS |= ER1_NEF;
|
|
||||||
uptr->CMD |= CS_ATA;
|
|
||||||
tu_error(uptr, MTSE_OK);
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
uptr->CMD |= CS_MOTION;
|
|
||||||
/* Always skip at least one record */
|
/* Always skip at least one record */
|
||||||
if (GET_FNC(uptr->CMD) == FNC_SPACEF)
|
if (GET_FNC(uptr->CMD) == FNC_SPACEF)
|
||||||
r = sim_tape_sprecf(uptr, &reclen);
|
r = sim_tape_sprecf(uptr, &reclen);
|
||||||
else
|
else
|
||||||
r = sim_tape_sprecr(uptr, &reclen);
|
r = sim_tape_sprecr(uptr, &reclen);
|
||||||
tu_frame[ctlr] = 0177777 & (tu_frame[ctlr] + 1);
|
regs[TUDC]++;
|
||||||
|
if (regs[TUDC] == 0)
|
||||||
|
regs[TUTC] &= ~TC_FCS;
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case MTSE_OK: /* no error */
|
case MTSE_OK: /* no error */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTSE_BOT: /* beginning of tape */
|
case MTSE_BOT: /* beginning of tape */
|
||||||
uptr->STATUS |= ER1_NEF;
|
regs[TUER1] |= ER1_NEF;
|
||||||
/* Fall Through */
|
/* Fall Through */
|
||||||
|
|
||||||
case MTSE_TMK: /* tape mark */
|
case MTSE_TMK: /* tape mark */
|
||||||
case MTSE_EOM: /* end of medium */
|
case MTSE_EOM: /* end of medium */
|
||||||
if (tu_frame[ctlr] != 0)
|
if (regs[TUDC] != 0)
|
||||||
uptr->STATUS |= ER1_FCE;
|
regs[TUER1] |= ER1_FCE;
|
||||||
else
|
uptr->STATUS |= DS_ATA;
|
||||||
tu_tcr[ctlr] &= ~(TC_FCS);
|
|
||||||
uptr->CMD |= CS_ATA;
|
|
||||||
/* Stop motion if we recieve any of these */
|
/* Stop motion if we recieve any of these */
|
||||||
tu_error(uptr, r);
|
tu_error(uptr, r);
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o space finish %06o %o\n", dptr->name, unit, regs[TUDC], GET_FNC(uptr->CMD));
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
if (tu_frame[ctlr] == 0) {
|
if (regs[TUDC] == 0) {
|
||||||
uptr->CMD |= CS_ATA;
|
uptr->STATUS |= DS_ATA;
|
||||||
tu_error(uptr, MTSE_OK);
|
tu_error(uptr, MTSE_OK);
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o space finish1 %06o %o\n", dptr->name, unit, regs[TUDC], GET_FNC(uptr->CMD));
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
} else {
|
} else {
|
||||||
tu_tcr[ctlr] &= ~(TC_FCS);
|
|
||||||
sim_activate(uptr, reclen * 100);
|
sim_activate(uptr, reclen * 100);
|
||||||
|
sim_debug(DEBUG_DETAIL, dptr, "%s%o space cont %06o %o\n", dptr->name, unit, regs[TUDC], GET_FNC(uptr->CMD));
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -795,11 +847,12 @@ t_stat tu_srv(UNIT * uptr)
|
||||||
t_stat
|
t_stat
|
||||||
tu_reset(DEVICE * dptr)
|
tu_reset(DEVICE * dptr)
|
||||||
{
|
{
|
||||||
int ctlr;
|
struct rh_if *rhc = &tu_rh[0];
|
||||||
for (ctlr = 0; ctlr < NUM_DEVS_TU; ctlr++) {
|
uint16 *regs = &rhc->regs[0];
|
||||||
tu_rh[ctlr].attn = 0;
|
|
||||||
tu_rh[ctlr].rae = 0;
|
rh_reset(dptr, &tu_rh[0]);
|
||||||
}
|
regs[TUER1] = 0;
|
||||||
|
regs[TUTC] = TC_1600;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,11 +875,14 @@ void tu_read_word(UNIT *uptr) {
|
||||||
t_stat
|
t_stat
|
||||||
tu_boot(int32 unit_num, DEVICE * dptr)
|
tu_boot(int32 unit_num, DEVICE * dptr)
|
||||||
{
|
{
|
||||||
UNIT *uptr = &dptr->units[unit_num];
|
UNIT *uptr = &dptr->units[unit_num];
|
||||||
t_mtrlnt reclen;
|
int ctlr = GET_CNTRL_RH(uptr->flags);
|
||||||
t_stat r;
|
struct rh_if *rhc = &tu_rh[ctlr];
|
||||||
uint32 addr;
|
uint16 *regs = &rhc->regs[0];
|
||||||
int wc;
|
t_mtrlnt reclen;
|
||||||
|
t_stat r;
|
||||||
|
uint32 addr;
|
||||||
|
int wc;
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0)
|
if ((uptr->flags & UNIT_ATT) == 0)
|
||||||
return SCPE_UNATT; /* attached? */
|
return SCPE_UNATT; /* attached? */
|
||||||
|
@ -834,6 +890,36 @@ tu_boot(int32 unit_num, DEVICE * dptr)
|
||||||
r = sim_tape_rewind(uptr);
|
r = sim_tape_rewind(uptr);
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
return r;
|
return r;
|
||||||
|
uptr->CMD = 0;
|
||||||
|
#if KS
|
||||||
|
/* Skip first file, which is micro code */
|
||||||
|
while (r == MTSE_OK)
|
||||||
|
r = sim_tape_rdrecf(uptr, &tu_buf[0][0], &reclen, TU_NUMFR);
|
||||||
|
|
||||||
|
if (r != MTSE_TMK)
|
||||||
|
return r;
|
||||||
|
/* Next read in the boot block */
|
||||||
|
r = sim_tape_rdrecf(uptr, &tu_buf[0][0], &reclen, TU_NUMFR);
|
||||||
|
if (r != MTSE_OK)
|
||||||
|
return r;
|
||||||
|
uptr->DATAPTR = 0;
|
||||||
|
uptr->hwmark = reclen;
|
||||||
|
wc = reclen;
|
||||||
|
|
||||||
|
addr = 01000;
|
||||||
|
while (uptr->DATAPTR < wc) {
|
||||||
|
tu_read_word(uptr);
|
||||||
|
M[addr] = tu_boot_buffer;
|
||||||
|
addr ++;
|
||||||
|
}
|
||||||
|
regs[TUTC] |= unit_num;
|
||||||
|
M[036] = rhc->dib->uba_addr | (rhc->dib->uba_ctl << 18);
|
||||||
|
M[037] = 0;
|
||||||
|
M[040] = regs[TUTC];
|
||||||
|
PC = 01000;
|
||||||
|
rh_boot_dev = dptr;
|
||||||
|
rh_boot_unit = unit_num;
|
||||||
|
#else
|
||||||
r = sim_tape_rdrecf(uptr, &tu_buf[0][0], &reclen, TU_NUMFR);
|
r = sim_tape_rdrecf(uptr, &tu_buf[0][0], &reclen, TU_NUMFR);
|
||||||
if (r != SCPE_OK)
|
if (r != SCPE_OK)
|
||||||
return r;
|
return r;
|
||||||
|
@ -865,6 +951,8 @@ tu_boot(int32 unit_num, DEVICE * dptr)
|
||||||
M[addr] = tu_boot_buffer;
|
M[addr] = tu_boot_buffer;
|
||||||
|
|
||||||
PC = tu_boot_buffer & RMASK;
|
PC = tu_boot_buffer & RMASK;
|
||||||
|
regs[TUTC] |= unit_num;
|
||||||
|
#endif
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,7 +967,7 @@ tu_attach(UNIT * uptr, CONST char *file)
|
||||||
uptr->STATUS = 0;
|
uptr->STATUS = 0;
|
||||||
r = sim_tape_attach_ex(uptr, file, 0, 0);
|
r = sim_tape_attach_ex(uptr, file, 0, 0);
|
||||||
if (r == SCPE_OK && (sim_switches & SIM_SW_REST) == 0) {
|
if (r == SCPE_OK && (sim_switches & SIM_SW_REST) == 0) {
|
||||||
uptr->CMD = CS_ATA|CS_CHANGE;
|
uptr->STATUS = DS_ATA|DS_SSC;
|
||||||
rh_setattn(rhc, 0);
|
rh_setattn(rhc, 0);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -891,9 +979,7 @@ tu_detach(UNIT * uptr)
|
||||||
int ctlr = GET_CNTRL_RH(uptr->flags);
|
int ctlr = GET_CNTRL_RH(uptr->flags);
|
||||||
struct rh_if *rhc = &tu_rh[ctlr];
|
struct rh_if *rhc = &tu_rh[ctlr];
|
||||||
|
|
||||||
/* Find df10 */
|
uptr->STATUS = DS_ATA|DS_SSC;
|
||||||
uptr->STATUS = 0;
|
|
||||||
uptr->CMD = CS_ATA|CS_CHANGE;
|
|
||||||
rh_setattn(rhc, 0);
|
rh_setattn(rhc, 0);
|
||||||
return sim_tape_detach(uptr);
|
return sim_tape_detach(uptr);
|
||||||
}
|
}
|
||||||
|
@ -910,6 +996,17 @@ 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");
|
||||||
fprintf (st, "The TU device supports the BOOT command.\n");
|
fprintf (st, "The TU device supports the BOOT command.\n");
|
||||||
sim_tape_attach_help (st, dptr, uptr, flag, cptr);
|
sim_tape_attach_help (st, dptr, uptr, flag, cptr);
|
||||||
|
#if KS
|
||||||
|
fprintf (st, "The RH11 is a unibus device, various parameters can be changed on these devices\n");
|
||||||
|
fprintf (st, "\n The address of the device can be set with: \n");
|
||||||
|
fprintf (st, " sim> SET TUA ADDR=octal default address= 772440\n");
|
||||||
|
fprintf (st, "\n The interrupt vector can be set with: \n");
|
||||||
|
fprintf (st, " sim> SET TUA VECT=octal default 224\n");
|
||||||
|
fprintf (st, "\n The interrupt level can be set with: \n");
|
||||||
|
fprintf (st, " sim> SET TUA BR=# # should be between 4 and 7.\n");
|
||||||
|
fprintf (st, "\n The unibus addaptor that the DZ is on can be set with:\n");
|
||||||
|
fprintf (st, " sim> SET TUA CTL=# # can be either 1 or 3\n");
|
||||||
|
#endif
|
||||||
fprint_reg_help (st, dptr);
|
fprint_reg_help (st, dptr);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ dct_devio(uint32 dev, uint64 *data) {
|
||||||
clr_interrupt(dev);
|
clr_interrupt(dev);
|
||||||
if (uptr->STATUS & DB_RQ) {
|
if (uptr->STATUS & DB_RQ) {
|
||||||
*data = dct_buf[u];
|
*data = dct_buf[u];
|
||||||
uptr->STATUS &= ~(DB_RQ);
|
uptr->STATUS &= ~(NUM_CHARS|DB_RQ);
|
||||||
uptr->STATUS |= DB_MV;
|
uptr->STATUS |= DB_MV;
|
||||||
sim_activate(uptr, 10);
|
sim_activate(uptr, 10);
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ dct_devio(uint32 dev, uint64 *data) {
|
||||||
dev, *data, u, PC);
|
dev, *data, u, PC);
|
||||||
if (uptr->STATUS & DB_RQ) {
|
if (uptr->STATUS & DB_RQ) {
|
||||||
dct_buf[u] = *data;
|
dct_buf[u] = *data;
|
||||||
uptr->STATUS &= ~(DB_RQ);
|
uptr->STATUS &= ~(NUM_CHARS|DB_RQ);
|
||||||
uptr->STATUS |= DB_MV;
|
uptr->STATUS |= DB_MV;
|
||||||
sim_activate(uptr, 10);
|
sim_activate(uptr, 10);
|
||||||
}
|
}
|
||||||
|
|
BIN
doc/ka10_doc.doc
BIN
doc/ka10_doc.doc
Binary file not shown.
BIN
doc/ki10_doc.doc
BIN
doc/ki10_doc.doc
Binary file not shown.
BIN
doc/kl10_doc.doc
BIN
doc/kl10_doc.doc
Binary file not shown.
BIN
doc/ks10_doc.doc
Normal file
BIN
doc/ks10_doc.doc
Normal file
Binary file not shown.
BIN
doc/pdp6_doc.doc
BIN
doc/pdp6_doc.doc
Binary file not shown.
Loading…
Add table
Reference in a new issue