Added needed DUP interfaces to allow use by KMC11/KDP.

This commit is contained in:
Mark Pizzolato 2013-06-02 13:19:23 -07:00
parent 4064cc079a
commit 596cb3f580
3 changed files with 136 additions and 101 deletions

View file

@ -41,7 +41,105 @@
/* Support routines */
void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail);
/* crc16 polynomial x^16 + x^15 + x^2 + 1 (0xA001) CCITT LSB */
static uint16 crc16_nibble[16] = {
0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400,
};
static uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len)
{
const unsigned char* buf = (const unsigned char*)vbuf;
while(0 != len--) {
crc = (crc>>4) ^ crc16_nibble[(*buf ^ crc) & 0xF];
crc = (crc>>4) ^ crc16_nibble[((*buf++)>>4 ^ crc) & 0xF];
};
return(crc);
}
/* Debug routines */
#include <ctype.h>
static void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail)
{
if (sim_deb && dptr && (reason & dptr->dctrl)) {
sim_debug(reason, dptr, "%s len: %d\n", txt, len);
if (detail) {
int i, same, group, sidx, oidx;
char outbuf[80], strbuf[18];
static char hex[] = "0123456789ABCDEF";
switch (msg[0]) {
case DDCMP_SOH: /* Data Message */
sim_debug (reason, dptr, "Data Message, Link: %d, Count: %d, Resp: %d, Num: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)|msg[1], msg[3], msg[4],
(0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)|msg[1]))) ? "OK" : "BAD");
break;
case DDCMP_ENQ: /* Control Message */
sim_debug (reason, dptr, "Control: Type: %d ", msg[1]);
switch (msg[1]) {
case 1: /* ACK */
sim_debug (reason, dptr, "(ACK) ACKSUB: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]);
break;
case 2: /* NAK */
sim_debug (reason, dptr, "(NAK) Reason: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]);
break;
case 3: /* REP */
sim_debug (reason, dptr, "(REP) REPSUB: %d, Link: %d, Num: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[4]);
break;
case 6: /* STRT */
sim_debug (reason, dptr, "(STRT) STRTSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6);
break;
case 7: /* STACK */
sim_debug (reason, dptr, "(STACK) STCKSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6);
break;
default: /* Unknown */
sim_debug (reason, dptr, "(Unknown=0%o)\n", msg[1]);
break;
}
if (len != 8) {
sim_debug (reason, dptr, "Unexpected Control Message Length: %d expected 8\n", len);
}
if (0 != ddcmp_crc16 (0, msg, len)) {
sim_debug (reason, dptr, "Unexpected Message CRC\n");
}
break;
case DDCMP_DLE: /* Maintenance Message */
sim_debug (reason, dptr, "Maintenance Message, Link: %d, Count: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)| msg[1],
(0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)| msg[1]))) ? "OK" : "BAD");
break;
}
for (i=same=0; i<len; i += 16) {
if ((i > 0) && (0 == memcmp(&msg[i], &msg[i-16], 16))) {
++same;
continue;
}
if (same > 0) {
sim_debug(reason, dptr, "%04X thru %04X same as above\n", i-(16*same), i-1);
same = 0;
}
group = (((len - i) > 16) ? 16 : (len - i));
for (sidx=oidx=0; sidx<group; ++sidx) {
outbuf[oidx++] = ' ';
outbuf[oidx++] = hex[(msg[i+sidx]>>4)&0xf];
outbuf[oidx++] = hex[msg[i+sidx]&0xf];
if (isprint(msg[i+sidx]))
strbuf[sidx] = msg[i+sidx];
else
strbuf[sidx] = '.';
}
outbuf[oidx] = '\0';
strbuf[sidx] = '\0';
sim_debug(reason, dptr, "%04X%-48s %s\n", i, outbuf, strbuf);
}
if (same > 0) {
sim_debug(reason, dptr, "%04X thru %04X same as above\n", i-(16*same), len-1);
}
}
}
}
uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len);
#endif /* PDP11_DDCMP_H_ */

View file

