mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-22 18:41:11 +00:00
KA10: More WAITS fixes.
This commit is contained in:
parent
9681d2ab1a
commit
930fc24f01
@ -2179,7 +2179,7 @@ int page_lookup_waits(int addr, int flag, int *loc, int wr, int cur_context, int
|
||||
/* Figure out if this is a user space access */
|
||||
if (flag)
|
||||
uf = 0;
|
||||
else if (xct_flag != 0 && !fetch) {
|
||||
else if (xct_flag != 0 && !fetch && !uf) {
|
||||
if (xct_flag & 010 && cur_context) /* Indirect */
|
||||
uf = 1;
|
||||
if (xct_flag & 004 && wr == 0) /* XR */
|
||||
@ -2211,7 +2211,21 @@ int Mem_read_waits(int flag, int cur_context, int fetch) {
|
||||
int addr;
|
||||
|
||||
if (AB < 020) {
|
||||
MB = get_reg(AB);
|
||||
int uf = (FLAGS & USER) != 0;
|
||||
if (uf || flag || xct_flag == 0 || fetch) {
|
||||
MB = get_reg(AB);
|
||||
return 0;
|
||||
}
|
||||
if (xct_flag & 010 && cur_context) /* Indirect */
|
||||
uf = 1;
|
||||
if (xct_flag & 004) /* XR */
|
||||
uf = 1;
|
||||
if (xct_flag & 001 && BYF5) /* XW or XLB or XDB */
|
||||
uf = 1;
|
||||
if (uf)
|
||||
MB = M[AB + Rl];
|
||||
else
|
||||
MB = get_reg(AB);
|
||||
} else {
|
||||
sim_interval--;
|
||||
if (!page_lookup_waits(AB, flag, &addr, 0, cur_context, fetch))
|
||||
@ -2237,7 +2251,19 @@ int Mem_write_waits(int flag, int cur_context) {
|
||||
int addr;
|
||||
|
||||
if (AB < 020) {
|
||||
set_reg(AB, MB);
|
||||
int uf = (FLAGS & USER) != 0;
|
||||
if (uf || xct_flag == 0) {
|
||||
set_reg(AB, MB);
|
||||
return 0;
|
||||
}
|
||||
if (xct_flag & 010 && cur_context) /* Indirect */
|
||||
uf = 1;
|
||||
if (xct_flag & 001 && BYF5) /* XW or XLB or XDB */
|
||||
uf = 1;
|
||||
if (uf)
|
||||
M[AB + Rl] = MB;
|
||||
else
|
||||
set_reg(AB, MB);
|
||||
} else {
|
||||
sim_interval--;
|
||||
if (!page_lookup_waits(AB, flag, &addr, 1, cur_context, 0))
|
||||
|
||||
@ -62,10 +62,6 @@
|
||||
#error "Please define only one type of CPU"
|
||||
#endif
|
||||
|
||||
#ifndef PDP6_DEV /* Include PDP6 devices */
|
||||
#define PDP6_DEV PDP6
|
||||
#endif
|
||||
|
||||
#ifndef KI_22BIT
|
||||
#define KI_22BIT KI|KL
|
||||
#endif
|
||||
@ -85,6 +81,11 @@
|
||||
#define WAITS KA
|
||||
#endif
|
||||
|
||||
#ifndef PDP6_DEV /* Include PDP6 devices */
|
||||
#define PDP6_DEV PDP6|WAITS
|
||||
#endif
|
||||
|
||||
|
||||
/* MPX interrupt multiplexer for ITS systems */
|
||||
#define MPX_DEV ITS
|
||||
|
||||
@ -374,6 +375,7 @@ extern DEVICE dct_dev; /* PDP6 devices. */
|
||||
extern DEVICE dtc_dev;
|
||||
extern DEVICE mtc_dev;
|
||||
extern DEVICE dsk_dev;
|
||||
extern DEVICE t630_dev;
|
||||
|
||||
extern t_stat (*dev_tab[128])(uint32 dev, t_uint64 *data);
|
||||
|
||||
@ -449,6 +451,7 @@ int auxcpu_write (int addr, t_uint64);
|
||||
#define NUM_DEVS_DCT 2
|
||||
#define NUM_DEVS_MTC 1
|
||||
#define NUM_DEVS_DSK 1
|
||||
#define NUM_DEVS_T630 1
|
||||
#endif
|
||||
#if !PDP6
|
||||
#define NUM_DEVS_MT 1
|
||||
|
||||
107
PDP10/ka10_pmp.c
107
PDP10/ka10_pmp.c
@ -505,8 +505,11 @@ pmp_devio(uint32 dev, uint64 *data) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pmp_cur_unit == NULL)
|
||||
if (pmp_cur_unit == NULL) {
|
||||
pmp_statusb &= ~REQ_CH;
|
||||
if (pmp_statusb & CMD_LD)
|
||||
pmp_startcmd();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*data & CLR_DATCH) /* Data chaining */
|
||||
@ -531,10 +534,7 @@ pmp_devio(uint32 dev, uint64 *data) {
|
||||
dev, *data, PC);
|
||||
pmp_cmd_hold = (*data) & HOLD_MASK;
|
||||
pmp_statusb |= CMD_LD;
|
||||
if ((pmp_statusb & CMD_LD) != 0) {
|
||||
if ((pmp_statusb & (IDLE_CH)) != 0)
|
||||
pmp_startcmd();
|
||||
}
|
||||
pmp_startcmd();
|
||||
(void)pmp_checkirq();
|
||||
break;
|
||||
}
|
||||
@ -616,8 +616,8 @@ load:
|
||||
if ((pmp_cnt & 03) == 0)
|
||||
pmp_cnt |= BUFF_EMPTY;
|
||||
} else {
|
||||
if (pmp_cnt & 0x4) {
|
||||
if ((pmp_cnt & 07) == 0x4) { /* Split byte */
|
||||
if ((pmp_cnt & 0xf) > 0x3) {
|
||||
if ((pmp_cnt & 0xf) == 0x4) { /* Split byte */
|
||||
byte = (pmp_data << 4) & 0xf0;
|
||||
if (pmp_cnt & BUFF_CHNEND) {
|
||||
*data = byte;
|
||||
@ -631,13 +631,13 @@ load:
|
||||
xfer = 1; /* Read in a word */
|
||||
byte |= pmp_data & 0xf;
|
||||
} else {
|
||||
byte = (pmp_data >> 4 + (8 * (8 - (pmp_cnt & 0x3)))) & 0xff;
|
||||
byte = (pmp_data >> 4 + (8 * (8 - (pmp_cnt & 0xf)))) & 0xff;
|
||||
}
|
||||
} else {
|
||||
byte = (pmp_data >> 4 + (8 * (3 - (pmp_cnt & 0x3)))) & 0xff;
|
||||
byte = (pmp_data >> 4 + (8 * (3 - (pmp_cnt & 0xf)))) & 0xff;
|
||||
}
|
||||
pmp_cnt =(pmp_cnt + 1);
|
||||
if ((pmp_cnt & 017) == 9) {
|
||||
if ((pmp_cnt & 0xf) == 9) {
|
||||
pmp_cnt = BUFF_EMPTY;
|
||||
if (pmp_cnt & BUFF_CHNEND)
|
||||
goto next;
|
||||
@ -709,40 +709,40 @@ chan_write_byte(uint8 *data) {
|
||||
if (pmp_addr >= (int)MEMSIZE)
|
||||
return pmp_posterror(NXM_ERR);
|
||||
M[pmp_addr] = pmp_data;
|
||||
sim_debug(DEBUG_DATA, &pmp_dev, "chan_write %06o %012llo\n", pmp_addr, pmp_data);
|
||||
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo\n", pmp_addr, pmp_data);
|
||||
pmp_addr++;
|
||||
xfer = 1;
|
||||
}
|
||||
} else {
|
||||
if (pmp_cnt & 0x4) {
|
||||
if ((pmp_cnt & 07) == 0x4) { /* Split byte */
|
||||
if ((pmp_cnt & 0xf) > 0x3) {
|
||||
if ((pmp_cnt & 0xf) == 0x4) { /* Split byte */
|
||||
pmp_data &= ~0xf;
|
||||
pmp_data |= (uint64)((*data >> 4) & 0xf);
|
||||
if (pmp_addr >= (int)MEMSIZE)
|
||||
return pmp_posterror(NXM_ERR);
|
||||
M[pmp_addr] = pmp_data;
|
||||
sim_debug(DEBUG_DATA, &pmp_dev, "chan_write %06o %012llo %2x\n", pmp_addr, pmp_data, pmp_cnt);
|
||||
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo %2x\n", pmp_addr, pmp_data, pmp_cnt);
|
||||
pmp_addr++;
|
||||
xfer = 1; /* Read in a word */
|
||||
pmp_data = *data & 0xf;
|
||||
pmp_cnt |= BUFF_DIRTY;
|
||||
} else {
|
||||
pmp_data &= ~(0xff <<(4 + (8 * (8 - (pmp_cnt & 0x3)))));
|
||||
pmp_data |= (uint64)(*data & 0xff) << (4 + (8 * (8 - (pmp_cnt & 0x3))));
|
||||
pmp_data &= ~(0xff <<(4 + (8 * (8 - (pmp_cnt & 0xf)))));
|
||||
pmp_data |= (uint64)(*data & 0xff) << (4 + (8 * (8 - (pmp_cnt & 0xf))));
|
||||
pmp_cnt |= BUFF_DIRTY;
|
||||
}
|
||||
} else {
|
||||
pmp_data &= ~(0xff <<(4 + (8 * (3 - (pmp_cnt & 0x3)))));
|
||||
pmp_data |= (uint64)(*data & 0xff) << (4 + (8 * (3 - (pmp_cnt & 0x3))));
|
||||
pmp_data &= ~(0xff <<(4 + (8 * (3 - (pmp_cnt & 0xf)))));
|
||||
pmp_data |= (uint64)(*data & 0xff) << (4 + (8 * (3 - (pmp_cnt & 0xf))));
|
||||
pmp_cnt |= BUFF_DIRTY;
|
||||
}
|
||||
pmp_cnt++;
|
||||
if ((pmp_cnt & 017) == 9) {
|
||||
if ((pmp_cnt & 0xf) == 9) {
|
||||
pmp_cnt = BUFF_EMPTY;
|
||||
if (pmp_addr >= (int)MEMSIZE)
|
||||
return pmp_posterror(NXM_ERR);
|
||||
M[pmp_addr] = pmp_data;
|
||||
sim_debug(DEBUG_DATA, &pmp_dev, "chan_write %06o %012llo %2x\n", pmp_addr, pmp_data, pmp_cnt);
|
||||
sim_debug(DEBUG_DETAIL, &pmp_dev, "chan_write %06o %012llo %2x\n", pmp_addr, pmp_data, pmp_cnt);
|
||||
pmp_addr++;
|
||||
xfer = 1; /* Read in a word */
|
||||
}
|
||||
@ -813,19 +813,7 @@ chan_end(uint8 flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise if there is command chaining, try new command */
|
||||
if (pmp_cmd & CMDCH_ON) {
|
||||
/* Channel in operation, must be command chaining */
|
||||
if (((pmp_cmd & SKP_MOD_OFF) != 0) && ((pmp_status & ST_MOD) == 0)) {
|
||||
pmp_statusb &= ~(CMD_LD);
|
||||
(void)pmp_checkirq();
|
||||
return;
|
||||
}
|
||||
if (((pmp_cmd & SKP_MOD_ON) != 0) && ((pmp_status & ST_MOD) != 0)) {
|
||||
pmp_statusb &= ~(CMD_LD);
|
||||
(void)pmp_checkirq();
|
||||
return;
|
||||
}
|
||||
pmp_startcmd();
|
||||
(void)pmp_checkirq();
|
||||
return;
|
||||
@ -845,6 +833,7 @@ pmp_startcmd() {
|
||||
int i;
|
||||
int unit;
|
||||
int cmd;
|
||||
int old_cmd = pmp_cmd;
|
||||
uint8 ch;
|
||||
|
||||
sim_debug(DEBUG_CMD, &pmp_dev, "start command %o\n", pmp_statusb);
|
||||
@ -892,7 +881,7 @@ pmp_startcmd() {
|
||||
|
||||
/* Check if device busy */
|
||||
if ((pmp_cur_unit->CMD & 0xff) != 0) {
|
||||
sim_debug(DEBUG_CMD, &pmp_dev, "busy %o\n", pmp_statusb);
|
||||
sim_debug(DEBUG_CMD, &pmp_dev, "busy %o\n", pmp_statusb);
|
||||
if (pmp_statusb & IS_CH)
|
||||
(void)pmp_posterror(SEL_ERR);
|
||||
pmp_status |= UNU_END|BSY;
|
||||
@ -903,7 +892,7 @@ pmp_startcmd() {
|
||||
/* Copy over command */
|
||||
if ((pmp_statusb & CMD_LD) != 0) {
|
||||
pmp_cmd = pmp_cmd_hold;
|
||||
sim_debug(DEBUG_CMD, &pmp_dev, "load %o\n", pmp_cmd);
|
||||
sim_debug(DEBUG_CMD, &pmp_dev, "load %o\n", pmp_cmd);
|
||||
pmp_statusb &= ~(CMD_LD);
|
||||
if (pmp_statusb & WCMA_LD) {
|
||||
pmp_statusb &= ~(WCMA_LD);
|
||||
@ -912,6 +901,21 @@ pmp_startcmd() {
|
||||
pmp_cnt = BUFF_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise if there is command chaining, try new command */
|
||||
if (old_cmd & CMDCH_ON) {
|
||||
/* Channel in operation, must be command chaining */
|
||||
if (((old_cmd & SKP_MOD_OFF) != 0) && ((pmp_status & ST_MOD) == 0)) {
|
||||
pmp_statusb &= ~(CMD_LD);
|
||||
(void)pmp_checkirq();
|
||||
return;
|
||||
}
|
||||
if (((old_cmd & SKP_MOD_ON) != 0) && ((pmp_status & ST_MOD) != 0)) {
|
||||
pmp_statusb &= ~(CMD_LD);
|
||||
(void)pmp_checkirq();
|
||||
return;
|
||||
}
|
||||
}
|
||||
sim_debug(DEBUG_CMD, &pmp_dev, "CMD unit=%d %02x %06o\n", unit, pmp_cmd, pmp_addr);
|
||||
|
||||
(void)pmp_checkirq();
|
||||
@ -949,19 +953,21 @@ pmp_startcmd() {
|
||||
return;
|
||||
}
|
||||
|
||||
pmp_statusb &= ~IDLE_CH;
|
||||
/* Issue the actual command */
|
||||
switch (cmd & 0x3) {
|
||||
case 0x3: /* Control */
|
||||
if (cmd == DK_RELEASE) {
|
||||
if (cmd == 0x3 || cmd == DK_RELEASE) {
|
||||
pmp_status &= ~(STS_MASK);
|
||||
pmp_status |= NEW_STS|CHN_END|DEV_END;
|
||||
(void)pmp_checkirq();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fall Through */
|
||||
|
||||
case 0x1: /* Write command */
|
||||
case 0x2: /* Read command */
|
||||
pmp_statusb &= ~IDLE_CH;
|
||||
pmp_cur_unit->CMD &= ~(DK_PARAM);
|
||||
pmp_cur_unit->CMD |= cmd;
|
||||
sim_debug(DEBUG_CMD, &pmp_dev, "CMD unit=%d CMD=%02x\n", unit, pmp_cur_unit->CMD);
|
||||
@ -969,17 +975,19 @@ pmp_startcmd() {
|
||||
|
||||
case 0x0: /* Status */
|
||||
if (cmd == 0x4) { /* Sense */
|
||||
pmp_statusb &= ~IDLE_CH;
|
||||
pmp_cur_unit->CMD |= cmd;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
pmp_status &= ~(STS_MASK);
|
||||
if (pmp_cur_unit->SENSE & 0xff)
|
||||
pmp_status |= UNU_END|UNIT_CHK;
|
||||
pmp_status |= NEW_STS|CHN_END|DEV_END;
|
||||
pmp_statusb |= IDLE_CH;
|
||||
pmp_statusb &= ~OP1;
|
||||
sim_debug(DEBUG_CMD, &pmp_dev, "CMD unit=%d finish\n", unit);
|
||||
sim_debug(DEBUG_CMD, &pmp_dev, "CMD unit=%d finish\n", unit);
|
||||
(void)pmp_checkirq();
|
||||
}
|
||||
|
||||
@ -1159,9 +1167,9 @@ index:
|
||||
/* Check for end of track */
|
||||
if ((rec[0] & rec[1] & rec[2] & rec[3]) == 0xff)
|
||||
data->state = DK_POS_END;
|
||||
sim_activate(uptr, 10);
|
||||
sim_activate(uptr, 40);
|
||||
} else
|
||||
sim_activate(uptr, 1);
|
||||
sim_activate(uptr, 10);
|
||||
break;
|
||||
case DK_POS_CNT: /* In count (c) */
|
||||
data->tpos++;
|
||||
@ -1180,9 +1188,9 @@ index:
|
||||
data->state = DK_POS_KEY;
|
||||
if (data->klen == 0)
|
||||
data->state = DK_POS_DATA;
|
||||
sim_activate(uptr, 20);
|
||||
sim_activate(uptr, 50);
|
||||
} else {
|
||||
sim_activate(uptr, 1);
|
||||
sim_activate(uptr, 10);
|
||||
}
|
||||
break;
|
||||
case DK_POS_KEY: /* In Key area */
|
||||
@ -1194,9 +1202,9 @@ index:
|
||||
data->count = 0;
|
||||
count = 0;
|
||||
state = DK_POS_DATA;
|
||||
sim_activate(uptr, 10);
|
||||
sim_activate(uptr, 50);
|
||||
} else {
|
||||
sim_activate(uptr, 1);
|
||||
sim_activate(uptr, 10);
|
||||
}
|
||||
break;
|
||||
case DK_POS_DATA: /* In Data area */
|
||||
@ -1205,9 +1213,9 @@ index:
|
||||
sim_debug(DEBUG_EXP, dptr, "state data unit=%d %d %d\n", unit, data->rec,
|
||||
data->count);
|
||||
data->state = DK_POS_AM;
|
||||
sim_activate(uptr, 10);
|
||||
sim_activate(uptr, 50);
|
||||
} else {
|
||||
sim_activate(uptr, 1);
|
||||
sim_activate(uptr, 10);
|
||||
}
|
||||
break;
|
||||
case DK_POS_AM: /* Beginning of record */
|
||||
@ -1222,7 +1230,7 @@ index:
|
||||
/* Check for end of track */
|
||||
if ((rec[0] & rec[1] & rec[2] & rec[3]) == 0xff)
|
||||
data->state = DK_POS_END;
|
||||
sim_activate(uptr, 20);
|
||||
sim_activate(uptr, 60);
|
||||
break;
|
||||
case DK_POS_END: /* Past end of data */
|
||||
data->tpos+=10;
|
||||
@ -1378,8 +1386,9 @@ sense_end:
|
||||
if ((uptr->POS >> 8) == data->cyl) {
|
||||
uptr->LASTCMD = cmd;
|
||||
uptr->CMD &= ~(0xff);
|
||||
uptr->CMD |= DK_ATTN;
|
||||
pmp_statusb |= REQ_CH;
|
||||
// uptr->CMD |= DK_ATTN;
|
||||
// pmp_statusb |= REQ_CH;
|
||||
chan_end(SNS_DEVEND|SNS_CHNEND);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "seek end unit=%d %d %d %x\n", unit,
|
||||
uptr->POS >> 8, data->cyl, data->state);
|
||||
}
|
||||
@ -1450,7 +1459,7 @@ sense_end:
|
||||
uptr->CMD |= DK_PARAM;
|
||||
data->state = DK_POS_SEEK;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "seek unit=%d doing\n", unit);
|
||||
chan_end(SNS_CHNEND);
|
||||
// chan_end(SNS_CHNEND);
|
||||
} else {
|
||||
pmp_adjpos(uptr);
|
||||
uptr->LASTCMD = cmd;
|
||||
|
||||
@ -141,6 +141,9 @@ DEVICE *sim_devices[] = {
|
||||
#if (NUM_DEVS_DC > 0)
|
||||
&dc_dev,
|
||||
#endif
|
||||
#if (NUM_DEVS_T630 > 0)
|
||||
&t630_dev,
|
||||
#endif
|
||||
#if (NUM_DEVS_DK > 0)
|
||||
&dk_dev,
|
||||
#endif
|
||||
|
||||
480
PDP10/pdp6_dcs.c
Normal file
480
PDP10/pdp6_dcs.c
Normal file
@ -0,0 +1,480 @@
|
||||
/* pdp6_dcs.c: PDP-6 DC630 communication server simulator
|
||||
|
||||
Copyright (c) 2011-2017, 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 "ka10_defs.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#ifndef NUM_DEVS_T630
|
||||
#define NUM_DEVS_T630 0
|
||||
#endif
|
||||
|
||||
#if (NUM_DEVS_T630 > 0)
|
||||
|
||||
#define T630_DEVNUM 0300
|
||||
|
||||
#define T630_LINES 16
|
||||
|
||||
|
||||
#define STATUS u3
|
||||
|
||||
#define RPI_CHN 000007 /* IN STATUS. */
|
||||
#define TPI_CHN 000700 /* In STATUS */
|
||||
#define RLS_SCN 000010 /* CONO DCSA release scanner */
|
||||
#define RST_SCN 000020 /* CONO DCSA reset to 0 */
|
||||
#define RSCN_ACT 000040 /* Scanner line is active */
|
||||
#define XMT_RLS 004000 /* Clear transmitter flag */
|
||||
#define XSCN_ACT 004000 /* Transmit scanner active */
|
||||
|
||||
#define DATA 0000377
|
||||
#define LINE 0000077 /* Line number in Left */
|
||||
|
||||
|
||||
int t630_rx_scan = 0; /* Scan counter */
|
||||
int t630_tx_scan = 0; /* Scan counter */
|
||||
int t630_send_line = 0; /* Send line number */
|
||||
TMLN t630_ldsc[T630_LINES] = { 0 }; /* Line descriptors */
|
||||
TMXR t630_desc = { T630_LINES, 0, 0, t630_ldsc };
|
||||
uint32 t630_tx_enable, t630_rx_rdy; /* Flags */
|
||||
uint32 t630_enable; /* Enable line */
|
||||
uint32 t630_rx_conn; /* Connection flags */
|
||||
extern int32 tmxr_poll;
|
||||
|
||||
t_stat t630_devio(uint32 dev, uint64 *data);
|
||||
t_stat t630_svc (UNIT *uptr);
|
||||
t_stat t630_doscan (UNIT *uptr);
|
||||
t_stat t630_reset (DEVICE *dptr);
|
||||
t_stat t630_setnl (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
t_stat t630_set_log (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
t_stat t630_set_nolog (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
t_stat t630_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
t_stat t630_attach (UNIT *uptr, CONST char *cptr);
|
||||
t_stat t630_detach (UNIT *uptr);
|
||||
t_stat t630_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||
const char *cptr);
|
||||
const char *t630_description (DEVICE *dptr);
|
||||
|
||||
/* Type 630 data structures
|
||||
|
||||
t630_dev Type 630 device descriptor
|
||||
t630_unit Type 630 unit descriptor
|
||||
t630_reg Type 630 register list
|
||||
*/
|
||||
|
||||
DIB t630_dib = { T630_DEVNUM, 2, &t630_devio, NULL };
|
||||
|
||||
UNIT t630_unit = {
|
||||
UDATA (&t630_svc, TT_MODE_7B+UNIT_IDLE+UNIT_ATTABLE, 0), KBD_POLL_WAIT
|
||||
};
|
||||
|
||||
REG t630_reg[] = {
|
||||
{ DRDATA (TIME, t630_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (STATUS, t630_unit.STATUS, 18), PV_LEFT },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB t630_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, 1, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &t630_desc, "Disconnect a specific line" },
|
||||
{ UNIT_ATT, UNIT_ATT, "SUMMARY", NULL,
|
||||
NULL, &tmxr_show_summ, (void *) &t630_desc, "Display a summary of line states" },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &tmxr_show_cstat, (void *) &t630_desc, "Display current connections" },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &tmxr_show_cstat, (void *) &t630_desc, "Display multiplexer statistics" },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "LINES", "LINES=n",
|
||||
&t630_setnl, &tmxr_show_lines, (void *) &t630_desc, "Set number of lines" },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NC, 0, NULL, "LOG=n=file",
|
||||
&t630_set_log, NULL, (void *)&t630_desc },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, NULL, "NOLOG",
|
||||
&t630_set_nolog, NULL, (void *)&t630_desc, "Disable logging on designated line" },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "LOG", NULL,
|
||||
NULL, &t630_show_log, (void *)&t630_desc, "Display logging for all lines" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE t630_dev = {
|
||||
"DCS", &t630_unit, t630_reg, t630_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
&tmxr_ex, &tmxr_dep, &t630_reset,
|
||||
NULL, &t630_attach, &t630_detach,
|
||||
&t630_dib, DEV_NET | DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
|
||||
NULL, NULL, &t630_help, NULL, NULL, &t630_description
|
||||
};
|
||||
|
||||
|
||||
/* IOT routine */
|
||||
t_stat t630_devio(uint32 dev, uint64 *data) {
|
||||
UNIT *uptr = &t630_unit;
|
||||
TMLN *lp;
|
||||
int ln;
|
||||
|
||||
switch(dev & 7) {
|
||||
case CONI:
|
||||
/* Check if we might have any interrupts pending */
|
||||
if ((uptr->STATUS & (RSCN_ACT|XSCN_ACT)) != 0)
|
||||
t630_doscan(uptr);
|
||||
*data = uptr->STATUS & (RPI_CHN|TPI_CHN);
|
||||
if ((uptr->STATUS & (RSCN_ACT)) == 0)
|
||||
*data |= 010LL;
|
||||
if ((uptr->STATUS & (XSCN_ACT)) == 0)
|
||||
*data |= 01000LL;
|
||||
sim_debug(DEBUG_CONI, &t630_dev, "T630 %03o CONI %06o PC=%o\n",
|
||||
dev, (uint32)*data, PC);
|
||||
break;
|
||||
|
||||
case CONO:
|
||||
/* Set PI */
|
||||
uptr->STATUS &= ~(RPI_CHN|TPI_CHN);
|
||||
uptr->STATUS |= (RPI_CHN|TPI_CHN) & *data;
|
||||
if (*data & RST_SCN)
|
||||
t630_rx_scan = 0;
|
||||
if ((*data & (RLS_SCN|RST_SCN)) != 0)
|
||||
uptr->STATUS |= RSCN_ACT;
|
||||
if ((*data & (XSCN_ACT)) != 0)
|
||||
uptr->STATUS |= XSCN_ACT;
|
||||
|
||||
sim_debug(DEBUG_CONO, &t630_dev, "T630 %03o CONO %06o PC=%06o\n",
|
||||
dev, (uint32)*data, PC);
|
||||
t630_doscan(uptr);
|
||||
break;
|
||||
|
||||
case DATAO:
|
||||
case DATAO|4:
|
||||
ln = (dev & 4) ? t630_send_line : t630_tx_scan;
|
||||
if (ln < t630_desc.lines) {
|
||||
lp = &t630_ldsc[ln];
|
||||
if (lp->conn) {
|
||||
int32 ch = *data & DATA;
|
||||
ch = sim_tt_outcvt(ch, TT_GET_MODE (t630_unit.flags) | TTUF_KSR);
|
||||
tmxr_putc_ln (lp, ch);
|
||||
t630_tx_enable |= (1 << ln);
|
||||
}
|
||||
}
|
||||
if (dev & 4) {
|
||||
uptr->STATUS |= XSCN_ACT;
|
||||
t630_doscan(uptr);
|
||||
}
|
||||
sim_debug(DEBUG_DATAIO, &t630_dev, "DC %03o DATO %012llo PC=%06o\n",
|
||||
dev, *data, PC);
|
||||
break;
|
||||
|
||||
case DATAI:
|
||||
case DATAI|4:
|
||||
ln = t630_rx_scan;
|
||||
if (ln < t630_desc.lines) {
|
||||
/* Nothing happens if no recieve data, which is transmit ready */
|
||||
lp = &t630_ldsc[ln];
|
||||
if (tmxr_rqln (lp) > 0) {
|
||||
int32 ch = tmxr_getc_ln (lp);
|
||||
if (ch & SCPE_BREAK) /* break? */
|
||||
ch = 0;
|
||||
else
|
||||
ch = sim_tt_inpcvt (ch, TT_GET_MODE(t630_unit.flags) | TTUF_KSR);
|
||||
*data = (uint64)(ch & DATA);
|
||||
t630_tx_enable &= ~(1 << ln);
|
||||
}
|
||||
t630_rx_rdy &= ~(1 << ln);
|
||||
}
|
||||
if (dev & 4) {
|
||||
uptr->STATUS |= RSCN_ACT;
|
||||
t630_doscan(uptr);
|
||||
}
|
||||
sim_debug(DEBUG_DATAIO, &t630_dev, "T630 %03o DATI %012llo PC=%06o\n",
|
||||
dev, *data, PC);
|
||||
break;
|
||||
case CONI|4:
|
||||
/* Read in scanner */
|
||||
if ((uptr->STATUS & (RSCN_ACT)) != 0)
|
||||
*data = (uint64)(t630_tx_scan);
|
||||
else
|
||||
*data = (uint64)(t630_rx_scan);
|
||||
sim_debug(DEBUG_CONI, &t630_dev, "T630 %03o CONI %06o PC=%o recieve line\n",
|
||||
dev, (uint32)*data, PC);
|
||||
break;
|
||||
|
||||
case CONO|4:
|
||||
/* Output buffer pointer */
|
||||
t630_send_line = (int)(*data & 077);
|
||||
sim_debug(DEBUG_CONO, &t630_dev, "T630 %03o CONO %06o PC=%06o send line\n",
|
||||
dev, (uint32)*data, PC);
|
||||
break;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat t630_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ln;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return SCPE_OK;
|
||||
ln = tmxr_poll_conn (&t630_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? rcv enb*/
|
||||
t630_ldsc[ln].rcve = 1;
|
||||
t630_tx_enable |= 1 << ln;
|
||||
sim_debug(DEBUG_DETAIL, &t630_dev, "DC line connect %d\n", ln);
|
||||
}
|
||||
tmxr_poll_tx(&t630_desc);
|
||||
tmxr_poll_rx(&t630_desc);
|
||||
for (ln = 0; ln < t630_desc.lines; ln++) {
|
||||
/* Check to see if any pending data for this line */
|
||||
if (tmxr_rqln(&t630_ldsc[ln]) > 0) {
|
||||
t630_rx_rdy |= (1 << ln);
|
||||
sim_debug(DEBUG_DETAIL, &t630_dev, "DC recieve %d\n", ln);
|
||||
}
|
||||
/* Check if disconnect */
|
||||
if ((t630_rx_conn & (1 << ln)) != 0 && t630_ldsc[ln].conn == 0) {
|
||||
t630_tx_enable &= ~(1 << ln);
|
||||
t630_rx_conn &= ~(1 << ln);
|
||||
sim_debug(DEBUG_DETAIL, &t630_dev, "DC line disconnect %d\n", ln);
|
||||
}
|
||||
}
|
||||
|
||||
/* If any pending status request, raise the PI signal */
|
||||
t630_doscan(uptr);
|
||||
sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Scan to see if something to do */
|
||||
t_stat t630_doscan (UNIT *uptr) {
|
||||
uint32 lmask;
|
||||
|
||||
if ((uptr->STATUS & (RSCN_ACT|XSCN_ACT)) == 0)
|
||||
return SCPE_OK;
|
||||
clr_interrupt(T630_DEVNUM);
|
||||
if ((uptr->STATUS & (RSCN_ACT)) != 0) {
|
||||
for (;t630_rx_rdy != 0; t630_rx_scan++) {
|
||||
t630_rx_scan &= 037;
|
||||
/* Check if we found it */
|
||||
if (t630_rx_rdy & (1 << t630_rx_scan)) {
|
||||
uptr->STATUS &= ~RSCN_ACT;
|
||||
/* Stop scanner */
|
||||
set_interrupt(T630_DEVNUM, uptr->STATUS);
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((uptr->STATUS & (XSCN_ACT)) != 0) {
|
||||
for (;t630_tx_enable != 0; t630_tx_scan++) {
|
||||
t630_tx_scan &= 037;
|
||||
/* Check if we found it */
|
||||
if (t630_tx_enable & (1 << t630_tx_scan)) {
|
||||
uptr->STATUS &= ~XSCN_ACT;
|
||||
/* Stop scanner */
|
||||
set_interrupt(T630_DEVNUM, (uptr->STATUS >> 6));
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat t630_reset (DEVICE *dptr)
|
||||
{
|
||||
if (t630_unit.flags & UNIT_ATT) /* if attached, */
|
||||
sim_activate (&t630_unit, tmxr_poll); /* activate */
|
||||
else
|
||||
sim_cancel (&t630_unit); /* else stop */
|
||||
t630_tx_enable = 0;
|
||||
t630_rx_rdy = 0; /* Flags */
|
||||
t630_rx_conn = 0;
|
||||
t630_send_line = 0;
|
||||
t630_tx_scan = 0;
|
||||
t630_rx_scan = 0;
|
||||
t630_unit.STATUS = 0;
|
||||
clr_interrupt(T630_DEVNUM);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* SET LINES processor */
|
||||
|
||||
t_stat t630_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, T630_LINES, &r);
|
||||
if ((r != SCPE_OK) || (newln == t630_desc.lines))
|
||||
return r;
|
||||
if ((newln == 0) || (newln >= T630_LINES) || (newln % 8) != 0)
|
||||
return SCPE_ARG;
|
||||
if (newln < t630_desc.lines) {
|
||||
for (i = newln, t = 0; i < t630_desc.lines; i++)
|
||||
t = t | t630_ldsc[i].conn;
|
||||
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
|
||||
return SCPE_OK;
|
||||
for (i = newln; i < t630_desc.lines; i++) {
|
||||
if (t630_ldsc[i].conn) {
|
||||
tmxr_linemsg (&t630_ldsc[i], "\r\nOperator disconnected line\r\n");
|
||||
tmxr_send_buffered_data (&t630_ldsc[i]);
|
||||
}
|
||||
tmxr_detach_ln (&t630_ldsc[i]); /* completely reset line */
|
||||
}
|
||||
}
|
||||
if (t630_desc.lines < newln)
|
||||
memset (t630_ldsc + t630_desc.lines, 0, sizeof(*t630_ldsc)*(newln-t630_desc.lines));
|
||||
t630_desc.lines = newln;
|
||||
return t630_reset (&t630_dev); /* setup lines and auto config */
|
||||
}
|
||||
|
||||
/* SET LOG processor */
|
||||
|
||||
t_stat t630_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, t630_desc.lines, &r);
|
||||
if ((r != SCPE_OK) || (ln >= t630_desc.lines))
|
||||
return SCPE_ARG;
|
||||
return tmxr_set_log (NULL, ln, cptr, desc);
|
||||
}
|
||||
|
||||
/* SET NOLOG processor */
|
||||
|
||||
t_stat t630_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, t630_desc.lines, &r);
|
||||
if ((r != SCPE_OK) || (ln >= t630_desc.lines))
|
||||
return SCPE_ARG;
|
||||
return tmxr_set_nolog (NULL, ln, NULL, desc);
|
||||
}
|
||||
|
||||
/* SHOW LOG processor */
|
||||
|
||||
t_stat t630_show_log (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
for (i = 0; i < t630_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 t630_attach (UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
t_stat reason;
|
||||
|
||||
reason = tmxr_attach (&t630_desc, uptr, cptr);
|
||||
if (reason != SCPE_OK)
|
||||
return reason;
|
||||
sim_activate (uptr, tmxr_poll);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Detach routine */
|
||||
|
||||
t_stat t630_detach (UNIT *uptr)
|
||||
{
|
||||
int32 i;
|
||||
t_stat reason;
|
||||
reason = tmxr_detach (&t630_desc, uptr);
|
||||
for (i = 0; i < t630_desc.lines; i++)
|
||||
t630_ldsc[i].rcve = 0;
|
||||
sim_cancel (uptr);
|
||||
return reason;
|
||||
}
|
||||
|
||||
t_stat t630_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||
{
|
||||
fprintf (st, "Type 630 Terminal Interfaces\n\n");
|
||||
fprintf (st, "The Type 630 supported up to 8 blocks of 8 lines. Modem control was on a seperate\n");
|
||||
fprintf (st, "line. The simulator supports this by setting modem control to a fixed offset\n");
|
||||
fprintf (st, "from the given line. The number of lines is specified with a SET command:\n\n");
|
||||
fprintf (st, " sim> SET DC 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 default offset for modem lines is 32. This can be changed with\n\n");
|
||||
fprintf (st, " sim> SET DC MODEM=n set offset for modem control to n [8-32]\n\n");
|
||||
fprintf (st, "Modem control must be set larger then the number of lines\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 DCn LOG command enables\n");
|
||||
fprintf (st, "logging on a line:\n\n");
|
||||
fprintf (st, " sim> SET DCn LOG=filename log output of line n to filename\n\n");
|
||||
fprintf (st, "The SET DCn NOLOG command disables logging and closes the open log file,\n");
|
||||
fprintf (st, "if any.\n\n");
|
||||
fprintf (st, "Once DC 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 DC DISCONNECT command, or a DETACH DC command.\n\n");
|
||||
fprintf (st, "Other special commands:\n\n");
|
||||
fprintf (st, " sim> SHOW DC CONNECTIONS show current connections\n");
|
||||
fprintf (st, " sim> SHOW DC STATISTICS show statistics for active connections\n");
|
||||
fprintf (st, " sim> SET DCn DISCONNECT disconnects the specified line.\n");
|
||||
fprint_reg_help (st, &t630_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 DC is detached.\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
const char *t630_description (DEVICE *dptr)
|
||||
{
|
||||
return "Type 630 asynchronous line interface";
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user