PDP10,PDP11,VAX: Addition of inter operable DUP11, DMC11 and KDP11 devices

This is the results of external KDP development activities.  The KDP side done by Timothe Litt and DMC and DUP by Mark Pizzolato

Additionally, other PDP10 updates from Timothe Litt
This commit is contained in:
Mark Pizzolato 2013-11-25 07:00:17 -08:00
parent a7c2d7bf35
commit 55c5d20517
28 changed files with 7817 additions and 2627 deletions

View file

@ -115,7 +115,8 @@ typedef t_int64 d10; /* PDP-10 data (36b) */
#define STOP_ILLIOC 10 /* invalid UBA num */
#define STOP_ASTOP 11 /* address stop */
#define STOP_CONSOLE 12 /* FE halt */
#define STOP_UNKNOWN 13 /* unknown stop */
#define STOP_IOALIGN 13 /* DMA word access to odd address */
#define STOP_UNKNOWN 14 /* unknown stop */
#define PAGE_FAIL -1 /* page fail */
#define INTERRUPT -2 /* interrupt */
#define ABORT(x) longjmp (save_env, (x)) /* abort */
@ -614,6 +615,10 @@ struct pdp_dib {
int32 vec; /* value */
int32 (*ack[VEC_DEVMAX])(void); /* ack routines */
uint32 ulnt; /* IO length per unit */
uint32 flags; /* Special flags */
#define DIB_M_REGSIZE 03 /* Device register size */
#define DIB_REG16BIT 00
#define DIB_REG18BIT 01
};
typedef struct pdp_dib DIB;
@ -622,6 +627,8 @@ typedef struct pdp_dib DIB;
#define DZ_MUXES 4 /* max # of muxes */
#define DZ_LINES 8 /* lines per mux */
#define KMC_UNITS 1 /* max # of KMCs */
#define INITIAL_KMCS 0 /* Number initially enabled */
#define DUP_LINES 4 /* max # of DUP11's */
#define DIB_MAX 100 /* max DIBs */
@ -700,9 +707,10 @@ typedef struct pdp_dib DIB;
#define INT_V_RP 6 /* RH11/RP,RM drives */
#define INT_V_TU 7 /* RH11/TM03/TU45 */
#define INT_V_DMCRX 13
#define INT_V_DMCTX 14
#define INT_V_XU 15 /* DEUNA/DELUA */
#define INT_V_KMCA 8 /* KMC11 */
#define INT_V_KMCB 9
#define INT_V_DMCRX 8 /* DMC11/DMR11 */
#define INT_V_DMCTX 9
#define INT_V_DZRX 16 /* DZ11 */
#define INT_V_DZTX 17
#define INT_V_RY 18 /* RX211 */
@ -715,6 +723,8 @@ typedef struct pdp_dib DIB;
#define INT_RP (1u << INT_V_RP)
#define INT_TU (1u << INT_V_TU)
#define INT_KMCA (1u << INT_V_KMCA)
#define INT_KMCB (1u << INT_V_KMCB)
#define INT_DMCRX (1u << INT_V_DMCRX)
#define INT_DMCTX (1u << INT_V_DMCTX)
#define INT_XU (1u << INT_V_XU)
@ -730,8 +740,8 @@ typedef struct pdp_dib DIB;
#define IPL_RP 6 /* int levels */
#define IPL_TU 6
#define IPL_DMCRX 5
#define IPL_DMCTX 5
#define IPL_KMCA 5
#define IPL_KMCB 5
#define IPL_XU 5
#define IPL_DZRX 5
#define IPL_DZTX 5
@ -759,8 +769,6 @@ typedef struct pdp_dib DIB;
#define VEC_CR 0230
#define VEC_RP 0254
#define VEC_RY 0264
#define VEC_DZRX 0340
#define VEC_DZTX 0344
#define VEC_LP20 0754
#define VEC_AUTO 0 /* Set by Auto Configure */

View file