@ -51,7 +51,6 @@
#include "sim_tmxr.h"
#include "pdp11_ddcmp.h"
#include "pdp11_dup.h"
#include <ctype.h>
#if !defined(DUP_LINES)
#define DUP_LINES 8
@ -99,8 +98,6 @@ 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);
void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail);
uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len);
int32 dup_rxinta (void);
int32 dup_txinta (void);
void dup_update_rcvi (void);
@ -623,11 +620,16 @@ if ((dup_rxcsr[dup] & RXCSR_M_DSCHNG) &&
return SCPE_OK;
}
/*
* Public routines for use by other devices (i.e. KDP11)
*/
int32 dup_csr_to_linenum (int32 CSRPA)
{
DEVICE *dptr = DUPDPTR;
DIB *dib = (DIB *)dptr->ctxt;
CSRPA += IOPAGEBASE;
if ((dib->ba > (uint32)CSRPA) || ((uint32)CSRPA > (dib->ba + dib->lnt)))
return -1;
@ -636,15 +638,44 @@ 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))
return;
dup_rcv_packet_callback[dup] = receive;
dup_xmt_complete_callback[dup] = transmit;
}
int32 dup_get_line_speed (int32 dup)
{
if ((dup < 0) || (dup >= dup_desc.lines))
return -1;
return dup_speed[dup];
}
int32 dup_get_DCD (int32 dup)
{
if ((dup < 0) || (dup >= dup_desc.lines))
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))
return SCPE_IERR;
dup_set_modem (dup, state ? (RXCSR_M_DTR | RXCSR_M_RTS) : 0);
return SCPE_OK;
}
t_stat dup_set_DDCMP (int32 dup, t_bool state)
{
if ((dup < 0) || (dup >= dup_desc.lines))
return SCPE_IERR;
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)
{
@ -862,86 +893,6 @@ else {
return SCPE_OK;
}
/* Debug routines */
void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail)
{
if (sim_deb && dptr && (reason & dptr->dctrl)) {
sim_debug(reason, dptr, "%s len: %d\n", txt, len);
if (detail) {
int i, same, group, sidx, oidx;
char outbuf[80], strbuf[18];
static char hex[] = "0123456789ABCDEF";
switch (msg[0]) {
case DDCMP_SOH: /* Data Message */
sim_debug (reason, dptr, "Data Message, Link: %d, Count: %d, Resp: %d, Num: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)|msg[1], msg[3], msg[4],
(0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)|msg[1]))) ? "OK" : "BAD");
break;
case DDCMP_ENQ: /* Control Message */
sim_debug (reason, dptr, "Control: Type: %d ", msg[1]);
switch (msg[1]) {
case 1: /* ACK */
sim_debug (reason, dptr, "(ACK) ACKSUB: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]);
break;
case 2: /* NAK */
sim_debug (reason, dptr, "(NAK) Reason: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]);
break;
case 3: /* REP */
sim_debug (reason, dptr, "(REP) REPSUB: %d, Link: %d, Num: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[4]);
break;
case 6: /* STRT */
sim_debug (reason, dptr, "(STRT) STRTSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6);
break;
case 7: /* STACK */
sim_debug (reason, dptr, "(STACK) STCKSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6);
break;
default: /* Unknown */
sim_debug (reason, dptr, "(Unknown=0%o)\n", msg[1]);
break;
}
if (len != 8) {
sim_debug (reason, dptr, "Unexpected Control Message Length: %d expected 8\n", len);
}
if (0 != ddcmp_crc16 (0, msg, len)) {
sim_debug (reason, dptr, "Unexpected Message CRC\n");
}
break;
case DDCMP_DLE: /* Maintenance Message */
sim_debug (reason, dptr, "Maintenance Message, Link: %d, Count: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)| msg[1],
(0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)| msg[1]))) ? "OK" : "BAD");
break;
}
for (i=same=0; i<len; i += 16) {
if ((i > 0) && (0 == memcmp(&msg[i], &msg[i-16], 16))) {
++same;
continue;
}
if (same > 0) {
sim_debug(reason, dptr, "%04X thru %04X same as above\n", i-(16*same), i-1);
same = 0;
}
group = (((len - i) > 16) ? 16 : (len - i));
for (sidx=oidx=0; sidx<group; ++sidx) {
outbuf[oidx++] = ' ';
outbuf[oidx++] = hex[(msg[i+sidx]>>4)&0xf];
outbuf[oidx++] = hex[msg[i+sidx]&0xf];
if (isprint(msg[i+sidx]))
strbuf[sidx] = msg[i+sidx];
else
strbuf[sidx] = '.';
}
outbuf[oidx] = '\0';
strbuf[sidx] = '\0';
sim_debug(reason, dptr, "%04X%-48s %s\n", i, outbuf, strbuf);
}
if (same > 0) {
sim_debug(reason, dptr, "%04X thru %04X same as above\n", i-(16*same), len-1);
}
}
}
}
/* Interrupt routines */
void dup_clr_rxint (int32 dup)
@ -1221,20 +1172,3 @@ char *dup_description (DEVICE *dptr)
return (UNIBUS) ? "DUP11 bit synchronous interface" :
"DPV11 bit synchronous interface";
}
/* crc16 polynomial x^16 + x^15 + x^2 + 1 (0xA001) CCITT LSB */
static uint16 crc16_nibble[16] = {
0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400,
};
uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len)
{
const unsigned char* buf = (const unsigned char*)vbuf;
while(0 != len--) {
crc = (crc>>4) ^ crc16_nibble[(*buf ^ crc) & 0xF];
crc = (crc>>4) ^ crc16_nibble[((*buf++)>>4 ^ crc) & 0xF];
};
return(crc);
}

View file

@ -38,6 +38,9 @@ typedef void (*PACKET_RECEIVE_CALLBACK)(int32 dup, uint8 *buf, size_t len);
typedef void (*PACKET_TRANSMIT_COMPLETE_CALLBACK)(int32 dup, int status);
int32 dup_get_line_speed (int32 dup);
int32 dup_get_DCD (int32 dup);
t_stat dup_set_DTR (int32 dup, t_bool state);
t_stat dup_set_DDCMP (int32 dup, t_bool state);
int32 dup_csr_to_linenum (int32 CSRPA);
void dup_set_callback_mode (int32 dup, PACKET_RECEIVE_CALLBACK receive, PACKET_TRANSMIT_COMPLETE_CALLBACK transmit);