1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-04-26 20:18:04 +00:00

KA10: Updated KS10 devices.

This commit is contained in:
Richard Cornwell
2021-01-30 11:43:50 -05:00
parent d67165fb51
commit 15886417e8
6 changed files with 798 additions and 222 deletions

View File

@@ -137,7 +137,7 @@ t_stat ctyi_svc (UNIT *uptr)
while (!full(&cty_in)) {
ch = sim_poll_kbd ();
if (ch & SCPE_KFLAG) {
ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (uptr->flags));
ch = 0177 & sim_tt_inpcvt(ch, TT_GET_MODE (cty_unit[0].flags));
cty_in.buff[cty_in.in_ptr] =ch & 0377;
inci(&cty_in);
sim_debug(DEBUG_DETAIL, &cty_dev, "CTY char %o '%c'\n", ch,
@@ -176,6 +176,7 @@ t_stat ctyo_svc (UNIT *uptr)
sim_debug(DEBUG_DETAIL, &cty_dev, "CTY Write %012llo\n", buffer);
if (buffer & CTY_CHAR) {
if (!full(&cty_out)) {
buffer = sim_tt_outcvt ( buffer, TT_GET_MODE (uptr->flags));
cty_out.buff[cty_out.in_ptr] = (uint8)(buffer & 0377);
buffer = 0;
if (Mem_write_word(CTY_OUT, &buffer, 0) == 0) {

545
PDP10/ks10_dz.c Normal file
View File

@@ -0,0 +1,545 @@
/* 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 DC10_LINES 8
#define STATUS u3
#define DTS_LINE 007700 /* Scanner line number in STATUS */
#define PI_CHN 000007 /* IN STATUS. */
#define RCV_PI 000010 /* IN STATUS. */
#define XMT_PI 000020 /* IN STATUS. */
#define DTR_DIS 000040 /* DTR FLAG */
#define RST_SCN 000010 /* CONO */
#define DTR_SET 000020 /* CONO */
#define CLR_SCN 000040 /* CONO */
#define DATA 0000377
#define FLAG 0000400 /* Recieve data/ transmit disable */
#define LINE 0000077 /* Line number in Left */
#define LFLAG 0000100 /* Direct line number flag */
/* DC10E flags */
#define CTS 0000004 /* Clear to send */
#define RES_DET 0000002 /* Ring detect */
#define DLO 0000040 /* (ACU) Data line occupied */
#define PND 0000020 /* (ACU) Present next digit */
#define ACR 0000010 /* (ACU) Abandon Call and retry */
#define CRQ 0000040 /* (ACU) Call Request */
#define DPR 0000020 /* (ACU) Digit Presented */
#define NB 0000017 /* (ACU) Number */
#define OFF_HOOK 0000100 /* Off Hook (CD) */
#define CAUSE_PI 0000200 /* Cause PI */
uint64 dz_l_status; /* Line status */
int dz_l_count = 0; /* Scan counter */
int dz_modem = DC10_MLINES; /* Modem base address */
uint8 dcix_buf[DC10_MLINES] = { 0 }; /* Input buffers */
uint8 dcox_buf[DC10_MLINES] = { 0 }; /* Output buffers */
TMLN dz_ldsc[DC10_MLINES] = { 0 }; /* Line descriptors */
TMXR dz_desc = { DC10_LINES, 0, 0, dz_ldsc };
uint32 tx_enable, rx_rdy; /* Flags */
uint32 dz_enable; /* Enable line */
uint32 dz_ring; /* Connection pending */
uint32 rx_conn; /* Connection flags */
extern int32 tmxr_poll;
int dz_write(t_addr addr, uint16 data, int32 access);
int dz_read(t_addr addr, uint16 *data, int32 access);
t_stat dz_svc (UNIT *uptr);
t_stat dz_doscan (UNIT *uptr);
t_stat dz_reset (DEVICE *dptr);
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);
/* DC10 data structures
dz_dev DC10 device descriptor
dz_unit DC10 unit descriptor
dz_reg DC10 register list
*/
DIB dz_dib = { 0776000, 077, 0340, 5, 3, &dz_read, &dz_write, 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 },
{ DRDATA (STATUS, dz_unit.STATUS, 18), 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, 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
};
/* IOT routine */
t_stat dz_devio(uint32 dev, uint64 *data) {
UNIT *uptr = &dz_unit;
TMLN *lp;
int ln;
switch(dev & 3) {
case CONI:
/* Check if we might have any interrupts pending */
if ((uptr->STATUS & (RCV_PI|XMT_PI)) == 0)
dz_doscan(uptr);
*data = uptr->STATUS & (PI_CHN|RCV_PI|XMT_PI);
sim_debug(DEBUG_CONI, &dz_dev, "DC %03o CONI %06o PC=%o\n",
dev, (uint32)*data, PC);
break;
case CONO:
/* Set PI */
uptr->STATUS &= ~PI_CHN;
uptr->STATUS |= PI_CHN & *data;
if (*data & RST_SCN)
dz_l_count = 0;
if (*data & DTR_SET)
uptr->STATUS |= DTR_SET;
if (*data & CLR_SCN) {
uptr->STATUS &= PI_CHN;
for (ln = 0; ln < dz_desc.lines; ln++) {
lp = &dz_ldsc[ln];
if (lp->conn) {
tmxr_linemsg (lp, "\r\nLine Hangup\r\n");
tmxr_reset_ln(lp);
}
}
tx_enable = 0;
dz_enable = 0;
rx_rdy = 0; /* Flags */
rx_conn = 0;
dz_ring = 0;
dz_l_status = 0;
}
sim_debug(DEBUG_CONO, &dz_dev, "DC %03o CONO %06o PC=%06o\n",
dev, (uint32)*data, PC);
dz_doscan(uptr);
break;
case DATAO:
if (*data & (LFLAG << 18))
ln = (*data >> 18) & 077;
else
ln = dz_l_count;
if (ln >= dz_modem) {
if (*data & CAUSE_PI)
dz_l_status |= (1LL << ln);
else
dz_l_status &= ~(1LL << ln);
ln -= dz_modem;
sim_debug(DEBUG_DETAIL, &dz_dev, "DC line modem %d %03o\n",
ln, (uint32)(*data & 0777));
if ((*data & OFF_HOOK) == 0) {
uint32 mask = ~(1 << ln);
rx_rdy &= mask;
tx_enable &= mask;
dz_enable &= mask;
lp = &dz_ldsc[ln];
if (rx_conn & (1 << ln) && lp->conn) {
sim_debug(DEBUG_DETAIL, &dz_dev, "DC line hangup %d\n", ln);
tmxr_linemsg (lp, "\r\nLine Hangup\r\n");
tmxr_reset_ln(lp);
rx_conn &= mask;
}
} else {
sim_debug(DEBUG_DETAIL, &dz_dev, "DC line off-hook %d\n", ln);
dz_enable |= 1<<ln;
if (dz_ring & (1 << ln)) {
dz_l_status |= (1LL << (ln + dz_modem));
dz_ring &= ~(1 << ln);
rx_conn |= (1 << ln);
}
}
} else if (ln < dz_desc.lines) {
lp = &dz_ldsc[ln];
if (*data & FLAG) {
tx_enable &= ~(1 << ln);
dz_l_status &= ~(1LL << ln);
} else if (lp->conn) {
int32 ch = *data & DATA;
ch = sim_tt_outcvt(ch, TT_GET_MODE (dz_unit.flags) | TTUF_KSR);
tmxr_putc_ln (lp, ch);
if (lp->xmte)
tx_enable |= (1 << ln);
else
tx_enable &= ~(1 << ln);
dz_l_status |= (1LL << ln);
}
}
dz_doscan(uptr);
sim_debug(DEBUG_DATAIO, &dz_dev, "DC %03o DATO %012llo PC=%06o\n",
dev, *data, PC);
break;
case DATAI:
ln = dz_l_count;
*data = (uint64)(ln) << 18;
if (ln >= dz_modem) {
dz_l_status &= ~(1LL << ln);
ln = ln - dz_modem;
lp = &dz_ldsc[ln];
if (dz_enable & (1 << ln))
*data |= FLAG|OFF_HOOK;
if (rx_conn & (1 << ln) && lp->conn)
*data |= FLAG|CTS;
if (dz_ring & (1 << ln))
*data |= FLAG|RES_DET;
} else if (ln < dz_desc.lines) {
/* Nothing happens if no recieve data, which is transmit ready */
lp = &dz_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(dz_unit.flags) | TTUF_KSR);
*data |= FLAG | (uint64)(ch & DATA);
}
if (tmxr_rqln (lp) > 0) {
rx_rdy |= 1 << ln;
dz_l_status |= (1LL << ln);
} else {
rx_rdy &= ~(1 << ln);
dz_l_status &= ~(1LL << ln);
}
}
dz_doscan(uptr);
sim_debug(DEBUG_DATAIO, &dz_dev, "DC %03o DATI %012llo PC=%06o\n",
dev, *data, PC);
break;
}
return SCPE_OK;
}
/* Unit service */
t_stat dz_svc (UNIT *uptr)
{
int32 ln;
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_ldsc[ln].rcve = 1;
dz_ring |= (1 << ln);
dz_l_status |= (1LL << (ln + dz_modem)); /* Flag modem line */
sim_debug(DEBUG_DETAIL, &dz_dev, "DC line connect %d\n", ln);
}
tmxr_poll_tx(&dz_desc);
tmxr_poll_rx(&dz_desc);
for (ln = 0; ln < dz_desc.lines; ln++) {
/* Check if buffer empty */
if (dz_ldsc[ln].xmte && ((dz_l_status & (1ll << ln)) != 0)) {
tx_enable |= 1 << ln;
}
/* Check to see if any pending data for this line */
if (tmxr_rqln(&dz_ldsc[ln]) > 0) {
rx_rdy |= (1 << ln);
dz_l_status |= (1LL << ln); /* Flag line */
sim_debug(DEBUG_DETAIL, &dz_dev, "DC recieve %d\n", ln);
}
/* Check if disconnect */
if ((rx_conn & (1 << ln)) != 0 && dz_ldsc[ln].conn == 0) {
rx_conn &= ~(1 << ln);
dz_l_status |= (1LL << (ln + dz_modem)); /* Flag modem line */
sim_debug(DEBUG_DETAIL, &dz_dev, "DC line disconnect %d\n", ln);
}
}
/* If any pending status request, raise the PI signal */
if (dz_l_status)
set_interrupt(DC_DEVNUM, uptr->STATUS);
sim_clock_coschedule(uptr, tmxr_poll); /* continue poll */
return SCPE_OK;
}
/* Scan to see if something to do */
t_stat dz_doscan (UNIT *uptr) {
int32 lmask;
uptr->STATUS &= ~(RCV_PI|XMT_PI);
clr_interrupt(DC_DEVNUM);
for (;dz_l_status != 0; dz_l_count++) {
dz_l_count &= 077;
/* Check if we found it */
if (dz_l_status & (1LL << dz_l_count)) {
/* Check if modem control or data line */
if (dz_l_count >= dz_modem) {
uptr->STATUS |= RCV_PI;
} else {
/* Must be data line */
lmask = 1 << dz_l_count;
if (rx_rdy & lmask)
uptr->STATUS |= RCV_PI;
if (tx_enable & lmask)
uptr->STATUS |= XMT_PI;
}
/* Stop scanner */
set_interrupt(DC_DEVNUM, uptr->STATUS);
return SCPE_OK;
}
}
return SCPE_OK;
}
/* Reset routine */
t_stat dz_reset (DEVICE *dptr)
{
if (dz_unit.flags & UNIT_ATT) /* if attached, */
sim_activate (&dz_unit, tmxr_poll); /* activate */
else
sim_cancel (&dz_unit); /* else stop */
tx_enable = 0;
rx_rdy = 0; /* Flags */
rx_conn = 0;
dz_l_status = 0;
dz_l_count = 0;
dz_unit.STATUS = 0;
clr_interrupt(DC_DEVNUM);
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, DC10_MLINES, &r);
if ((r != SCPE_OK) || (newln == dz_desc.lines))
return r;
if (newln > dz_modem)
return SCPE_ARG;
if ((newln == 0) || (newln > DC10_MLINES) || (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, "DC10E Terminal Interfaces\n\n");
fprintf (st, "The DC10 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, &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 DC is detached.\n");
return SCPE_OK;
}
const char *dz_description (DEVICE *dptr)
{
return "DZ11 asynchronous line interface";
}
#endif

View File

@@ -75,10 +75,10 @@
#define CS1_RDY 0000200 /* Drive ready */
#define CS1_UBA 0001400 /* High order UBA bits */
#define CS1_PSEL 0002000 /* */
#define CS1_DVA 0004000 /* drive avail NI */
#define CS1_DVA 0004000 /* drive avail */
#define CS1_MCPE 0020000 /* */
#define CS1_TRE 0040000 /* */
#define CS1_SC 0100000 /* */
#define CS1_TRE 0040000 /* Set if CS2 0177400 */
#define CS1_SC 0100000 /* Set if TRE or ATTN */
/* RPWC - 176702 - word count */
@@ -116,10 +116,15 @@
#define CS2_WCE 0040000 /* write check err */
#define CS2_DLT 0100000 /* data late NI */
/* u3 low */
/* RPDS - 176712 - drive status */
#define STATUS us9
#define DS_OFF 0000001 /* offset mode */
#define DS_DF5 0000001 /* Drive forward 5in/sec */
#define DS_DF20 0000002 /* Drive forward 20in/sec */
#define DS_DIGB 0000004 /* Drive inner gaurd band */
#define DS_GRV 0000010 /* Go reverse read */
#define DS_DL64 0000020 /* Difference less 64 */
#define DS_DE1 0000040 /* Difference equal 1 */
#define DS_VV 0000100 /* volume valid */
#define DS_DRY 0000200 /* drive ready */
#define DS_DPR 0000400 /* drive present */
@@ -130,7 +135,6 @@
#define DS_PIP 0020000 /* pos in progress */
#define DS_ERR 0040000 /* error */
#define DS_ATA 0100000 /* attention active */
#define DS_MBZ 0000076
/* u3 high */
/* RPER1 - 176714 - error status 1 */
@@ -189,11 +193,11 @@
/* u5 low */
/* RPCC - 176736 - current cylinder */
/* RPER2 - 176740 - error status 2 - drive unsafe conditions */
/* RPER2 - 176740 - error status 2 - drive unsafe conditions - unimplemented */
/* RPER3 - 176742 - error status 3 - more unsafe conditions - unimplemented */
#define ERR2 us9
//#define ERR2 us9
/* us9 */
#define ERR3 us10
//#define ERR3 us10
#define DATAPTR u6
@@ -272,8 +276,7 @@ uint64 rp_buf[RP_NUMWD];
uint16 rp_wc;
uint16 rp_db;
t_addr rp_ba;
uint8 rp_attn;
int rp_unit;
uint16 rp_cs2;
uint8 rp_ie;
@@ -321,8 +324,7 @@ MTAB rp_mod[] = {
REG rpa_reg[] = {
{ORDATA(WC, rp_wc, 16)},
{ORDATA(BA, rp_ba, 18)},
{ORDATA(ATTN, rp_attn, 8)},
{ORDATA(UNIT, rp_unit, 3)},
{ORDATA(UNIT, rp_cs2, 16)},
{ORDATA(IE, rp_ie, 8), REG_HRO},
{BRDATA(BUFF, rp_buf, 16, 64, RP_NUMWD), REG_HRO},
{0}
@@ -339,6 +341,7 @@ DEVICE rpa_dev = {
int
rp_write(t_addr addr, uint16 data, int32 access) {
int i;
int rp_unit = rp_cs2 & 07;
UNIT *uptr = &rpa_unit[rp_unit];
int dtype = GET_DTYPE(uptr->flags);
@@ -352,29 +355,26 @@ rp_write(t_addr addr, uint16 data, int32 access) {
return 0;
sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o Status=%06o\n", rp_unit, uptr->CMD);
/* Set if drive not writable */
if (uptr->flags & UNIT_WLK)
uptr->CMD |= DS_WRL;
/* If drive not ready don't do anything */
if ((uptr->CMD & DS_DRY) == 0) {
uptr->CMD |= (ER1_RMR << 16)|DS_ERR;
if ((rp_ie & CS1_GO) != 0|| (uptr->STATUS & DS_PIP) != 0) {
uptr->CMD |= (ER1_RMR << 16);
sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o not ready\n", rp_unit);
return 0;
}
rp_ba = ((data << 7) & 0600000) | (rp_ba & 0177777);
rp_ie = data & CS1_IE;
rp_ie = data & (CS1_IE|CS1_GO);
/* Check if GO bit set */
uptr->CMD = data & 076;
if ((data & 1) == 0) {
uptr->CMD &= ~076;
uptr->CMD |= data & 076;
sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o no go\n", rp_unit);
sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o no go %06o\n", rp_unit, data);
return 0; /* No, nop */
}
if ((uptr->flags & UNIT_ATT) == 0) {
sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o unattached %06o\n", rp_unit, data);
return 0; /* No, nop */
}
uptr->CMD &= DS_ATA|DS_VV|DS_DPR|DS_MOL|DS_WRL;
uptr->CMD |= data & 076;
switch (GET_FNC(data)) {
case FNC_NOP:
uptr->CMD |= DS_DRY;
break;
case FNC_RECAL: /* recalibrate */
@@ -384,7 +384,6 @@ rp_write(t_addr addr, uint16 data, int32 access) {
case FNC_RETURN: /* return to center */
case FNC_OFFSET: /* offset */
case FNC_UNLOAD: /* unload */
uptr->CMD &= ~DS_OFF;
/* Fall through */
case FNC_SEARCH: /* search */
@@ -394,56 +393,52 @@ rp_write(t_addr addr, uint16 data, int32 access) {
case FNC_WRITEH: /* write w/ headers */
case FNC_READ: /* read */
case FNC_READH: /* read w/ headers */
uptr->CMD |= DS_PIP;
uptr->STATUS |= DS_PIP;
if (GET_CY(uptr->DA) >= rp_drv_tab[dtype].cyl ||
GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) {
rp_attn &= ~(1<<rp_unit);
uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA;
uptr->CMD &= ~DS_PIP;
uptr->CMD |= (ER1_IAE << 16);
uptr->STATUS |= DS_ATA;
uptr->STATUS &= ~DS_PIP;
break;
}
uptr->CMD |= CS1_GO;
rp_ie |= CS1_GO;
CLR_BUF(uptr);
uptr->DATAPTR = 0;
break;
case FNC_DCLR: /* drive clear */
uptr->CMD |= DS_DRY;
uptr->CMD &= ~(DS_ATA|CS1_GO);
uptr->STATUS &= ~(DS_ATA);
rp_ie &= ~(CS1_GO);
uptr->DA &= 003400177777;
uptr->CCYL &= 0177777;
uptr->ERR2 = 0;
uptr->ERR3 = 0;
// uptr->ERR2 = 0;
// uptr->ERR3 = 0;
rp_ie = 0;
rp_attn &= ~(1<<rp_unit);
break;
case FNC_PRESET: /* read-in preset */
uptr->DA = 0;
uptr->CCYL &= 0177777;
uptr->CMD &= ~DS_OFF;
/* Fall through */
case FNC_RELEASE: /* port release */
case FNC_PACK: /* pack acknowledge */
if ((uptr->flags & UNIT_ATT) != 0)
uptr->CMD |= DS_VV;
uptr->CMD |= DS_DRY;
break;
default:
uptr->CMD |= DS_DRY|DS_ERR|DS_ATA;
uptr->STATUS |= DS_ATA;
uptr->CMD |= (ER1_ILF << 16);
rp_attn |= (1<<rp_unit);
}
if (uptr->CMD & CS1_GO)
if (GET_FNC(data) >= FNC_XFER)
uptr->STATUS = rp_cs2 = 0;
if (rp_ie & CS1_GO)
sim_activate(uptr, 1000);
sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o AStatus=%06o\n", rp_unit, uptr->CMD);
return 0;
break;
case 002: /* RPWC - 176702 - word count */
if (access == BYTE) {
if (addr & 1)
@@ -476,12 +471,13 @@ rp_write(t_addr addr, uint16 data, int32 access) {
case 010: /* RPCS2 - 176710 - Control and Status register 2 */
if (access == BYTE) {
if (addr & 1)
data = data | rp_unit;
data = data | rp_cs2;
}
rp_unit = data & 07;
rp_cs2 = (CS2_UAI|CS2_PAT|07) & data;
if (data & 040) {
rp_reset(&rpa_dev);
}
rp_cs2 |= CS2_IR;
break;
case 012: /* RPDS - 176712 - drive status */
@@ -496,17 +492,17 @@ rp_write(t_addr addr, uint16 data, int32 access) {
}
uptr->CMD &= 0177777;
uptr->CMD |= data << 16;
uptr->CMD &= ~DS_ERR;
if ((((uptr->CMD >> 16) & 0177777) | uptr->ERR2 | uptr->ERR3) != 0)
uptr->CMD |= DS_ERR;
// uptr->CMD &= ~DS_ERR;
// if ((((uptr->CMD >> 16) & 0177777) | uptr->ERR2 | uptr->ERR3) != 0)
// if ((((uptr->CMD >> 16) & 0177777)) != 0)
// uptr->CMD |= DS_ERR;
break;
case 016: /* RPAS - 176716 - attention summary */
for (i = 0; i < 8; i++) {
if (data & (1<<i)) {
UNIT *u = &rpa_unit[i];
u->CMD &= ~DS_ATA;
rp_attn &= ~(1<<i);
u->STATUS &= ~DS_ATA;
}
}
break;
@@ -517,6 +513,8 @@ rp_write(t_addr addr, uint16 data, int32 access) {
break;
case 022: /* RPDB - 176722 - data buffer */
rp_db = data;
rp_cs2 |= CS2_OR;
rp_cs2 &= ~CS2_IR;
break;
/* RPCS2 - 176710 - control/status 2 */
case 032: /* RPOF - 176732 - offset register */
@@ -534,16 +532,18 @@ rp_write(t_addr addr, uint16 data, int32 access) {
uptr->DA |= data;
break;
case 040: /* RPER2 - 176740 - error status 2 - drive unsafe conditions */
uptr->ERR2 = data;
uptr->CMD &= ~DS_ERR;
if ((((uptr->CMD >> 16) & 0177777) | uptr->ERR2 | uptr->ERR3) != 0)
uptr->CMD |= DS_ERR;
// uptr->ERR2 = data;
// uptr->CMD &= ~DS_ERR;
// if ((((uptr->CMD >> 16) & 0177777) | uptr->ERR2 | uptr->ERR3) != 0)
// if ((((uptr->CMD >> 16) & 0177777)) != 0)
// uptr->CMD |= DS_ERR;
break;
case 042: /* RPER3 - 176742 - error status 3 - more unsafe conditions */
uptr->ERR3 = data;
uptr->CMD &= ~DS_ERR;
if ((((uptr->CMD >> 16) & 0177777) | uptr->ERR2 | uptr->ERR3) != 0)
uptr->CMD |= DS_ERR;
// uptr->ERR3 = data;
// uptr->CMD &= ~DS_ERR;
// if ((((uptr->CMD >> 16) & 0177777) | uptr->ERR2 | uptr->ERR3) != 0)
// if ((((uptr->CMD >> 16) & 0177777)) != 0)
// uptr->CMD |= DS_ERR;
break;
case 030: /* RPSN - 176730 - serial number */
case 036: /* RPCC - 176736 - current cylinder */
@@ -558,6 +558,7 @@ rp_write(t_addr addr, uint16 data, int32 access) {
int
rp_read(t_addr addr, uint16 *data, int32 access) {
int rp_unit = rp_cs2 & 07;
UNIT *uptr = &rpa_unit[rp_unit];
uint16 temp = 0;
int i;
@@ -565,15 +566,16 @@ rp_read(t_addr addr, uint16 *data, int32 access) {
/* RPDB - 176722 - data buffer */
switch(addr & 076) {
case 000: /* RPC - 176700 - control */
temp = uptr->CMD & (DS_DRY|076);
temp = uptr->CMD & 077;
temp |= (uint16)rp_ie;
temp |= (rp_ba & 0600000) >> 7;
if (uptr->flags & UNIT_ATT)
if (uptr->flags & UNIT_ATT) {
temp |= CS1_DVA;
if (uptr->CMD & CS1_GO)
temp |= CS1_GO;
else if (GET_FNC(uptr->CMD) < FNC_XFER)
temp |= CS1_RDY;
if (rp_ie & CS1_GO)
temp |= CS1_GO;
if ((rp_ie & CS1_GO) == 0 && (uptr->STATUS & DS_PIP) == 0)
temp |= CS1_RDY;
}
break;
case 002: /* RPWC - 176702 - word count */
temp = rp_wc;
@@ -585,14 +587,22 @@ rp_read(t_addr addr, uint16 *data, int32 access) {
temp = (uptr->DA >> 16) & 0177777;
break;
case 010: /* RPCS2 - 176710 - control/status 2 */
temp = rp_unit;
temp = rp_cs2;
if (uptr->flags & UNIT_DIS)
temp |= CS2_NED;
break;
case 012: /* RPDS - 176712 - drive status */
temp = uptr->CMD & 0177600;
temp = uptr->STATUS;
if (((uptr->CMD >> 16) & 0177777) != 0)
temp |= DS_ERR;
if ((uptr->flags & UNIT_DIS) == 0)
temp |= DS_DPR;
if ((uptr->flags & UNIT_ATT) != 0)
temp |= DS_VV;
temp |= DS_VV|DS_MOL;
if ((uptr->flags & UNIT_WLK) != 0)
temp |= DS_WRL;
if ((rp_ie & CS1_GO) == 0 && (uptr->STATUS & DS_PIP) == 0)
temp |= DS_DRY;
break;
case 014: /* RPER1 - 176714 - error status 1 */
temp = (uptr->CMD >> 16) & 0177777;
@@ -600,7 +610,7 @@ rp_read(t_addr addr, uint16 *data, int32 access) {
case 016: /* RPAS - 176716 - attention summary */
for (i = 0; i < 8; i++) {
UNIT *u = &rpa_unit[i];
if (u->CMD & DS_ATA) {
if (u->STATUS & DS_ATA) {
temp |= 1 << i;
}
}
@@ -612,6 +622,8 @@ rp_read(t_addr addr, uint16 *data, int32 access) {
break;
case 022: /* RPDB - 176722 - data buffer */
temp = rp_db;
rp_cs2 &= ~CS2_OR;
rp_cs2 |= CS2_IR;
break;
case 024: /* RPMR - 176724 - maintenace register */
break;
@@ -631,18 +643,18 @@ rp_read(t_addr addr, uint16 *data, int32 access) {
temp = uptr->CCYL & 0177777;
break;
case 040: /* RPER2 - 176740 - error status 2 - drive unsafe conditions */
temp = uptr->ERR2;
// temp = uptr->ERR2;
break;
case 042: /* RPER3 - 176742 - error status 3 - more unsafe conditions */
temp = uptr->ERR3;
// temp = uptr->ERR3;
break;
case 044: /* RPEC1 - 176744 - ECC status 1 - unimplemented */
case 046: /* RPEC2 - 176746 - ECC status 2 - unimplemented */
break;
}
*data = temp;
sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o read %02o %06o\n", rp_unit,
addr & 076, temp);
sim_debug(DEBUG_DETAIL, &rpa_dev, "RP%o read %02o %06o %06o\n", rp_unit,
addr & 076, temp, PC);
return 0;
}
@@ -650,7 +662,6 @@ rp_read(t_addr addr, uint16 *data, int32 access) {
/* Set the attention flag for a unit */
void rp_setattn(int unit)
{
rp_attn |= 1<<unit;
if (rp_ie)
uba_set_irq(&rpa_dib);
}
@@ -671,7 +682,9 @@ t_stat rp_svc (UNIT *uptr)
dptr = uptr->dptr;
unit = uptr - dptr->units;
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
uptr->CMD |= (ER1_UNS << 16) | DS_ATA|DS_ERR; /* set drive error */
uptr->CMD |= (ER1_UNS << 16); /* set drive error */
uptr->STATUS |= DS_ATA;
rp_ie &= ~(CS1_GO);
if (GET_FNC(uptr->CMD) >= FNC_XFER) { /* xfr? set done */
if (rp_ie)
uba_set_irq(&rpa_dib);
@@ -682,11 +695,13 @@ t_stat rp_svc (UNIT *uptr)
}
/* Check if seeking */
if (uptr->CMD & DS_PIP) {
if (uptr->STATUS & DS_PIP) {
sim_debug(DEBUG_DETAIL, dptr, "%s%o seek %d %d\n", dptr->name, unit, cyl, uptr->CCYL);
if (cyl >= rp_drv_tab[dtype].cyl) {
uptr->CMD &= ~DS_PIP;
uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA;
uptr->STATUS &= ~DS_PIP;
uptr->STATUS |= DS_ATA;
uptr->CMD |= (ER1_IAE << 16);
rp_ie &= ~CS1_GO;
rp_setattn(unit);
}
diff = cyl - (uptr->CCYL & 01777);
@@ -715,7 +730,7 @@ t_stat rp_svc (UNIT *uptr)
}
return SCPE_OK;
} else {
uptr->CMD &= ~DS_PIP;
uptr->STATUS &= ~DS_PIP;
uptr->DATAPTR = 0;
}
}
@@ -730,7 +745,6 @@ t_stat rp_svc (UNIT *uptr)
rp_detach(uptr);
/* Fall through */
case FNC_OFFSET: /* offset */
uptr->CMD |= DS_OFF;
/* Fall through */
case FNC_RETURN: /* return to center */
case FNC_PRESET: /* read-in preset */
@@ -738,9 +752,9 @@ t_stat rp_svc (UNIT *uptr)
case FNC_SEEK: /* seek */
if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf)
uptr->CMD |= (ER1_IAE << 16)|DS_ERR;
uptr->CMD |= DS_DRY|DS_ATA;
uptr->CMD &= ~CS1_GO;
uptr->CMD |= (ER1_IAE << 16);
uptr->STATUS |= DS_ATA;
rp_ie &= ~CS1_GO;
rp_setattn(unit);
sim_debug(DEBUG_DETAIL, dptr, "%s%o seekdone %d %o\n", dptr->name, unit, cyl, uptr->CMD);
break;
@@ -748,9 +762,9 @@ t_stat rp_svc (UNIT *uptr)
case FNC_SEARCH: /* search */
if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf)
uptr->CMD |= (ER1_IAE << 16)|DS_ERR;
uptr->CMD |= DS_DRY|DS_ATA;
uptr->CMD &= ~CS1_GO;
uptr->CMD |= (ER1_IAE << 16);
uptr->STATUS |= DS_ATA;
rp_ie &= ~CS1_GO;
rp_setattn(unit);
sim_debug(DEBUG_DETAIL, dptr, "%s%o searchdone %d %o\n", dptr->name, unit, cyl, uptr->CMD);
break;
@@ -758,15 +772,12 @@ t_stat rp_svc (UNIT *uptr)
case FNC_READ: /* read */
case FNC_READH: /* read w/ headers */
case FNC_WCHK: /* write check */
if (uptr->CMD & DS_ERR) {
sim_debug(DEBUG_DETAIL, dptr, "%s%o read error\n", dptr->name, unit);
goto rd_end;
}
if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) {
uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA;
uptr->CMD &= ~CS1_GO;
uptr->CMD |= (ER1_IAE << 16);
uptr->STATUS |= DS_ATA;
rp_ie &= ~CS1_GO;
if (uptr->CMD & CS1_IE)
uba_set_irq(&rpa_dib);
sim_debug(DEBUG_DETAIL, dptr, "%s%o readx done\n", dptr->name, unit);
@@ -787,22 +798,24 @@ t_stat rp_svc (UNIT *uptr)
dptr->name, unit, buf, rp_ba, rp_wc);
if ((sts = uba_write_npr(rp_ba, rpa_dib.uba_ctl, buf)) == 0)
goto rd_end;
rp_ba += 4;
if ((rp_cs2 & CS2_UAI) == 0)
rp_ba += 4;
rp_wc = (rp_wc + 2) & 0177777;
if (rp_wc == 0) {
sts = 0;
goto rd_end;
sts = 0;
goto rd_end;
}
buf = (((uint64)(unit + 1)) << 18) | (uint64)(unit);
sim_debug(DEBUG_DATA, dptr, "%s%o read word h2 %012llo %09o %06o\n",
dptr->name, unit, buf, rp_ba, rp_wc);
if ((sts = uba_write_npr(rp_ba, rpa_dib.uba_ctl, buf)) == 0)
goto rd_end;
rp_ba += 4;
if ((rp_cs2 & CS2_UAI) == 0)
rp_ba += 4;
rp_wc = (rp_wc + 2) & 0177777;
if (rp_wc == 0) {
sts = 0;
goto rd_end;
sts = 0;
goto rd_end;
}
}
@@ -811,11 +824,12 @@ t_stat rp_svc (UNIT *uptr)
sim_debug(DEBUG_DATA, dptr, "%s%o read word %d %012llo %09o %06o\n",
dptr->name, unit, uptr->DATAPTR, buf, rp_ba, rp_wc);
sts = uba_write_npr(rp_ba, rpa_dib.uba_ctl, buf);
rp_ba += 4;
if ((rp_cs2 & CS2_UAI) == 0)
rp_ba += 4;
rp_wc = (rp_wc + 2) & 0177777;
if (rp_wc == 0) {
sts = 0;
goto rd_end;
sts = 0;
goto rd_end;
}
}
@@ -830,7 +844,7 @@ t_stat rp_svc (UNIT *uptr)
if (GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) {
uptr->DA &= (DC_M_CY << DC_V_CY);
uptr->DA += 1 << DC_V_CY;
uptr->CMD |= DS_PIP;
uptr->STATUS |= DS_PIP;
}
}
sim_activate(uptr, 10);
@@ -838,23 +852,18 @@ t_stat rp_svc (UNIT *uptr)
}
rd_end:
sim_debug(DEBUG_DETAIL, dptr, "%s%o read done\n", dptr->name, unit);
uptr->CMD |= DS_DRY;
uptr->CMD &= ~CS1_GO;
rp_ie &= ~CS1_GO;
if (rp_ie)
uba_set_irq(&rpa_dib);
return SCPE_OK;
case FNC_WRITE: /* write */
case FNC_WRITEH: /* write w/ headers */
if (uptr->CMD & DS_ERR) {
sim_debug(DEBUG_DETAIL, dptr, "%s%o read error\n", dptr->name, unit);
goto wr_end;
}
if (GET_SC(uptr->DA) >= rp_drv_tab[dtype].sect ||
GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) {
uptr->CMD |= (ER1_IAE << 16)|DS_ERR|DS_DRY|DS_ATA;
uptr->CMD &= ~CS1_GO;
uptr->CMD |= (ER1_IAE << 16);
uptr->STATUS |= DS_ATA;
rp_ie &= ~CS1_GO;
uba_set_irq(&rpa_dib);
sim_debug(DEBUG_DETAIL, dptr, "%s%o writex done\n", dptr->name, unit);
return SCPE_OK;
@@ -863,22 +872,24 @@ rd_end:
/* On Write headers, transfer 2 words to start */
if (GET_FNC(uptr->CMD) == FNC_WRITEH) {
if (uba_read_npr(rp_ba, rpa_dib.uba_ctl, &buf) == 0)
goto wr_end;
rp_ba += 4;
goto wr_done;
if ((rp_cs2 & CS2_UAI) == 0)
rp_ba += 4;
rp_wc = (rp_wc + 2) & 0177777;
if (rp_wc == 0) {
sts = 0;
goto wr_end;
sts = 0;
goto wr_done;
}
sim_debug(DEBUG_DATA, dptr, "%s%o write word h1 %012llo %07o\n",
dptr->name, unit, buf, rp_wc);
if (uba_read_npr(rp_ba, rpa_dib.uba_ctl, &buf) == 0)
goto wr_end;
rp_ba += 4;
goto wr_done;
if ((rp_cs2 & CS2_UAI) == 0)
rp_ba += 4;
rp_wc = (rp_wc + 2) & 0177777;
if (rp_wc == 0) {
sts = 0;
goto wr_end;
sts = 0;
goto wr_done;
}
sim_debug(DEBUG_DATA, dptr, "%s%o write word h2 %012llo %07o\n",
dptr->name, unit, buf, rp_wc);
@@ -886,23 +897,24 @@ rd_end:
uptr->DATAPTR = 0;
uptr->hwmark = 0;
buf = 0;
while (uptr->DATAPTR < RP_NUMWD &&
(sts = uba_read_npr(rp_ba, rpa_dib.uba_ctl, &buf)) != 0) {
rp_buf[uptr->DATAPTR++] = buf;
sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %07o %06o\n",
while (uptr->DATAPTR < RP_NUMWD) {
if ((sts = uba_read_npr(rp_ba, rpa_dib.uba_ctl, &buf)) == 0)
break;
rp_buf[uptr->DATAPTR++] = buf;
sim_debug(DEBUG_DATA, dptr, "%s%o write word %d %012llo %07o %06o\n",
dptr->name, unit, uptr->DATAPTR, buf, rp_ba, rp_wc);
rp_ba += 4;
if ((rp_cs2 & CS2_UAI) == 0)
rp_ba += 4;
rp_wc = (rp_wc + 2) & 0177777;
if (rp_wc == 0) {
sts = 0;
goto wr_end;
sts = 0;
goto wr_done;
}
}
rp_buf[uptr->DATAPTR++] = buf;
wr_done:
while (uptr->DATAPTR < RP_NUMWD) {
rp_buf[uptr->DATAPTR++] = 0;
}
wr_done:
sim_debug(DEBUG_DETAIL, dptr, "%s%o write (%d,%d,%d)\n", dptr->name,
unit, cyl, GET_SF(uptr->DA), GET_SC(uptr->DA));
da = GET_DA(uptr->DA, dtype);
@@ -916,17 +928,16 @@ wr_done:
if (GET_SF(uptr->DA) >= rp_drv_tab[dtype].surf) {
uptr->DA &= (DC_M_CY << DC_V_CY);
uptr->DA += 1 << DC_V_CY;
uptr->CMD |= DS_PIP;
uptr->STATUS |= DS_PIP;
}
}
if (sts) {
sim_activate(uptr, 10);
} else {
wr_end:
sim_debug(DEBUG_DETAIL, dptr, "RP%o write done\n", unit);
uptr->CMD |= DS_DRY;
uptr->CMD &= ~CS1_GO;
uptr->STATUS &= ~DS_PIP;
rp_ie &= ~CS1_GO;
if (rp_ie)
uba_set_irq(&rpa_dib);
}
@@ -951,18 +962,17 @@ rp_set_type(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
t_stat
rp_reset(DEVICE * rptr)
rp_reset(DEVICE * dptr)
{
int i;
rp_attn = 0;
rp_ba = 0;
rp_wc = 0177777;
rp_cs2 = CS2_IR;
for (i = 0; i < 8; i++) {
UNIT *u = &rpa_unit[i];
u->CMD &= DS_VV|DS_DRY|DS_DPR|DS_MOL;
rp_attn &= ~(1<<i);
u->ERR2 = u->ERR3 = 0;
u->STATUS = 0;
}
sim_debug(DEBUG_DETAIL, dptr, "RP reset done\n");
return SCPE_OK;
}
@@ -1055,13 +1065,13 @@ t_stat rp_attach (UNIT *uptr, CONST char *cptr)
if (rptr == 0)
return SCPE_OK;
dib = (DIB *) rptr->ctxt;
if (uptr->flags & UNIT_WLK)
uptr->CMD |= DS_WRL;
// if (uptr->flags & UNIT_WLK)
// uptr->CMD |= DS_WRL;
if (sim_switches & SIM_SW_REST)
return SCPE_OK;
uptr->DA = 0;
uptr->CMD &= ~DS_VV;
uptr->CMD |= DS_DPR|DS_MOL|DS_DRY;
// uptr->CMD &= ~DS_VV;
// uptr->CMD |= DS_DPR|DS_MOL|DS_DRY;
rp_setattn(uptr - &rpa_unit[0]);
return SCPE_OK;
}
@@ -1074,7 +1084,7 @@ t_stat rp_detach (UNIT *uptr)
return SCPE_OK;
if (sim_is_active (uptr)) /* unit active? */
sim_cancel (uptr); /* cancel operation */
uptr->CMD &= ~(DS_VV|DS_WRL|DS_DPR|DS_DRY);
// uptr->CMD &= ~(DS_VV|DS_WRL|DS_DPR|DS_DRY);
return disk_detach (uptr);
}

View File

@@ -30,7 +30,7 @@
#if (NUM_DEVS_TU > 0)
#define NUM_UNITS_TU 8
#define NUM_UNITS_TU 4
#define TU_NUMFR (64*1024)
#define BUF_EMPTY(u) (u->hwmark == 0xFFFFFFFF)
@@ -215,10 +215,6 @@ UNIT tua_unit[] = {
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
{ UDATA (&tu_srv, TU_UNIT+CNTRL_RH(0), 0) },
};
DIB tua_dib = {0772440, 037, 0224, 6, 3, &tu_read, &tu_write, 0};
@@ -279,11 +275,11 @@ tu_write(t_addr addr, uint16 data, int32 access) {
switch(addr & 036) {
case 000: /* TUCS - control */
sim_debug(DEBUG_DETAIL, &tua_dev, "TU %d Status=%06o\n", unit, uptr->STATUS);
sim_debug(DEBUG_DETAIL, &tua_dev, "TU %d Status=%06o %08o\n", unit, uptr->STATUS,
uptr->CMD);
if (access == BYTE && addr & 1)
return 0;
sim_debug(DEBUG_DETAIL, &tua_dev, "TU %d Status=%06o\n", unit, uptr->CMD);
tu_ba = ((data << 7) & 0600000) | (tu_ba & 0177777);
tu_ie = data & CS1_IE;
uptr->CMD = data & 076;
@@ -316,9 +312,9 @@ tu_write(t_addr addr, uint16 data, int32 access) {
case FNC_UNLOAD: /* unload */
case FNC_WCHKREV: /* write w/ headers */
uptr->CMD |= CS1_GO;
uptr->STATUS |= DS_PIP;
uptr->STATUS = DS_PIP;
tu_attn = 0;
for (i = 0; i < 8; i++) {
for (i = 0; i < NUM_UNITS_TU; i++) {
if (tua_unit[i].STATUS & DS_ATA)
tu_attn = 1;
}
@@ -332,7 +328,7 @@ tu_write(t_addr addr, uint16 data, int32 access) {
uptr->STATUS = 0;
tu_ie = 0;
tu_attn = 0;
for (i = 0; i < 8; i++) {
for (i = 0; i < NUM_UNITS_TU; i++) {
if (tua_unit[i].STATUS & DS_ATA)
tu_attn = 1;
}
@@ -342,6 +338,8 @@ tu_write(t_addr addr, uint16 data, int32 access) {
tu_attn = 1;
}
sim_debug(DEBUG_DETAIL, &tua_dev, "TU %o AStatus=%06o\n", unit, uptr->CMD);
if (tu_attn && tu_ie)
uba_set_irq(&tua_dib);
}
break;
case 002: /* TUWC - 172442 - word count */
@@ -379,7 +377,6 @@ tu_write(t_addr addr, uint16 data, int32 access) {
tu_cs2 = data & (CS2_PAT|CS2_UAI|CS2_UNIT);
break;
case 012: /* 772452 status */
break;
@@ -390,7 +387,7 @@ tu_write(t_addr addr, uint16 data, int32 access) {
case 016: /* 772456 atten summary */
tu_attn = 0;
if (data & 1) {
for (i = 0; i < 8; i++)
for (i = 0; i < NUM_UNITS_TU; i++)
tua_unit[i].STATUS &= ~DS_ATA;
}
break;
@@ -410,16 +407,16 @@ tu_write(t_addr addr, uint16 data, int32 access) {
tu_tcr = data;
break;
}
sim_debug(DEBUG_DETAIL, &tua_dev, "TU %o write %02o %06o\n", tu_tcr & 7,
addr & 036, data);
sim_debug(DEBUG_DETAIL, &tua_dev, "TU %o write %02o %06o %06o %06o\n", unit,
addr & 036, data, PC, tu_tcr);
return 0;
}
int
tu_read(t_addr addr, uint16 *data, int32 access)
{
UNIT *uptr = &tua_unit[tu_tcr & 07];
int tu_drive = tu_tcr & 07;
UNIT *uptr = &tua_unit[tu_drive];
uint16 temp = 0;
int i;
@@ -427,7 +424,8 @@ tu_read(t_addr addr, uint16 *data, int32 access)
switch(addr & 036) {
case 000: /* 772440 control */
temp = uptr->CMD & 076;
temp |= CS1_DVA;
if ((tu_cs2 & 07) == 0)
temp |= CS1_DVA;
temp |= (uint16)tu_ie;
temp |= (tu_ba & 0600000) << 7;
if (uptr->CMD & CS1_GO)
@@ -455,25 +453,29 @@ tu_read(t_addr addr, uint16 *data, int32 access)
break;
case 012: /* 772452 - status */
temp = uptr->STATUS & 0177777;
temp |= DS_PES;
temp |= ((tu_cs2 & 07) == 0) ? DS_DPR : 0;
if (((uptr->STATUS >> 16) & 0177777) != 0)
temp |= DS_ERR;
if ((uptr->flags & UNIT_ATT) != 0) {
if ((tu_cs2 & 07) == 0) {
temp |= DS_MOL;
if (uptr->flags & MTUF_WLK)
temp |= DS_WRL;
if ((uptr->CMD & CS1_GO) == 0 && (uptr->STATUS & DS_PIP) == 0)
temp |= DS_DRY;
if (sim_tape_bot(uptr))
temp |= DS_BOT;
if (sim_tape_eot(uptr))
temp |= DS_EOT;
if ((uptr->flags & UNIT_ATT) != 0) {
if (uptr->flags & MTUF_WLK)
temp |= DS_WRL;
if ((uptr->CMD & CS1_GO) == 0 && (uptr->STATUS & DS_PIP) == 0)
temp |= DS_DRY;
if (sim_tape_bot(uptr))
temp |= DS_BOT;
if (sim_tape_eot(uptr))
temp |= DS_EOT;
}
}
break;
case 014: /* 772454 - error register 1 */
temp = (uptr->STATUS >> 16) & 0177777;
break;
case 016: /* 772456 - atten summary */
for (i = 0; i < 8; i++) {
for (i = 0; i < NUM_UNITS_TU; i++) {
if (tua_unit[i].STATUS & DS_ATA)
temp |= 1;
}
@@ -489,13 +491,15 @@ tu_read(t_addr addr, uint16 *data, int32 access)
break;
case 026: /* 772466 - drive type */
if ((uptr->flags & UNIT_DIS) == 0)
temp = 042054;
temp = 0142054;
break;
case 030: /* 772470 - serial no */
temp = 020 + (tu_drive + 1);
if ((tu_cs2 & 07) == 0)
temp = 020 + (tu_drive + 1);
break;
case 032: /* 772472 - tape control register */
temp = tu_tcr;
if ((tu_cs2 & 07) == 0)
temp = tu_tcr;
break;
default:
uptr->STATUS |= (ER1_ILR << 16);
@@ -503,8 +507,10 @@ tu_read(t_addr addr, uint16 *data, int32 access)
tu_attn = 1;
}
*data = temp;
sim_debug(DEBUG_DETAIL, &tua_dev, "TU %o read %02o %06o\n", tu_tcr & 7,
addr & 036, *data);
sim_debug(DEBUG_DETAIL, &tua_dev, "TU %o read %02o %06o %06o %o\n", tu_tcr & 7,
addr & 036, *data, PC, tu_cs2);
if (tu_attn && tu_ie)
uba_set_irq(&tua_dib);
return 0;
}
@@ -697,9 +703,8 @@ t_stat tu_srv(UNIT * uptr)
tu_error(uptr, MTSE_OK);
return SCPE_OK;
}
sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo %d\n",
dptr->name, unit, tu_cbuf, uptr->DATAPTR);
tu_cbuf = 0;
sim_debug(DEBUG_DATA, dptr, "%s%o read %012llo %d %06o\n",
dptr->name, unit, tu_cbuf, uptr->DATAPTR, tu_tcr);
tu_cbuf = 0;
if ((tu_cs2 & CS2_UAI) == 0)
tu_ba += 4;
@@ -709,8 +714,8 @@ t_stat tu_srv(UNIT * uptr)
}
} else {
if (uptr->CPOS != 0) {
sim_debug(DEBUG_DATA, dptr, "%s%o readf %012llo\n",
dptr->name, unit, tu_cbuf);
sim_debug(DEBUG_DATA, dptr, "%s%o readf %012llo %d\n",
dptr->name, unit, tu_cbuf, uptr->DATAPTR);
uba_write_npr(tu_ba, tua_dib.uba_ctl, tu_cbuf);
}
rd_end:
@@ -724,8 +729,7 @@ rd_end:
case FNC_WRITE:
if (BUF_EMPTY(uptr)) {
if (tu_frame == 0) {
uptr->STATUS |= ER1_NEF << 16;
uptr->CMD |= DS_ATA;
uptr->STATUS |= (ER1_NEF << 16) | DS_ATA;
tu_error(uptr, MTSE_OK);
return SCPE_OK;
}
@@ -788,7 +792,7 @@ wr_end:
break;
case FNC_WTM:
uptr->CMD |= DS_ATA;
uptr->STATUS |= DS_ATA;
if ((uptr->flags & MTUF_WLK) != 0) {
tu_error(uptr, MTSE_WRP);
} else {
@@ -860,7 +864,7 @@ tu_reset(DEVICE * dptr)
tu_ba = tu_frame = tu_tcr = 0;
tu_wc = 0177777;
tu_cs2 = 0;
for (i = 0; i < 8; i++) {
for (i = 0; i < NUM_UNITS_TU; i++) {
tua_unit[i].STATUS = 0;
}
return SCPE_OK;
@@ -917,7 +921,7 @@ tu_boot(int32 unit_num, DEVICE * dptr)
addr ++;
}
M[036] = tua_dib.uba_addr | (tua_dib.uba_ctl << 18);
M[037] = unit_num;
M[037] = 0;
M[040] = tu_tcr;
PC = 01000;
return SCPE_OK;

View File

@@ -112,7 +112,7 @@ uba_write(t_addr addr, int ctl, uint64 data, int access)
uint32 map = (uint32)(data & 03777) << 9;
map |= (uint32)(data & 0740000) << 13;
uba_map[ubm][addr & 077] = map;
//fprintf(stderr, "Wr MAP %02o %012llo %06o\n\r", addr & 077, data, map);
sim_debug(DEBUG_EXP, &cpu_dev, "Wr MAP %02o %012llo %06o\n\r", addr & 077, data, map);
return 0;
} else if ((addr & 077) == 0) {
uba_status[ubm] &= (uint32)(074000 ^ data) | 0746000;
@@ -160,8 +160,7 @@ uba_read_npr(t_addr addr, uint16 ctl, uint64 *data)
return 0;
if ((map & MAP_VALID) == 0)
return 0;
map |= (addr >> 2) & 0777;
addr = (map & (PAGE_MASK|0777));
addr = (map & PAGE_MASK) | (addr >> 2) & 0777;
*data = M[addr];
if (map & MAP_EN16)
*data &= 0177777177777;
@@ -178,11 +177,10 @@ t_addr oaddr = addr;
return 0;
if ((map & MAP_VALID) == 0)
return 0;
map |= (addr >> 2) & 0777;
addr = (map & (PAGE_MASK|0777));
addr = (map & PAGE_MASK) | (addr >> 2) & 0777;
if (map & MAP_EN16)
data &= 0177777177777;
//fprintf(stderr, "Wr NPR %08o %08o %012llo\n\r", oaddr, addr, data);
sim_debug(DEBUG_DATA, &cpu_dev, "Wr NPR %08o %08o %012llo\n\r", oaddr, addr, data);
M[addr] = data;
return 1;
}
@@ -219,6 +217,7 @@ uba_set_irq(DIB *dibp)
if (ubm < 0)
return;
/* Figure out what channel device should IRQ on */
if (dibp->uba_br > 5) {
pi = uba_status[ubm] >> 3;
uba_status[ubm] |= UBST_INTH;
@@ -226,8 +225,9 @@ uba_set_irq(DIB *dibp)
pi = uba_status[ubm];
uba_status[ubm] |= UBST_INTL;
}
dibp->uba_irq_pend |= 0200 >> pi;
set_interrupt(dibp->uba_ctl, pi);
/* Save in device temp the irq value */
dibp->uba_irq_pend = 0200 >> (pi & 07);
set_interrupt(dibp->uba_ctl << 2, pi);
}
t_addr
@@ -236,43 +236,62 @@ uba_get_vect(t_addr addr, int lvl)
DEVICE *dptr;
DIB *idev = NULL;
uint64 buffer;
uint8 ivect;
int i;
int high = 0;
int ctl = 17;
int msk[16] = {0};
int pi;
int ubm;
/* Look for device */
for(i = 0; (dptr = sim_devices[i]) != NULL; i++) {
DIB *dibp = (DIB *) dptr->ctxt;
if (dibp == NULL)
continue;
/* If device is pending on this level save */
if ((dibp->uba_irq_pend & lvl) != 0) {
if (dibp->uba_ctl < ctl)
/* But only if it is highest UBA */
if (dibp->uba_ctl < ctl) {
ctl = dibp->uba_ctl;
idev = dibp;
continue;
}
msk[dibp->uba_ctl] |= dibp->uba_irq_pend;
}
if (idev != NULL) {
if (idev->uba_br > 5) {
pi = uba_status[idev->uba_ctl] >> 3;
uba_status[idev->uba_ctl] &= ~UBST_INTH;
if (msk[idev->uba_ctl] & (0200 >> pi))
uba_status[idev->uba_ctl] |= UBST_INTH;
} else {
pi = uba_status[idev->uba_ctl];
uba_status[idev->uba_ctl] &= ~UBST_INTL;
if (msk[idev->uba_ctl] & (0200 >> pi))
uba_status[idev->uba_ctl] |= UBST_INTL;
idev = dibp;
}
}
idev->uba_irq_pend &= ~(0200 >> pi);
if (msk[idev->uba_ctl] & (0200 >> pi))
set_interrupt(idev->uba_ctl, pi);
else
clr_interrupt(idev->uba_ctl);
}
/* Should have a device */
if (idev != NULL) {
/* Figure out what pi channel this will interrupt on */
ubm = uba_device[idev->uba_ctl];
if (idev->uba_br > 5) {
pi = (uba_status[ubm] >> 3) & 07;
high = 1;
uba_status[ubm] &= ~UBST_INTH;
} else {
pi = uba_status[ubm] & 07;
uba_status[ubm] &= ~UBST_INTL;
}
/* Clear interrupts */
idev->uba_irq_pend = 0;
/* Any other devices waiting on this PI channel? */
clr_interrupt(idev->uba_ctl << 2);
for(i = 0; (dptr = sim_devices[i]) != NULL; i++) {
DIB *dibp = (DIB *) dptr->ctxt;
if (dibp == NULL)
continue;
/* If device is pending on this level save */
if (dibp->uba_ctl == idev->uba_ctl &&
(dibp->uba_irq_pend & lvl) != 0) {
set_interrupt(idev->uba_ctl << 2, pi);
uba_status[ubm] |= UBST_INTL << high;
/* At least one, no need to continue */
break;
}
}
/* Fetch vector */
if (Mem_read_word(0100 | idev->uba_ctl, &buffer, 1))
return addr;
ivect = idev->uba_vect;
if (idev->irqv != NULL)
ivect = (idev->irqv)(idev);
addr = (buffer & RMASK) + (idev->uba_vect >> 2);
}
return addr;

View File

@@ -314,17 +314,13 @@ extern DEBTAB crd_debug[];
#if KI_22BIT|KI
#define MAXMEMSIZE 4096 * 1024
#else
#if PDP6
#elif PDP6
#define MAXMEMSIZE 256 * 1024
#else
#if KS
#define MAXMEMSIZE 512 * 1024
#elif KS
#define MAXMEMSIZE 1024 * 1024
#else
#define MAXMEMSIZE 1024 * 1024
#endif
#endif
#endif
#define MEMSIZE (cpu_unit[0].capac)
#define ICWA 0000000000776
@@ -527,6 +523,7 @@ struct pdp_dib {
uint16 uba_ctl; /* Unibus controller number */
t_stat (*rd_io)(t_addr addr, uint16 *data, int32 access);
t_stat (*wr_io)(t_addr addr, uint16 data, int32 access);
uint8 (*irqv)(struct pdp_dib *dibp);
uint8 uba_irq_pend; /* Device has pending */
};
typedef struct pdp_dib DIB;