@ -265,8 +265,8 @@ if (M[FE_KEEPA] & INT64_C(0020000000000)) { /* KSRLD - "Forced" (ac
}
else if (M[FE_KEEPA] & INT64_C(0010000000000)) { /* KPACT */
d10 kav = M[FE_KEEPA] & INT64_C(0000000177400); /* KPALIV */
if (kaf_unit.u3 != (uint32)kav) {
kaf_unit.u3 = (uint32)kav;
if (kaf_unit.u3 != (int32)kav) {
kaf_unit.u3 = (int32)kav;
kaf_unit.u4 = 0;
}
else if (++kaf_unit.u4 >= 15) {

View file

@ -43,7 +43,8 @@
The KS10 uses the PDP-11 Unibus for its I/O, via adapters. While
nominally four adapters are supported, in practice only 1 and 3
are implemented. The disks are placed on adapter 1, the rest of
the I/O devices on adapter 3.
the I/O devices on adapter 3. (adapter 4 IS used in some supported
configurations, but those devices haven't been emulated yet.)
In theory, we should maintain completely separate Unibuses, with
distinct PI systems. In practice, this simulator has so few devices
@ -71,6 +72,7 @@
#include "pdp10_defs.h"
#include <setjmp.h>
#include <assert.h>
#include "sim_sock.h"
#include "sim_tmxr.h"
@ -91,8 +93,8 @@
((op == WRITEB)? PF_BYTE: 0) | \
(TSTF (F_USR)? PF_USER: 0) | (pa); \
ABORT (PAGE_FAIL)
/* Is Unibus address mapped to host memory */
#define HOST_MAPPED(ub,ba) ((ubmap[ub][PAG_GETVPN(((ba) & 0777777) >> 2)] & UMAP_VLD) != 0)
/* Is Unibus address mapped to -10 memory */
#define TEN_MAPPED(ub,ba) ((ubmap[ub][PAG_GETVPN(((ba) & 0777777) >> 2)] & UMAP_VLD) != 0)
/* Translate UBA number in a PA to UBA index. 1,,* -> ubmap[0], all others -> ubmap[1] */
#define ADDR2UBA(x) (iocmap[GET_IOUBA (x)])
@ -100,7 +102,7 @@
/* Unibus adapter data */
int32 ubcs[UBANUM] = { 0 }; /* status registers */
int32 ubmap[UBANUM][UMAP_MEMSIZE] = { 0 }; /* Unibus maps */
int32 ubmap[UBANUM][UMAP_MEMSIZE] = {{ 0 }}; /* Unibus maps */
int32 int_req = 0; /* interrupt requests */
int32 autcon_enb = 1; /* auto configure enabled */
@ -118,7 +120,41 @@ static const int32 ubabr76[UBANUM] = {
static const int32 ubabr54[UBANUM] = {
INT_UB1 & (INT_IPL5 | INT_IPL4), INT_UB3 & (INT_IPL5 | INT_IPL4)
};
static const int32 ubashf[4] = { 18, 26, 0, 8 };
/* Masks for Unibus quantities */
#define M_BYTE (0xFF)
#define M_WORD (0xFFFF)
#define M_WORD18 (0777777)
#define M_LH (0777777000000)
#define M_RH (0000000777777)
/* Bits to shift for each Unibus byte */
#define V_BYTE0 (18)
#define V_BYTE1 (26)
#define V_BYTE2 (0)
#define V_BYTE3 (8)
#define V_WORD0 V_BYTE0
#define V_WORD1 V_BYTE2
#if 0
static const int32 ubashf[4] = { V_BYTE0, V_BYTE1, V_BYTE2, V_BYTE3 };
#endif
/* Bits to preserve when writing each Unibus byte.
* This excludes the XX bits so they are cleared.
*/
#define M_BYTE0 (~INT64_C (0000377000000)) /* Clear byte 0 */
#define M_BYTE1 (~INT64_C (0777400000000)) /* Clear byte 1 + XX */
#define M_BYTE2 (~INT64_C (0000000000377)) /* Clear byte 2 */
#define M_BYTE3 (~INT64_C (0000000777400)) /* Clear byte 3 + XX */
#define M_WORD0 (~INT64_C (0777777000000)) /* Clear word 0 + XX */
#define M_WORD1 (~INT64_C (0000000777777)) /* Clear word 1 + XX */
#if 0
static const d10 ubamask[4] = { M_BYTE0, M_BYTE1, M_BYTE2, M_BYTE3 };
#endif
extern d10 *M; /* main memory */
extern d10 *ac_cur;
@ -254,7 +290,7 @@ return ReadIO (ea); /* RDIO, IORD */
void io713 (d10 val, a10 ea)
{
WriteIO (ea, val & 0177777, WRITE); /* WRIO, IOWR */
WriteIO (ea, val, WRITE); /* WRIO, IOWR */
return;
}
@ -266,7 +302,6 @@ void io714 (d10 val, a10 ea)
{
d10 temp;
val = val & 0177777;
if (Q_ITS) /* IOWRI */
WriteIO (IO_UBA3 | ea, val, WRITE);
else {
@ -285,7 +320,6 @@ void io715 (d10 val, a10 ea)
{
d10 temp;
val = val & 0177777;
if (Q_ITS) /* IOWRQ */
WriteIO (IO_UBA1 | ea, val, WRITE);
else {
@ -358,7 +392,7 @@ return GETBYTE (ea, val);
void io723 (d10 val, a10 ea)
{
WriteIO (ea, val & 0377, WRITEB); /* WRIOB, IOWRB */
WriteIO (ea, val & M_BYTE, WRITEB); /* WRIOB, IOWRB */
return;
}
@ -370,7 +404,7 @@ void io724 (d10 val, a10 ea)
{
d10 temp;
val = val & 0377;
val = val & M_BYTE;
if (Q_ITS) /* IOWRBI */
WriteIO (IO_UBA3 | ea, val, WRITEB);
else {
@ -390,7 +424,7 @@ void io725 (d10 val, a10 ea)
{
d10 temp;
val = val & 0377;
val = val & M_BYTE;
if (Q_ITS) /* IOWRBQ */
WriteIO (IO_UBA1 | ea, val, WRITEB);
else {
@ -407,6 +441,13 @@ return;
simulator and the 32b world of the device simulators.
*/
/* UBReadIO and UBWriteIO handle the device lookup and access
* These are used for all IO space accesses. They return status.
*
* ReadIO and WriteIO are used by the CPU instructions, and generate
* UBA NXM page fails for unassigned IO addresses.
*/
static t_stat UBReadIO (int32 *data, int32 ba, int32 access)
{
uint32 pa = (uint32) ba;
@ -445,6 +486,9 @@ DIB *dibp;
for (i = 0; (dibp = dib_tab[i]); i++ ) {
if ((pa >= dibp->ba) &&
(pa < (dibp->ba + dibp->lnt))) {
if ((dibp->flags & DIB_M_REGSIZE) == DIB_REG16BIT) {
data &= M_WORD;
}
dibp->wr (data, ba, access);
pi_eval ();
return SCPE_OK;
@ -465,10 +509,10 @@ UBNXM_FAIL (pa, mode);
/* Mapped read and write routines - used by standard Unibus devices on Unibus 1
* I/O space accesses will work. Note that Unibus addresses with bit 17 set can
* not be mapped by the UBA, so I/O space (and more) can not be mapped to host memory.
* not be mapped by the UBA, so I/O space (and more) can not be mapped to -10 memory.
*/
a10 Map_Addr10 (a10 ba, int32 ub, int32 *ubmp)
static a10 Map_Addr10 (a10 ba, int32 ub, int32 *ubmp)
{
a10 pa10;
int32 vpn = PAG_GETVPN (ba >> 2); /* get PDP-10 page number */
@ -489,13 +533,90 @@ pa10 = (ubm + PAG_GETOFF (ba >> 2)) & PAMASK;
return pa10;
}
/* Routines for Bytes, Words (16-bit) and Words (18-bit).
*
* Note that the byte count argument is always BYTES, even if
* the unit transfered is a word. This is for compatibility with
* the 11/VAX system Unibus; these routines abstract DMA for all
* U/Q device simulations.
*
* All return the number of bytes NOT transferred; 0 means success.
* A non-zero return implies a NXM was encountered.
*
* Unaligned accesses to 16/18-bit words in IOSPACE are a STOP condition.
* (Should be in memory too, but some devices are lazy.)
*
* Unibus memory is mapped into 36-bit words so that 16-bit
* values appear in 18-bit half-words, and PDP10 byte pointers will
* increment through 16-bit (but not 8-bit) data. Viewed as bytes or
* words from the PDP10, memory looks like this:
*
* +-----+-----------+------------+-------+------------+------------+
* | 0 1 | 2 9 | 10 17 | 18 19 | 20 27| 28 35 | PDP10 bits
* +-----+-----------+------------+-------+------------+------------+
* | X X | BYTE 1<01>| BYTE 0<00> | X X | BYTE 3<11> | BYTE 2<10> | PDP11 bytes
* +-----+-----------+------------+-------+------------+------------+
* | X X | WORD 0 <00> | X X | WORD 1 <10> | PDP11 words
* +-----+-----------+------------+-------+------------+------------+
*
* <nn> are the values of the two low-order address bits as viewed on
* the Unibus.
*
* The bits marked XX are written as zero for 8 and 16 bit transfers
* and with data from the Unibus parity lines for 18 bit transfers.
* In a -10 read-modify-write cycle, they are cleared if the high byte
* of the adjacent word is written, and preserved otherwise.
*
* Unibus addressing does not change with 18-bit transfers; they are
* accounted for as 2 bytes. <0:1> are bits <17:16> of word 0;
* <18:19> are bits <17:16> of word 1.
*
* Normal writes assume that DMA will access sequential Unibus addresses.
* The UBA optimizes this by writing NPR data to <00> addresses
* without preserving the rest of the -10 word. This allows a memory
* write cycle, rather than the read-modify-write cycle required to
* preserve the rest of the word. The 'read reverse' bit in the UBA
* map forces a read-modify-write on all addresses.
*
* 16-bit transfers (the d18 bit in the map selects) write 0s into
* the correspnding X bits when <00> or <10> are written.
*
* Address mapping uses bits <1:0> of the Unibus address to select
* the byte as indicated above. Bits <10:2> are the offset within
* the PDP10 page; thus Unibus addressing assumes 4 bytes/PDP10 word.
*
* 9 bits = 512 words/PDP10 page = 2048 bytes / Unibus page
*
* Bits 16:11 select a UBA mapping register, which indicates whether
* PDP10 memory at that address is accessible, and if so, provides
* PDP10 bus address bits that replace and extend the Unibus bits.
*
* Unibus addresses with bit 17 set do not map PDP10 memory. The
* high end is reserved for Unibus IO space. The rest is used for
* UBA maintenance modes (not simulated).
*
* IO space accesses may have side effects in the device; an aligned
* read of two bytes is NOT equivalent to two one byte reads of the
* same addresses.
*
* The memory access in these routines is optimized to minimize UBA
* page table lookups and shift/merge operations with PDP10 memory.
*
* Memory transfers happen in up to 3 pieces:
* head : 0-3 bytes to an aligned PDP10 word (UB address 000b)
* body : As many PDP10 whole words as possible (4 bytes 32/36 bits)
* tail : 0-3 bytes remaining after the body.
*/
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf)
{
uint32 lim, cp, np;
a10 pa10;
uint32 ea, ofs, cp, np;
int32 seg;
a10 pa10 = ~0u;
d10 m;
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
{ /* IOPAGE: device register read */
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000) {
/* IOPAGE: device register read */
int32 csr;
while (bc) {
@ -507,34 +628,120 @@ if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
}
return bc;
}
lim = ba + bc;
for ( cp = ~ba ; ba < lim; ba++) { /* by bytes */
/* Memory */
if (bc == 0)
return 0;
cp = ~ba;
ofs = ba & 3;
seg = (4 - ofs) & 3;
if (seg) { /* Unaligned head */
if (seg > bc)
seg = bc;
cp = UBMPAGE (ba); /* Only one word, can't cross page */
pa10 = Map_Addr10 (ba, 1, NULL); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return bc; /* return bc */
}
m = M[pa10++];
ba += seg;
bc -= seg;
switch (ofs) {
case 1:
*buf++ = (uint8) ((m >> V_BYTE1) & M_BYTE);
if (!--seg)
break;
case 2:
*buf++ = (uint8) (m & M_BYTE); /* V_BYTE2 */
if (!--seg)
break;
case 3:
*buf++ = (uint8) ((m >> V_BYTE3) & M_BYTE);
--seg;
break;
default:
assert (FALSE);
}
if (bc == 0)
return 0;
} /* Head */
/* At this point, ba is aligned. Therefore, ea<1:0> are the tail's length */
ea = ba + bc;
seg = bc - (ea & 3);
if (seg > 0) { /* Body: Whole PDP-10 words, 4 bytes */
assert (((seg & 3) == 0) && (bc >= seg));
bc -= seg;
for ( ; seg; seg -= 4, ba += 4) { /* aligned longwords */
np = UBMPAGE (ba);
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, NULL); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */
return (lim - ba); /* return bc */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc + seg); /* return bc */
}
cp = np;
}
*buf++ = (uint8) ((M[pa10] >> ubashf[ba & 3]) & 0377);
if ((ba & 3) == 3)
pa10++;
m = M[pa10++]; /* Next word from -10 */
buf[2] = (uint8) (m & M_BYTE); /* Byte 2 */
m >>= 8;
buf[3] = (uint8) (m & M_BYTE); /* Byte 3 */
m >>= 10;
buf[0] = (uint8) (m & M_BYTE); /* Byte 0 */
m >>= 8;
buf[1] = (uint8) (m & M_BYTE); /* Byte 1 */
buf += 4;
}
} /* Body */
/* Tail: partial -10 word, must be aligned. 1-3 bytes */
assert ((bc >= 0) && ((ba & 3) == 0));
if (bc) {
assert (bc <= 3);
np = UBMPAGE (ba); /* Only one word, last possible page crossing */
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, NULL); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) {/* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc); /* return bc */
}
}
m = M[pa10];
switch (bc) {
case 3:
buf[2] = (uint8) (m & M_BYTE); /* V_BYTE2 */
case 2:
buf[1] = (uint8) ((m >> V_BYTE1) & M_BYTE);
case 1:
buf[0] = (uint8) ((m >> V_BYTE0) & M_BYTE);
break;
default:
assert (FALSE);
}
}
return 0;
}
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf)
{
uint32 lim, cp, np;
a10 pa10;
uint32 ea, cp, np;
int32 seg;
a10 pa10 = ~0u;
d10 m;
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
{ /* IOPAGE: device register read */
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000) {
/* IOPAGE: device register read */
int32 csr;
if ((ba & 1) || (bc & 1))
return bc;
if ((ba | bc) & 1)
ABORT (STOP_IOALIGN);
while (bc) {
if (UBReadIO (&csr, ba, READ) != SCPE_OK)
break;
@ -544,37 +751,97 @@ if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
}
return bc;
}
ba = ba & ~01; /* align start */
lim = ba + (bc & ~01);
for ( cp = ~ba; ba < lim; ba = ba + 2) { /* by words */
/* Memory */
if (bc == 0)
return 0;
ba &= ~1;
if (bc & 1)
ABORT (STOP_IOALIGN);
cp = ~ba;
seg = (4 - (ba & 3)) & 3;
if (seg) { /* Unaligned head, can only be WORD1 */
assert ((ba & 2) && (seg == 2));
if (seg > bc)
seg = bc;
cp = UBMPAGE (ba); /* Only one word, can't cross page */
pa10 = Map_Addr10 (ba, 1, NULL); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return bc; /* return bc */
}
ba += seg;
*buf++ = (uint16) (M[pa10++] & M_WORD);
if ((bc -= seg) == 0)
return 0;
} /* Head */
ea = ba + bc;
seg = bc - (ea & 3);
if (seg > 0) {
assert (((seg & 3) == 0) && (bc >= seg));
bc -= seg;
for ( ; seg; seg -= 4, ba += 4) { /* aligned longwords */
np = UBMPAGE (ba);
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, NULL); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */
return (lim - ba); /* return bc */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc + seg); /* return bc */
}
cp = np;
}
*buf++ = (uint16) ((M[pa10] >> ((ba & 2)? 0: 18)) & 0177777);
if (ba & 2 )
pa10++;
m = M[pa10++]; /* Next word from -10 */
buf[1] = (uint16) (m & M_WORD); /* Bytes 3,,2 */
m >>= 18;
buf[0] = (uint16) (m & M_WORD); /* Bytes 1,,0 */
buf += 2;
}
} /* Body */
/* Tail: partial word, must be aligned, can only be WORD0 */
assert ((bc >= 0) && ((ba & 3) == 0));
if (bc) {
assert (bc == 2);
np = UBMPAGE (ba); /* Only one word, last possible page crossing */
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, NULL); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) {/* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc); /* return bc */
}
}
*buf = (uint16) ((M[pa10] >> V_WORD0) & M_WORD);
}
return 0;
}
/* Word reads returning 18-bit data */
/* Word reads returning 18-bit data
*
* Identical to 16-bit reads except that buffer is uint32
* and masked to 18 bits.
*/
int32 Map_ReadW18 (uint32 ba, int32 bc, uint32 *buf)
{
uint32 lim, cp, np;
a10 pa10;
uint32 ea, cp, np;
int32 seg;
a10 pa10 = ~0u;
d10 m;
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
{ /* IOPAGE: device register read */
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000) {
/* IOPAGE: device register read */
int32 csr;
if ((ba & 1) || (bc & 1))
return bc;
if ((ba | bc) & 1)
ABORT (STOP_IOALIGN);
while (bc) {
if (UBReadIO (&csr, ba, READ) != SCPE_OK)
break;
@ -584,22 +851,74 @@ if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
}
return bc;
}
ba = ba & ~01; /* align start */
lim = ba + (bc & ~01);
for ( cp = ~ba; ba < lim; ba = ba + 2) { /* by words */
/* Memory */
if (bc == 0)
return 0;
ba &= ~1;
if (bc & 1)
ABORT (STOP_IOALIGN);
cp = ~ba;
seg = (4 - (ba & 3)) & 3;
if (seg) { /* Unaligned head */
assert ((ba & 2) && (seg == 2));
if (seg > bc)
seg = bc;
cp = UBMPAGE (ba); /* Only one word, can't cross page */
pa10 = Map_Addr10 (ba, 1, NULL); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return bc; /* return bc */
}
ba += seg;
*buf++ = (uint32) (M[pa10++] & M_RH);
if ((bc -= seg) == 0)
return 0;
} /* Head */
ea = ba + bc;
seg = bc - (ea & 3);
if (seg > 0) {
assert (((seg & 3) == 0) && (bc >= seg));
bc -= seg;
for ( ; seg; seg -= 4, ba += 4) { /* aligned longwords */
np = UBMPAGE (ba);
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, NULL); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */
return (lim - ba); /* return bc */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc + seg); /* return bc */
}
cp = np;
}
*buf++ = (uint32) ((M[pa10] >> ((ba & 2)? 0: 18)) & 0777777);
if (ba & 2 )
pa10++;
m = M[pa10++]; /* Next word from -10 */
buf[1] = (uint32) (m & M_RH); /* Bytes 3,,2 */
m >>= 18;
buf[0] = (uint32) (m & M_RH); /* Bytes 1,,0 */
buf += 2;
}
} /* Body */
/* Tail: partial word, must be aligned */
assert ((bc >= 0) && ((ba & 3) == 0));
if (bc) {
assert (bc == 2);
np = UBMPAGE (ba); /* Only one word, last possible page crossing */
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, NULL); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc); /* return bc */
}
}
*buf++ = (uint32) ((M[pa10] >> V_WORD0) & M_RH);
}
return 0;
}
@ -607,12 +926,14 @@ return 0;
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf)
{
uint32 lim, cp, np;
a10 pa10;
d10 mask;
uint32 ea, ofs, cp, np;
int32 seg, ubm = 0;
a10 pa10 = ~0u;
d10 m;
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000) {
/* IOPAGE: device register write */
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
{ /* IOPAGE: device register write */
while (bc) {
if (UBWriteIO (*buf++ & 0xff, ba, WRITEB) != SCPE_OK)
break;
@ -621,28 +942,117 @@ if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
}
return bc;
}
lim = ba + bc;
for ( cp = ~ba; ba < lim; ba++) { /* by bytes */
/* Memory */
if (bc == 0)
return 0;
cp = ~ba;
ofs = ba & 3;
seg = (4 - ofs) & 3;
if (seg) { /* Unaligned head */
if (seg > bc)
seg = bc;
cp = UBMPAGE (ba); /* Only one word, can't cross page */
pa10 = Map_Addr10 (ba, 1, &ubm); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return bc; /* return bc */
}
m = M[pa10];
ba += seg;
bc -= seg;
switch (ofs) {
case 1:
m = (m & M_BYTE1) | (((d10) (*buf++)) << V_BYTE1);
if (!--seg)
break;
case 2:
m = (m & M_BYTE2) | ((d10) (*buf++)); /* V_BYTE2 */
if (!--seg)
break;
case 3:
m = (m & M_BYTE3) | (((d10) (*buf++)) << V_BYTE3);
--seg;
break;
default:
assert (FALSE);
}
M[pa10++] = m;
if (bc == 0)
return 0;
} /* Head */
ea = ba + bc;
seg = bc - (ea & 3);
if (seg > 0) {
assert (((seg & 3) == 0) && (bc >= seg));
bc -= seg;
for ( ; seg; seg -= 4, ba += 4) { /* aligned longwords */
np = UBMPAGE (ba);
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, NULL); /* map addr */
pa10 = Map_Addr10 (ba, 1, &ubm); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */
return (lim - ba); /* return bc */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc + seg); /* return bc */
}
cp = np;
}
if( (ba&3) == 0 ) { /* byte 0 writes memory; other bytes & <0:1,18:19> of M[] are undefined. */
M[pa10] = ((d10) *buf++) << 18; /* Clears undefined bits */
} else { /* RPW - clear byte position, and UB<17:16> of correct 1/2 word when writing high byte */
mask = 0377<< ubashf[ba & 3];
if (ba & 1)
mask |= INT64_C(0000000600000) << ((ba & 2)? 0 : 18);
M[pa10] = (M[pa10] & ~mask) | (((d10) *buf++) << ubashf[ba & 3]);
if ((ba & 3) == 3)
pa10++;
M[pa10++] = (((d10)((buf[1] << 8) | buf[0])) << 18) | /* <0:1,18:19> = 0 */
((buf[3] << 8) | buf[2]);
buf += 4;
}
} /* Body */
/* Tail: partial word, must be aligned */
assert ((bc >= 0) && ((ba & 3) == 0));
if (bc) {
assert (bc <= 3);
np = UBMPAGE (ba); /* Only one word, last possible page crossing */
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, &ubm); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc); /* return bc */
}
}
m = M[pa10];
if ((ubm & UMAP_RRV )) { /* RMW */
switch (bc) {
case 3:
m = (m & M_BYTE2) | ((d10) (buf[2])); /* V_BYTE2 */
case 2:
m = (m & M_BYTE1) | (((d10) (buf[1])) << V_BYTE1);
case 1:
m = (m & M_BYTE0) | (((d10) (buf[0])) << V_BYTE0);
break;
default:
assert (FALSE);
}
}
else {
switch (bc) { /* Write byte 0 + RMW bytes 1 & 2 */
case 3:
m = (((d10) (buf[1])) << V_BYTE1) | (((d10) (buf[0])) << V_BYTE0) |
((d10) (buf[2])); /* V_BYTE2 */
break;
case 2:
m = (((d10) (buf[1])) << V_BYTE1) | (((d10) (buf[0])) << V_BYTE0);
break;
case 1:
m = ((d10) (buf[0])) << V_BYTE0;
break;
default:
assert (FALSE);
}
}
M[pa10] = m;
}
return 0;
}
@ -650,15 +1060,16 @@ return 0;
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf)
{
uint32 lim, cp, np;
int32 ubm;
a10 pa10;
d10 val;
uint32 ea, cp, np;
int32 seg, ubm = 0;
a10 pa10 = ~0u;
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000) {
/* IOPAGE: device register write */
if ((ba | bc) & 1)
ABORT (STOP_IOALIGN);
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
{ /* IOPAGE: device register write */
if ((ba & 1) || (bc &1))
return bc;
while (bc) {
if (UBWriteIO (*buf++ & 0xffff, ba, WRITE) != SCPE_OK)
break;
@ -667,33 +1078,78 @@ if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
}
return bc;
}
ba = ba & ~01; /* align start */
lim = ba + (bc & ~01);
for ( cp = ~ba; ba < lim; ba+= 2) { /* by words */
/* Memory */
if (bc == 0)
return 0;
ba &= ~1;
if (bc & 1)
ABORT (STOP_IOALIGN);
cp = ~ba;
seg = (4 - (ba & 3)) & 3;
if (seg) { /* Unaligned head */
assert ((ba & 2) && (seg == 2));
if (seg > bc)
seg = bc;
cp = UBMPAGE (ba); /* Only one word, can't cross page */
pa10 = Map_Addr10 (ba, 1, &ubm); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return bc; /* return bc */
}
M[pa10] = (M[pa10] & M_WORD1) | ((d10) (*buf++));
pa10++;
if ((bc -= seg) == 0)
return 0;
ba += seg;
} /* Head */
ea = ba + bc;
seg = bc - (ea & 3);
if (seg > 0) {
assert (((seg & 3) == 0) && (bc >= seg));
bc -= seg;
for ( ; seg; seg -= 4, ba += 4) { /* aligned longwords */
np = UBMPAGE (ba);
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, &ubm); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */
return (lim - ba); /* return bc */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc + seg); /* return bc */
}
cp = np;
}
val = *buf++; /* get 16-bit data, clearing <17:16> */
if (ubm & UMAP_RRV ) { /* Read reverse preserves even word */
if (ba & 2) {
M[pa10] = (M[pa10] & INT64_C(0777777000000)) | val;
pa10++;
} else
M[pa10] = (M[pa10] & INT64_C(0000000777777)) | (val << 18); /* preserve */
} else { /* Not RRV */
if (ba & 2) { /* Write odd preserves even word */
M[pa10] = (M[pa10] & INT64_C(0777777000000)) | val;
pa10++;
} else
M[pa10] = val << 18; /* Write even clears odd */
M[pa10++] = (((d10)(buf[0])) << V_WORD0) | buf[1];/* <0:1,18:19> = 0
* V_WORD1
*/
buf += 2;
}
} /* Body */
/* Tail: partial word, must be aligned, can only be WORD0 */
assert ((bc >= 0) && ((ba & 3) == 0));
if (bc) {
assert (bc == 2);
np = UBMPAGE (ba); /* Only one word, last possible page crossing */
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, &ubm); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc); /* return bc */
}
}
if (ubm & UMAP_RRV ) /* Read reverse preserves RH */
M[pa10] = (((d10)(buf[0])) << V_WORD0) | (M[pa10] & M_WORD0);
else
M[pa10] = ((d10)(buf[0])) << V_WORD0;
}
return 0;
}
@ -702,50 +1158,94 @@ return 0;
int32 Map_WriteW18 (uint32 ba, int32 bc, uint32 *buf)
{
uint32 lim, cp, np;
int32 ubm;
a10 pa10;
d10 val;
uint32 ea, cp, np;
int32 seg, ubm = 0;
a10 pa10 = ~0u;
if ((ba & ~((IO_M_UBA<<IO_V_UBA)|0017777)) == 0760000)
{ /* IOPAGE: device register write */
if ((ba & 1) || (bc &1))
return bc;
if ((ba | bc) & 1)
ABORT (STOP_IOALIGN);
while (bc) {
if (UBWriteIO (*buf++ & 0777777, ba, WRITE) != SCPE_OK)
if (UBWriteIO (*buf++ & M_RH, ba, WRITE) != SCPE_OK)
break;
ba += 2;
bc -= 2;
}
return bc;
}
ba = ba & ~01; /* align start */
lim = ba + (bc & ~01);
for ( cp = ~ba; ba < lim; ba+= 2) { /* by words */
/* Memory */
if (bc == 0)
return 0;
ba &= ~1;
if (bc & 1)
ABORT (STOP_IOALIGN);
cp = ~ba;
seg = (4 - (ba & 3)) & 3;
if (seg) { /* Unaligned head */
assert ((ba & 2) && (seg == 2));
if (seg > bc)
seg = bc;
cp = UBMPAGE (ba); /* Only one word, can't cross page */
pa10 = Map_Addr10 (ba, 1, &ubm); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return bc; /* return bc */
}
M[pa10] = (M[pa10] & M_WORD1) | ((d10) (M_WORD18 & *buf++)); /* V_WORD1 */
pa10++;
if ((bc -= seg) == 0)
return 0;
ba += seg;
} /* Head */
ea = ba + bc;
seg = bc - (ea & 3);
if (seg > 0) {
assert (((seg & 3) == 0) && (bc >= seg));
bc -= seg;
for ( ; seg; seg -= 4, ba += 4) { /* aligned longwords */
np = UBMPAGE (ba);
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, &ubm); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */
return (lim - ba); /* return bc */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc + seg); /* return bc */
}
cp = np;
}
val = *buf++; /* get 18-bit data */
if (ubm & UMAP_RRV ) { /* Read reverse preserves even word */
if (ba & 2) {
M[pa10] = (M[pa10] & INT64_C(0777777000000)) | val;
pa10++;
} else
M[pa10] = (M[pa10] & INT64_C(0000000777777)) | (val << 18); /* preserve */
} else { /* Not RRV */
if (ba & 2) { /* Write odd preserves even word */
M[pa10] = (M[pa10] & INT64_C(0777777000000)) | val;
pa10++;
} else
M[pa10] = val << 18; /* Write even clears odd */
M[pa10++] = (((d10)(M_WORD18 & buf[0])) << V_WORD0) | (M_WORD18 & buf[1]);/* V_WORD1 */
buf += 2;
}
} /* Body */
/* Tail: partial word, must be aligned */
assert ((bc >= 0) && ((ba & 3) == 0));
if (bc) {
assert (bc == 2);
np = UBMPAGE (ba); /* Only one word, last possible page crossing */
if (np != cp) { /* New (or first) page? */
pa10 = Map_Addr10 (ba, 1, &ubm); /* map addr */
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA timeout */
return (bc); /* return bc */
}
}
if (ubm & UMAP_RRV ) /* Read reverse preserves RH */
M[pa10] = (M[pa10] & M_WORD0) | (((d10)(M_WORD18 & buf[0])) << V_WORD0);
else
M[pa10] = ((d10)(M_WORD18 & buf[0])) << V_WORD0;
}
return 0;
}
@ -1208,6 +1708,8 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */
{0000300}, {0570} }, /* DUP11 bit sync - fx CSR, fx VEC */
{ { "KDP" }, 1, 2, 0, 0,
{0000540}, {0540} }, /* KMC11-A comm IOP-DUP ucode - fx CSR, fx VEC */
{ { "DMR" }, 1, 2, 0, 0,
{0000700}, {0440} }, /* DMR11 comm - fx CSR, fx VEC */
#else
{ { "QBA" }, 1, 0, 0, 0,
{017500} }, /* doorbell - fx CSR, no VEC */

