1
0
mirror of https://github.com/simh/simh.git synced 2026-01-11 23:52:58 +00:00

Refactored (and renamed) pdp11_kdp to leverage the pdp11_dup dup implementation.

This commit is contained in:
Mark Pizzolato 2013-06-03 10:03:46 -07:00
parent 02fcc2ced6
commit 531cdd42f7
14 changed files with 1140 additions and 1524 deletions

View File

@ -660,8 +660,6 @@ typedef struct pdp_dib DIB;
#define IOLN_UBMNT3 001
#define IOBA_XU (IO_UBA3 + 0774510) /* DEUNA/DELUA */
#define IOLN_XU 010
#define IOBA_DMR (IO_UBA3 + 0764000) /* DMR11 */
#define IOLN_DMR 010
#define IOBA_CR (IO_UBA3 + 0777160) /* CD/CR/CM */
#define IOLN_CR 010
#define IOBA_RY (IO_UBA3 + 0777170) /* RX211 */
@ -700,13 +698,8 @@ 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_KMCA 8 /* KMC11 */
#define INT_V_KMCA 8 /* KMC11 */
#define INT_V_KMCB 9
#define INT_V_DMRA 10 /* DMR11 */
#define INT_V_DMRB 11
#define INT_V_DMCRX 13
#define INT_V_DMCTX 14
#define INT_V_XU 15 /* DEUNA/DELUA */
#define INT_V_DZRX 16 /* DZ11 */
#define INT_V_DZTX 17
#define INT_V_RY 18 /* RX211 */
@ -714,7 +707,6 @@ typedef struct pdp_dib DIB;
#define INT_V_PTP 25
#define INT_V_LP20 26 /* LPT20 */
#define INT_V_CR 27 /* CD20 (CD11) */
#define INT_V_CR 27 /* CD20 (CD11) */
#define INT_V_DUPRX 28 /* DUP11 */
#define INT_V_DUPTX 29
@ -722,10 +714,6 @@ typedef struct pdp_dib DIB;
#define INT_TU (1u << INT_V_TU)
#define INT_KMCA (1u << INT_V_KMCA)
#define INT_KMCB (1u << INT_V_KMCB)
#define INT_DMRA (1u << INT_V_DMRA)
#define INT_DMRB (1u << INT_V_DMRB)
#define INT_DMCRX (1u << INT_V_DMCRX)
#define INT_DMCTX (1u << INT_V_DMCTX)
#define INT_XU (1u << INT_V_XU)
#define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZTX (1u << INT_V_DZTX)
@ -741,10 +729,6 @@ typedef struct pdp_dib DIB;
#define IPL_TU 6
#define IPL_KMCA 5
#define IPL_KMCB 5
#define IPL_DMRA 5
#define IPL_DMRB 5
#define IPL_DMCRX 5
#define IPL_DMCTX 5
#define IPL_XU 5
#define IPL_DZRX 5
#define IPL_DZTX 5
@ -772,12 +756,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_KMCA 0540
#define VEC_KMCB 0544
#define VEC_DMRA 0610
#define VEC_DMRB 0614
#define VEC_LP20 0754
#define VEC_AUTO 0 /* Set by Auto Configure */

View File

@ -856,7 +856,7 @@ DIB *dibp;
for (i = 0; i < 32; i++) { /* clear intr tables */
int_vec[i] = 0;
int_ack[i] = NULL;
}
}
for (i = j = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */
dibp = (DIB *) dptr->ctxt; /* get DIB */
if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */
@ -961,12 +961,10 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */
{0017550}, {0070} }, /* PC11 reader - fx CSR, fx VEC */
{ { "PTP" }, 1, 1, 0, 0,
{0017554}, {0074} }, /* PC11 punch - fx CSR, fx VEC */
{ { "DUP" }, 1, 2, 0, 0,
{0000300}, {0300} }, /* DUP11 bit sync - fx CSR, fx VEC */
{ { "KMC" }, 1, 2, 0, 0,
{0000540}, {0540} }, /* KMC11 - fx CSR, fx VEC */
{ { "DUP0" }, 1, 2, 0, 0,
{0000300}, {0300} }, /* DUP11 sync - fx CSR, fx VEC */
{ { "DUP1" }, 1, 2, 0, 0,
{0000310}, {0310} }, /* DUP11 sync - fx CSR, fx VEC */
{0000540}, {0540} }, /* KMC11 comm - fx CSR, fx VEC */
#else
{ { "QBA" }, 1, 0, 0, 0,
{017500} }, /* doorbell - fx CSR, no VEC */

View File

@ -55,8 +55,8 @@ extern DEVICE dz_dev;
extern DEVICE ry_dev;
extern DEVICE cr_dev;
extern DEVICE lp20_dev;
extern DEVICE kmc_dev;
extern DEVICE dup_dev;
extern DEVICE kmc_dev;
extern UNIT cpu_unit;
extern REG cpu_reg[];
extern d10 *M;
@ -92,8 +92,8 @@ DEVICE *sim_devices[] = {
&rp_dev,
&tu_dev,
&dz_dev,
&kmc_dev,
&dup_dev,
&kmc_dev,
NULL
};

View File

@ -600,10 +600,10 @@ typedef struct pdp_dib DIB;
#define INT_V_RC 17
#define INT_V_DMCRX 18
#define INT_V_DMCTX 19
#define INT_V_KMCA 20
#define INT_V_KMCB 21
#define INT_V_DUPRX 20
#define INT_V_DUPTX 21
#define INT_V_KMCA 20
#define INT_V_KMCB 21
#define INT_V_DUPRX 22
#define INT_V_DUPTX 23
#define INT_V_PIR4 0 /* BR4 */
#define INT_V_TTI 1

View File

