1
0
mirror of https://github.com/simh/simh.git synced 2026-02-17 04:58:14 +00:00

PDP11, all VAX: Add TU58 device simulator with support for 32 drives plus the VAX 730 and 750 console devices

This commit is contained in:
Mark Pizzolato
2015-09-22 15:06:12 -07:00
parent 8652294fd6
commit 9f59823ae3
34 changed files with 1829 additions and 973 deletions

View File

@@ -242,6 +242,8 @@ typedef struct {
#define INT_V_QDSS 19 /* QDSS */
#define INT_V_CR 20
#define INT_V_QVSS 21 /* QVSS */
#define INT_V_TDRX 22
#define INT_V_TDTX 23
#define INT_CLK (1u << INT_V_CLK)
#define INT_RQ (1u << INT_V_RQ)
@@ -266,6 +268,8 @@ typedef struct {
#define INT_QDSS (1u << INT_V_QDSS)
#define INT_CR (1u << INT_V_CR)
#define INT_QVSS (1u << INT_V_QVSS)
#define INT_TDRX (1u << INT_V_TDRX)
#define INT_TDTX (1u << INT_V_TDTX)
#define IPL_CLK (0x16 - IPL_HMIN) /* relative IPL */
#define IPL_RQ (0x14 - IPL_HMIN)
@@ -290,6 +294,8 @@ typedef struct {
#define IPL_QDSS (0x14 - IPL_HMIN)
#define IPL_CR (0x14 - IPL_HMIN)
#define IPL_QVSS (0x14 - IPL_HMIN)
#define IPL_TDRX (0x14 - IPL_HMIN)
#define IPL_TDTX (0x14 - IPL_HMIN)
#define IPL_HMAX 0x17 /* highest hwre level */
#define IPL_HMIN 0x14 /* lowest hwre level */

View File

@@ -44,6 +44,7 @@ extern DEVICE tlb_dev;
extern DEVICE sysd_dev;
extern DEVICE qba_dev;
extern DEVICE tti_dev, tto_dev;
extern DEVICE tdc_dev;
extern DEVICE cr_dev;
extern DEVICE lpt_dev;
extern DEVICE clk_dev;
@@ -70,6 +71,7 @@ DEVICE *sim_devices[] = {
&clk_dev,
&tti_dev,
&tto_dev,
&tdc_dev,
&dz_dev,
&vh_dev,
&cr_dev,

View File

@@ -294,6 +294,8 @@ typedef struct {
#define INT_V_QVSS 21 /* QVSS */
#define INT_V_DMCRX 22
#define INT_V_DMCTX 23
#define INT_V_TDRX 24 /* TU58 */
#define INT_V_TDTX 25
#define INT_CLK (1u << INT_V_CLK)
#define INT_RQ (1u << INT_V_RQ)
@@ -320,6 +322,8 @@ typedef struct {
#define INT_QVSS (1u << INT_V_QVSS)
#define INT_DMCRX (1u << INT_V_DMCRX)
#define INT_DMCTX (1u << INT_V_DMCTX)
#define INT_TDRX (1u << INT_V_TDRX)
#define INT_TDTX (1u << INT_V_TDTX)
#define IPL_CLK (0x16 - IPL_HMIN) /* relative IPL */
#define IPL_RQ (0x14 - IPL_HMIN)
@@ -346,6 +350,8 @@ typedef struct {
#define IPL_QVSS (0x14 - IPL_HMIN)
#define IPL_DMCRX (0x14 - IPL_HMIN)
#define IPL_DMCTX (0x14 - IPL_HMIN)
#define IPL_TDRX (0x14 - IPL_HMIN)
#define IPL_TDTX (0x14 - IPL_HMIN)
#define IPL_HMAX 0x17 /* highest hwre level */
#define IPL_HMIN 0x14 /* lowest hwre level */

View File

@@ -55,6 +55,7 @@ extern DEVICE wtc_dev;
extern DEVICE sysd_dev;
extern DEVICE qba_dev;
extern DEVICE tti_dev, tto_dev;
extern DEVICE tdc_dev;
extern DEVICE cr_dev;
extern DEVICE lpt_dev;
extern DEVICE clk_dev;
@@ -84,6 +85,7 @@ DEVICE *sim_devices[] = {
&clk_dev,
&tti_dev,
&tto_dev,
&tdc_dev,
&dz_dev,
&vh_dev,
&cr_dev,

View File

@@ -268,6 +268,8 @@ typedef struct {
#define INT_V_CR 3
#define INT_V_VHRX 4
#define INT_V_VHTX 5
#define INT_V_TDRX 6
#define INT_V_TDTX 7
#define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZTX (1u << INT_V_DZTX)
@@ -289,6 +291,8 @@ typedef struct {
#define INT_DMCTX (1u << INT_V_DMCTX)
#define INT_DUPRX (1u << INT_V_DUPRX)
#define INT_DUPTX (1u << INT_V_DUPTX)
#define INT_TDRX (1u << INT_V_TDRX)
#define INT_TDTX (1u << INT_V_TDTX)
#define IPL_DZRX (0x15 - IPL_HMIN)
#define IPL_DZTX (0x15 - IPL_HMIN)
@@ -310,6 +314,8 @@ typedef struct {
#define IPL_DMCTX (0x15 - IPL_HMIN)
#define IPL_DUPRX (0x15 - IPL_HMIN)
#define IPL_DUPTX (0x15 - IPL_HMIN)
#define IPL_TDRX (0x14 - IPL_HMIN)
#define IPL_TDTX (0x14 - IPL_HMIN)
/* Device vectors */

View File

@@ -60,6 +60,8 @@
#include "vax_defs.h"
#include "sim_tmxr.h"
#include "pdp11_td.h"
/* Terminal definitions */
#define RXCS_RD (CSR_DONE + CSR_IE) /* terminal input */
@@ -82,9 +84,6 @@
#define MISC_CLCS 0x4 /* clear cold start */
#define TXDB_SEL (TXDB_M_SEL << TXDB_V_SEL) /* non-terminal */
#define TXDB_GETSEL(x) (((x) >> TXDB_V_SEL) & TXDB_M_SEL)
#define CSTS_BRK 0x1
#define CSTS_RD (CSR_DONE + CSR_IE + CSTS_BRK) /* terminal output */
#define CSTS_WR (CSR_IE + CSTS_BRK)
/* Clock definitions */
@@ -165,13 +164,8 @@ int32 tto_csr = 0; /* control/status */
int32 tto_buf = 0; /* buffer */
int32 tto_int = 0; /* interrupt */
int32 csi_csr = 0; /* control/status */
int32 csi_buf = 0; /* buffer */
int32 csi_int = 0; /* interrupt */
int32 cso_csr = 0; /* control/status */
int32 cso_buf = 0; /* buffer */
int32 cso_int = 0; /* interrupt */
int32 cso_state = 0; /* state */
int32 tmr_iccs = 0; /* interval timer csr */
uint32 tmr_icr = 0; /* curr interval */
@@ -189,22 +183,7 @@ struct todr_battery_info {
};
typedef struct todr_battery_info TOY;
int32 td_swait = 100; /* seek, per block */
int32 td_cwait = 150; /* command time */
int32 td_xwait = 180; /* tr set time */
int32 td_iwait = 180; /* init time */
uint8 td_ibuf[TD_NUMBY] = { 0 }; /* input buffer */
int32 td_ibptr = 0; /* input buffer pointer */
int32 td_ilen = 0; /* input length */
uint8 td_obuf[TD_NUMBY] = { 0 }; /* output buffer */
int32 td_obptr = 0; /* output buffer pointer */
int32 td_olen = 0; /* output length */
int32 td_block = 0; /* current block number */
int32 td_txsize = 0; /* remaining transfer size */
int32 td_offset = 0; /* offset into current transfer */
int32 td_state = TD_IDLE;
int32 td_unitno = 0; /* active unit number */
int32 td_ecode = 0; /* end packet success code */
int32 td_regval; /* temp location used in reg declarations */
extern jmp_buf save_env;
@@ -226,15 +205,12 @@ t_stat clk_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cpt
t_stat clk_attach (UNIT *uptr, char *cptr);
t_stat clk_detach (UNIT *uptr);
t_stat tmr_reset (DEVICE *dptr);
t_stat td_svc (UNIT *uptr);
t_stat td_reset (DEVICE *dptr);
int32 icr_rd (t_bool interp);
void tmr_incr (uint32 inc);
void tmr_sched (void);
t_stat todr_resync (void);
t_stat txdb_misc_wr (int32 data);
void td_process_packet();
t_bool td_test_xfr (UNIT *uptr, int32 state);
/* TTI data structures
@@ -362,19 +338,29 @@ DEVICE tmr_dev = {
td_mod RX modifier list
*/
UNIT td_unit[] = {
{ UDATA (&td_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, TD_SIZE) },
{ UDATA (&td_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, TD_SIZE) }
};
UNIT td_unit[2];
REG td_reg[] = {
{ HRDATAD (ECODE, td_ecode, 8, "end packet success code") },
{ HRDATAD (BLK, td_block, 8, "current block number") },
{ DRDATAD (PSTATE, td_state, 4, "state"), REG_RO },
{ DRDATAD (BPTR, td_obptr, 7, "output buffer pointer") },
{ DRDATAD (CTIME, td_cwait, 24, "command time"), PV_LEFT },
{ DRDATAD (STIME, td_swait, 24, "seek, per block"), PV_LEFT },
{ DRDATAD (XTIME, td_xwait, 24, "tr set time"), PV_LEFT },
{ HRDATAD (ECODE, td_regval, 8, "end packet success code") },
{ HRDATAD (BLOCK, td_regval, 8, "current block number") },
{ HRDATAD (RX_CSR, td_regval,16, "input control/status register") },
{ HRDATAD (RX_BUF, td_regval,16, "input buffer register") },
{ HRDATAD (TX_CSR, td_regval,16, "output control/status register") },
{ HRDATAD (TX_BUF, td_regval,16, "output buffer register") },
{ DRDATAD (P_STATE,td_regval, 4, "protocol state"), REG_RO },
{ DRDATAD (O_STATE,td_regval, 4, "output state"), REG_RO },
{ DRDATAD (IBPTR, td_regval, 9, "input buffer pointer") },
{ DRDATAD (OBPTR, td_regval, 9, "output buffer pointer") },
{ DRDATAD (ILEN, td_regval, 9, "input length") },
{ DRDATAD (OLEN, td_regval, 9, "output length") },
{ DRDATAD (TXSIZE, td_regval, 9, "remaining transfer size") },
{ DRDATAD (OFFSET, td_regval, 9, "offset into current transfer") },
{ DRDATAD (CTIME, td_regval,24, "command time"), PV_LEFT },
{ DRDATAD (STIME, td_regval,24, "seek, per block"), PV_LEFT },
{ DRDATAD (XTIME, td_regval,24, "tr set time"), PV_LEFT },
{ DRDATAD (ITIME, td_regval,24, "init time"), PV_LEFT },
{ BRDATAD (IBUF, &td_regval,16, 8, 512, "input buffer"), },
{ BRDATAD (OBUF, &td_regval,16, 8, 512, "output buffer"), },
{ NULL }
};
@@ -389,10 +375,26 @@ DEVICE td_dev = {
2, DEV_RDX, 20, 1, DEV_RDX, 8,
NULL, NULL, &td_reset,
NULL, NULL, NULL,
NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, DEV_DEBUG, 0, td_deb, NULL, NULL, NULL, NULL, NULL,
&td_description
};
static void set_csi_int (int ctlr, t_bool val)
{
if (csi_int ^ val) {
csi_int = val;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(%d)\n", val);
}
}
static void set_cso_int (int ctlr, t_bool val)
{
if (cso_int ^ val) {
cso_int = val;
sim_debug (TDDEB_INT, &td_dev, "CSO_INT(%d)\n", val);
}
}
/* Console storage MxPR routines
csrs_rd/wr input control/status
@@ -401,202 +403,50 @@ DEVICE td_dev = {
cstd_wr output buffer
*/
#define ctlr up7
int32 csrs_rd (void)
{
return (csi_csr & RXCS_RD);
int32 data;
sim_debug (TDDEB_IRD, &td_dev, "csrs_rd()\n");
td_rd_i_csr ((CTLR *)td_unit[0].ctlr, &data);
return data;
}
void csrs_wr (int32 data)
{
if ((data & CSR_IE) == 0)
cso_int = 0;
else if ((csi_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
csi_int = 1;
csi_csr = (csi_csr & ~RXCS_WR) | (data & RXCS_WR);
return;
sim_debug (TDDEB_IWR, &td_dev, "csrs_wr()\n");
td_wr_i_csr ((CTLR *)td_unit[0].ctlr, data);
}
int32 csrd_rd (void)
{
int32 t = csi_buf; /* char + error */
csi_csr = csi_csr & ~CSR_DONE; /* clr done */
csi_buf = csi_buf & BMASK; /* clr errors */
csi_int = 0;
return t;
int32 data;
sim_debug (TDDEB_IRD, &td_dev, "csrd_rd()\n");
td_rd_i_buf ((CTLR *)td_unit[0].ctlr, &data);
return data;
}
int32 csts_rd (void)
{
return (cso_csr & TXCS_RD);
int32 data;
sim_debug (TDDEB_ORD, &td_dev, "csts_rd()\n");
td_rd_o_csr ((CTLR *)td_unit[0].ctlr, &data);
return data;
}
void csts_wr (int32 data)
{
if ((cso_csr & CSTS_BRK) && !(data & CSTS_BRK)) {
td_ibptr = 0;
td_ibuf[td_ibptr++] = TD_OPINI;
td_process_packet(); /* check packet */
}
if ((data & CSR_IE) == 0)
cso_int = 0;
else if ((cso_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
cso_int = 1;
cso_csr = (cso_csr & ~CSTS_WR) | (data & CSTS_WR);
return;
sim_debug (TDDEB_OWR, &td_dev, "csts_wr()\n");
td_wr_o_csr ((CTLR *)td_unit[0].ctlr, data);
}
void cstd_wr (int32 data)
{
cso_buf = data & WMASK; /* save data */
cso_csr = cso_csr & ~CSR_DONE; /* clear flag */
cso_int = 0; /* clear int */
switch (cso_state) {
case TD_GETOPC:
td_ibptr = 0;
td_ibuf[td_ibptr++] = cso_buf;
td_process_packet(); /* check packet */
break;
case TD_GETLEN:
td_ibuf[td_ibptr++] = cso_buf;
td_ilen = cso_buf + 4; /* packet length + header + checksum */
cso_state = TD_GETDATA;
break;
case TD_GETDATA:
td_ibuf[td_ibptr++] = cso_buf;
if (td_ibptr >= td_ilen) {
cso_state = TD_GETOPC;
td_process_packet();
}
break;
}
cso_csr = cso_csr | CSR_DONE; /* set input flag */
if (cso_csr & CSR_IE)
cso_int = 1;
return;
}
void td_process_packet()
{
int32 opcode = td_ibuf[0];
switch (opcode) {
case TD_OPDAT:
if (td_state != TD_WRITE1) { /* expecting data? */
sim_printf("TU58 protocol error 1\n");
return;
}
if (td_ibptr < 2) { /* whole packet read? */
cso_state = TD_GETLEN; /* get rest of packet */
return;
}
td_state = TD_WRITE2;
sim_activate (&td_dev.units[td_unitno], td_cwait); /* sched command */
break;
case TD_OPCMD:
if (td_state != TD_IDLE) { /* expecting command? */
sim_printf("TU58 protocol error 2\n");
return;
}
if (td_ibptr < 2) { /* whole packet read? */
cso_state = TD_GETLEN; /* get rest of packet */
return;
}
switch (td_ibuf[2]) {
case TD_CMDNOP: /* NOP */
case TD_CMDGST: /* Get status */
case TD_CMDSST: /* Set status */
td_unitno = td_ibuf[4];
td_state = TD_END; /* All treated as NOP */
td_ecode = TD_STSOK;
td_offset = 0;
sim_activate (&td_dev.units[td_unitno], td_cwait); /* sched command */
break;
case TD_CMDINI:
sim_printf("Warning: TU58 command 'INIT' not implemented\n");
break;
case TD_CMDRD:
td_unitno = td_ibuf[4];
td_block = ((td_ibuf[11] << 8) | td_ibuf[10]);
td_txsize = ((td_ibuf[9] << 8) | td_ibuf[8]);
td_state = TD_READ;
td_offset = 0;
sim_activate (&td_dev.units[td_unitno], td_cwait); /* sched command */
break;
case TD_CMDWR:
td_unitno = td_ibuf[4];
td_block = ((td_ibuf[11] << 8) | td_ibuf[10]);
td_txsize = ((td_ibuf[9] << 8) | td_ibuf[8]);
td_state = TD_WRITE;
td_offset = 0;
sim_activate (&td_dev.units[td_unitno], td_cwait); /* sched command */
break;
case TD_CMDPOS:
sim_printf("Warning: TU58 command 'Position' not implemented\n");
break;
case TD_CMDDIA:
sim_printf("Warning: TU58 command 'Diagnose' not implemented\n");
break;
case TD_CMDMRSP: /* MRSP supported? */
csi_buf = TD_OPDAT; /* TP_OPCMD = yes, TP_OPDAT = no */
csi_csr = csi_csr | CSR_DONE; /* set input flag */
if (csi_csr & CSR_IE)
csi_int = 1;
break;
}
break;
case TD_OPINI:
sim_cancel (&td_dev.units[0]);
sim_cancel (&td_dev.units[1]);
td_ibptr = 0;
td_obptr = 0;
td_olen = 0;
td_offset = 0;
td_txsize = 0;
cso_state = TD_GETOPC;
td_state = TD_INIT;
sim_activate (&td_dev.units[0], td_iwait); /* sched command */
break;
case TD_OPBOO:
if (td_state != TD_IDLE) {
sim_printf("TU58 protocol error 3\n");
return;
}
if (td_ibptr < 2) { /* whole packet read? */
td_ilen = 2;
cso_state = TD_GETDATA; /* get rest of packet */
return;
}
td_unitno = td_ibuf[1];
td_block = 0;
td_txsize = 512;
td_state = TD_READ;
td_offset = 0;
sim_activate (&td_dev.units[td_unitno], td_cwait); /* sched command */
break;
case TD_OPCNT:
break;
default:
//sim_printf("TU58: Unknown opcode %d\n", opcode);
break;
}
sim_debug (TDDEB_OWR, &td_dev, "cstd_wr()\n");
td_wr_o_buf ((CTLR *)td_unit[0].ctlr, data);
}
/* Terminal MxPR routines
@@ -1089,199 +939,11 @@ if (sel == TXDB_MISC) { /* misc function? */
return SCPE_OK;
}
t_stat td_svc (UNIT *uptr)
{
int32 i, t, data_size;
uint16 c, w;
uint32 da;
int8 *fbuf = uptr->filebuf;
switch (td_state) { /* case on state */
case TD_IDLE: /* idle */
return SCPE_IERR; /* done */
case TD_READ: case TD_WRITE: /* read, write */
if (td_test_xfr (uptr, td_state)) { /* transfer ok? */
t = abs (td_block - 0); /* # blocks to seek */
if (t == 0) /* minimum 1 */
t = 1;
td_state++; /* set next state */
sim_activate (uptr, td_swait * t); /* schedule seek */
break;
}
else td_state = TD_END;
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_READ1: /* build data packet */
// da = CALC_DA (td_block); /* get tape address */
da = (td_block * 512) + td_offset; /* get tape address */
if (td_txsize > 128) /* Packet length */
data_size = 128;
else data_size = td_txsize;
td_txsize = td_txsize - data_size;
td_offset = td_offset + data_size;
td_obptr = 0;
td_obuf[td_obptr++] = TD_OPDAT; /* Data packet */
td_obuf[td_obptr++] = data_size; /* Data length */
for (i = 0; i < data_size; i++) /* copy sector to buf */
td_obuf[td_obptr++] = fbuf[da + i];
c = 0;
for (i = 0; i < (data_size + 2); i++) { /* Calculate checksum */
w = (td_obuf[i] << ((i & 0x1) ? 8 : 0));
c = c + w + ( (uint32)((uint32)c + (uint32)w) > 0xFFFF ? 1 : 0);
}
td_obuf[td_obptr++] = (c & 0xFF); /* Checksum L */
td_obuf[td_obptr++] = ((c >> 8) & 0xFF); /* Checksum H */
td_olen = td_obptr;
td_obptr = 0;
td_state = TD_READ2; /* go empty */
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_READ2: /* send data packet to host */
if ((csi_csr & CSR_DONE) == 0) { /* prev data taken? */
csi_buf = td_obuf[td_obptr++]; /* get next byte */
csi_csr = csi_csr | CSR_DONE; /* set input flag */
if (csi_csr & CSR_IE)
csi_int = 1;
if (td_obptr >= td_olen) { /* buffer empty? */
if (td_txsize > 0)
td_state = TD_READ1;
else
td_state = TD_END;
}
}
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_WRITE1: /* send continue */
if ((csi_csr & CSR_DONE) == 0) { /* prev data taken? */
csi_buf = TD_OPCNT;
csi_csr = csi_csr | CSR_DONE; /* set input flag */
if (csi_csr & CSR_IE)
csi_int = 1;
break;
}
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_WRITE2: /* write data to buffer */
da = (td_block * 512) + td_offset; /* get tape address */
td_olen = td_ibuf[1];
for (i = 0; i < td_olen; i++) /* write data to buffer */
fbuf[da + i] = td_ibuf[i + 2];
td_offset += td_olen;
td_txsize -= td_olen;
da = da + td_olen;
if (da > uptr->hwmark) /* update hwmark */
uptr->hwmark = da;
if (td_txsize > 0)
td_state = TD_WRITE1;
else { /* check whole number of blocks written */
if ((td_olen = (512 - (td_offset % 512)) != 512)) {
for (i = 0; i < td_olen; i++)
fbuf[da + i] = 0; /* zero fill */
da = da + td_olen;
if (da > uptr->hwmark) /* update hwmark */
uptr->hwmark = da;
}
td_state = TD_END;
}
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_END: /* build end packet */
td_obptr = 0;
td_obuf[td_obptr++] = TD_OPCMD; /* Command packet */
td_obuf[td_obptr++] = 0xA; /* ** Need definition ** */
td_obuf[td_obptr++] = TD_CMDEND;
td_obuf[td_obptr++] = td_ecode; /* Success code */
td_obuf[td_obptr++] = td_unitno; /* Unit number */
td_obuf[td_obptr++] = 0; /* Not used */
td_obuf[td_obptr++] = 0; /* Sequence L (not used) */
td_obuf[td_obptr++] = 0; /* Sequence H (not used) */
td_obuf[td_obptr++] = (td_offset & 0xFF); /* Byte count L */
td_obuf[td_obptr++] = ((td_offset >> 8) & 0xFF);/* Byte count H */
td_obuf[td_obptr++] = 0; /* Summary status L */
td_obuf[td_obptr++] = 0; /* Summary status H */
c = 0;
for (i = 0; i < (0xA + 2); i++) { /* Calculate checksum */
w = (td_obuf[i] << ((i & 0x1) ? 8 : 0));
c = c + w + ( (uint32)((uint32)c + (uint32)w) > 0xFFFF ? 1 : 0);
}
td_obuf[td_obptr++] = c & 0xFF; /* Checksum L */
td_obuf[td_obptr++] = (c >> 8) & 0xFF; /* Checksum H */
td_olen = td_obptr;
td_obptr = 0;
td_state = TD_END1; /* go empty */
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_END1: /* send end packet to host */
if ((csi_csr & CSR_DONE) == 0) { /* prev data taken? */
csi_buf = td_obuf[td_obptr++]; /* get next byte */
csi_csr = csi_csr | CSR_DONE; /* set input flag */
if (csi_csr & CSR_IE)
csi_int = 1;
if (td_obptr >= td_olen) { /* buffer empty? */
td_state = TD_IDLE;
break;
}
}
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_INIT:
if ((csi_csr & CSR_DONE) == 0) { /* prev data taken? */
csi_buf = TD_OPCNT;
csi_csr = csi_csr | CSR_DONE; /* set input flag */
if (csi_csr & CSR_IE)
csi_int = 1;
td_state = TD_IDLE;
break;
}
sim_activate (uptr, td_xwait); /* schedule next */
break;
}
return SCPE_OK;
}
/* Test for data transfer okay */
t_bool td_test_xfr (UNIT *uptr, int32 state)
{
if ((uptr->flags & UNIT_BUF) == 0) /* not buffered? */
td_ecode = TD_STSNC;
else if (td_block >= TD_NUMBLK) /* bad block? */
td_ecode = TD_STSBBN;
else if ((state == TD_WRITE) && (uptr->flags & UNIT_WPRT)) /* write and locked? */
td_ecode = TD_STSWP;
else {
td_ecode = TD_STSOK;
return TRUE;
}
return FALSE;
}
/* Reset */
t_stat td_reset (DEVICE *dptr)
{
cso_buf = 0;
cso_csr = CSR_DONE;
cso_int = 0;
cso_state = TD_GETOPC;
td_ibptr = 0;
td_obptr = 0;
td_olen = 0;
td_offset = 0;
td_txsize = 0;
sim_cancel (&td_dev.units[0]);
sim_cancel (&td_dev.units[1]);
return SCPE_OK;
return td_connect_console_device (&td_dev, set_csi_int, set_cso_int);
}
const char *td_description (DEVICE *dptr)

View File

@@ -40,6 +40,7 @@ extern DEVICE clk_dev;
extern DEVICE tmr_dev;
extern DEVICE tti_dev, tto_dev;
extern DEVICE td_dev;
extern DEVICE tdc_dev;
extern DEVICE cr_dev;
extern DEVICE lpt_dev;
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
@@ -68,6 +69,7 @@ DEVICE *sim_devices[] = {
&tti_dev,
&tto_dev,
&td_dev,
&tdc_dev,
&dz_dev,
&vh_dev,
&cr_dev,

View File

@@ -309,6 +309,8 @@ typedef struct {
#define INT_V_CR 3
#define INT_V_VHRX 4
#define INT_V_VHTX 5
#define INT_V_TDRX 6
#define INT_V_TDTX 7
#define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZTX (1u << INT_V_DZTX)
@@ -329,6 +331,8 @@ typedef struct {
#define INT_DMCTX (1u << INT_V_DMCTX)
#define INT_DUPRX (1u << INT_V_DUPRX)
#define INT_DUPTX (1u << INT_V_DUPTX)
#define INT_TDRX (1u << INT_V_TDRX)
#define INT_TDTX (1u << INT_V_TDTX)
#define IPL_DZRX (0x15 - IPL_HMIN)
#define IPL_DZTX (0x15 - IPL_HMIN)
@@ -349,6 +353,8 @@ typedef struct {
#define IPL_DMCTX (0x15 - IPL_HMIN)
#define IPL_DUPRX (0x15 - IPL_HMIN)
#define IPL_DUPTX (0x15 - IPL_HMIN)
#define IPL_TDRX (0x14 - IPL_HMIN)
#define IPL_TDTX (0x14 - IPL_HMIN)
/* Device vectors */

View File

@@ -62,6 +62,8 @@
#include "sim_tmxr.h"
#include <time.h>
#include "pdp11_td.h"
/* Terminal definitions */
#define RXCS_RD (CSR_DONE + CSR_IE) /* terminal input */
@@ -81,9 +83,6 @@
#define MISC_CLCS 0x4 /* clear cold start */
#define TXDB_SEL (TXDB_M_SEL << TXDB_V_SEL) /* non-terminal */
#define TXDB_GETSEL(x) (((x) >> TXDB_V_SEL) & TXDB_M_SEL)
#define CSTS_BRK 0x1
#define CSTS_RD (CSR_DONE + CSR_IE + CSTS_BRK) /* terminal output */
#define CSTS_WR (CSR_IE + CSTS_BRK)
static BITFIELD rx_csr_bits[] = {
BITNCF(6), /* unused */
@@ -145,63 +144,7 @@ static BITFIELD tx_buf_bits[] = {
#define TD_NUMBY 512 /* bytes/block */
#define TD_SIZE (TD_NUMBLK * TD_NUMBY) /* bytes/tape */
#define TD_OPDAT 001 /* Data */
#define TD_OPCMD 002 /* Command */
#define TD_OPINI 004 /* INIT */
#define TD_OPBOO 010 /* Bootstrap */
#define TD_OPCNT 020 /* Continue */
#define TD_OPXOF 023 /* XOFF */
#define TD_CMDNOP 0000 /* NOP */
#define TD_CMDINI 0001 /* INIT */
#define TD_CMDRD 0002 /* Read */
#define TD_CMDWR 0003 /* Write */
#define TD_CMDPOS 0005 /* Position */
#define TD_CMDDIA 0007 /* Diagnose */
#define TD_CMDGST 0010 /* Get Status */
#define TD_CMDSST 0011 /* Set Status */
#define TD_CMDMRSP 0012 /* MRSP Request */
#define TD_CMDEND 0100 /* END */
#define TD_STSOK 0000 /* Normal success */
#define TD_STSRTY 0001 /* Success with retries */
#define TD_STSFAIL 0377 /* Failed selftest */
#define TD_STSPO 0376 /* Partial operation (end of medium) */
#define TD_STSBUN 0370 /* Bad unit number */
#define TD_STSNC 0367 /* No cartridge */
#define TD_STSWP 0365 /* Write protected */
#define TD_STSDCE 0357 /* Data check error */
#define TD_STSSE 0340 /* Seek error (block not found) */
#define TD_STSMS 0337 /* Motor stopped */
#define TD_STSBOP 0320 /* Bad opcode */
#define TD_STSBBN 0311 /* Bad block number (>511) */
#define TD_GETOPC 0 /* get opcode state */
#define TD_GETLEN 1 /* get length state */
#define TD_GETDATA 2 /* get data state */
#define TD_IDLE 0 /* idle state */
#define TD_READ 1 /* read */
#define TD_READ1 2 /* fill buffer */
#define TD_READ2 3 /* empty buffer */
#define TD_WRITE 4 /* write */
#define TD_WRITE1 5 /* write */
#define TD_WRITE2 6 /* write */
#define TD_END 7 /* empty buffer */
#define TD_END1 8 /* empty buffer */
#define TD_INIT 9 /* empty buffer */
static char *td_states[] = {
"IDLE", "READ", "READ1", "READ2", "WRITE", "WRITE1", "WRITE2", "END", "END1", "INIT"
};
static char *td_ops[] = {
"NOP", "INI", "RD", "WR", "POS", "DIA", "GST", "SST", "MRSP"
};
static char *td_csostates[] = {
"GETOPC", "GETLEN", "GETDATA"
};
int32 tti_csr = 0; /* control/status */
uint32 tti_buftime; /* time input character arrived */
@@ -211,13 +154,8 @@ int32 tto_csr = 0; /* control/status */
int32 tto_buf = 0; /* buffer */
int32 tto_int = 0; /* interrupt */
int32 csi_csr = 0; /* control/status */
int32 csi_buf = 0; /* buffer */
int32 csi_int = 0; /* interrupt */
int32 cso_csr = 0; /* control/status */
int32 cso_buf = 0; /* buffer */
int32 cso_int = 0; /* interrupt */
int32 cso_state = 0; /* state */
int32 tmr_iccs = 0; /* interval timer csr */
uint32 tmr_icr = 0; /* curr interval */
@@ -235,21 +173,7 @@ struct todr_battery_info {
};
typedef struct todr_battery_info TOY;
int32 td_swait = 100; /* seek, per block */
int32 td_cwait = 150; /* command time */
int32 td_xwait = 180; /* tr set time */
int32 td_iwait = 180; /* init time */
uint8 td_ibuf[TD_NUMBY] = { 0 }; /* input buffer */
int32 td_ibptr = 0; /* input buffer pointer */
int32 td_ilen = 0; /* input length */
uint8 td_obuf[TD_NUMBY] = { 0 }; /* output buffer */
int32 td_obptr = 0; /* output buffer pointer */
int32 td_olen = 0; /* output length */
int32 td_block = 0; /* current block number */
int32 td_txsize = 0; /* remaining transfer size */
int32 td_offset = 0; /* offset into current transfer */
int32 td_state = TD_IDLE;
int32 td_ecode = 0; /* end packet success code */
int32 td_regval; /* temp location used in reg declarations */
extern jmp_buf save_env;
@@ -270,7 +194,6 @@ t_stat clk_attach (UNIT *uptr, char *cptr);
t_stat clk_detach (UNIT *uptr);
t_stat tmr_reset (DEVICE *dptr);
const char *tmr_description (DEVICE *dptr);
t_stat td_svc (UNIT *uptr);
t_stat td_reset (DEVICE *dptr);
const char *td_description (DEVICE *dptr);
int32 icr_rd (t_bool interp);
@@ -278,8 +201,6 @@ void tmr_incr (uint32 inc);
void tmr_sched (void);
t_stat todr_resync (void);
t_stat txdb_misc_wr (int32 data);
void td_process_packet();
t_bool td_test_xfr (UNIT *uptr, int32 state);
extern int32 con_halt (int32 code, int32 cc);
@@ -409,17 +330,29 @@ DEVICE tmr_dev = {
td_mod RX modifier list
*/
UNIT td_unit = { UDATA (&td_svc,
UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF, TD_SIZE) };
UNIT td_unit;
REG td_reg[] = {
{ HRDATAD (ECODE, td_ecode, 8, "end packet success code") },
{ HRDATAD (BLK, td_block, 8, "current block number") },
{ DRDATAD (PSTATE, td_state, 4, "state"), REG_RO },
{ DRDATAD (BPTR, td_obptr, 7, "output buffer pointer") },
{ DRDATAD (CTIME, td_cwait, 24, "command time"), PV_LEFT },
{ DRDATAD (STIME, td_swait, 24, "seek, per block"), PV_LEFT },
{ DRDATAD (XTIME, td_xwait, 24, "tr set time"), PV_LEFT },
{ HRDATAD (ECODE, td_regval, 8, "end packet success code") },
{ HRDATAD (BLOCK, td_regval, 8, "current block number") },
{ HRDATAD (RX_CSR, td_regval,16, "input control/status register") },
{ HRDATAD (RX_BUF, td_regval,16, "input buffer register") },
{ HRDATAD (TX_CSR, td_regval,16, "output control/status register") },
{ HRDATAD (TX_BUF, td_regval,16, "output buffer register") },
{ DRDATAD (P_STATE,td_regval, 4, "protocol state"), REG_RO },
{ DRDATAD (O_STATE,td_regval, 4, "output state"), REG_RO },
{ DRDATAD (IBPTR, td_regval, 9, "input buffer pointer") },
{ DRDATAD (OBPTR, td_regval, 9, "output buffer pointer") },
{ DRDATAD (ILEN, td_regval, 9, "input length") },
{ DRDATAD (OLEN, td_regval, 9, "output length") },
{ DRDATAD (TXSIZE, td_regval, 9, "remaining transfer size") },
{ DRDATAD (OFFSET, td_regval, 9, "offset into current transfer") },
{ DRDATAD (CTIME, td_regval,24, "command time"), PV_LEFT },
{ DRDATAD (STIME, td_regval,24, "seek, per block"), PV_LEFT },
{ DRDATAD (XTIME, td_regval,24, "tr set time"), PV_LEFT },
{ DRDATAD (ITIME, td_regval,24, "init time"), PV_LEFT },
{ BRDATAD (IBUF, &td_regval,16, 8, 512, "input buffer"), },
{ BRDATAD (OBUF, &td_regval,16, 8, 512, "output buffer"), },
{ NULL }
};
@@ -429,33 +362,6 @@ MTAB td_mod[] = {
{ 0 }
};
/* Debug detail levels */
#define TDDEB_OPS 00001 /* transactions */
#define TDDEB_IRD 00002 /* input reg reads */
#define TDDEB_ORD 00004 /* output reg reads */
#define TDDEB_RRD 00006 /* reg reads */
#define TDDEB_IWR 00010 /* input reg writes */
#define TDDEB_OWR 00020 /* output reg writes */
#define TDDEB_RWR 00030 /* reg writes */
#define TDDEB_TRC 00040 /* trace */
#define TDDEB_INT 00100 /* interrupts */
#define TDDEB_PKT 00200 /* packet */
DEBTAB td_deb[] = {
{ "OPS", TDDEB_OPS, "transactions" },
{ "PKT", TDDEB_PKT, "packet" },
{ "RRD", TDDEB_RRD, "reg reads"},
{ "IRD", TDDEB_IRD, "input reg reads" },
{ "ORD", TDDEB_ORD, "output reg reads" },
{ "RWR", TDDEB_RWR, "reg writes" },
{ "IWR", TDDEB_IWR, "input reg writes" },
{ "OWR", TDDEB_OWR, "output reg writes" },
{ "INT", TDDEB_INT, "interrupts" },
{ "TRC", TDDEB_TRC, "trace" },
{ NULL, 0 }
};
DEVICE td_dev = {
"TD", &td_unit, td_reg, td_mod,
1, DEV_RDX, 20, 1, DEV_RDX, 8,
@@ -465,6 +371,23 @@ DEVICE td_dev = {
&td_description
};
static void set_csi_int (int ctlr, t_bool val)
{
if (csi_int ^ val) {
csi_int = val;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(%d)\n", val);
}
}
static void set_cso_int (int ctlr, t_bool val)
{
if (cso_int ^ val) {
cso_int = val;
sim_debug (TDDEB_INT, &td_dev, "CSO_INT(%d)\n", val);
}
}
/* Console storage MxPR routines
csrs_rd/wr input control/status
@@ -473,260 +396,50 @@ DEVICE td_dev = {
cstd_wr output buffer
*/
#define ctlr up7
int32 csrs_rd (void)
{
sim_debug(TDDEB_IRD, &td_dev, "csrs_rd()\n");
sim_debug_bits_hdr(TDDEB_IRD, &td_dev, "RX_CSR", rx_csr_bits, csi_csr, csi_csr, 1);
return (csi_csr & RXCS_RD);
int32 data;
sim_debug (TDDEB_IRD, &td_dev, "csrs_rd()\n");
td_rd_i_csr ((CTLR *)td_unit.ctlr, &data);
return data;
}
void csrs_wr (int32 data)
{
sim_debug(TDDEB_IWR, &td_dev, "csrs_wr()\n");
sim_debug_bits_hdr(TDDEB_IWR, &td_dev, "RX_CSR", rx_csr_bits, data, data, 1);
if ((data & CSR_IE) == 0) {
csi_int = 0;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(0)\n");
}
else if ((csi_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) {
csi_int = 1;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(1)\n");
}
csi_csr = (csi_csr & ~RXCS_WR) | (data & RXCS_WR);
return;
sim_debug (TDDEB_IWR, &td_dev, "csrs_wr()\n");
td_wr_i_csr ((CTLR *)td_unit.ctlr, data);
}
int32 csrd_rd (void)
{
int32 t = csi_buf; /* char + error */
sim_debug(TDDEB_IRD, &td_dev, "csrd_rd()\n");
sim_debug_bits_hdr(TDDEB_IRD, &td_dev, "RX_BUF", rx_buf_bits, t, t, 1);
csi_csr = csi_csr & ~CSR_DONE; /* clr done */
csi_buf = csi_buf & BMASK; /* clr errors */
if (csi_int) {
csi_int = 0;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(0)\n");
}
return t;
int32 data;
sim_debug (TDDEB_IRD, &td_dev, "csrd_rd()\n");
td_rd_i_buf ((CTLR *)td_unit.ctlr, &data);
return data;
}
int32 csts_rd (void)
{
sim_debug(TDDEB_ORD, &td_dev, "csts_rd()\n");
sim_debug_bits_hdr(TDDEB_ORD, &td_dev, "TX_CSR", tx_csr_bits, cso_csr, cso_csr, 1);
return (cso_csr & TXCS_RD);
int32 data;
sim_debug (TDDEB_ORD, &td_dev, "csts_rd()\n");
td_rd_o_csr ((CTLR *)td_unit.ctlr, &data);
return data;
}
void csts_wr (int32 data)
{
sim_debug(TDDEB_OWR, &td_dev, "csts_wr()\n");
sim_debug_bits_hdr(TDDEB_OWR, &td_dev, "TX_CSR", tx_csr_bits, data, data, 1);
if ((cso_csr & CSTS_BRK) && !(data & CSTS_BRK)) {
td_ibptr = 0;
td_ibuf[td_ibptr++] = TD_OPINI;
td_process_packet(); /* check packet */
}
if ((data & CSR_IE) == 0) {
if (cso_int) {
cso_int = 0;
sim_debug (TDDEB_INT, &td_dev, "CSO_INT(0)\n");
}
}
else if ((cso_csr & (CSR_DONE + CSR_IE)) == CSR_DONE) {
cso_int = 1;
sim_debug (TDDEB_INT, &td_dev, "CSO_INT(1)\n");
}
cso_csr = (cso_csr & ~CSTS_WR) | (data & CSTS_WR);
return;
sim_debug (TDDEB_OWR, &td_dev, "csts_wr()\n");
td_wr_o_csr ((CTLR *)td_unit.ctlr, data);
}
void cstd_wr (int32 data)
{
sim_debug(TDDEB_OWR, &td_dev, "cstd_wr() state=%s, ibptr=%d, ilen=%d\n", td_csostates[cso_state], td_ibptr, td_ilen);
sim_debug_bits_hdr(TDDEB_OWR, &td_dev, "TX_BUF", tx_buf_bits, data, data, 1);
cso_buf = data & BMASK; /* save data */
cso_csr = cso_csr & ~CSR_DONE; /* clear flag */
if (cso_int) {
cso_int = 0; /* clear int */
sim_debug (TDDEB_INT, &td_dev, "CSO_INT(0)\n");
}
switch (cso_state) {
case TD_GETOPC:
td_ibptr = 0;
td_ibuf[td_ibptr++] = cso_buf;
td_process_packet(); /* check packet */
break;
case TD_GETLEN:
td_ibuf[td_ibptr++] = cso_buf;
td_ilen = cso_buf + 4; /* packet length + header + checksum */
cso_state = TD_GETDATA;
break;
case TD_GETDATA:
td_ibuf[td_ibptr++] = cso_buf;
if (td_ibptr >= td_ilen) {
cso_state = TD_GETOPC;
td_process_packet();
}
break;
}
cso_csr = cso_csr | CSR_DONE; /* set input flag */
if (cso_csr & CSR_IE) {
cso_int = 1;
sim_debug (TDDEB_INT, &td_dev, "CSO_INT(1)\n");
}
return;
}
void td_process_packet()
{
int32 opcode = td_ibuf[0];
char *opcode_name, *command_name;
switch (opcode) {
case TD_OPDAT:
opcode_name = "OPDAT";
break;
case TD_OPCMD:
opcode_name = "OPCMD";
break;
case TD_OPINI:
opcode_name = "OPINI";
break;
case TD_OPBOO:
opcode_name = "OPBOO";
break;
case TD_OPCNT:
opcode_name = "OPCNT";
break;
case TD_OPXOF:
opcode_name = "OPXOF";
break;
default:
opcode_name = "unknown";
}
sim_debug (TDDEB_TRC, &td_dev, "td_process_packet() Opcode=%s(%d)\n", opcode_name, opcode);
switch (opcode) {
case TD_OPDAT:
if (td_state != TD_WRITE1) { /* expecting data? */
sim_printf("TU58 protocol error 1\n");
return;
}
if (td_ibptr < 2) { /* whole packet read? */
cso_state = TD_GETLEN; /* get rest of packet */
return;
}
td_state = TD_WRITE2;
sim_activate (&td_unit, td_cwait); /* sched command */
break;
case TD_OPCMD:
if (td_state != TD_IDLE) { /* expecting command? */
sim_printf("TU58 protocol error 2\n");
return;
}
if (td_ibptr < 2) { /* whole packet read? */
cso_state = TD_GETLEN; /* get rest of packet */
return;
}
if (td_ibuf[2] == TD_CMDEND)
command_name = "END";
else
command_name = td_ops[td_ibuf[2]];
sim_debug (TDDEB_OPS, &td_dev, "strt: fnc=%d(%s), block=%d, size=%d\n", td_ibuf[2], command_name, ((td_ibuf[11] << 8) | td_ibuf[10]), ((td_ibuf[9] << 8) | td_ibuf[8]));
switch (td_ibuf[2]) {
case TD_CMDNOP: /* NOP */
case TD_CMDGST: /* Get status */
case TD_CMDSST: /* Set status */
td_state = TD_END; /* All treated as NOP */
td_ecode = TD_STSOK;
td_offset = 0;
sim_activate (&td_unit, td_cwait); /* sched command */
break;
case TD_CMDINI:
sim_printf("Warning: TU58 command 'INIT' not implemented\n");
break;
case TD_CMDRD:
td_block = ((td_ibuf[11] << 8) | td_ibuf[10]);
td_txsize = ((td_ibuf[9] << 8) | td_ibuf[8]);
td_state = TD_READ;
td_offset = 0;
if (td_block == 0)
td_block = td_block;
sim_activate (&td_unit, td_cwait); /* sched command */
break;
case TD_CMDWR:
td_block = ((td_ibuf[11] << 8) | td_ibuf[10]);
td_txsize = ((td_ibuf[9] << 8) | td_ibuf[8]);
td_state = TD_WRITE;
td_offset = 0;
sim_activate (&td_unit, td_cwait); /* sched command */
break;
case TD_CMDPOS:
sim_printf("Warning: TU58 command 'Position' not implemented\n");
break;
case TD_CMDDIA:
sim_printf("Warning: TU58 command 'Diagnose' not implemented\n");
break;
case TD_CMDMRSP:
csi_buf = TD_OPDAT;
csi_csr = csi_csr | CSR_DONE; /* set input flag */
if (csi_csr & CSR_IE) {
csi_int = 1;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(1)\n");
}
break;
}
break;
case TD_OPINI:
sim_cancel (&td_unit);
td_ibptr = 0;
td_obptr = 0;
td_olen = 0;
td_offset = 0;
td_txsize = 0;
cso_state = TD_GETOPC;
td_state = TD_INIT;
sim_activate (&td_unit, td_iwait); /* sched command */
break;
case TD_OPBOO:
if (td_state != TD_IDLE) {
sim_printf("TU58 protocol error 3\n");
return;
}
if (td_ibptr < 2) { /* whole packet read? */
td_ilen = 2;
cso_state = TD_GETDATA; /* get rest of packet */
return;
}
td_block = 0;
td_txsize = 512;
td_state = TD_READ;
td_offset = 0;
sim_activate (&td_unit, td_cwait); /* sched command */
break;
case TD_OPCNT:
break;
default:
//sim_printf("TU58: Unknown opcode %d\n", opcode);
break;
}
sim_debug (TDDEB_OWR, &td_dev, "cstd_wr()\n");
td_wr_o_buf ((CTLR *)td_unit.ctlr, data);
}
/* Terminal MxPR routines
@@ -824,10 +537,6 @@ tti_buf = 0;
tti_csr = 0;
tti_int = 0;
sim_activate_abs (&tti_unit, KBD_WAIT (tti_unit.wait, tmr_poll));
csi_buf = 0;
csi_csr = 0;
csi_int = 0;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(0)\n");
return SCPE_OK;
}
@@ -1224,209 +933,11 @@ if (sel == TXDB_MISC) { /* misc function? */
return SCPE_OK;
}
t_stat td_svc (UNIT *uptr)
{
int32 i, t, data_size;
uint16 c, w;
uint32 da;
int8 *fbuf = uptr->filebuf;
sim_debug (TDDEB_TRC, &td_dev, "td_svc(state=%s)\n", td_states[td_state]);
switch (td_state) { /* case on state */
case TD_IDLE: /* idle */
return SCPE_IERR; /* done */
case TD_READ: case TD_WRITE: /* read, write */
if (td_test_xfr (uptr, td_state)) { /* transfer ok? */
t = abs (td_block - 0); /* # blocks to seek */
if (t == 0) /* minimum 1 */
t = 1;
td_state++; /* set next state */
sim_activate (uptr, td_swait * t); /* schedule seek */
break;
}
else td_state = TD_END;
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_READ1: /* build data packet */
da = (td_block * 512) + td_offset; /* get tape address */
if (td_txsize > 128) /* Packet length */
data_size = 128;
else data_size = td_txsize;
td_txsize = td_txsize - data_size;
td_offset = td_offset + data_size;
td_obptr = 0;
td_obuf[td_obptr++] = TD_OPDAT; /* Data packet */
td_obuf[td_obptr++] = data_size; /* Data length */
for (i = 0; i < data_size; i++) /* copy sector to buf */
td_obuf[td_obptr++] = fbuf[da + i];
c = 0;
for (i = 0; i < (data_size + 2); i++) { /* Calculate checksum */
w = (td_obuf[i] << ((i & 0x1) ? 8 : 0));
c = c + w + ( (uint32)((uint32)c + (uint32)w) > 0xFFFF ? 1 : 0);
}
td_obuf[td_obptr++] = (c & 0xFF); /* Checksum L */
td_obuf[td_obptr++] = ((c >> 8) & 0xFF); /* Checksum H */
td_olen = td_obptr;
td_obptr = 0;
td_state = TD_READ2; /* go empty */
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_READ2: /* send data packet to host */
if ((csi_csr & CSR_DONE) == 0) { /* prev data taken? */
csi_buf = td_obuf[td_obptr++]; /* get next byte */
csi_csr = csi_csr | CSR_DONE; /* set input flag */
if (csi_csr & CSR_IE) {
csi_int = 1;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(1)\n");
}
if (td_obptr >= td_olen) { /* buffer empty? */
if (td_txsize > 0)
td_state = TD_READ1;
else
td_state = TD_END;
}
}
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_WRITE1: /* send continue */
if ((csi_csr & CSR_DONE) == 0) { /* prev data taken? */
csi_buf = TD_OPCNT;
csi_csr = csi_csr | CSR_DONE; /* set input flag */
if (csi_csr & CSR_IE) {
csi_int = 1;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(1)\n");
}
break;
}
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_WRITE2: /* write data to buffer */
da = (td_block * 512) + td_offset; /* get tape address */
td_olen = td_ibuf[1];
for (i = 0; i < td_olen; i++) /* write data to buffer */
fbuf[da + i] = td_ibuf[i + 2];
td_offset += td_olen;
td_txsize -= td_olen;
da = da + td_olen;
if (da > uptr->hwmark) /* update hwmark */
uptr->hwmark = da;
if (td_txsize > 0)
td_state = TD_WRITE1;
else { /* check whole number of blocks written */
if ((td_olen = (512 - (td_offset % 512))) != 512) {
for (i = 0; i < td_olen; i++)
fbuf[da + i] = 0; /* zero fill */
da = da + td_olen;
if (da > uptr->hwmark) /* update hwmark */
uptr->hwmark = da;
}
td_state = TD_END;
}
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_END: /* build end packet */
td_obptr = 0;
td_obuf[td_obptr++] = TD_OPCMD; /* Command packet */
td_obuf[td_obptr++] = 0xA; /* ** Need definition ** */
td_obuf[td_obptr++] = TD_CMDEND;
td_obuf[td_obptr++] = td_ecode; /* Success code */
td_obuf[td_obptr++] = 0; /* Unit number */
td_obuf[td_obptr++] = 0; /* Not used */
td_obuf[td_obptr++] = 0; /* Sequence L (not used) */
td_obuf[td_obptr++] = 0; /* Sequence H (not used) */
td_obuf[td_obptr++] = (td_offset & 0xFF); /* Byte count L */
td_obuf[td_obptr++] = ((td_offset >> 8) & 0xFF);/* Byte count H */
td_obuf[td_obptr++] = 0; /* Summary status L */
td_obuf[td_obptr++] = 0; /* Summary status H */
c = 0;
for (i = 0; i < (0xA + 2); i++) { /* Calculate checksum */
w = (td_obuf[i] << ((i & 0x1) ? 8 : 0));
c = c + w + ( (uint32)((uint32)c + (uint32)w) > 0xFFFF ? 1 : 0);
}
td_obuf[td_obptr++] = c & 0xFF; /* Checksum L */
td_obuf[td_obptr++] = (c >> 8) & 0xFF; /* Checksum H */
td_olen = td_obptr;
td_obptr = 0;
td_state = TD_END1; /* go empty */
sim_debug(TDDEB_PKT, &td_dev, "END PKT: Generated - Success Code: %X\n", td_ecode);
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_END1: /* send end packet to host */
if ((csi_csr & CSR_DONE) == 0) { /* prev data taken? */
csi_buf = td_obuf[td_obptr++]; /* get next byte */
csi_csr = csi_csr | CSR_DONE; /* set input flag */
if (csi_csr & CSR_IE) {
csi_int = 1;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(1)\n");
}
if (td_obptr >= td_olen) { /* buffer empty? */
sim_debug(TDDEB_PKT, &td_dev, "END PKT: Sent\n");
td_state = TD_IDLE;
break;
}
}
sim_activate (uptr, td_xwait); /* schedule next */
break;
case TD_INIT:
if ((csi_csr & CSR_DONE) == 0) { /* prev data taken? */
csi_buf = TD_OPCNT;
csi_csr = csi_csr | CSR_DONE; /* set input flag */
if (csi_csr & CSR_IE) {
csi_int = 1;
sim_debug (TDDEB_INT, &td_dev, "CSI_INT(1)\n");
}
td_state = TD_IDLE;
break;
}
sim_activate (uptr, td_xwait); /* schedule next */
break;
}
return SCPE_OK;
}
/* Test for data transfer okay */
t_bool td_test_xfr (UNIT *uptr, int32 state)
{
if ((uptr->flags & UNIT_BUF) == 0) /* not buffered? */
td_ecode = TD_STSNC;
else if (td_block >= TD_NUMBLK) /* bad block? */
td_ecode = TD_STSBBN;
else if ((state == TD_WRITE) && (uptr->flags & UNIT_WPRT)) /* write and locked? */
td_ecode = TD_STSWP;
else {
td_ecode = TD_STSOK;
return TRUE;
}
return FALSE;
}
/* Reset */
t_stat td_reset (DEVICE *dptr)
{
cso_buf = 0;
cso_csr = CSR_DONE;
cso_int = 0;
sim_debug (TDDEB_INT, &td_dev, "CSO_INT(0)\n");
cso_state = TD_GETOPC;
td_ibptr = 0;
td_obptr = 0;
td_olen = 0;
td_offset = 0;
td_txsize = 0;
sim_cancel (&td_unit);
return SCPE_OK;
return td_connect_console_device (&td_dev, set_csi_int, set_cso_int);
}
const char *td_description (DEVICE *dptr)

View File

@@ -41,6 +41,7 @@ extern DEVICE clk_dev;
extern DEVICE tmr_dev;
extern DEVICE tti_dev, tto_dev;
extern DEVICE td_dev;
extern DEVICE tdc_dev;
extern DEVICE cr_dev;
extern DEVICE lpt_dev;
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
@@ -73,6 +74,7 @@ DEVICE *sim_devices[] = {
&tti_dev,
&tto_dev,
&td_dev,
&tdc_dev,
&dz_dev,
&vh_dev,
&cr_dev,

View File

@@ -323,6 +323,8 @@ typedef struct {
#define INT_V_CR 3
#define INT_V_VHRX 4
#define INT_V_VHTX 5
#define INT_V_TDRX 6
#define INT_V_TDTX 7
#define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZTX (1u << INT_V_DZTX)
@@ -343,6 +345,8 @@ typedef struct {
#define INT_DMCTX (1u << INT_V_DMCTX)
#define INT_DUPRX (1u << INT_V_DUPRX)
#define INT_DUPTX (1u << INT_V_DUPTX)
#define INT_TDRX (1u << INT_V_TDRX)
#define INT_TDTX (1u << INT_V_TDTX)
#define IPL_DZRX (0x15 - IPL_HMIN)
#define IPL_DZTX (0x15 - IPL_HMIN)
@@ -363,6 +367,8 @@ typedef struct {
#define IPL_DMCTX (0x15 - IPL_HMIN)
#define IPL_DUPRX (0x15 - IPL_HMIN)
#define IPL_DUPTX (0x15 - IPL_HMIN)
#define IPL_TDRX (0x14 - IPL_HMIN)
#define IPL_TDTX (0x14 - IPL_HMIN)
/* Device vectors */

View File

@@ -48,6 +48,7 @@ extern DEVICE clk_dev;
extern DEVICE tmr_dev;
extern DEVICE tti_dev, tto_dev;
extern DEVICE fl_dev;
extern DEVICE tdc_dev;
extern DEVICE cr_dev;
extern DEVICE lpt_dev;
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
@@ -81,6 +82,7 @@ DEVICE *sim_devices[] = {
&tti_dev,
&tto_dev,
&fl_dev,
&tdc_dev,
&dz_dev,
&vh_dev,
&cr_dev,

View File

@@ -353,6 +353,8 @@ typedef struct {
#define INT_V_CR 3
#define INT_V_VHRX 4
#define INT_V_VHTX 5
#define INT_V_TDRX 6
#define INT_V_TDTX 7
#define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZTX (1u << INT_V_DZTX)
@@ -373,6 +375,8 @@ typedef struct {
#define INT_DMCTX (1u << INT_V_DMCTX)
#define INT_DUPRX (1u << INT_V_DUPRX)
#define INT_DUPTX (1u << INT_V_DUPTX)
#define INT_TDRX (1u << INT_V_TDRX)
#define INT_TDTX (1u << INT_V_TDTX)
#define IPL_DZRX (0x15 - IPL_HMIN)
#define IPL_DZTX (0x15 - IPL_HMIN)
@@ -393,6 +397,8 @@ typedef struct {
#define IPL_DMCTX (0x15 - IPL_HMIN)
#define IPL_DUPRX (0x15 - IPL_HMIN)
#define IPL_DUPTX (0x15 - IPL_HMIN)
#define IPL_TDRX (0x14 - IPL_HMIN)
#define IPL_TDTX (0x14 - IPL_HMIN)
/* Device vectors */

View File

@@ -48,6 +48,7 @@ extern DEVICE clk_dev;
extern DEVICE tmr_dev;
extern DEVICE tti_dev, tto_dev;
extern DEVICE rlcs_dev;
extern DEVICE tdc_dev;
extern DEVICE cr_dev;
extern DEVICE lpt_dev;
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
@@ -79,6 +80,7 @@ DEVICE *sim_devices[] = {
&tti_dev,
&tto_dev,
&rlcs_dev,
&tdc_dev,
&dz_dev,
&vh_dev,
&cr_dev,

View File

@@ -46,6 +46,7 @@ extern DEVICE nvr_dev;
extern DEVICE sysd_dev;
extern DEVICE qba_dev;
extern DEVICE tti_dev, tto_dev;
extern DEVICE tdc_dev;
extern DEVICE cr_dev;
extern DEVICE lpt_dev;
extern DEVICE clk_dev;
@@ -77,6 +78,7 @@ DEVICE *sim_devices[] = {
&tto_dev,
&csi_dev,
&cso_dev,
&tdc_dev,
&dz_dev,
&vh_dev,
&cr_dev,

View File

@@ -344,6 +344,8 @@ typedef struct {
#define INT_V_QVSS 21 /* QVSS */
#define INT_V_DMCRX 22 /* DMC11 */
#define INT_V_DMCTX 23
#define INT_V_TDRX 24 /* TU58 */
#define INT_V_TDTX 25
#define INT_CLK (1u << INT_V_CLK)
#define INT_RQ (1u << INT_V_RQ)
@@ -370,6 +372,8 @@ typedef struct {
#define INT_QVSS (1u << INT_V_QVSS)
#define INT_DMCRX (1u << INT_V_DMCRX)
#define INT_DMCTX (1u << INT_V_DMCTX)
#define INT_TDRX (1u << INT_V_TDRX)
#define INT_TDTX (1u << INT_V_TDTX)
#define IPL_CLK (0x16 - IPL_HMIN) /* relative IPL */
#define IPL_RQ (0x14 - IPL_HMIN)
@@ -396,6 +400,8 @@ typedef struct {
#define IPL_QVSS (0x14 - IPL_HMIN)
#define IPL_DMCRX (0x14 - IPL_HMIN)
#define IPL_DMCTX (0x14 - IPL_HMIN)
#define IPL_TDRX (0x14 - IPL_HMIN)
#define IPL_TDTX (0x14 - IPL_HMIN)
#define IPL_HMAX 0x17 /* highest hwre level */
#define IPL_HMIN 0x14 /* lowest hwre level */