View file

@ -429,7 +429,7 @@ else { /* TOPS-20 paging */
int32 pmi, vpn, xpte;
int32 flg, t;
t_bool stop;
a10 pa, csta;
a10 pa, csta = 0;
d10 ptr, cste;
d10 acc = PTE_T20_W | PTE_T20_C; /* init access bits */

View file

@ -1229,7 +1229,7 @@ return SCPE_OK;
static const d10 boot_rom_dec[] = {
INT64_C(0510040000000)+FE_RHBASE, /* boot:hllz 1,FE_RHBASE ; uba # */
INT64_C(0201000140001), /* movei 0,140001 ; vld,fst,pg 1 */
INT64_C(0713001000000)+(IOBA_UBMAP+1 & RMASK), /* wrio 0,763001(1); set ubmap */
INT64_C(0713001000000)+((IOBA_UBMAP+1) & RMASK), /* wrio 0,763001(1); set ubmap */
INT64_C(0200040000000)+FE_RHBASE, /* move 1,FE_RHBASE */
INT64_C(0201000000040), /* movei 0,40 ; ctrl reset */
INT64_C(0713001000010), /* wrio 0,10(1) ; ->RPCS2 */
@ -1293,7 +1293,7 @@ static const d10 boot_rom_dec[] = {
static const d10 boot_rom_its[] = {
INT64_C(0510040000001)+FE_RHBASE, /* boot:hllzi 1,FE_RHBASE ; uba # */
INT64_C(0201000140001), /* movei 0,140001 ; vld,fst,pg 1 */
INT64_C(0715000000000)+(IOBA_UBMAP+1 & RMASK), /* iowrq 0,763001 ; set ubmap */
INT64_C(0715000000000)+((IOBA_UBMAP+1) & RMASK), /* iowrq 0,763001 ; set ubmap */
INT64_C(0200040000000)+FE_RHBASE, /* move 1,FE_RHBASE */
INT64_C(0201000000040), /* movei 0,40 ; ctrl reset */
INT64_C(0715001000010), /* iowrq 0,10(1) ; ->RPCS2 */

View file

@ -56,6 +56,8 @@ extern DEVICE ry_dev;
extern DEVICE cr_dev;
extern DEVICE lp20_dev;
extern DEVICE dup_dev;
extern DEVICE kmc_dev;
extern DEVICE dmc_dev;
extern UNIT cpu_unit;
extern REG cpu_reg[];
extern d10 *M;
@ -92,6 +94,8 @@ DEVICE *sim_devices[] = {
&tu_dev,
&dz_dev,
&dup_dev,
&kmc_dev,
&dmc_dev,
NULL
};
@ -109,6 +113,7 @@ const char *sim_stop_messages[] = {
"Invalid I/O controller",
"Address stop",
"Console FE halt",
"Unaligned DMA",
"Panic stop"
};

View file

@ -810,7 +810,7 @@ return;
t_stat tu_svc (UNIT *uptr)
{
int32 fnc, fmt, i, j, k, wc10, ba10;
int32 ba, fc, wc, drv, mpa10, vpn;
int32 ba, fc, wc, drv, mpa10 = 0, vpn;
d10 val, v[4];
t_mtrlnt tbc;
t_stat st, r = SCPE_OK;
@ -1258,7 +1258,7 @@ return sim_tape_detach (uptr);
static const d10 boot_rom_dec[] = {
INT64_C(0510040000000)+FE_RHBASE, /* boot:hllz 1,FE_RHBASE ; uba # */
INT64_C(0201000040001), /* movei 0,40001 ; vld,pg 1 */
INT64_C(0713001000000)+(IOBA_UBMAP+1 & RMASK), /* wrio 0,763001(1); set ubmap */
INT64_C(0713001000000)+((IOBA_UBMAP+1) & RMASK), /* wrio 0,763001(1); set ubmap */
INT64_C(0200040000000)+FE_RHBASE, /* move 1,FE_RHBASE */
INT64_C(0201000000040), /* movei 0,40 ; ctrl reset */
INT64_C(0713001000010), /* wrio 0,10(1) ; ->MTFS */
@ -1312,7 +1312,7 @@ static const d10 boot_rom_dec[] = {
static const d10 boot_rom_its[] = {
INT64_C(0510040000000)+FE_RHBASE, /* boot:hllz 1,FE_RHBASE ; uba # - not used */
INT64_C(0201000040001), /* movei 0,40001 ; vld,pg 1 */
INT64_C(0714000000000)+(IOBA_UBMAP+1 & RMASK), /* iowri 0,763001 ; set ubmap */
INT64_C(0714000000000)+((IOBA_UBMAP+1) & RMASK), /* iowri 0,763001 ; set ubmap */
INT64_C(0200040000000)+FE_RHBASE, /* move 1,FE_RHBASE */
INT64_C(0201000000040), /* movei 0,40 ; ctrl reset */
INT64_C(0714001000010), /* iowri 0,10(1) ; ->MTFS */

View file

@ -155,41 +155,41 @@ d10 xlate (d10 by, a10 tblad, d10 *xflgs, int32 pflgs);
void filldst (d10 fill, int32 ac, d10 cnt, int32 pflgs);
static const d10 pwrs10[23][2] = {
INT64_C(0), INT64_C(0),
INT64_C(0), INT64_C(1),
INT64_C(0), INT64_C(10),
INT64_C(0), INT64_C(100),
INT64_C(0), INT64_C(1000),
INT64_C(0), INT64_C(10000),
INT64_C(0), INT64_C(100000),
INT64_C(0), INT64_C(1000000),
INT64_C(0), INT64_C(10000000),
INT64_C(0), INT64_C(100000000),
INT64_C(0), INT64_C(1000000000),
INT64_C(0), INT64_C(10000000000),
INT64_C(2), INT64_C(31280523264),
INT64_C(29), INT64_C(3567587328),
INT64_C(291), INT64_C(1316134912),
INT64_C(2910), INT64_C(13161349120),
INT64_C(29103), INT64_C(28534276096),
INT64_C(291038), INT64_C(10464854016),
INT64_C(2910383), INT64_C(1569325056),
INT64_C(29103830), INT64_C(15693250560),
INT64_C(291038304), INT64_C(19493552128),
INT64_C(2910383045), INT64_C(23136829440),
INT64_C(29103830456), INT64_C(25209864192)
{ INT64_C(0), INT64_C(0),},
{ INT64_C(0), INT64_C(1),},
{ INT64_C(0), INT64_C(10),},
{ INT64_C(0), INT64_C(100),},
{ INT64_C(0), INT64_C(1000),},
{ INT64_C(0), INT64_C(10000),},
{ INT64_C(0), INT64_C(100000),},
{ INT64_C(0), INT64_C(1000000),},
{ INT64_C(0), INT64_C(10000000),},
{ INT64_C(0), INT64_C(100000000),},
{ INT64_C(0), INT64_C(1000000000),},
{ INT64_C(0), INT64_C(10000000000),},
{ INT64_C(2), INT64_C(31280523264),},
{ INT64_C(29), INT64_C(3567587328),},
{ INT64_C(291), INT64_C(1316134912),},
{ INT64_C(2910), INT64_C(13161349120),},
{ INT64_C(29103), INT64_C(28534276096),},
{ INT64_C(291038), INT64_C(10464854016),},
{ INT64_C(2910383), INT64_C(1569325056),},
{ INT64_C(29103830), INT64_C(15693250560),},
{ INT64_C(291038304), INT64_C(19493552128),},
{ INT64_C(2910383045), INT64_C(23136829440),},
{ INT64_C(29103830456), INT64_C(25209864192),},
};
int xtend (int32 ac, int32 ea, int32 pflgs)
{
d10 b1, b2, ppi;
d10 xinst, xoff, digit, f1, f2, rs[2];
d10 xinst, xoff = 0, digit, f1, f2, rs[2];
d10 xflgs = 0;
a10 e1, entad;
a10 e1 = 0, entad;
int32 p1 = ADDAC (ac, 1);
int32 p3 = ADDAC (ac, 3);
int32 p4 = ADDAC (ac, 4);
int32 flg, i, s2, t, pp, pat, xop, xac, ret;
int32 flg, i, s2 = 0, t, pp, pat, xop, xac, ret;
xinst = Read (ea, MM_OPND); /* get extended instr */
xop = GET_OP (xinst); /* get opcode */

View file

@ -31,6 +31,8 @@
#ifndef PDP11_DDCMP_H_
#define PDP11_DDCMP_H_ 0
#include "sim_tmxr.h"
/* DDCMP packet types */
#define DDCMP_SYN 0226u /* Sync character on synchronous links */
@ -39,6 +41,27 @@
#define DDCMP_ENQ 0005u /* Control Message Identifier */
#define DDCMP_DLE 0220u /* Maintenance Message Identifier */
#define DDCMP_CTL_ACK 1 /* Control Message ACK Type */
#define DDCMP_CTL_NAK 2 /* Control Message NAK Type */
#define DDCMP_CTL_REP 3 /* Control Message REP Type */
#define DDCMP_CTL_STRT 6 /* Control Message STRT Type */
#define DDCMP_CTL_STACK 7 /* Control Message STACK Type */
#define DDCMP_FLAG_SELECT 0x2 /* Link Select */
#define DDCMP_FLAG_QSYNC 0x1 /* Quick Sync (next message won't abut this message) */
#define DDCMP_CRC_SIZE 2 /* Bytes in DDCMP CRC fields */
#define DDCMP_HEADER_SIZE 8 /* Bytes in DDCMP Control and Data Message headers (including header CRC) */
#define DDCMP_RESP_OFFSET 3 /* Byte offset of response (ack) number field */
#define DDCMP_NUM_OFFSET 4 /* Byte offset of packet number field */
#define DDCMP_PACKET_TIMEOUT 4 /* Seconds before sending REP command for unacknowledged packets */
#define DDCMP_DBG_PXMT TMXR_DBG_PXMT /* Debug Transmitted Packet Header Contents */
#define DDCMP_DBG_PRCV TMXR_DBG_PRCV /* Debug Received Packet Header Contents */
#define DDCMP_DBG_PDAT 0x1000000 /* Debug Packet Data */
/* Support routines */
/* crc16 polynomial x^16 + x^15 + x^2 + 1 (0xA001) CCITT LSB */
@ -62,54 +85,62 @@ return(crc);
#include <ctype.h>
static void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail)
static void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len)
{
if (sim_deb && dptr && (reason & dptr->dctrl)) {
sim_debug(reason, dptr, "%s len: %d\n", txt, len);
if (detail) {
int i, same, group, sidx, oidx;
char outbuf[80], strbuf[18];
static char hex[] = "0123456789ABCDEF";
static const char hex[] = "0123456789ABCDEF";
static const char *const flags [4] = { "..", ".Q", "S.", "SQ" };
static const char *const nak[18] = { "", " (HCRC)", " (DCRC)", " (REPREPLY)", /* 0-3 */
"", "", "", "", /* 4-7 */
" (NOBUF)", " (RXOVR)", "", "", /* 8-11 */
"", "", "", "", /* 12-15 */
" (TOOLONG)", " (HDRFMT)" }; /* 16-17 */
const char *flag = flags[msg[2]>>6];
int msg2 = msg[2] & 0x3F;
sim_debug(reason, dptr, "%s len: %d\n", txt, len);
switch (msg[0]) {
case DDCMP_SOH: /* Data Message */
sim_debug (reason, dptr, "Data Message, Link: %d, Count: %d, Resp: %d, Num: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)|msg[1], msg[3], msg[4],
(0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)|msg[1]))) ? "OK" : "BAD");
sim_debug (reason, dptr, "Data Message, Count: %d, Num: %d, Flags: %s, Resp: %d, HDRCRC: %s, DATACRC: %s\n", (msg2 << 8)|msg[1], msg[4], flag, msg[3],
(0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+((msg2 << 8)|msg[1]))) ? "OK" : "BAD");
break;
case DDCMP_ENQ: /* Control Message */
sim_debug (reason, dptr, "Control: Type: %d ", msg[1]);
switch (msg[1]) {
case 1: /* ACK */
sim_debug (reason, dptr, "(ACK) ACKSUB: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]);
case DDCMP_CTL_ACK: /* ACK */
sim_debug (reason, dptr, "(ACK) ACKSUB: %d, Flags: %s, Resp: %d\n", msg2, flag, msg[3]);
break;
case 2: /* NAK */
sim_debug (reason, dptr, "(NAK) Reason: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]);
case DDCMP_CTL_NAK: /* NAK */
sim_debug (reason, dptr, "(NAK) Reason: %d%s, Flags: %s, Resp: %d\n", msg2, ((msg2 > 17)? "": nak[msg2]), flag, msg[3]);
break;
case 3: /* REP */
sim_debug (reason, dptr, "(REP) REPSUB: %d, Link: %d, Num: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[4]);
case DDCMP_CTL_REP: /* REP */
sim_debug (reason, dptr, "(REP) REPSUB: %d, Num: %d, Flags: %s\n", msg2, msg[4], flag);
break;
case 6: /* STRT */
sim_debug (reason, dptr, "(STRT) STRTSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6);
case DDCMP_CTL_STRT: /* STRT */
sim_debug (reason, dptr, "(STRT) STRTSUB: %d, Flags: %s\n", msg2, flag);
break;
case 7: /* STACK */
sim_debug (reason, dptr, "(STACK) STCKSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6);
case DDCMP_CTL_STACK: /* STACK */
sim_debug (reason, dptr, "(STACK) STCKSUB: %d, Flags: %s\n", msg2, flag);
break;
default: /* Unknown */
sim_debug (reason, dptr, "(Unknown=0%o)\n", msg[1]);
break;
}
if (len != 8) {
sim_debug (reason, dptr, "Unexpected Control Message Length: %d expected 8\n", len);
if (len != DDCMP_HEADER_SIZE) {
sim_debug (reason, dptr, "Unexpected Control Message Length: %d expected %d\n", len, DDCMP_HEADER_SIZE);
}
if (0 != ddcmp_crc16 (0, msg, len)) {
sim_debug (reason, dptr, "Unexpected Message CRC\n");
}
break;
case DDCMP_DLE: /* Maintenance Message */
sim_debug (reason, dptr, "Maintenance Message, Link: %d, Count: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)| msg[1],
(0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)| msg[1]))) ? "OK" : "BAD");
sim_debug (reason, dptr, "Maintenance Message, Count: %d, Flags: %s, HDRCRC: %s, DATACRC: %s\n", (msg2 << 8)| msg[1], flag,
(0 == ddcmp_crc16 (0, msg, DDCMP_HEADER_SIZE)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+DDCMP_HEADER_SIZE, 2+((msg2 << 8)| msg[1]))) ? "OK" : "BAD");
break;
}
if (DDCMP_DBG_PDAT & dptr->dctrl) {
for (i=same=0; i<len; i += 16) {
if ((i > 0) && (0 == memcmp(&msg[i], &msg[i-16], 16))) {
++same;
@ -142,4 +173,228 @@ if (sim_deb && dptr && (reason & dptr->dctrl)) {
uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len);
/* Get packet from specific line
Inputs:
*lp = pointer to terminal line descriptor
**pbuf = pointer to pointer of packet contents
*psize = pointer to packet size
Output:
SCPE_LOST link state lost
SCPE_OK Packet returned OR no packet available
Implementation notes:
1. If a packet is not yet available, then the pbuf address returned is
NULL, but success (SCPE_OK) is returned
*/
static t_stat ddcmp_tmxr_get_packet_ln (TMLN *lp, const uint8 **pbuf, uint16 *psize)
{
int32 c;
size_t payloadsize;
while (TMXR_VALID & (c = tmxr_getc_ln (lp))) {
c &= ~TMXR_VALID;
if (lp->rxpboffset + 1 > lp->rxpbsize) {
lp->rxpbsize += 512;
lp->rxpb = (uint8 *)realloc (lp->rxpb, lp->rxpbsize);
}
lp->rxpb[lp->rxpboffset] = c;
if ((lp->rxpboffset == 0) && ((c == DDCMP_SYN) || (c == DDCMP_DEL))) {
tmxr_debug (DDCMP_DBG_PRCV, lp, "Ignoring Interframe Sync Character", (char *)&lp->rxpb[0], 1);
continue;
}
lp->rxpboffset += 1;
if (lp->rxpboffset == 1) {
switch (c) {
default:
tmxr_debug (DDCMP_DBG_PRCV, lp, "Ignoring unexpected byte in DDCMP mode", (char *)&lp->rxpb[0], 1);
lp->rxpboffset = 0;
case DDCMP_SOH:
case DDCMP_ENQ:
case DDCMP_DLE:
continue;
}
}
if (lp->rxpboffset >= DDCMP_HEADER_SIZE) {
if (lp->rxpb[0] == DDCMP_ENQ) { /* Control Message? */
++lp->rxpcnt;
*pbuf = lp->rxpb;
*psize = DDCMP_HEADER_SIZE;
lp->rxpboffset = 0;
ddcmp_packet_trace (DDCMP_DBG_PRCV, lp->mp->dptr, "<<< RCV Packet", lp->rxpb, *psize);
return SCPE_OK;
}
payloadsize = ((lp->rxpb[2] & 0x3F) << 8)| lp->rxpb[1];
if (lp->rxpboffset >= 10 + payloadsize) {
++lp->rxpcnt;
*pbuf = lp->rxpb;
*psize = 10 + payloadsize;
ddcmp_packet_trace (DDCMP_DBG_PRCV, lp->mp->dptr, "<<< RCV Packet", lp->rxpb, *psize);
lp->rxpboffset = 0;
return SCPE_OK;
}
}
}
*pbuf = NULL;
*psize = 0;
if (lp->conn)
return SCPE_OK;
return SCPE_LOST;
}
/* Store packet in line buffer (or store packet in line buffer and add needed CRCs)
Inputs:
*lp = pointer to line descriptor
*buf = pointer to packet data
size = size of packet
Outputs:
status = ok, connection lost, or stall
Implementation notea:
1. If the line is not connected, SCPE_LOST is returned.
2. If prior packet transmission still in progress, SCPE_STALL is
returned and no packet data is stored. The caller must retry later.
*/
static t_stat ddcmp_tmxr_put_packet_ln (TMLN *lp, const uint8 *buf, size_t size)
{
t_stat r;
if (!lp->conn)
return SCPE_LOST;
if (lp->txppoffset < lp->txppsize) {
tmxr_debug (DDCMP_DBG_PXMT, lp, "Skipped Sending Packet - Transmit Busy", (char *)&lp->txpb[3], size);
return SCPE_STALL;
}
if (lp->txpbsize < size) {
lp->txpbsize = size;
lp->txpb = (uint8 *)realloc (lp->txpb, lp->txpbsize);
}
memcpy (lp->txpb, buf, size);
lp->txppsize = size;
lp->txppoffset = 0;
ddcmp_packet_trace (DDCMP_DBG_PXMT, lp->mp->dptr, ">>> XMT Packet", lp->txpb, lp->txppsize);
++lp->txpcnt;
while ((lp->txppoffset < lp->txppsize) &&
(SCPE_OK == (r = tmxr_putc_ln (lp, lp->txpb[lp->txppoffset]))))
++lp->txppoffset;
tmxr_send_buffered_data (lp);
return lp->conn ? SCPE_OK : SCPE_LOST;
}
static t_stat ddcmp_tmxr_put_packet_crc_ln (TMLN *lp, uint8 *buf, size_t size)
{
uint16 hdr_crc16 = ddcmp_crc16(0, buf, DDCMP_HEADER_SIZE-DDCMP_CRC_SIZE);
buf[DDCMP_HEADER_SIZE-DDCMP_CRC_SIZE] = hdr_crc16 & 0xFF;
buf[DDCMP_HEADER_SIZE-DDCMP_CRC_SIZE+1] = (hdr_crc16>>8) & 0xFF;
if (size > DDCMP_HEADER_SIZE) {
uint16 data_crc16 = ddcmp_crc16(0, buf+DDCMP_HEADER_SIZE, size-(DDCMP_HEADER_SIZE+DDCMP_CRC_SIZE));
buf[size-DDCMP_CRC_SIZE] = data_crc16 & 0xFF;
buf[size-DDCMP_CRC_SIZE+1] = (data_crc16>>8) & 0xFF;
}
return ddcmp_tmxr_put_packet_ln (lp, buf, size);
}
static void ddcmp_build_data_packet (uint8 *buf, size_t size, uint8 flags, uint8 sequence, uint8 ack)
{
buf[0] = DDCMP_SOH;
buf[1] = size & 0xFF;
buf[2] = ((size >> 8) & 0x3F) | (flags << 6);
buf[3] = ack;
buf[4] = sequence;
buf[5] = 1;
}
static void ddcmp_build_maintenance_packet (uint8 *buf, size_t size)
{
buf[0] = DDCMP_DLE;
buf[1] = size & 0xFF;
buf[2] = ((size >> 8) & 0x3F) | (DDCMP_FLAG_SELECT|DDCMP_FLAG_QSYNC << 6);
buf[3] = 0;
buf[4] = 0;
buf[5] = 1;
}
static t_stat ddcmp_tmxr_put_data_packet_ln (TMLN *lp, uint8 *buf, size_t size, uint8 flags, uint8 sequence, uint8 ack)
{
ddcmp_build_data_packet (buf, size, flags, sequence, ack);
return ddcmp_tmxr_put_packet_crc_ln (lp, buf, size);
}
static void ddcmp_build_control_packet (uint8 *buf, uint8 type, uint8 subtype, uint8 flags, uint8 sndr, uint8 rcvr)
{
buf[0] = DDCMP_ENQ; /* Control Message */
buf[1] = type; /* STACK type */
buf[2] = (subtype & 0x3f) | (flags << 6);
/* STACKSUB type and flags */
buf[3] = rcvr; /* RCVR */
buf[4] = sndr; /* SNDR */
buf[5] = 1; /* ADDR */
}
static t_stat ddcmp_tmxr_put_control_packet_ln (TMLN *lp, uint8 *buf, uint8 type, uint8 subtype, uint8 flags, uint8 sndr, uint8 rcvr)
{
ddcmp_build_control_packet (buf, type, subtype, flags, sndr, rcvr);
return ddcmp_tmxr_put_packet_crc_ln (lp, buf, DDCMP_HEADER_SIZE);
}
static void ddcmp_build_ack_packet (uint8 *buf, uint8 ack, uint8 flags)
{
ddcmp_build_control_packet (buf, DDCMP_CTL_ACK, 0, flags, 0, ack);
}
static t_stat ddcmp_tmxr_put_ack_packet_ln (TMLN *lp, uint8 *buf, uint8 ack, uint8 flags)
{
ddcmp_build_ack_packet (buf, ack, flags);
return ddcmp_tmxr_put_packet_crc_ln (lp, buf, DDCMP_HEADER_SIZE);
}
static void ddcmp_build_nak_packet (uint8 *buf, uint8 reason, uint8 nack, uint8 flags)
{
ddcmp_build_control_packet (buf, DDCMP_CTL_NAK, reason, flags, 0, nack);
}
static t_stat ddcmp_tmxr_put_nak_packet_ln (TMLN *lp, uint8 *buf, uint8 reason, uint8 nack, uint8 flags)
{
return ddcmp_tmxr_put_control_packet_ln (lp, buf, DDCMP_CTL_NAK, reason, flags, 0, nack);
}
static void ddcmp_build_rep_packet (uint8 *buf, uint8 ack, uint8 flags)
{
ddcmp_build_control_packet (buf, DDCMP_CTL_REP, 0, flags, ack, 0);
}
static t_stat ddcmp_tmxr_put_rep_packet_ln (TMLN *lp, uint8 *buf, uint8 ack, uint8 flags)
{
return ddcmp_tmxr_put_control_packet_ln (lp, buf, DDCMP_CTL_REP, 0, flags, ack, 0);
}
static void ddcmp_build_start_packet (uint8 *buf)
{
ddcmp_build_control_packet (buf, DDCMP_CTL_STRT, 0, DDCMP_FLAG_SELECT|DDCMP_FLAG_QSYNC, 0, 0);
}
static t_stat ddcmp_tmxr_put_start_packet_ln (TMLN *lp, uint8 *buf)
{
ddcmp_build_start_packet (buf);
return ddcmp_tmxr_put_packet_crc_ln (lp, buf, DDCMP_HEADER_SIZE);
}
static void ddcmp_build_start_ack_packet (uint8 *buf)
{
ddcmp_build_control_packet (buf, DDCMP_CTL_STACK, 0, DDCMP_FLAG_SELECT|DDCMP_FLAG_QSYNC, 0, 0);
}
static t_stat ddcmp_tmxr_put_start_ack_packet_ln (TMLN *lp, uint8 *buf)
{
ddcmp_build_start_ack_packet (buf);
return ddcmp_tmxr_put_packet_crc_ln (lp, buf, DDCMP_HEADER_SIZE);
}
#endif /* PDP11_DDCMP_H_ */

View file

@ -485,6 +485,8 @@ typedef struct {
#define DLX_LINES 16 /* max # of KL11/DL11's */
#define DCX_LINES 16 /* max # of DC11's */
#define DUP_LINES 8 /* max # of DUP11/DPV11's */
#define KMC_UNITS 2 /* max # of KMC11s */
#define INITIAL_KMCS 0 /* Number to initially enable */
#define MT_MAXFR (1 << 16) /* magtape max rec */
#define DIB_MAX 100 /* max DIBs */
@ -607,6 +609,8 @@ typedef struct pdp_dib DIB;
#define INT_V_DMCTX 20
#define INT_V_DUPRX 21
#define INT_V_DUPTX 22
#define INT_V_KMCA 23
#define INT_V_KMCB 24
#define INT_V_PIR4 0 /* BR4 */
#define INT_V_TTI 1
@ -661,6 +665,8 @@ typedef struct pdp_dib DIB;
#define INT_RS (1u << INT_V_RS)
#define INT_DMCRX (1u << INT_V_DMCRX)
#define INT_DMCTX (1u << INT_V_DMCTX)
#define INT_KMCA (1u << INT_V_KMCA)
#define INT_KMCB (1u << INT_V_KMCB)
#define INT_DUPRX (1u << INT_V_DUPRX)
#define INT_DUPTX (1u << INT_V_DUPTX)
#define INT_PIR4 (1u << INT_V_PIR4)
@ -717,6 +723,8 @@ typedef struct pdp_dib DIB;
#define IPL_RS 5
#define IPL_DMCRX 5
#define IPL_DMCTX 5
#define IPL_KMCA 5
#define IPL_KMCB 5
#define IPL_DUPRX 5
#define IPL_DUPTX 5
#define IPL_PTR 4

File diff suppressed because it is too large Load diff

View file

@ -1,146 +0,0 @@
/* pdp11_dmc.h: DMC11 Emulation
------------------------------------------------------------------------------
Copyright (c) 2011, Robert M. A. Jarratt
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of the author shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from the author.
------------------------------------------------------------------------------
Modification history:
15-Jan-13 RJ Contribution from Paul Koning of support for RSTS using the ROM
INPUT (ROM I) command to get the DMC11 to report DSR status.
------------------------------------------------------------------------------*/
// Notes
// Base address needs to be 760060 according to DMC11 manual, but SYSGEN seems to think CSR is 0760100. However if I use
// 0760100 I get a conflict with the DZ because the first 13 bits are still 00100. If I use 760060 VMS sees the XM device, but
// if I remove the DZ to prevent the conflict VMS does not see an XM device, but I do get lots of reads and writes, possibly
// because it thinks it is a different device. What worries me more though is that there seems to be overlap in the 13-bit base
// addresses of the DZ and DMC.
#ifndef PDP11_DMC_H
#define PDP11_DMC_H
#if defined (VM_VAX) /* VAX version */
#include "vax_defs.h"
extern int32 int_req[IPL_HLVL];
#elif defined(VM_PDP10)
#include "pdp10_defs.h"
//#define IPL_HLVL 8 /* # int levels */
extern int32 int_req;
#else /* PDP-11 version */
#include "pdp11_defs.h"
extern int32 int_req[IPL_HLVL];
#endif
#include "sim_sock.h"
#define DMC_NUMDEVICE 4 /* # DMC-11 devices */
#define DMC_UNITSPERDEVICE 1 /* # units per DMC-11 */
#define DMP_NUMDEVICE 1 /* # DMP-11 devices */
#define DMP_UNITSPERDEVICE 1 /* # units per DMP-11 */
#define DMC_RDX 8
/* debugging bitmaps */
#define DBG_TRC 0x0001 /* trace routine calls */
#define DBG_REG 0x0002 /* trace read/write registers */
#define DBG_WRN 0x0004 /* display warnings */
#define DBG_INF 0x0008 /* display informational messages (high level trace) */
#define DBG_DAT 0x0010 /* display data buffer contents */
#define DBG_DTS 0x0020 /* display data summary */
#define DBG_SOK 0x0040 /* display socket open/close */
#define DBG_CON 0x0080 /* display socket connection establishment */
#define TYPE_BACCI 0
#define TYPE_CNTLI 1
#define TYPE_BASEI 03
#define TYPE_BACCO 0
#define TYPE_CNTLO 1
#define TYPE_DMP_MODE 2
#define TYPE_DMP_CONTROL 1
#define TYPE_DMP_RECEIVE 0
#define TYPE_DMP_TRANSMIT 4
/* SEL0 */
#define DMC_TYPE_INPUT_MASK 0x0003
#define DMC_IN_IO_MASK 0x0004
#define DMP_IEO_MASK 0x0010
#define DMC_RQI_MASK 0x0020
#define DMP_RQI_MASK 0x0080
#define DMC_RDYI_MASK 0x0080
#define DMC_IEI_MASK 0x0040
#define DMP_IEI_MASK 0x0001
#define ROMI_MASK 0x0200
#define LU_LOOP_MASK 0x0800
#define MASTER_CLEAR_MASK 0x4000
#define RUN_MASK 0x8000
/* SEL2 */
#define DMP_IN_IO_MASK 0x0004
#define DMP_TYPE_INPUT_MASK 0x0007
#define TYPE_OUTPUT_MASK 0x0003
#define OUT_IO_MASK 0x0004
#define DMC_RDYO_MASK 0x0080
#define DMC_IEO_MASK 0x0040
#define DMP_RDYI_MASK 0x0010
/* BSEL6 */
#define LOST_DATA_MASK 0x0010
#define DISCONNECT_MASK 0x0040
#define DSPDSR 0x22b3 /* KMC opcode to move line unit status to SEL2 */
#define SEL0_RUN_BIT 15
#define SEL0_MCLR_BIT 14
#define SEL0_LU_LOOP_BIT 11
#define SEL0_ROMI_BIT 9
#define SEL0_RDI_BIT 7
#define SEL0_DMC_IEI_BIT 6
#define SEL0_DMP_IEI_BIT 0
#define SEL0_DMP_IEO_BIT 4
#define SEL0_DMC_RQI_BIT 5
#define SEL0_DMP_RQI_BIT 7
#define SEL0_IN_IO_BIT 2
#define SEL0_TYPEI_BIT 0
#define SEL2_TYPEO_BIT 0
#define SEL2_RDO_BIT 7
#define SEL2_IEO_BIT 6
#define SEL2_OUT_IO_BIT 2
#define SEL2_LINE_BIT 8
#define SEL2_LINE_BIT_LENGTH 6
#define SEL2_PRIO_BIT 14
#define SEL2_PRIO_BIT_LENGTH 2
#define SEL6_LOST_DATA_BIT 4
#define SEL6_DISCONNECT_BIT 6
#define BUFFER_QUEUE_SIZE 7
#endif /* _VAX_DMC_H */

File diff suppressed because it is too large Load diff

View file

@ -34,17 +34,30 @@
#ifndef PDP11_DUP_H_
#define PDP11_DUP_H_ 0
typedef void (*PACKET_RECEIVE_CALLBACK)(int32 dup, uint8 *buf, size_t len);
typedef void (*PACKET_DATA_AVAILABLE_CALLBACK)(int32 dup, int len);
typedef void (*PACKET_TRANSMIT_COMPLETE_CALLBACK)(int32 dup, int status);
typedef void (*MODEM_CHANGE_CALLBACK)(int32 dup);
int32 dup_get_line_speed (int32 dup);
int32 dup_get_DSR (int32 dup);
int32 dup_get_DCD (int32 dup);
int32 dup_get_CTS (int32 dup);
int32 dup_get_RING (int32 dup);
int32 dup_get_RCVEN (int32 dup);
t_stat dup_set_DTR (int32 dup, t_bool state);
t_stat dup_set_DDCMP (int32 dup, t_bool state);
t_stat dup_set_RTS (int32 dup, t_bool state);
t_stat dup_set_W3_option (int32 dup, t_bool state);
t_stat dup_set_W5_option (int32 dup, t_bool state);
t_stat dup_set_W6_option (int32 dup, t_bool state);
t_stat dup_set_RCVEN (int32 dup, t_bool state);
t_stat dup_setup_dup (int32 dup, t_bool enable, t_bool protocol_DDCMP, t_bool crc_inhibit, t_bool halfduplex, uint8 station);
t_stat dup_reset_dup (int32 dup);
int32 dup_csr_to_linenum (int32 CSRPA);
void dup_set_callback_mode (int32 dup, PACKET_RECEIVE_CALLBACK receive, PACKET_TRANSMIT_COMPLETE_CALLBACK transmit);
void dup_set_callback_mode (int32 dup, PACKET_DATA_AVAILABLE_CALLBACK receive, PACKET_TRANSMIT_COMPLETE_CALLBACK transmit, MODEM_CHANGE_CALLBACK modem);
t_bool dup_put_msg_bytes (int32 dup, uint8 *bytes, size_t len, t_bool start, t_bool end);
t_stat dup_get_packet (int32 dup, const uint8 **pbuf, uint16 *psize);
#endif /* PDP11_DUP_H_ */

3225
PDP11/pdp11_kmc.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -108,9 +108,10 @@ extern DEVICE xq_dev, xqb_dev;
extern DEVICE xu_dev, xub_dev;
extern DEVICE ke_dev;
extern DEVICE kg_dev;
extern DEVICE dmc_dev[];
extern DEVICE dmc_dev;
extern DEVICE dup_dev;
extern DEVICE dpv_dev;
extern DEVICE kmc_dev;
extern UNIT cpu_unit;
extern REG cpu_reg[];
extern uint16 *M;
@ -180,12 +181,10 @@ DEVICE *sim_devices[] = {
&xub_dev,
&ke_dev,
&kg_dev,
&dmc_dev[0],
&dmc_dev[1],
&dmc_dev[2],
&dmc_dev[3],
&dmc_dev,
&dup_dev,
&dpv_dev,
&kmc_dev,
NULL
};

View file

@ -42,7 +42,9 @@ A remote console session will close when an EOF character is entered (i.e. ^D or
RQ device has a settable controller type (RQDX3, UDA50, KLESI, RUX50)
RQ disks default to Autosize without regard to disk type
RQ disks on PDP11 can have RAUSER size beyond 2GB
DMC11 DDCMP DECnet device simulation from Rob Jarratt. Up to 4 DMC11 devices are supported.
DMC11/DMR11 DDCMP DECnet device simulation. Up to 8 DMC devices are supported.
KDP11 on PDP11 for DECnet
DUP11 on PDP11 for DECnet connectivity to talk to DMC, KDP or other DUP devices
DZ on Unibus systems can have up to 256 ports (default of 32), on
Qbus systems 128 port limit (default of 16).
DZ devices optionally support full modem control (and port speed settings
@ -54,6 +56,9 @@ A remote console session will close when an EOF character is entered (i.e. ^D or
MicroVAX I has a SET CPU MODEL=(MicroVAX|VAXSTATION) command to change between system types
MicroVAX II has a SET CPU MODEL=(MicroVAX|VAXSTATION) command to change between system types
#### PDP10 Enhancements
KDP11 (from Timothe Litt) for DECnet connectivity to simulators with DMC, DUP or KDP devices
#### Terminal Multiplexer additions
Added support for TCP connections using IPv4 and/or IPv6.
Logging - Traffic going out individual lines can be optionally logged to

View file

@ -52,8 +52,7 @@ extern DEVICE tq_dev;
extern DEVICE dz_dev;
extern DEVICE vh_dev;
extern DEVICE xu_dev, xub_dev;
extern DEVICE dmc_dev[];
extern DEVICE dup_dev;
extern DEVICE dmc_dev;
extern UNIT cpu_unit;
extern void WriteB (uint32 pa, int32 val);
@ -85,11 +84,7 @@ DEVICE *sim_devices[] = {
&tq_dev,
&xu_dev,
&xub_dev,
&dmc_dev[0],
&dmc_dev[1],
&dmc_dev[2],
&dmc_dev[3],
&dup_dev,
&dmc_dev,
NULL
};

View file

@ -54,8 +54,7 @@ extern DEVICE tu_dev;
extern DEVICE dz_dev;
extern DEVICE vh_dev;
extern DEVICE xu_dev, xub_dev;
extern DEVICE dmc_dev[];
extern DEVICE dup_dev;
extern DEVICE dmc_dev;
extern UNIT cpu_unit;
extern void WriteB (uint32 pa, int32 val);
@ -90,11 +89,7 @@ DEVICE *sim_devices[] = {
&tq_dev,
&xu_dev,
&xub_dev,
&dmc_dev[0],
&dmc_dev[1],
&dmc_dev[2],
&dmc_dev[3],
&dup_dev,
&dmc_dev,
NULL
};

View file

@ -54,8 +54,7 @@ extern DEVICE tu_dev;
extern DEVICE dz_dev;
extern DEVICE vh_dev;
extern DEVICE xu_dev, xub_dev;
extern DEVICE dmc_dev[];
extern DEVICE dup_dev;
extern DEVICE dmc_dev;
extern UNIT cpu_unit;
extern void WriteB (uint32 pa, int32 val);
@ -92,11 +91,7 @@ DEVICE *sim_devices[] = {
&tq_dev,
&xu_dev,
&xub_dev,
&dmc_dev[0],
&dmc_dev[1],
&dmc_dev[2],
&dmc_dev[3],
&dup_dev,
&dmc_dev,
NULL
};

View file

@ -54,8 +54,7 @@ extern DEVICE tu_dev;
extern DEVICE dz_dev;
extern DEVICE vh_dev;
extern DEVICE xu_dev, xub_dev;
extern DEVICE dmc_dev[];
extern DEVICE dup_dev;
extern DEVICE dmc_dev;
extern UNIT cpu_unit;
extern void WriteB (uint32 pa, int32 val);
@ -90,11 +89,7 @@ DEVICE *sim_devices[] = {
&tq_dev,
&xu_dev,
&xub_dev,
&dmc_dev[0],
&dmc_dev[1],
&dmc_dev[2],
&dmc_dev[3],
&dup_dev,
&dmc_dev,
NULL
};

View file

@ -239,6 +239,10 @@
RelativePath="..\PDP11\pdp11_cr.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dmc.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dup.c"
>
@ -247,6 +251,10 @@
RelativePath="..\PDP11\pdp11_dz.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_kmc.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_pt.c"
>

View file

@ -255,6 +255,10 @@
RelativePath="..\PDP11\pdp11_kg.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_kmc.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_lp.c"
>

View file

@ -206,10 +206,6 @@
RelativePath="..\PDP11\pdp11_dmc.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dup.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dz.c"
>
@ -388,7 +384,7 @@
>
</File>
<File
RelativePath="..\PDP11\pdp11_dmc.h"
RelativePath="..\PDP11\pdp11_dup.h"
>
</File>
<File

View file

@ -206,10 +206,6 @@
RelativePath="..\PDP11\pdp11_dmc.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dup.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dz.c"
>
@ -396,7 +392,7 @@
>
</File>
<File
RelativePath="..\PDP11\pdp11_dmc.h"
RelativePath="..\PDP11\pdp11_dup.h"
>
</File>
<File

View file

@ -209,10 +209,6 @@
RelativePath="..\PDP11\pdp11_dmc.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dup.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dz.c"
>
@ -408,7 +404,7 @@
>
</File>
<File
RelativePath="..\PDP11\pdp11_dmc.h"
RelativePath="..\PDP11\pdp11_dup.h"
>
</File>
<File

View file

@ -209,10 +209,6 @@
RelativePath="..\PDP11\pdp11_dmc.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dup.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dz.c"
>
@ -400,7 +396,7 @@
>
</File>
<File
RelativePath="..\PDP11\pdp11_dmc.h"
RelativePath="..\PDP11\pdp11_dup.h"
>
</File>
<File

View file

@ -743,8 +743,8 @@ PDP11 = ${PDP11D}/pdp11_fp.c ${PDP11D}/pdp11_cpu.c ${PDP11D}/pdp11_dz.c \
${PDP11D}/pdp11_cr.c ${PDP11D}/pdp11_rf.c ${PDP11D}/pdp11_dl.c \
${PDP11D}/pdp11_ta.c ${PDP11D}/pdp11_rc.c ${PDP11D}/pdp11_kg.c \
${PDP11D}/pdp11_ke.c ${PDP11D}/pdp11_dc.c ${PDP11D}/pdp11_dmc.c \
${PDP11D}/pdp11_dup.c ${PDP11D}/pdp11_rs.c ${PDP11D}/pdp11_vt.c \
${PDP11D}/pdp11_io_lib.c $(DISPLAYL) $(DISPLAYVT)
${PDP11D}/pdp11_kmc.c ${PDP11D}/pdp11_dup.c ${PDP11D}/pdp11_rs.c \
${PDP11D}/pdp11_vt.c ${PDP11D}/pdp11_io_lib.c $(DISPLAYL) $(DISPLAYVT)
PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT} $(DISPLAY_OPT)
@ -851,7 +851,7 @@ PDP10 = ${PDP10D}/pdp10_fe.c ${PDP11D}/pdp11_dz.c ${PDP10D}/pdp10_cpu.c \
${PDP10D}/pdp10_pag.c ${PDP10D}/pdp10_rp.c ${PDP10D}/pdp10_sys.c \
${PDP10D}/pdp10_tim.c ${PDP10D}/pdp10_tu.c ${PDP10D}/pdp10_xtnd.c \
${PDP11D}/pdp11_pt.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_cr.c \
${PDP11D}/pdp11_dup.c
${PDP11D}/pdp11_dup.c ${PDP11D}/pdp11_dmc.c ${PDP11D}/pdp11_kmc.c
PDP10_OPT = -DVM_PDP10 -DUSE_INT64 -I ${PDP10D} -I ${PDP11D}