@ -65,57 +65,57 @@ extern int32 tmxr_poll; /* calibrated delay */
extern int32 clk_tps; /* clock ticks per second */
extern int32 tmr_poll; /* instructions per tick */
uint16 dup_rxcsr[DUP_LINES];
uint16 dup_rxdbuf[DUP_LINES];
uint16 dup_parcsr[DUP_LINES];
uint16 dup_txcsr[DUP_LINES];
uint16 dup_txdbuf[DUP_LINES];
uint32 dup_rxi = 0; /* rcv interrupts */
uint32 dup_txi = 0; /* xmt interrupts */
uint32 dup_wait[DUP_LINES]; /* rcv/xmt byte delay */
uint32 dup_speed[DUP_LINES]; /* line speed (bits/sec) */
uint8 *dup_rcvpacket[DUP_LINES]; /* rcv buffer */
uint16 dup_rcvpksize[DUP_LINES]; /* rcv buffer size */
uint16 dup_rcvpkoffset[DUP_LINES]; /* rcv buffer offset */
uint16 dup_rcvpkinoff[DUP_LINES]; /* rcv packet in offset */
uint8 *dup_xmtpacket[DUP_LINES]; /* xmt buffer */
uint16 dup_xmtpksize[DUP_LINES]; /* xmt buffer size */
uint16 dup_xmtpkoffset[DUP_LINES]; /* xmt buffer offset */
uint16 dup_xmtpkoutoff[DUP_LINES]; /* xmt packet out offset */
t_bool dup_xmtpkrdy[DUP_LINES]; /* xmt packet ready */
static uint16 dup_rxcsr[DUP_LINES];
static uint16 dup_rxdbuf[DUP_LINES];
static uint16 dup_parcsr[DUP_LINES];
static uint16 dup_txcsr[DUP_LINES];
static uint16 dup_txdbuf[DUP_LINES];
static uint32 dup_rxi = 0; /* rcv interrupts */
static uint32 dup_txi = 0; /* xmt interrupts */
static uint32 dup_wait[DUP_LINES]; /* rcv/xmt byte delay */
static uint32 dup_speed[DUP_LINES]; /* line speed (bits/sec) */
static uint8 *dup_rcvpacket[DUP_LINES]; /* rcv buffer */
static uint16 dup_rcvpksize[DUP_LINES]; /* rcv buffer size */
static uint16 dup_rcvpkoffset[DUP_LINES]; /* rcv buffer offset */
static uint16 dup_rcvpkinoff[DUP_LINES]; /* rcv packet in offset */
static uint8 *dup_xmtpacket[DUP_LINES]; /* xmt buffer */
static uint16 dup_xmtpksize[DUP_LINES]; /* xmt buffer size */
static uint16 dup_xmtpkoffset[DUP_LINES]; /* xmt buffer offset */
static uint16 dup_xmtpkoutoff[DUP_LINES]; /* xmt packet out offset */
static t_bool dup_xmtpkrdy[DUP_LINES]; /* xmt packet ready */
PACKET_RECEIVE_CALLBACK dup_rcv_packet_callback[DUP_LINES];
PACKET_TRANSMIT_COMPLETE_CALLBACK dup_xmt_complete_callback[DUP_LINES];
static PACKET_RECEIVE_CALLBACK dup_rcv_packet_callback[DUP_LINES];
static PACKET_TRANSMIT_COMPLETE_CALLBACK dup_xmt_complete_callback[DUP_LINES];
t_stat dup_rd (int32 *data, int32 PA, int32 access);
t_stat dup_wr (int32 data, int32 PA, int32 access);
t_stat dup_set_modem (int32 dup, int32 rxcsr_bits);
t_stat dup_get_modem (int32 dup);
t_stat dup_svc (UNIT *uptr);
t_stat dup_poll_svc (UNIT *uptr);
t_stat dup_rcv_byte (int32 dup);
t_stat dup_reset (DEVICE *dptr);
t_stat dup_attach (UNIT *uptr, char *ptr);
t_stat dup_detach (UNIT *uptr);
t_stat dup_clear (int32 dup, t_bool flag);
int32 dup_rxinta (void);
int32 dup_txinta (void);
void dup_update_rcvi (void);
void dup_update_xmti (void);
void dup_clr_rxint (int32 dup);
void dup_set_rxint (int32 dup);
void dup_clr_txint (int32 dup);
void dup_set_txint (int32 dup);
t_stat dup_setnl (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat dup_setspeed (UNIT* uptr, int32 val, char* cptr, void* desc);
t_stat dup_showspeed (FILE* st, UNIT* uptr, int32 val, void* desc);
t_stat dup_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
t_stat dup_help_attach (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
char *dup_description (DEVICE *dptr);
static t_stat dup_rd (int32 *data, int32 PA, int32 access);
static t_stat dup_wr (int32 data, int32 PA, int32 access);
static t_stat dup_set_modem (int32 dup, int32 rxcsr_bits);
static t_stat dup_get_modem (int32 dup);
static t_stat dup_svc (UNIT *uptr);
static t_stat dup_poll_svc (UNIT *uptr);
static t_stat dup_rcv_byte (int32 dup);
static t_stat dup_reset (DEVICE *dptr);
static t_stat dup_attach (UNIT *uptr, char *ptr);
static t_stat dup_detach (UNIT *uptr);
static t_stat dup_clear (int32 dup, t_bool flag);
static int32 dup_rxinta (void);
static int32 dup_txinta (void);
static void dup_update_rcvi (void);
static void dup_update_xmti (void);
static void dup_clr_rxint (int32 dup);
static void dup_set_rxint (int32 dup);
static void dup_clr_txint (int32 dup);
static void dup_set_txint (int32 dup);
static t_stat dup_setnl (UNIT *uptr, int32 val, char *cptr, void *desc);
static t_stat dup_setspeed (UNIT* uptr, int32 val, char* cptr, void* desc);
static t_stat dup_showspeed (FILE* st, UNIT* uptr, int32 val, void* desc);
static t_stat dup_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
static t_stat dup_help_attach (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
static char *dup_description (DEVICE *dptr);
/* RXCSR - 16XXX0 - receiver control/status register */
BITFIELD dup_rxcsr_bits[] = {
static BITFIELD dup_rxcsr_bits[] = {
BIT(BDATSET), /* Data Set Change B */
#define RXCSR_V_BDATSET 0
#define RXCSR_M_BDATSET (1<<RXCSR_V_BDATSET)
@ -172,7 +172,7 @@ BITFIELD dup_rxcsr_bits[] = {
/* RXDBUF - 16XXX2 - receiver Data Buffer register */
BITFIELD dup_rxdbuf_bits[] = {
static BITFIELD dup_rxdbuf_bits[] = {
BITF(RXDBUF,8), /* Receive Data Buffer */
#define RXDBUF_V_RXDBUF 0
#define RXDBUF_S_RXDBUF 8
@ -203,7 +203,7 @@ BITFIELD dup_rxdbuf_bits[] = {
/* PARCSR - 16XXX2 - Parameter Control/Status register */
BITFIELD dup_parcsr_bits[] = {
static BITFIELD dup_parcsr_bits[] = {
BITF(ADSYNC,8), /* Secondart Station Address/Receiver Sync Char */
#define PARCSR_V_ADSYNC 0
#define PARCSR_S_ADSYNC 8
@ -227,7 +227,7 @@ BITFIELD dup_parcsr_bits[] = {
/* TXCSR - 16XXX4 - Transmitter Control/Status register */
BITFIELD dup_txcsr_bits[] = {
static BITFIELD dup_txcsr_bits[] = {
BITNCF(3), /* reserved */
BIT(HALFDUP), /* Half Duplex */
#define TXCSR_V_HALFDUP 3
@ -272,7 +272,7 @@ BITFIELD dup_txcsr_bits[] = {
/* TXDBUF - 16XXX6 - transmitter Data Buffer register */
BITFIELD dup_txdbuf_bits[] = {
static BITFIELD dup_txdbuf_bits[] = {
BITF(TXDBUF,8), /* Transmit Data Buffer */
#define TXDBUF_V_TXDBUF 0
#define TXDBUF_S_TXDBUF 8
@ -323,17 +323,17 @@ DIB dup_dib = {
{ &dup_rxinta, &dup_txinta }/* int. ack. routines */
};
UNIT dup_unit_template = {
static UNIT dup_unit_template = {
UDATA (&dup_svc, UNIT_ATTABLE, 0),
};
UNIT dup_poll_unit_template = {
static UNIT dup_poll_unit_template = {
UDATA (&dup_poll_svc, UNIT_DIS, 0),
};
UNIT dup_units[DUP_LINES+1]; /* One unit per line and a polling unit */
static UNIT dup_units[DUP_LINES+1]; /* One unit per line and a polling unit */
REG dup_reg[] = {
static REG dup_reg[] = {
{ BRDATADF (RXCSR, dup_rxcsr, DEV_RDX, 16, DUP_LINES, "receive control/status register", dup_rxcsr_bits) },
{ BRDATADF (RXDBUF, dup_rxdbuf, DEV_RDX, 16, DUP_LINES, "receive data buffer", dup_rxdbuf_bits) },
{ BRDATADF (PARCSR, dup_parcsr, DEV_RDX, 16, DUP_LINES, "receive control/status register", dup_parcsr_bits) },
@ -351,10 +351,10 @@ REG dup_reg[] = {
{ NULL }
};
TMLN *dup_ldsc = NULL; /* line descriptors */
TMXR dup_desc = { INITIAL_DUP_LINES, 0, 0, NULL }; /* mux descriptor */
static TMLN *dup_ldsc = NULL; /* line descriptors */
static TMXR dup_desc = { INITIAL_DUP_LINES, 0, 0, NULL }; /* mux descriptor */
MTAB dup_mod[] = {
static MTAB dup_mod[] = {
{ MTAB_XTD|MTAB_VUN, 0, "SPEED", "SPEED=bits/sec (0=unrestricted)" ,
&dup_setspeed, &dup_showspeed, NULL, "Display rate limit" },
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 020, "ADDRESS", "ADDRESS",
@ -381,7 +381,7 @@ MTAB dup_mod[] = {
#define DBG_TRC TMXR_DBG_TRC /* display trace routine calls */
#define DBG_ASY TMXR_DBG_ASY /* display Asynchronous Activities */
DEBTAB dup_debug[] = {
static DEBTAB dup_debug[] = {
{"REG", DBG_REG},
{"INT", DBG_INT},
{"PKT", DBG_PKT},
@ -452,7 +452,7 @@ static char *dup_wr_regs[] =
dup_detach process detach
*/
t_stat dup_rd (int32 *data, int32 PA, int32 access)
static t_stat dup_rd (int32 *data, int32 PA, int32 access)
{
static BITFIELD* bitdefs[] = {dup_rxcsr_bits, dup_rxdbuf_bits, dup_txcsr_bits, dup_txdbuf_bits};
static uint16 *regs[] = {dup_rxcsr, dup_rxdbuf, dup_txcsr, dup_txdbuf};
@ -493,7 +493,7 @@ sim_debug_bits(DBG_REG, DUPDPTR, bitdefs[(PA >> 1) & 03], (uint32)(orig_val), (u
return SCPE_OK;
}
t_stat dup_wr (int32 data, int32 PA, int32 access)
static t_stat dup_wr (int32 data, int32 PA, int32 access)
{
static BITFIELD* bitdefs[] = {dup_rxcsr_bits, dup_parcsr_bits, dup_txcsr_bits, dup_txdbuf_bits};
static uint16 *regs[] = {dup_rxcsr, dup_parcsr, dup_txcsr, dup_txdbuf};
@ -579,7 +579,7 @@ sim_debug_bits(DBG_REG, DUPDPTR, bitdefs[(PA >> 1) & 03], (uint32)orig_val, (uin
return SCPE_OK;
}
t_stat dup_set_modem (int32 dup, int32 rxcsr_bits)
static t_stat dup_set_modem (int32 dup, int32 rxcsr_bits)
{
int32 bits_to_set, bits_to_clear;
@ -591,7 +591,7 @@ tmxr_set_get_modem_bits (dup_desc.ldsc+dup, bits_to_set, bits_to_clear, NULL);
return SCPE_OK;
}
t_stat dup_get_modem (int32 dup)
static t_stat dup_get_modem (int32 dup)
{
int32 modem_bits;
int32 old_rxcsr_a_modem_bits, new_rxcsr_a_modem_bits, old_rxcsr_b_modem_bits, new_rxcsr_b_modem_bits;
@ -630,7 +630,7 @@ DEVICE *dptr = DUPDPTR;
DIB *dib = (DIB *)dptr->ctxt;
CSRPA += IOPAGEBASE;
if ((dib->ba > (uint32)CSRPA) || ((uint32)CSRPA > (dib->ba + dib->lnt)))
if ((dib->ba > (uint32)CSRPA) || ((uint32)CSRPA > (dib->ba + dib->lnt)) || (DUPDPTR->flags & DEV_DIS))
return -1;
return ((uint32)CSRPA - dib->ba)/dib->lnt;
@ -638,7 +638,7 @@ return ((uint32)CSRPA - dib->ba)/dib->lnt;
void dup_set_callback_mode (int32 dup, PACKET_RECEIVE_CALLBACK receive, PACKET_TRANSMIT_COMPLETE_CALLBACK transmit)
{
if ((dup < 0) || (dup >= dup_desc.lines))
if ((dup < 0) || (dup >= dup_desc.lines) || (DUPDPTR->flags & DEV_DIS))
return;
dup_rcv_packet_callback[dup] = receive;
dup_xmt_complete_callback[dup] = transmit;
@ -646,29 +646,30 @@ dup_xmt_complete_callback[dup] = transmit;
int32 dup_get_line_speed (int32 dup)
{
if ((dup < 0) || (dup >= dup_desc.lines))
if ((dup < 0) || (dup >= dup_desc.lines) || (DUPDPTR->flags & DEV_DIS))
return -1;
return dup_speed[dup];
}
int32 dup_get_DCD (int32 dup)
{
if ((dup < 0) || (dup >= dup_desc.lines))
if ((dup < 0) || (dup >= dup_desc.lines) || (DUPDPTR->flags & DEV_DIS))
return -1;
return (dup_rxcsr[dup] & RXCSR_M_DCD) ? 1 : 0;
}
t_stat dup_set_DTR (int32 dup, t_bool state)
{
if ((dup < 0) || (dup >= dup_desc.lines))
if ((dup < 0) || (dup >= dup_desc.lines) || (DUPDPTR->flags & DEV_DIS))
return SCPE_IERR;
dup_set_modem (dup, state ? (RXCSR_M_DTR | RXCSR_M_RTS) : 0);
dup_ldsc[dup].rcve = state;
return SCPE_OK;
}
t_stat dup_set_DDCMP (int32 dup, t_bool state)
{
if ((dup < 0) || (dup >= dup_desc.lines))
if ((dup < 0) || (dup >= dup_desc.lines) || (DUPDPTR->flags & DEV_DIS))
return SCPE_IERR;
dup_rxcsr[dup] &= ~RXCSR_M_STRSYN;
@ -677,37 +678,7 @@ dup_parcsr[dup] &= ~PARCSR_M_NOCRC;
dup_parcsr[dup] |= (state ? 0: PARCSR_M_NOCRC);
dup_parcsr[dup] &= ~PARCSR_M_DECMODE;
dup_parcsr[dup] |= (state ? PARCSR_M_DECMODE : 0);
return SCPE_OK;
}
t_stat dup_rcv_byte (int32 dup)
{
sim_debug (DBG_TRC, DUPDPTR, "dup_rcv_byte(dup=%d) - %s, byte %d of %d\n", dup,
(dup_rxcsr[dup] & RXCSR_M_RCVEN) ? "enabled" : "disabled",
dup_rcvpkinoff[dup], dup_rcvpkoffset[dup]);
if (!(dup_rxcsr[dup] & RXCSR_M_RCVEN) || (dup_rcvpkoffset[dup] == 0) || (dup_rxcsr[dup] & RXCSR_M_RXDONE))
return SCPE_OK;
if (dup_rcv_packet_callback[dup]) {
dup_rcv_packet_callback[dup](dup, dup_rcvpacket[dup], dup_rcvpkoffset[dup]);
return SCPE_OK;
}
dup_rxcsr[dup] |= RXCSR_M_RXACT;
dup_rxdbuf[dup] &= ~RXDBUF_M_RCRCER;
dup_rxdbuf[dup] &= ~RXDBUF_M_RXDBUF;
dup_rxdbuf[dup] |= dup_rcvpacket[dup][dup_rcvpkinoff[dup]++];
dup_rxcsr[dup] |= RXCSR_M_RXDONE;
if (((dup_rcvpkinoff[dup] == 8) ||
(dup_rcvpkinoff[dup] >= dup_rcvpkoffset[dup])) &&
(0 == ddcmp_crc16 (0, dup_rcvpacket[dup], dup_rcvpkinoff[dup])))
dup_rxdbuf[dup] |= RXDBUF_M_RCRCER;
else
dup_rxdbuf[dup] &= ~RXDBUF_M_RCRCER;
if (dup_rcvpkinoff[dup] >= dup_rcvpkoffset[dup]) {
dup_rcvpkinoff[dup] = dup_rcvpkoffset[dup] = 0;
dup_rxcsr[dup] &= ~RXCSR_M_RXACT;
}
if (dup_rxcsr[dup] & RXCSR_M_RXIE)
dup_set_rxint (dup);
dup_rxcsr[dup] |= RXCSR_M_RCVEN;
return SCPE_OK;
}
@ -715,6 +686,9 @@ t_bool dup_put_msg_bytes (int32 dup, uint8 *bytes, size_t len, t_bool start, t_b
{
t_bool breturn = FALSE;
if ((dup < 0) || (dup >= dup_desc.lines) || (DUPDPTR->flags & DEV_DIS))
return FALSE;
if (!dup_xmtpkrdy[dup]) { /* Not Busy sending? */
if (start)
dup_xmtpkoffset[dup] = 0;
@ -748,11 +722,50 @@ if (!dup_xmtpkrdy[dup]) { /* Not Busy sending? */
}
sim_debug (DBG_TRC, DUPDPTR, "dup_put_msg_bytes(dup=%d, len=%d, start=%s, end=%s) %s\n",
dup, len, start ? "TRUE" : "FALSE", end ? "TRUE" : "FALSE", breturn ? "Good" : "Busy");
if (breturn && dup_xmtpkrdy[dup]) {
ddcmp_packet_trace (DBG_PKT, DUPDPTR, ">>> XMT Packet", dup_xmtpacket[dup], dup_xmtpkoffset[dup], TRUE);
if (dup_xmt_complete_callback[dup])
dup_svc(dup_units+dup);
}
return breturn;
}
static t_stat dup_rcv_byte (int32 dup)
{
sim_debug (DBG_TRC, DUPDPTR, "dup_rcv_byte(dup=%d) - %s, byte %d of %d\n", dup,
(dup_rxcsr[dup] & RXCSR_M_RCVEN) ? "enabled" : "disabled",
dup_rcvpkinoff[dup], dup_rcvpkoffset[dup]);
if (!(dup_rxcsr[dup] & RXCSR_M_RCVEN) || (dup_rcvpkoffset[dup] == 0) || (dup_rxcsr[dup] & RXCSR_M_RXDONE))
return SCPE_OK;
if (dup_rcv_packet_callback[dup]) {
dup_rcv_packet_callback[dup](dup, dup_rcvpacket[dup], dup_rcvpkoffset[dup]);
dup_rcvpkinoff[dup] = dup_rcvpkoffset[dup] = 0;
dup_rxcsr[dup] &= ~RXCSR_M_RXACT;
return SCPE_OK;
}
dup_rxcsr[dup] |= RXCSR_M_RXACT;
dup_rxdbuf[dup] &= ~RXDBUF_M_RCRCER;
dup_rxdbuf[dup] &= ~RXDBUF_M_RXDBUF;
dup_rxdbuf[dup] |= dup_rcvpacket[dup][dup_rcvpkinoff[dup]++];
dup_rxcsr[dup] |= RXCSR_M_RXDONE;
if (((dup_rcvpkinoff[dup] == 8) ||
(dup_rcvpkinoff[dup] >= dup_rcvpkoffset[dup])) &&
(0 == ddcmp_crc16 (0, dup_rcvpacket[dup], dup_rcvpkinoff[dup])))
dup_rxdbuf[dup] |= RXDBUF_M_RCRCER;
else
dup_rxdbuf[dup] &= ~RXDBUF_M_RCRCER;
if (dup_rcvpkinoff[dup] >= dup_rcvpkoffset[dup]) {
dup_rcvpkinoff[dup] = dup_rcvpkoffset[dup] = 0;
dup_rxcsr[dup] &= ~RXCSR_M_RXACT;
}
if (dup_rxcsr[dup] & RXCSR_M_RXIE)
dup_set_rxint (dup);
return SCPE_OK;
}
/* service routine to delay device activity */
t_stat dup_svc (UNIT *uptr)
static t_stat dup_svc (UNIT *uptr)
{
DEVICE *dptr = DUPDPTR;
int32 dup = (int32)(uptr-dptr->units);
@ -765,10 +778,9 @@ if (!(dup_txcsr[dup] & TXCSR_M_TXDONE) && (!dup_xmtpkrdy[dup])) {
dup_put_msg_bytes (dup, &data, (dup_txdbuf[dup] & TXDBUF_M_TEOM) && (dptr == &dup_dev) ? 0 : 1, dup_txdbuf[dup] & TXDBUF_M_TSOM, (dup_txdbuf[dup] & TXDBUF_M_TEOM));
if (dup_xmtpkrdy[dup]) { /* Packet ready to send? */
sim_debug(DBG_TRC, DUPDPTR, "dup_svc(dup=%d) - Packet Done %d bytes\n", dup, dup_xmtpkoffset[dup]);
ddcmp_packet_trace (DBG_PKT, DUPDPTR, ">>> XMT Packet", dup_xmtpacket[dup], dup_xmtpkoffset[dup], TRUE);
}
}
if (dup_xmtpkrdy[dup] && lp->xmte) {
if (dup_xmtpkrdy[dup] && (lp->xmte || (!lp->conn))) {
t_stat st = SCPE_OK;
while ((st == SCPE_OK) && (dup_xmtpkoutoff[dup] < dup_xmtpkoffset[dup])) {
@ -802,7 +814,7 @@ if (dup_rxcsr[dup] & RXCSR_M_RXACT)
return SCPE_OK;
}
t_stat dup_poll_svc (UNIT *uptr)
static t_stat dup_poll_svc (UNIT *uptr)
{
int32 dup, active, attached, c;
@ -839,7 +851,8 @@ for (dup=active=attached=0; dup < dup_desc.lines; dup++) {
dup_rcvpkoffset[dup] += 1;
if (dup_rcvpkoffset[dup] == 1) { /* Validate first byte in packet */
if ((dup_rxcsr[dup] & RXCSR_M_STRSYN) &&
(dup_rcvpacket[dup][0] == (dup_parcsr[dup] & PARCSR_M_ADSYNC))) {
((dup_rcvpacket[dup][0] == (dup_parcsr[dup] & PARCSR_M_ADSYNC)) ||
(dup_rcvpacket[dup][0] == DDCMP_DEL))) {
dup_rcvpkoffset[dup] = 0;
continue;
}
@ -898,7 +911,7 @@ return SCPE_OK;
/* Interrupt routines */
void dup_clr_rxint (int32 dup)
static void dup_clr_rxint (int32 dup)
{
dup_rxi = dup_rxi & ~(1 << dup); /* clr mux rcv int */
if (dup_rxi == 0) /* all clr? */
@ -907,7 +920,7 @@ else SET_INT (DUPRX); /* no, set intr */
return;
}
void dup_set_rxint (int32 dup)
static void dup_set_rxint (int32 dup)
{
dup_rxi = dup_rxi | (1 << dup); /* set mux rcv int */
SET_INT (DUPRX); /* set master intr */
@ -915,7 +928,7 @@ sim_debug(DBG_INT, DUPDPTR, "dup_set_rxint(dup=%d)\n", dup);
return;
}
int32 dup_rxinta (void)
static int32 dup_rxinta (void)
{
int32 dup;
@ -929,7 +942,7 @@ for (dup = 0; dup < dup_desc.lines; dup++) { /* find 1st mux */
return 0;
}
void dup_clr_txint (int32 dup)
static void dup_clr_txint (int32 dup)
{
dup_txi = dup_txi & ~(1 << dup); /* clr mux xmt int */
if (dup_txi == 0) /* all clr? */
@ -938,7 +951,7 @@ else SET_INT (DUPTX); /* no, set intr */
return;
}
void dup_set_txint (int32 dup)
static void dup_set_txint (int32 dup)
{
dup_txi = dup_txi | (1 << dup); /* set mux xmt int */
SET_INT (DUPTX); /* set master intr */
@ -946,7 +959,7 @@ sim_debug(DBG_INT, DUPDPTR, "dup_set_txint(dup=%d)\n", dup);
return;
}
int32 dup_txinta (void)
static int32 dup_txinta (void)
{
int32 dup;
@ -962,7 +975,7 @@ return 0;
/* Device reset */
t_stat dup_clear (int32 dup, t_bool flag)
static t_stat dup_clear (int32 dup, t_bool flag)
{
sim_debug(DBG_TRC, DUPDPTR, "dup_clear(dup=%d,flag=%d)\n", dup, flag);
@ -983,7 +996,7 @@ dup_ldsc[dup].rcve = 0; /* clr rcv enb */
return SCPE_OK;
}
t_stat dup_reset (DEVICE *dptr)
static t_stat dup_reset (DEVICE *dptr)
{
int32 i, ndev;
@ -1029,7 +1042,7 @@ if (ndev)
return auto_config (dptr->name, ndev); /* auto config */
}
t_stat dup_attach (UNIT *uptr, char *cptr)
static t_stat dup_attach (UNIT *uptr, char *cptr)
{
t_stat r;
DEVICE *dptr = DUPDPTR;
@ -1038,6 +1051,8 @@ char attach_string[512];
if (!cptr || !*cptr)
return SCPE_ARG;
if (!(uptr->flags & UNIT_ATTABLE))
return SCPE_NOATT;
sprintf (attach_string, "Line=%d,Buffered=16384,%s", dup, cptr);
r = tmxr_open_master (&dup_desc, attach_string); /* open master socket */
free (uptr->filename);
@ -1049,7 +1064,7 @@ sim_activate_after (dup_units+dup_desc.lines, 2000000); /* start poll */
return r;
}
t_stat dup_detach (UNIT *uptr)
static t_stat dup_detach (UNIT *uptr)
{
DEVICE *dptr = DUPDPTR;
int32 dup = (int32)(uptr-dptr->units);
@ -1075,7 +1090,7 @@ return tmxr_detach_ln (lp);
/* SET/SHOW SPEED processor */
t_stat dup_showspeed (FILE* st, UNIT* uptr, int32 val, void* desc)
static t_stat dup_showspeed (FILE* st, UNIT* uptr, int32 val, void* desc)
{
DEVICE *dptr = DUPDPTR;
int32 dup = (int32)(uptr-dptr->units);
@ -1087,7 +1102,7 @@ else
return SCPE_OK;
}
t_stat dup_setspeed (UNIT* uptr, int32 val, char* cptr, void* desc)
static t_stat dup_setspeed (UNIT* uptr, int32 val, char* cptr, void* desc)
{
DEVICE *dptr = DUPDPTR;
int32 dup = (int32)(uptr-dptr->units);
@ -1105,7 +1120,7 @@ return SCPE_OK;
/* SET LINES processor */
t_stat dup_setnl (UNIT *uptr, int32 val, char *cptr, void *desc)
static t_stat dup_setnl (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 newln, l;
uint32 i;
@ -1135,7 +1150,7 @@ dptr->numunits = newln + 1;
return dup_reset (dptr); /* setup lines and auto config */
}
t_stat dup_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
static t_stat dup_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
{
fprintf (st, "Bit Serial Synchronous interface (%s)\n\n", dptr->name);
fprintf (st, "The %s connects two systems to provide a network connection.\n", dptr->name);
@ -1155,7 +1170,7 @@ fprint_reg_help (st, dptr);
return SCPE_OK;
}
t_stat dup_help_attach (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
static t_stat dup_help_attach (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
{
fprintf (st, "The communication line performs input and output through a TCP session\n");
fprintf (st, "connected to a user-specified port. The ATTACH command specifies the\n");
@ -1170,7 +1185,7 @@ fprintf (st, "connecction destination system.\n\n");
return SCPE_OK;
}
char *dup_description (DEVICE *dptr)
static char *dup_description (DEVICE *dptr)
{
return (UNIBUS) ? "DUP11 bit synchronous interface" :
"DPV11 bit synchronous interface";

View File

@ -34,7 +34,7 @@
#ifndef PDP11_DUP_H_
#define PDP11_DUP_H_ 0
typedef void (*PACKET_RECEIVE_CALLBACK)(int32 dup, uint8 *buf, size_t len);
typedef void (*PACKET_RECEIVE_CALLBACK)(int32 dup, uint8 *buf, int len);
typedef void (*PACKET_TRANSMIT_COMPLETE_CALLBACK)(int32 dup, int status);
int32 dup_get_line_speed (int32 dup);

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
/* pdp11_kdp.h: KMC11/DUP11 Emulation
------------------------------------------------------------------------------
Written 2002 by Johnny Eriksson <bygg@stacken.kth.se>
Adapted to SIMH 3.? by Robert M. A. Jarratt in 2013
------------------------------------------------------------------------------
Modification history:
14-Apr-13 RJ Took original sources into latest source code.
------------------------------------------------------------------------------*/
#include "pdp10_defs.h"
#ifndef PDP11_KDP_H
#define PDP11_KDP_H
#define KMC_RDX 8 /* Octal in this incarnation. */
#define DUP_RDX 8
#endif

971
PDP11/pdp11_kmc.c Normal file
View File

@ -0,0 +1,971 @@
/* pdp11_kdp.c: KMC11/DUP11 Emulation
------------------------------------------------------------------------------
Written 2002 by Johnny Eriksson <bygg@stacken.kth.se>
Adapted to SIMH 3.? by Robert M. A. Jarratt in 2013
------------------------------------------------------------------------------
Modification history:
14-Apr-13 RJ Took original sources into latest source code.
15-Feb-02 JE Massive changes/cleanups.
23-Jan-02 JE Modify for version 2.9.
17-Jan-02 JE First attempt.
------------------------------------------------------------------------------*/
/*
** Loose ends, known problems etc:
**
** We don't handle NXM on the unibus. At all. In fact, we don't
** generate control-outs.
**
** We don't do anything but full-duplex DDCMP.
**
** We don't implement buffer flushing.
*/
#if defined (VM_PDP10) /* PDP10 version */
#include "pdp10_defs.h"
#elif defined (VM_VAX) /* VAX version */
#include "vax_defs.h"
#else /* PDP-11 version */
#include "pdp11_defs.h"
#endif
#define KMC_RDX 8
#include "pdp11_dup.h"
#define DF_CMD 0001 /* Print commands. */
#define DF_TX 0002 /* Print tx done. */
#define DF_RX 0004 /* Print rx done. */
#define DF_DATA 0010 /* Print data. */
#define DF_QUEUE 0020 /* Print rx/tx queue changes. */
#define DF_TRC 0040 /* Detailed trace. */
#define DF_INF 0100 /* Info */
extern int32 IREQ (HLVL);
extern int32 tmxr_poll; /* calibrated delay */
extern int32 clk_tps; /* clock ticks per second */
extern int32 tmr_poll; /* instructions per tick */
t_stat unibus_read(int32* data, int32 addr)
{
t_stat ans;
uint16 d;
*data = 0;
ans = Map_ReadW (addr, 2, &d);
*data = d;
return ans;
}
t_stat unibus_write(int32 data, int32 addr)
{
uint16 d;
d = data & 0xFFFF;
return Map_WriteW (addr, 2, &d);
}
t_stat dma_write(int32 ba, uint8* data, int length)
{
t_stat r;
uint32 wd;
if (length <= 0) return SCPE_OK;
if (ba & 1) {
r = unibus_read((int32 *)&wd, ba-1);
if (r != SCPE_OK)
return r;
wd &= 0377;
wd |= (*data++ << 8);
r = unibus_write(wd, ba-1);
if (r != SCPE_OK)
return r;
length -= 1;
ba += 1;
}
while (length >= 2) {
wd = *data++;
wd |= *data++ << 8;
r = unibus_write(wd, ba);
if (r != SCPE_OK)
return r;
length -= 2;
ba += 2;
}
if (length == 1) {
r = unibus_read((int32 *)&wd, ba);
if (r != SCPE_OK)
return r;
wd &= 0177400;
wd |= *data++;
r = unibus_write(wd, ba);
if (r != SCPE_OK)
return r;
}
return SCPE_OK;
}
/* dma a block from main memory */
t_stat dma_read(int32 ba, uint8* data, int length)
{
t_stat r;
uint32 wd;
if (ba & 1) { /* Starting on an odd boundary? */
r = unibus_read((int32 *)&wd, ba-1);
if (r != SCPE_OK) {
return r;
}
*data++ = wd >> 8;
ba += 1;
length -= 1;
}
while (length > 0) {
r = unibus_read((int32 *)&wd, ba);
if (r != SCPE_OK) {
return r;
}
*data++ = wd & 0377;
if (length > 1) {
*data++ = wd >> 8;
}
ba += 2;
length -= 2;
}
return SCPE_OK;
}
/* bits, sel0: */
#define KMC_RUN 0100000 /* Run bit. */
#define KMC_MRC 0040000 /* Master clear. */
#define KMC_CWR 0020000 /* CRAM write. */
#define KMC_SLU 0010000 /* Step Line Unit. */
#define KMC_LUL 0004000 /* Line Unit Loop. */
#define KMC_RMO 0002000 /* ROM output. */
#define KMC_RMI 0001000 /* ROM input. */
#define KMC_SUP 0000400 /* Step microprocessor. */
#define KMC_RQI 0000200 /* Request input. */
#define KMC_IEO 0000020 /* Interrupt enable output. */
#define KMC_IEI 0000001 /* Interrupt enable input. */
/* bits, sel2: */
#define KMC_OVR 0100000 /* Buffer overrun. */
#define KMC_LINE 0177400 /* Line number. */
#define KMC_RDO 0000200 /* Ready for output transaction. */
#define KMC_RDI 0000020 /* Ready for input transaction. */
#define KMC_IOT 0000004 /* I/O type, 1 = rx, 0 = tx. */
#define KMC_CMD 0000003 /* Command code. */
# define CMD_BUFFIN 0 /* Buffer in. */
# define CMD_CTRLIN 1 /* Control in. */
# define CMD_BASEIN 3 /* Base in. */
# define CMD_BUFFOUT 0 /* Buffer out. */
# define CMD_CTRLOUT 1 /* Control out. */
/* bits, sel6: */
#define BFR_EOM 0010000 /* End of message. */
#define BFR_KIL 0010000 /* Buffer Kill. */
/* buffer descriptor list bits: */
#define BDL_LDS 0100000 /* Last descriptor in list. */
#define BDL_RSY 0010000 /* Resync transmitter. */
#define BDL_XAD 0006000 /* Buffer address bits 17 & 16. */
#define BDL_EOM 0001000 /* End of message. */
#define BDL_SOM 0000400 /* Start of message. */
#define KMC_CRAMSIZE 1024 /* Size of CRAM. */
#ifndef MAXDUP
# define MAXDUP 2 /* Number of DUP-11's we can handle. */
#endif
#define MAXQUEUE 16 /* Number of rx bdl's we can handle. */
#define MAXMSG 2000 /* Largest message we handle. */
/* local variables: */
int kmc_running;
uint32 kmc_sel0;
uint32 kmc_sel2;
uint32 kmc_sel4;
uint32 kmc_sel6;
int kmc_rxi;
int kmc_txi;
uint16 kmc_microcode[KMC_CRAMSIZE];
struct dupblock {
int32 dupnumber; /* Line Number of all DUP11's on Unibus */
uint32 rxqueue[MAXQUEUE]; /* Queue of bd's to receive into. */
uint32 rxcount; /* No. bd's in above. */
uint32 rxnext; /* Next bd to receive into. */
uint32 txqueue[MAXQUEUE]; /* Queue of bd's to transmit. */
uint32 txcount; /* No. bd's in above. */
uint32 txnext; /* Next bd to transmit. */
uint32 txnow; /* No. bd's we are transmitting now. */
uint8 txbuf[MAXMSG]; /* contains next buffer to transmit */
uint8 txbuflen; /* length of message in buffer */
uint8 txbufbytessent; /* number of bytes from the message actually sent so far */
};
typedef struct dupblock dupblock;
dupblock dup[MAXDUP] = { 0 };
/* state/timing/etc: */
t_bool kmc_output = FALSE; /* Flag, need at least one output. */
int32 kmc_output_duetime; /* time to activate after buffer transmit */
/* forward decls: */
t_stat kmc_rd(int32* data, int32 PA, int32 access);
t_stat kmc_wr(int32 data, int32 PA, int32 access);
int32 kmc_rxint (void);
int32 kmc_txint (void);
void kmc_setrxint();
void kmc_clrrxint();
void kmc_settxint();
void kmc_clrtxint();
t_stat kmc_svc(UNIT * uptr);
t_stat kmc_reset(DEVICE * dptr);
void prbdl(uint32 dbits, DEVICE *dev, int32 ba, int prbuf);
DEBTAB kmc_debug[] = {
{"CMD", DF_CMD},
{"TX", DF_TX},
{"RX", DF_RX},
{"DATA", DF_DATA},
{"QUEUE", DF_QUEUE},
{"TRC", DF_TRC},
{"INF", DF_INF},
{0}
};
/* KMC11 data structs: */
#define IOLN_KMC 010
DIB kmc_dib = { IOBA_AUTO, IOLN_KMC, &kmc_rd, &kmc_wr, 2, IVCL (KMCA), VEC_AUTO, {&kmc_rxint, &kmc_txint} };
UNIT kmc_unit = { UDATA (&kmc_svc, 0, 0) };
REG kmc_reg[] = {
{ ORDATA ( SEL0, kmc_sel0, 16) },
{ ORDATA ( SEL2, kmc_sel2, 16) },
{ ORDATA ( SEL4, kmc_sel4, 16) },
{ ORDATA ( SEL6, kmc_sel6, 16) },
{ NULL },
};
MTAB kmc_mod[] = {
{ MTAB_XTD|MTAB_VDV, 010, "address", "ADDRESS",
&set_addr, &show_addr, NULL, "IP address" },
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "VECTOR", NULL,
&set_vec, &show_vec, NULL, "Interrupt vector" },
{ 0 },
};
DEVICE kmc_dev =
{
"KMC", &kmc_unit, kmc_reg, kmc_mod,
1, KMC_RDX, 13, 1, KMC_RDX, 8,
NULL, NULL, &kmc_reset,
NULL, NULL, NULL, &kmc_dib,
DEV_UBUS | DEV_DIS | DEV_DISABLE | DEV_DEBUG, 0, kmc_debug
};
void dup_send_complete (int32 dup, int status)
{
sim_activate_notbefore (&kmc_unit, kmc_output_duetime);
}
t_stat send_buffer(int dupindex)
{
t_stat r = SCPE_OK;
dupblock* d;
d = &dup[dupindex];
if (d->txnow > 0) {
if (dup_put_msg_bytes (d->dupnumber, d->txbuf, d->txbuflen, TRUE, TRUE)) {
int32 speed = dup_get_line_speed(d->dupnumber);
d->txnext += d->txnow;
d->txnow = 0;
kmc_output = TRUE;
kmc_output_duetime = sim_grtime();
if (speed > 7)
kmc_output_duetime += (tmxr_poll * clk_tps)/(speed/8);
}
}
return r;
}
char *format_packet_data(uint8 *data, size_t size)
{
static char buf[3 * 128 + 1];
int buflen;
int i;
int n;
buflen = 0;
n = (size > 128) ? 128 : size;
for (i = 0; i < n; i++)
{
sprintf(&buf[buflen], " %02X", data[i]);
buflen += 3;
}
return buf;
}
/*
** Update interrupt status:
*/
void kmc_updints(void)
{
if (kmc_sel0 & KMC_IEI) {
if (kmc_sel2 & KMC_RDI) {
kmc_setrxint();
} else {
kmc_clrrxint();
}
}
if (kmc_sel0 & KMC_IEO) {
if (kmc_sel2 & KMC_RDO) {
kmc_settxint();
} else {
kmc_clrtxint();
}
}
}
/*
** Try to set the RDO bit. If it can be set, set it and return true,
** else return false.
*/
t_bool kmc_getrdo(void)
{
if (kmc_sel2 & KMC_RDO) /* Already on? */
return FALSE;
if (kmc_sel2 & KMC_RDI) /* Busy doing input? */
return FALSE;
kmc_sel2 |= KMC_RDO;
return TRUE;
}
/*
** Try to do an output command.
*/
void kmc_tryoutput(void)
{
int i, j;
dupblock* d;
uint32 ba;
if (kmc_output) {
kmc_output = FALSE;
for (i = 0; i < MAXDUP; i += 1) {
d = &dup[i];
if (d->rxnext > 0) {
kmc_output = TRUE; /* At least one, need more scanning. */
if (kmc_getrdo()) {
ba = d->rxqueue[0];
kmc_sel2 &= ~KMC_LINE;
kmc_sel2 |= (i << 8);
kmc_sel2 &= ~KMC_CMD;
kmc_sel2 |= CMD_BUFFOUT;
kmc_sel2 |= KMC_IOT; /* Buffer type. */
kmc_sel4 = ba & 0177777;
kmc_sel6 = (ba >> 2) & 0140000;
kmc_sel6 |= BFR_EOM;
for (j = 1; j < (int)d->rxcount; j += 1) {
d->rxqueue[j-1] = d->rxqueue[j];
}
d->rxcount -= 1;
d->rxnext -= 1;
sim_debug(DF_QUEUE, &kmc_dev, "DUP%d: (tryout) ba = %6o, rxcount = %d, rxnext = %d\r\n", i, ba, d->rxcount, d->rxnext);
kmc_updints();
}
return;
}
if (d->txnext > 0) {
kmc_output = TRUE; /* At least one, need more scanning. */
if (kmc_getrdo()) {
ba = d->txqueue[0];
kmc_sel2 &= ~KMC_LINE;
kmc_sel2 |= (i << 8);
kmc_sel2 &= ~KMC_CMD;
kmc_sel2 |= CMD_BUFFOUT;
kmc_sel2 &= ~KMC_IOT; /* Buffer type. */
kmc_sel4 = ba & 0177777;
kmc_sel6 = (ba >> 2) & 0140000;
for (j = 1; j < (int)d->txcount; j += 1) {
d->txqueue[j-1] = d->txqueue[j];
}
d->txcount -= 1;
d->txnext -= 1;
sim_debug(DF_QUEUE, &kmc_dev, "DUP%d: (tryout) ba = %6o, txcount = %d, txnext = %d\r\n", i, ba, d->txcount, d->txnext);
kmc_updints();
}
return;
}
}
}
}
/*
** Try to start output. Does nothing if output is already in progress,
** or if there are no packets in the output queue.
*/
void dup_tryxmit(int dupindex)
{
dupblock* d;
int pos; /* Offset into transmit buffer. */
uint32 bda; /* Buffer Descriptor Address. */
uint32 bd[3]; /* Buffer Descriptor. */
uint32 bufaddr; /* Buffer Address. */
uint32 buflen; /* Buffer Length. */
int msglen; /* Message length. */
int dcount; /* Number of descriptors to use. */
t_bool lds; /* Found last descriptor. */
int i; /* Random loop var. */
d = &dup[dupindex];
if (d->txnow > 0) return; /* If xmit in progress, quit. */
if (d->txcount <= d->txnext) return;
/*
** check the transmit buffers we have queued up and find out if
** we have a full DDCMP frame.
*/
lds = FALSE; /* No last descriptor yet. */
dcount = msglen = 0; /* No data yet. */
/* accumulate length, scan for LDS flag */
for (i = d->txnext; i < (int)d->txcount; i += 1) {
bda = d->txqueue[i];
(void) unibus_read((int32 *)&bd[0], bda);
(void) unibus_read((int32 *)&bd[1], bda + 2);
(void) unibus_read((int32 *)&bd[2], bda + 4);
dcount += 1; /* Count one more descriptor. */
msglen += bd[1]; /* Count some more bytes. */
if (bd[2] & BDL_LDS) {
lds = TRUE;
break;
}
}
if (!lds) return; /* If no end of message, give up. */
d->txnow = dcount; /* Got a full frame, will send or ignore it. */
if (msglen <= MAXMSG) { /* If message fits in buffer, - */
pos = 0;
d->txbuflen = msglen;
for (i = d->txnext; i < (int)(d->txnext + dcount); i += 1) {
bda = d->txqueue[i];
(void) unibus_read((int32 *)&bd[0], bda);
(void) unibus_read((int32 *)&bd[1], bda + 2);
(void) unibus_read((int32 *)&bd[2], bda + 4);
bufaddr = bd[0] + ((bd[2] & 06000) << 6);
buflen = bd[1];
(void) dma_read(bufaddr, &d->txbuf[pos], buflen);
pos += buflen;
}
send_buffer(dupindex);
}
}
/*
** Here with a bdl for some new receive buffers. Set them up.
*/
void dup_newrxbuf(int line, int32 ba)
{
dupblock* d;
int32 w3;
d = &dup[line];
for (;;) {
if (d->rxcount < MAXQUEUE) {
d->rxqueue[d->rxcount] = ba;
d->rxcount += 1;
sim_debug(DF_QUEUE, &kmc_dev, "Queued rx buffer %d, descriptor address=0x%04X(%06o octal)\n", d->rxcount - 1, ba, ba);
}
else
{
sim_debug(DF_QUEUE, &kmc_dev, "(newrxb) no more room for buffers\n");
}
(void) unibus_read(&w3, ba + 4);
if (w3 & BDL_LDS)
break;
ba += 6;
}
sim_debug(DF_QUEUE, &kmc_dev, "(newrxb) rxcount = %d, rxnext = %d\n", d->rxcount, d->rxnext);
}
/*
** Here with a bdl for some new transmit buffers. Set them up and then
** try to start output if not already active.
*/
void dup_newtxbuf(int line, int32 ba)
{
dupblock* d;
int32 w3;
d = &dup[line];
for (;;) {
if (d->txcount < MAXQUEUE) {
d->txqueue[d->txcount] = ba;
d->txcount += 1;
}
(void) unibus_read(&w3, ba + 4);
if (w3 & BDL_LDS)
break;
ba += 6;
}
sim_debug(DF_QUEUE, &kmc_dev, "DUP%d: (newtxb) txcount = %d, txnext = %d\r\n", line, d->txcount, d->txnext);
dup_tryxmit(line); /* Try to start output. */
}
/*
** Here to store a block of data into a receive buffer.
*/
void dup_receive(int line, uint8* data, int count)
{
dupblock* d;
uint32 bda;
uint32 bd[3];
uint32 ba;
uint32 bl;
d = &dup[line];
if (d->rxcount > d->rxnext) {
count -= 2; /* strip incoming CSR */
bda = d->rxqueue[d->rxnext];
(void) unibus_read((int32 *)&bd[0], bda);
(void) unibus_read((int32 *)&bd[1], bda + 2);
(void) unibus_read((int32 *)&bd[2], bda + 4);
sim_debug(DF_QUEUE, &kmc_dev, "dup_receive ba=0x%04x(%06o octal). Descriptor is:\n", bda, bda);
prbdl(DF_QUEUE, &kmc_dev, bda, 0);
ba = bd[0] + ((bd[2] & 06000) << 6);
bl = bd[1];
if (count > (int)bl) count = bl; /* XXX */
sim_debug(DF_QUEUE, &kmc_dev, "Receive buf[%d] writing to address=0x%04X(%06o octal), bytes=%d\n", d->rxnext, ba, ba, count);
(void) dma_write(ba, data, count);
bd[2] |= (BDL_SOM | BDL_EOM);
(void) unibus_write(bd[2], bda + 4);
d->rxnext += 1;
}
}
/*
** testing testing
*/
void prbdl(uint32 dbits, DEVICE *dev, int32 ba, int prbuf)
{
int32 w1, w2, w3;
int32 dp;
for (;;) {
(void) unibus_read(&w1, ba);
(void) unibus_read(&w2, ba + 2);
(void) unibus_read(&w3, ba + 4);
sim_debug(dbits, dev, " Word 1 = 0x%04X(%06o octal)\n", w1, w1);
sim_debug(dbits, dev, " Word 2 = 0x%04X(%06o octal)\n", w2, w2);
sim_debug(dbits, dev, " Word 3 = 0x%04X(%06o octal)\n", w3, w3);
if (prbuf) {
if (w2 > 20) w2 = 20;
dp = w1 + ((w3 & 06000) << 6);
while (w2 > 0) {
(void) unibus_read(&w1, dp);
dp += 2;
w2 -= 2;
sim_debug(DF_CMD, dev, " %2x %2x", w1 & 0xff, w1 >> 8);
}
sim_debug(DF_CMD, dev, "\r\n");
}
if (w3 & BDL_LDS) break;
ba += 6;
}
}
void kmc_setrxint()
{
sim_debug(DF_TRC, &kmc_dev, "set rx interrupt\n");
kmc_rxi = 1;
SET_INT(KMCA);
}
void kmc_clrrxint()
{
sim_debug(DF_TRC, &kmc_dev, "clear rx interrupt\n");
kmc_rxi = 0;
CLR_INT(KMCA);
}
void kmc_settxint()
{
sim_debug(DF_TRC, &kmc_dev, "set tx interrupt\n");
kmc_txi = 1;
SET_INT(KMCB);
}
void kmc_clrtxint()
{
sim_debug(DF_TRC, &kmc_dev, "clear tx interrupt\n");
kmc_txi = 0;
CLR_INT(KMCB);
}
/*
** Here to perform an input command:
*/
void kmc_doinput(void)
{
int line;
int32 ba;
dupblock* d;
line = (kmc_sel2 & 077400) >> 8;
d = &dup[line];
ba = ((kmc_sel6 & 0140000) << 2) + kmc_sel4;
sim_debug(DF_CMD, &kmc_dev, "Input command: sel2=%06o sel4=%06o sel6=%06o\n", kmc_sel2, kmc_sel4, kmc_sel6);
sim_debug(DF_CMD, &kmc_dev, "Line %d ba=0x%04x(%06o octal)\n", line, ba, ba);
switch (kmc_sel2 & 7) {
case 0:
sim_debug(DF_CMD, &kmc_dev, "Descriptor for tx buffer:\n");
prbdl(DF_CMD, &kmc_dev, ba, 1);
break;
case 4:
sim_debug(DF_CMD, &kmc_dev, "Descriptor for rx buffer:\n");
prbdl(DF_CMD, &kmc_dev, ba, 0);
}
switch (kmc_sel2 & 7) {
case 0: /* Buffer in, data to send: */
dup_newtxbuf(line, ba);
break;
case 1: /* Control in. */
/*
** This lets us setup the dup for DDCMP mode, and possibly turn up DTR
** since nothing else seems to do that.
*/
sim_debug(DF_CMD, &kmc_dev, "Running DDCMP in full duplex on Line %d (dup %d):\n", line, d->dupnumber);
dup_set_DDCMP (d->dupnumber, TRUE);
dup_set_DTR (d->dupnumber, TRUE);
dup_set_callback_mode (d->dupnumber, dup_receive, dup_send_complete);
break;
case 3: /* Base in. */
/*
** This tell the KMC what unibus address the dup is at.
*/
sim_debug(DF_CMD, &kmc_dev, "Setting Line %d DUP unibus address to: 0x%x (0%o octal)\n", line, kmc_sel6+IOPAGEBASE, kmc_sel6+IOPAGEBASE);
d->dupnumber = dup_csr_to_linenum (kmc_sel6);
break;
case 4: /* Buffer in, receive buffer for us... */
dup_newrxbuf(line, ba);
break;
}
}
/*
** master clear the KMC:
*/
void kmc_mclear(void)
{
int i;
dupblock* d;
sim_debug(DF_INF, &kmc_dev, "Master clear\n");
kmc_running = 0;
kmc_sel0 = KMC_MRC;
kmc_sel2 = 0;
kmc_sel4 = 0;
kmc_sel6 = 0;
kmc_rxi = 0;
kmc_txi = 0;
/* clear out the dup's as well. */
for (i = 0; i < MAXDUP; i += 1) {
d = &dup[i];
d->rxcount = 0;
d->rxnext = 0;
d->txcount = 0;
d->txnext = 0;
d->txnow = 0;
}
sim_cancel(&kmc_unit); /* Stop the clock. */
sim_activate_after(&kmc_unit, 2000000);
}
/*
** KMC11, read registers:
*/
t_stat kmc_rd(int32* data, int32 PA, int32 access)
{
switch ((PA >> 1) & 03) {
case 00:
*data = kmc_sel0;
break;
case 01:
*data = kmc_sel2;
break;
case 02:
*data = kmc_sel4;
break;
case 03:
if (kmc_sel0 == KMC_RMO)
{
kmc_sel6 = kmc_microcode[kmc_sel4 & (KMC_CRAMSIZE - 1)];
}
*data = kmc_sel6;
break;
}
sim_debug(DF_TRC, &kmc_dev, "kmc_rd(), addr=0%o access=%d, result=0x%04x\n", PA, access, *data);
return SCPE_OK;
}
void kmc_domicroinstruction()
{
static uint32 save;
if (kmc_sel6 == 041222) /* MOVE <MEM><BSEL2> */
{
kmc_sel2 = (kmc_sel2 & ~0xFF) | (save & 0xFF);
}
else if (kmc_sel6 == 0122440) /* MOVE <BSEL2><MEM> */
{
save = kmc_sel2 & 0xFF;
}
}
/*
** KMC11, write registers:
*/
t_stat kmc_wr(int32 data, int32 PA, int32 access)
{
uint32 toggle;
int reg = PA & 07;
int sel = (PA >> 1) & 03;
if (access == WRITE)
{
sim_debug(DF_TRC, &kmc_dev, "kmc_wr(), addr=0%08o, SEL%d, data=0x%04x\n", PA, reg, data);
}
else
{
sim_debug(DF_TRC, &kmc_dev, "kmc_wr(), addr=0x%08o, BSEL%d, data=%04x\n", PA, reg, data);
}
switch (sel) {
case 00:
if (access == WRITEB) {
data = (PA & 1)
? (((data & 0377) << 8) | (kmc_sel0 & 0377))
: ((data & 0377) | (kmc_sel0 & 0177400));
}
toggle = kmc_sel0 ^ data;
kmc_sel0 = data;
if (kmc_sel0 & KMC_MRC) {
kmc_mclear();
break;
}
if ((toggle & KMC_CWR) && (toggle & KMC_RMO) && !(data & KMC_CWR) && !(data & KMC_RMO)) {
kmc_microcode[kmc_sel4 & (KMC_CRAMSIZE - 1)] = kmc_sel6;
}
if ((toggle & KMC_RMI) && (toggle & KMC_SUP) && !(data & KMC_RMI) && !(data & KMC_SUP))
{
kmc_domicroinstruction();
}
if (toggle & KMC_RUN) { /* Changing the run bit? */
if (kmc_sel0 & KMC_RUN)
{
sim_debug(DF_INF, &kmc_dev, "Started RUNing\n");
kmc_running = 1;
}
else
{
sim_debug(DF_INF, &kmc_dev, "Stopped RUNing\n");
sim_cancel(&kmc_unit);
kmc_running = 0;
}
}
break;
case 01:
if (access == WRITEB) {
data = (PA & 1)
? (((data & 0377) << 8) | (kmc_sel2 & 0377))
: ((data & 0377) | (kmc_sel2 & 0177400));
}
if (kmc_running)
{
if ((kmc_sel2 & KMC_RDI) && (!(data & KMC_RDI))) {
kmc_sel2 = data;
kmc_doinput();
} else if ((kmc_sel2 & KMC_RDO) && (!(data & KMC_RDO))) {
kmc_sel2 = data;
kmc_tryoutput();
} else {
kmc_sel2 = data;
}
}
else
{
kmc_sel2 = data;
}
break;
case 02:
if (kmc_sel0 & KMC_RMO) {
kmc_sel6 = kmc_microcode[data & (KMC_CRAMSIZE - 1)];
}
kmc_sel4 = data;
break;
case 03:
kmc_sel6 = data;
break;
}
if (kmc_running)
{
if (kmc_output) {
kmc_tryoutput();
}
if (kmc_sel0 & KMC_RQI) {
if (!(kmc_sel2 & KMC_RDO)) {
kmc_sel2 |= KMC_RDI;
}
}
kmc_updints();
}
return SCPE_OK;
}
int32 kmc_rxint (void)
{
int32 ans = 0; /* no interrupt request active */
if (kmc_rxi != 0)
{
ans = kmc_dib.vec;
kmc_clrrxint();
}
sim_debug(DF_TRC, &kmc_dev, "rx interrupt ack %d\n", ans);
return ans;
}
int32 kmc_txint (void)
{
int32 ans = 0; /* no interrupt request active */
if (kmc_txi != 0)
{
ans = kmc_dib.vec + 4;
kmc_clrtxint();
}
sim_debug(DF_TRC, &kmc_dev, "tx interrupt ack %d\n", ans);
return ans;
}
/*
** KMC11 service routine:
*/
t_stat kmc_svc (UNIT* uptr)
{
int dupno;
dupno = uptr->u3;
if (kmc_output) {
kmc_tryoutput(); /* Try to do an output transaction. */
}
sim_activate_after(uptr, 2000000);
return SCPE_OK;
}
/*
** KMC11, reset device:
*/
t_stat kmc_reset(DEVICE* dptr)
{
kmc_sel0 = 0;
kmc_sel2 = 0;
kmc_sel4 = 0;
kmc_sel6 = 0;
return auto_config (dptr->name, ((dptr->flags & DEV_DIS)? 0: 1 )); /* auto config */
}

View File

@ -174,9 +174,9 @@ DEVICE *sim_devices[] = {
&dmc_dev[1],
&dmc_dev[2],
&dmc_dev[3],
&kmc_dev,
&dup_dev,
&dpv_dev,
&kmc_dev,
NULL
};

View File

@ -247,6 +247,10 @@
RelativePath="..\PDP11\pdp11_dz.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_kmc.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_pt.c"
>
@ -308,6 +312,10 @@
RelativePath="..\PDP11\pdp11_ddcmp.h"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dup.h"
>
</File>
<File
RelativePath="..\scp.h"
>

View File

@ -243,10 +243,6 @@
RelativePath="..\PDP11\pdp11_io_lib.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_kdp.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_ke.c"
>
@ -255,6 +251,10 @@
RelativePath="..\PDP11\pdp11_kg.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_kmc.c"
>
</File>
<File
RelativePath="..\PDP11\pdp11_lp.c"
>
@ -432,6 +432,10 @@
RelativePath="..\PDP11\pdp11_dmc.h"
>
</File>
<File
RelativePath="..\PDP11\pdp11_dup.h"
>
</File>
<File
RelativePath="..\PDP11\pdp11_io_lib.h"
>

View File

@ -534,7 +534,8 @@ PDP11_SOURCE1 = $(PDP11_DIR)PDP11_FP.C,$(PDP11_DIR)PDP11_CPU.C,\
$(PDP11_DIR)PDP11_SYS.C,$(PDP11_DIR)PDP11_TC.C, \
$(PDP11_DIR)PDP11_CPUMOD.C,$(PDP11_DIR)PDP11_CR.C,\
$(PDP11_DIR)PDP11_TA.C,$(PDP11_DIR)PDP11_DMC.C,\
$(PDP11_DIR)PDP11_DUP.C,$(PDP11_DIR)PDP11_IO_LIB.C
$(PDP11_DIR)PDP11_DUP.C,$(PDP11_DIR)PDP11_KMC.C,\
$(PDP11_DIR)PDP11_IO_LIB.C
PDP11_LIB2 = $(LIB_DIR)PDP11L2-$(ARCH).OLB
PDP11_SOURCE2 = $(PDP11_DIR)PDP11_TM.C,$(PDP11_DIR)PDP11_TS.C,\
$(PDP11_DIR)PDP11_IO.C,$(PDP11_DIR)PDP11_RQ.C,\
@ -562,7 +563,7 @@ PDP10_SOURCE = $(PDP10_DIR)PDP10_FE.C,\
$(PDP10_DIR)PDP10_TIM.C,$(PDP10_DIR)PDP10_TU.C,\
$(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_DZ.C,\
$(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_CR.C,\
$(PDP11_DIR)PDP11_DUP.C
$(PDP11_DIR)PDP11_DUP.C,$(PDP11_DIR)PDP11_KMC.C
PDP10_OPTIONS = /INCL=($(SIMH_DIR),$(PDP10_DIR),$(PDP11_DIR))\
/DEF=($(CC_DEFS),"USE_INT64=1","VM_PDP10=1"$(PCAP_DEFS))

View File

@ -665,7 +665,7 @@ 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_io_lib.c
${PDP11D}/pdp11_dup.c ${PDP11D}/pdp11_kmc.c ${PDP11D}/pdp11_io_lib.c
PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT}
@ -770,7 +770,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_kmc.c
PDP10_OPT = -DVM_PDP10 -DUSE_INT64 -I ${PDP10D} -I ${PDP11D}