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:
parent
02fcc2ced6
commit
531cdd42f7
@ -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 */
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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);
|
||||
|
||||
1335
PDP11/pdp11_kdp.c
1335
PDP11/pdp11_kdp.c
File diff suppressed because it is too large
Load Diff
@ -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
971
PDP11/pdp11_kmc.c
Normal 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 */
|
||||
}
|
||||
@ -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
|
||||
};
|
||||
|
||||
|
||||
@ -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"
|
||||
>
|
||||
|
||||
@ -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"
|
||||
>
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
4
makefile
4
makefile
@ -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}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user