mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-24 03:17:02 +00:00
KA10: Added counters to NIA device.
This commit is contained in:
parent
a5d29b2dba
commit
ae8a6faacc
354
PDP10/kl10_nia.c
354
PDP10/kl10_nia.c
@ -61,6 +61,7 @@
|
||||
#define NIA_RAR 0377760000000LL /* Microcode address mask */
|
||||
#define NIA_MSB 0000020000000LL /* Half word select */
|
||||
|
||||
/* PCB Offsets */
|
||||
#define PCB_CQI 0 /* Command queue interlock */
|
||||
#define PCB_CQF 1 /* Command queue flink */
|
||||
#define PCB_CQB 2 /* Command queue blink */
|
||||
@ -134,6 +135,68 @@
|
||||
#define NIA_ERR_PAR 036 /* Parity error */
|
||||
#define NIA_ERR_INT 037 /* Internal error */
|
||||
|
||||
/* Counters */
|
||||
#define NIA_CNT_BR 000 /* Bytes received */
|
||||
#define NIA_CNT_BX 001 /* Bytes transmitted */
|
||||
#define NIA_CNT_FR 002 /* Frames received */
|
||||
#define NIA_CNT_FX 003 /* Frames transmitted */
|
||||
#define NIA_CNT_MCB 004 /* Multicast bytes received */
|
||||
#define NIA_CNT_MCF 005 /* Multicast frames received */
|
||||
#define NIA_CNT_FXD 006 /* Frames xmitted, initially deferred */
|
||||
#define NIA_CNT_FXS 007 /* Frames xmitted, single collision */
|
||||
#define NIA_CNT_FXM 010 /* Frames xmitted, multiple collisions */
|
||||
#define NIA_CNT_XF 011 /* Transmit failures */
|
||||
#define NIA_CNT_XFM 012 /* Transmit failure bit mask */
|
||||
#define NIA_XFM_LOC 04000 /* B24 - Loss of carrier */
|
||||
#define NIA_XFM_XBP 02000 /* B25 - Xmit buffer parity error */
|
||||
#define NIA_XFM_RFD 01000 /* B26 - Remote failure to defer */
|
||||
#define NIA_XFM_XFL 00400 /* B27 - Xmitted frame too long */
|
||||
#define NIA_XFM_OC 00200 /* B28 - Open circuit */
|
||||
#define NIA_XFM_SC 00100 /* B29 - Short circuit */
|
||||
#define NIA_XFM_CCF 00040 /* B30 - Collision detect check failed */
|
||||
#define NIA_XFM_EXC 00020 /* B31 - Excessive collisions */
|
||||
|
||||
#define NIA_CNT_CDF 013 /* Carrier detect check failed */
|
||||
#define NIA_CNT_RF 014 /* Receive failures */
|
||||
#define NIA_CNT_RFM 015 /* Receive failure bit mask */
|
||||
#define NIA_RFM_FLE 0400 /* B27 - free list parity error */
|
||||
#define NIA_RFM_NFB 0200 /* B28 - no free buffers */
|
||||
#define NIA_RFM_FTL 0100 /* B29 - frame too long */
|
||||
#define NIA_RFM_FER 0040 /* B30 - framing error */
|
||||
#define NIA_RFM_BCE 0020 /* B31 - block check error */
|
||||
|
||||
#define NIA_CNT_DUN 016 /* Discarded unknown */
|
||||
#define NIA_CNT_D01 017 /* Discarded position 1 */
|
||||
#define NIA_CNT_D02 020 /* Discarded position 2 */
|
||||
#define NIA_CNT_D03 021 /* Discarded position 3 */
|
||||
#define NIA_CNT_D04 022 /* Discarded position 4 */
|
||||
#define NIA_CNT_D05 023 /* Discarded position 5 */
|
||||
#define NIA_CNT_D06 024 /* Discarded position 6 */
|
||||
#define NIA_CNT_D07 025 /* Discarded position 7 */
|
||||
#define NIA_CNT_D08 026 /* Discarded position 8 */
|
||||
#define NIA_CNT_D09 027 /* Discarded position 9 */
|
||||
#define NIA_CNT_D10 030 /* Discarded position 10 */
|
||||
#define NIA_CNT_D11 031 /* Discarded position 11 */
|
||||
#define NIA_CNT_D12 032 /* Discarded position 12 */
|
||||
#define NIA_CNT_D13 033 /* Discarded position 13 */
|
||||
#define NIA_CNT_D14 034 /* Discarded position 14 */
|
||||
#define NIA_CNT_D15 035 /* Discarded position 15 */
|
||||
#define NIA_CNT_D16 036 /* Discarded position 16 */
|
||||
#define NIA_CNT_UFD 037 /* Unrecognized frame dest */
|
||||
#define NIA_CNT_DOV 040 /* Data overrun */
|
||||
#define NIA_CNT_SBU 041 /* System buffer unavailable */
|
||||
#define NIA_CNT_UBU 042 /* User buffer unavailable */
|
||||
#define NIA_CNT_RS0 043 /* Pli reg rd par error,,pli parity error */
|
||||
#define NIA_CNT_RS1 044 /* Mover parity error,,cbus parity error */
|
||||
#define NIA_CNT_RS2 045 /* Ebus parity error,,ebus que parity error */
|
||||
#define NIA_CNT_RS3 046 /* Channel error,,spur channel error */
|
||||
#define NIA_CNT_RS4 047 /* Spur xmit attn error,,cbus req timout error */
|
||||
#define NIA_CNT_RS5 050 /* Ebus req timeout error,,csr grnt timeout error */
|
||||
#define NIA_CNT_RS6 051 /* Used buff parity error,,xmit buff parity error */
|
||||
#define NIA_CNT_RS7 052 /* Reserved for ucode */
|
||||
#define NIA_CNT_RS8 053 /* Reserved for ucode */
|
||||
#define NIA_CNT_LEN 054 /* # of counters */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define PACKED_BEGIN __pragma( pack(push, 1) )
|
||||
# define PACKED_END __pragma( pack(pop) )
|
||||
@ -273,12 +336,16 @@ struct nia_device {
|
||||
t_addr mcast_addr; /* Address of Multicast table */
|
||||
int pia; /* Interrupt channel */
|
||||
t_addr cnt_addr; /* Address of counters */
|
||||
uint64 pcnt[NIA_CNT_LEN]; /* Counters */
|
||||
|
||||
int ptt_n; /* Number of Protocol entries */
|
||||
uint16 ptt_proto[17]; /* Protocol for entry */
|
||||
t_addr ptt_head[17]; /* Head of protocol queue */
|
||||
int macs_n; /* Number of multi-cast addresses */
|
||||
ETH_MAC macs[20]; /* Watched Multi-cast addresses */
|
||||
int amc; /* Recieve all multicast packets */
|
||||
int prmsc; /* Recieve all packets */
|
||||
int h4000; /* Heart beat detection */
|
||||
int rar;
|
||||
uint64 ebuf;
|
||||
uint32 uver[4]; /* Version information */
|
||||
@ -299,7 +366,6 @@ void nia_disable(UNIT *);
|
||||
void nia_error(UNIT *, int);
|
||||
t_stat nia_srv(UNIT *);
|
||||
t_stat nia_eth_srv(UNIT *);
|
||||
t_stat nia_tim_srv(UNIT *);
|
||||
t_stat nia_reset (DEVICE *dptr);
|
||||
t_stat nia_show_mac (FILE* st, UNIT* uptr, int32 val, CONST void* desc);
|
||||
t_stat nia_set_mac (UNIT* uptr, int32 val, CONST char* cptr, void* desc);
|
||||
@ -313,7 +379,6 @@ struct rh_if nia_rh = { NULL, NULL, NULL};
|
||||
UNIT nia_unit[] = {
|
||||
{UDATA(nia_srv, UNIT_IDLE+UNIT_ATTABLE, 0)}, /* 0 */
|
||||
{UDATA(nia_eth_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */
|
||||
{UDATA(nia_tim_srv, UNIT_IDLE+UNIT_DIS, 0)}, /* 0 */
|
||||
};
|
||||
|
||||
DIB nia_dib = {NIA_DEVNUM | RH20_DEV, 1, &nia_devio, NULL, &nia_rh };
|
||||
@ -351,28 +416,12 @@ DEBTAB nia_debug[] = {
|
||||
|
||||
DEVICE nia_dev = {
|
||||
"NI", nia_unit, NULL, nia_mod,
|
||||
3, 8, 0, 1, 8, 36,
|
||||
2, 8, 0, 1, 8, 36,
|
||||
NULL, NULL, &nia_reset, NULL, &nia_attach, &nia_detach,
|
||||
&nia_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG, 0, nia_debug,
|
||||
NULL, NULL, &nia_help, NULL, NULL, &nia_description
|
||||
};
|
||||
|
||||
static char *
|
||||
ipv4_inet_ntoa(struct in_addr ip)
|
||||
{
|
||||
static char str[20];
|
||||
|
||||
if (sim_end)
|
||||
sprintf (str, "%d.%d.%d.%d", ip.s_addr & 0xFF, (ip.s_addr >> 8) & 0xFF,
|
||||
(ip.s_addr >> 16) & 0xFF, (ip.s_addr >> 24) & 0xFF);
|
||||
else
|
||||
sprintf (str, "%d.%d.%d.%d", (ip.s_addr >> 24) & 0xFF, (ip.s_addr >> 16) & 0xFF,
|
||||
(ip.s_addr >> 8) & 0xFF, ip.s_addr & 0xFF);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
t_stat nia_devio(uint32 dev, uint64 *data)
|
||||
{
|
||||
DEVICE *dptr = &nia_dev;
|
||||
@ -422,7 +471,6 @@ t_stat nia_devio(uint32 dev, uint64 *data)
|
||||
case CONI:
|
||||
*data = (uint64)uptr->STATUS;
|
||||
*data |= NIA_PPT|NIA_PID;
|
||||
// *data &= ~NIA_CQA;
|
||||
sim_debug(DEBUG_CONI, dptr, "NIA %03o CONI %012llo PC=%o\n", dev,
|
||||
*data, PC);
|
||||
break;
|
||||
@ -464,6 +512,23 @@ t_stat nia_devio(uint32 dev, uint64 *data)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static char *
|
||||
ipv4_inet_ntoa(struct in_addr ip)
|
||||
{
|
||||
static char str[20];
|
||||
|
||||
if (sim_end)
|
||||
sprintf (str, "%d.%d.%d.%d", ip.s_addr & 0xFF, (ip.s_addr >> 8) & 0xFF,
|
||||
(ip.s_addr >> 16) & 0xFF, (ip.s_addr >> 24) & 0xFF);
|
||||
else
|
||||
sprintf (str, "%d.%d.%d.%d", (ip.s_addr >> 24) & 0xFF, (ip.s_addr >> 16) & 0xFF,
|
||||
(ip.s_addr >> 8) & 0xFF, ip.s_addr & 0xFF);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set error code and stop.
|
||||
*/
|
||||
void nia_error(UNIT * uptr, int err)
|
||||
{
|
||||
nia_data.rar = err;
|
||||
@ -472,9 +537,13 @@ void nia_error(UNIT * uptr, int err)
|
||||
set_interrupt(NIA_DEVNUM, uptr->STATUS & NIA_PIA);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start NIA device, load in 2 words using RH20 mode.
|
||||
*/
|
||||
void nia_start(UNIT * uptr)
|
||||
{
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA start\n");
|
||||
/* Set up RH20 to read 2 words */
|
||||
nia_rh.stcr = BIT7;
|
||||
nia_rh.imode = 2;
|
||||
rh20_setup(&nia_rh);
|
||||
@ -505,6 +574,9 @@ void nia_stop(UNIT *uptr)
|
||||
uptr->STATUS &= ~NIA_MRN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a MAC address from string to memory word.
|
||||
*/
|
||||
void nia_cpy_mac(UNIT *uptr, uint64 word1, uint64 word2, ETH_MAC *mac)
|
||||
{
|
||||
ETH_MAC m;
|
||||
@ -517,9 +589,13 @@ void nia_cpy_mac(UNIT *uptr, uint64 word1, uint64 word2, ETH_MAC *mac)
|
||||
memcpy(mac, &m, sizeof(ETH_MAC));
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy memory to a packet.
|
||||
*/
|
||||
uint8 *nia_cpy_to(UNIT *uptr, t_addr addr, uint8 *data, int len)
|
||||
{
|
||||
uint64 word;
|
||||
/* Copy full words */
|
||||
while (len > 3) {
|
||||
word = M[addr++];
|
||||
*data++ = (uint8)((word >> 28) & 0xff);
|
||||
@ -528,6 +604,7 @@ uint8 *nia_cpy_to(UNIT *uptr, t_addr addr, uint8 *data, int len)
|
||||
*data++ = (uint8)((word >> 4) & 0xff);
|
||||
len -= 4;
|
||||
}
|
||||
/* Grab last partial word */
|
||||
if (len) {
|
||||
word = M[addr++];
|
||||
switch (len) {
|
||||
@ -548,10 +625,14 @@ uint8 *nia_cpy_to(UNIT *uptr, t_addr addr, uint8 *data, int len)
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a packet to memory.
|
||||
*/
|
||||
uint8 *nia_cpy_from(UNIT *uptr, t_addr addr, uint8 *data, int len)
|
||||
{
|
||||
uint64 word;
|
||||
|
||||
/* Copy full words */
|
||||
while (len > 3) {
|
||||
word = (uint64)(*data++) << 28;
|
||||
word |= (uint64)(*data++) << 20;
|
||||
@ -560,6 +641,7 @@ uint8 *nia_cpy_from(UNIT *uptr, t_addr addr, uint8 *data, int len)
|
||||
M[addr++] = word;
|
||||
len -= 4;
|
||||
}
|
||||
/* Copy last partial word */
|
||||
if (len) {
|
||||
switch (len) {
|
||||
case 3:
|
||||
@ -594,7 +676,7 @@ void nia_load_ptt(UNIT *uptr)
|
||||
|
||||
word1 = M[addr++];
|
||||
word2 = M[addr++];
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %012llo %012llo\n\r",n, word1, word2);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %012llo %012llo\n\r",n, word1, word2);
|
||||
if (word1 & SMASK) {
|
||||
uint16 type;
|
||||
type = (uint16)(word1 >> 12) & 0xff;
|
||||
@ -606,7 +688,8 @@ void nia_load_ptt(UNIT *uptr)
|
||||
addr++;
|
||||
}
|
||||
for (i = 0; i < n; i++) {
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %04x %010o\n\r",n, nia_data.ptt_proto[i], nia_data.ptt_head[i]);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load ptt%d: %04x %010o\n\r",n, nia_data.ptt_proto[i],
|
||||
nia_data.ptt_head[i]);
|
||||
}
|
||||
nia_data.ptt_n = n;
|
||||
}
|
||||
@ -621,6 +704,7 @@ void nia_load_mcast(UNIT *uptr)
|
||||
char buffer[20];
|
||||
t_addr addr = nia_data.mcast_addr;
|
||||
|
||||
/* Start with our own address. */
|
||||
memcpy(&nia_data.macs[n], &nia_data.mac, sizeof (ETH_MAC));
|
||||
n++;
|
||||
memcpy(&nia_data.macs[n], &broadcast_ethaddr, sizeof (ETH_MAC));
|
||||
@ -637,13 +721,16 @@ void nia_load_mcast(UNIT *uptr)
|
||||
}
|
||||
for(i = 0; i< n; i++) {
|
||||
eth_mac_fmt(&nia_data.macs[i], buffer);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load mcast%d: %s\n\r",i, buffer);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA load mcast%d: %s\n\r",i, buffer);
|
||||
}
|
||||
nia_data.macs_n = n - 2;
|
||||
if (uptr->flags & UNIT_ATT)
|
||||
eth_filter (&nia_data.etherface, n, nia_data.macs, 0, 0);
|
||||
eth_filter (&nia_data.etherface, n, nia_data.macs, nia_data.amc, nia_data.prmsc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pretty print a packet for debugging.
|
||||
*/
|
||||
void nia_packet_debug(struct nia_device *nia, const char *action, ETH_PACK *packet) {
|
||||
struct nia_eth_hdr *eth = (struct nia_eth_hdr *)&packet->msg[0];
|
||||
struct arp_hdr *arp = (struct arp_hdr *)eth;
|
||||
@ -800,33 +887,30 @@ void nia_packet_debug(struct nia_device *nia, const char *action, ETH_PACK *pack
|
||||
/*
|
||||
* Send out a packet.
|
||||
*/
|
||||
void nia_send_pkt(UNIT *uptr, int len)
|
||||
int nia_send_pkt(UNIT *uptr)
|
||||
{
|
||||
uint64 word1, word2, cmd;
|
||||
struct nia_eth_hdr *hdr = (struct nia_eth_hdr *)(&nia_data.snd_buff.msg[0]);
|
||||
uint8 *data = &nia_data.snd_buff.msg[sizeof(struct nia_eth_hdr)];
|
||||
ETH_MAC dest;
|
||||
uint16 type;
|
||||
int len;
|
||||
int blen;
|
||||
|
||||
/* flink 0 */
|
||||
/* blink 1 */
|
||||
/* resv 2 */
|
||||
/* cmd 3 */
|
||||
/* len 4 */
|
||||
/* prot 5 */
|
||||
/* freeq 6 */
|
||||
/* dest 7 */
|
||||
/* text/bsd 9 */
|
||||
/* flink 0 */
|
||||
/* blink 1 */
|
||||
/* resv 2 */
|
||||
/* cmd 3 */
|
||||
/* len 4 */
|
||||
/* prot 5, 8 */
|
||||
/* freeq 6, 5 */
|
||||
/* dest 7, 6 */
|
||||
/* text/bsd 9 */
|
||||
len = (int)(M[nia_data.cmd_entry + 4] & 0177777) + sizeof(struct nia_eth_hdr);
|
||||
/* Check for runt packet */
|
||||
if (len < ETH_MIN_PACKET && (cmd & (NIA_FLG_PAD << 20)) == 0) {
|
||||
return NIA_ERR_RUN;
|
||||
}
|
||||
/* Check for too long of a packet */
|
||||
if (len > ETH_MAX_PACKET) {
|
||||
nia_data.pcnt[NIA_CNT_XF]++;
|
||||
nia_data.pcnt[NIA_CNT_XFM] |= NIA_XFM_XFL;
|
||||
return NIA_ERR_LNG;
|
||||
}
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return 0;
|
||||
len -= sizeof(struct nia_eth_hdr);
|
||||
/* Load destination address */
|
||||
word1 = M[nia_data.cmd_entry+7];
|
||||
word2 = M[nia_data.cmd_entry+8];
|
||||
@ -861,31 +945,47 @@ void nia_send_pkt(UNIT *uptr, int len)
|
||||
}
|
||||
}
|
||||
nia_packet_debug(&nia_data, "send", &nia_data.snd_buff);
|
||||
eth_write(&nia_data.etherface, &nia_data.snd_buff, NULL);
|
||||
if (eth_write(&nia_data.etherface, &nia_data.snd_buff, NULL) != SCPE_OK) {
|
||||
nia_data.pcnt[NIA_CNT_XF]++;
|
||||
nia_data.pcnt[NIA_CNT_XFM] |= NIA_XFM_LOC;
|
||||
}
|
||||
nia_data.pcnt[NIA_CNT_BX] += nia_data.snd_buff.len;
|
||||
nia_data.pcnt[NIA_CNT_FX] ++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable NIA 20.
|
||||
*
|
||||
* Read in PTT and MACS table.
|
||||
*/
|
||||
void nia_enable(UNIT *uptr)
|
||||
{
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA enable\n");
|
||||
/* Load pointers to various table */
|
||||
nia_data.unk_len = (int)(M[(nia_data.unk_hdr + 3) & AMASK] & AMASK);
|
||||
nia_data.unk_len = (int)(M[(nia_data.unk_hdr + PCB_UPL) & AMASK] & AMASK);
|
||||
/* Load PTT */
|
||||
nia_data.ptt_addr = (t_addr)(M[(nia_data.pcb + 015) & AMASK] & AMASK);
|
||||
nia_data.ptt_addr = (t_addr)(M[(nia_data.pcb + PCB_PTT) & AMASK] & AMASK);
|
||||
nia_load_ptt(uptr);
|
||||
/* Load MCT */
|
||||
nia_data.mcast_addr = (t_addr)(M[(nia_data.pcb + 016) & AMASK] & AMASK);
|
||||
nia_data.mcast_addr = (t_addr)(M[(nia_data.pcb + PCB_MCT) & AMASK] & AMASK);
|
||||
nia_load_mcast(uptr);
|
||||
/* Load read count buffer address */
|
||||
nia_data.rcb = (t_addr)(M[(nia_data.pcb + 030) & AMASK] & AMASK);
|
||||
nia_data.rcb = (t_addr)(M[(nia_data.pcb + PCB_RCB) & AMASK] & AMASK);
|
||||
uptr->STATUS |= NIA_ECP;
|
||||
uptr->STATUS &= ~NIA_DCP;
|
||||
/* Start receiver */
|
||||
sim_activate(&nia_unit[1], 200);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable NIA 20.
|
||||
*/
|
||||
void nia_disable(UNIT *uptr)
|
||||
{
|
||||
uptr->STATUS |= NIA_DCP;
|
||||
uptr->STATUS &= ~NIA_ECP;
|
||||
/* Stop receiver */
|
||||
sim_cancel(&nia_unit[1]);
|
||||
}
|
||||
|
||||
@ -893,8 +993,8 @@ void nia_disable(UNIT *uptr)
|
||||
int nia_getq(t_addr head, t_addr *entry)
|
||||
{
|
||||
uint64 temp;
|
||||
uint64 flink;
|
||||
uint64 blink;
|
||||
t_addr flink;
|
||||
t_addr nlink;
|
||||
int i;
|
||||
*entry = 0; /* For safty */
|
||||
|
||||
@ -905,21 +1005,19 @@ int nia_getq(t_addr head, t_addr *entry)
|
||||
|
||||
/* Increment lock here */
|
||||
|
||||
flink = M[head+1] & AMASK;
|
||||
flink = (t_addr)(M[head+1] & AMASK);
|
||||
/* Check if queue empty */
|
||||
if (flink == (head+1)) {
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA empty %08o\n", head);
|
||||
/* Decrement lock here */
|
||||
return 1;
|
||||
}
|
||||
blink = M[flink] & AMASK;
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA head: %08o %08llo %012llo\n", head, blink, M[flink+1]);
|
||||
M[head+1] = blink; /* Set Head Flink to point to next */
|
||||
M[blink+1] = head + 1; /* Set Next Blink to head */
|
||||
nlink = (t_addr)(M[flink] & AMASK);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA head: q=%08o f=%08o n=%08o\n", head, flink, nlink);
|
||||
M[head+1] = (uint64)nlink; /* Set Head Flink to point to next */
|
||||
M[nlink+1] = (uint64)(head + 1); /* Set Next Blink to head */
|
||||
*entry = flink;
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA get head: %08o %08o %012llo %012llo\n", head, head+1, M[head+1], M[head+2]);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA get entry: %08o %08o %012llo %012llo\n", head, *entry, M[*entry], M[*entry+1]);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA get next: %08o %08llo %012llo %012llo\n", head, blink, M[blink], M[blink+1]);
|
||||
|
||||
/* Decrement lock here */
|
||||
return 1;
|
||||
}
|
||||
@ -928,7 +1026,7 @@ int nia_getq(t_addr head, t_addr *entry)
|
||||
int nia_putq(UNIT *uptr, t_addr head, t_addr *entry)
|
||||
{
|
||||
uint64 temp;
|
||||
uint64 blink;
|
||||
t_addr blink;
|
||||
|
||||
temp = M[head];
|
||||
/* Check if entry locked */
|
||||
@ -936,18 +1034,14 @@ int nia_putq(UNIT *uptr, t_addr head, t_addr *entry)
|
||||
return 0;
|
||||
|
||||
/* Increment lock here */
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put: %08o %08o %012llo %012llo\n", head, *entry, M[head+1], M[head+2]);
|
||||
|
||||
/* Set up entry. */
|
||||
blink = M[head+2]; /* Get back link */
|
||||
M[blink] = *entry; /* Old prevous entry */
|
||||
M[*entry+1] = blink; /* Back link points to previous */
|
||||
M[*entry] = head+1; /* Flink is head of queue */
|
||||
M[head+2] = *entry; /* Old forward is new */
|
||||
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put head: %08o %08o %012llo %012llo\n", head, head+1, M[head+1], M[head+2]);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put entry: %08o %08o %012llo %012llo\n", head, *entry, M[*entry], M[*entry+1]);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put next: %08o %08llo %012llo %012llo\n", head, blink, M[blink], M[blink+1]);
|
||||
blink = (t_addr)(M[head+2] & AMASK); /* Get back link */
|
||||
M[blink] = (uint64)*entry; /* Old prevous entry */
|
||||
M[*entry] = (uint64)(head+1); /* Flink is head of queue */
|
||||
M[*entry+1] = (uint64)blink; /* Back link points to previous */
|
||||
M[head+2] = (uint64)*entry; /* Old forward is new */
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA put: q=%08o i=%08o b=%08o\n", head, *entry, blink);
|
||||
*entry = 0;
|
||||
/* Decement lock here */
|
||||
|
||||
@ -960,11 +1054,16 @@ int nia_putq(UNIT *uptr, t_addr head, t_addr *entry)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process commands.
|
||||
*/
|
||||
t_stat nia_srv(UNIT * uptr)
|
||||
{
|
||||
t_addr free_q = nia_data.unk_hdr;
|
||||
uint64 cmd, word1, word2;
|
||||
uint64 word1, word2;
|
||||
uint32 cmd;
|
||||
int len, i;
|
||||
int err;
|
||||
|
||||
/* See if we have command to process */
|
||||
if (nia_data.cmd_entry != 0) {
|
||||
@ -975,40 +1074,39 @@ t_stat nia_srv(UNIT * uptr)
|
||||
}
|
||||
nia_data.cmd_rply = 0;
|
||||
}
|
||||
|
||||
/* Check if we are running */
|
||||
if ((uptr->STATUS & NIA_MRN) == 0 || (uptr->STATUS & NIA_CQA) == 0) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* or no commands pending, just idle out */
|
||||
/* Try to get command off queue */
|
||||
if (nia_getq(nia_data.cmd_hdr, &nia_data.cmd_entry) == 0) {
|
||||
sim_activate(uptr, 200); /* Reschedule ourselves to deal with it */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Check if we got one */
|
||||
if (nia_data.cmd_entry == 0) {
|
||||
/* Nothing to do */
|
||||
uptr->STATUS &= ~NIA_CQA;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Preform function of command */
|
||||
cmd = M[nia_data.cmd_entry + 3];
|
||||
nia_data.cmd_status = (uint8)((M[nia_data.cmd_entry + 3] >> 20) & 0xff);
|
||||
// cmd &= ~(0xFFLL<<20); /* Clear status field */
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA cmd: %08x\n", (uint32)(cmd >> 12));
|
||||
cmd = (uint32)(M[nia_data.cmd_entry + 3] >> 12);
|
||||
/* Save initial status */
|
||||
nia_data.cmd_status = ((uint8)(cmd >> 16)) & 0xff;
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA cmd: %08x\n", cmd);
|
||||
cmd &= 0xffff;
|
||||
len = 5;
|
||||
switch((cmd >> 12) & 0xff) {
|
||||
switch(cmd & 0xff) {
|
||||
case NIA_CMD_SND: /* Send a datagram */
|
||||
len = (int)(M[nia_data.cmd_entry + 4] & 0177777) + sizeof(struct nia_eth_hdr);
|
||||
if (len < ETH_MIN_PACKET && (cmd & (NIA_FLG_PAD << 20)) == 0) {
|
||||
cmd |= (((uint64)NIA_ERR_RUN) << 29) | ((uint64)NIA_STS_ERR << 28);
|
||||
break;
|
||||
} if (len > ETH_MAX_PACKET) {
|
||||
cmd |= (((uint64)NIA_ERR_LNG) << 29) | ((uint64)NIA_STS_ERR << 28);
|
||||
break;
|
||||
} else
|
||||
nia_send_pkt(uptr, len - sizeof(struct nia_eth_hdr));
|
||||
cmd |= (uint64)NIA_STS_SR << 28;
|
||||
err = nia_send_pkt(uptr);
|
||||
if (err != 0)
|
||||
cmd |= ((err<<1)|1) << 16;
|
||||
cmd |= NIA_STS_SR << 16;
|
||||
len = 10;
|
||||
break;
|
||||
case NIA_CMD_LPTT: /* Load Protocol Type table */
|
||||
@ -1018,6 +1116,11 @@ t_stat nia_srv(UNIT * uptr)
|
||||
nia_load_mcast(uptr);
|
||||
break;
|
||||
case NIA_CMD_RCNT: /* Read counts */
|
||||
for (i = 0; i < NIA_CNT_LEN; i++) {
|
||||
M[nia_data.cnt_addr + i] = nia_data.pcnt[i];
|
||||
if ((cmd & (NIA_FLG_CLRC << 20)) != 0)
|
||||
nia_data.pcnt[i] = 0;
|
||||
}
|
||||
break;
|
||||
case NIA_CMD_WPLI: /* Write PLI */
|
||||
break;
|
||||
@ -1033,7 +1136,8 @@ t_stat nia_srv(UNIT * uptr)
|
||||
word2 = ((uint64)nia_data.mac[4]) << 28;
|
||||
word2 |= ((uint64)nia_data.mac[5]) << 20;
|
||||
M[nia_data.cmd_entry + 5] = word2;
|
||||
M[nia_data.cmd_entry + 6] = 0;
|
||||
M[nia_data.cmd_entry + 6] = (uint64)((nia_data.amc << 2)|
|
||||
(nia_data.h4000 << 1) |nia_data.prmsc);
|
||||
M[nia_data.cmd_entry + 7] = (nia_data.uver[3] << 12) | (0xF << 6) | 0xF;
|
||||
break;
|
||||
case NIA_CMD_WNSA: /* Write Station Address */
|
||||
@ -1041,31 +1145,40 @@ t_stat nia_srv(UNIT * uptr)
|
||||
word1 = M[nia_data.cmd_entry+4];
|
||||
word2 = M[nia_data.cmd_entry+5];
|
||||
nia_cpy_mac(uptr, word1, word2, &nia_data.mac);
|
||||
word1 = M[nia_data.cmd_entry+6];
|
||||
nia_data.prmsc = (int)(word1 & 1);
|
||||
nia_data.h4000 = (int)((word1 & 2) != 0);
|
||||
nia_data.amc = (int)((word1 & 4) != 0);
|
||||
memcpy(&nia_data.macs[0], &nia_data.mac, sizeof (ETH_MAC));
|
||||
eth_filter (&nia_data.etherface, nia_data.macs_n + 2, nia_data.macs, 0, 0);
|
||||
if (uptr->flags & UNIT_ATT)
|
||||
eth_filter (&nia_data.etherface, nia_data.macs_n + 2,
|
||||
nia_data.macs, 0, 0);
|
||||
break;
|
||||
|
||||
case NIA_CMD_RCV: /* Received datagram */
|
||||
default: /* Invalid command */
|
||||
cmd |= ((NIA_ERR_UNK<<1)|1) << 16;
|
||||
break;
|
||||
}
|
||||
|
||||
nia_data.cmd_rply = nia_data.unk_hdr;
|
||||
M[nia_data.cmd_entry+3] = cmd;
|
||||
if ((nia_data.cmd_status & 1) || ((M[nia_data.cmd_entry+3] >> 28) & 0xFF) != 0) {
|
||||
M[nia_data.cmd_entry+3] = ((uint64)cmd) << 12;
|
||||
if (((cmd >> 16) & 1) != 0 || (cmd & (NIA_FLG_RESP << 8)) != 0) {
|
||||
nia_data.cmd_rply = nia_data.resp_hdr;
|
||||
} else if (((cmd >> 12) & 0xff) == NIA_CMD_SND) {
|
||||
} else if ((cmd & 0xff) == NIA_CMD_SND) {
|
||||
nia_data.cmd_rply = M[nia_data.cmd_entry + 5];
|
||||
}
|
||||
for(i = 0; i < len; i++)
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA rcmd: %d %09llx %012llo\n", i, M[nia_data.cmd_entry + i],
|
||||
M[nia_data.cmd_entry + i]);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA rcmd: %d %09llx %012llo\n", i, M[nia_data.cmd_entry + i],
|
||||
M[nia_data.cmd_entry + i]);
|
||||
(void)nia_putq(uptr, nia_data.cmd_rply, &nia_data.cmd_entry);
|
||||
sim_activate(uptr, 500);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Receive ether net packets.
|
||||
*/
|
||||
t_stat nia_eth_srv(UNIT * uptr)
|
||||
{
|
||||
struct nia_eth_hdr *hdr;
|
||||
@ -1076,34 +1189,43 @@ t_stat nia_eth_srv(UNIT * uptr)
|
||||
t_addr bsd;
|
||||
t_addr word;
|
||||
uint8 *data;
|
||||
|
||||
sim_clock_coschedule(uptr, 100); /* continue poll */
|
||||
|
||||
/* Check if we are running */
|
||||
if ((nia_unit[0].STATUS & NIA_MRN) == 0)
|
||||
return SCPE_OK;
|
||||
|
||||
/* See if we have command to process */
|
||||
if (nia_data.rec_entry != 0) {
|
||||
/* Have to put this response queue */
|
||||
if (nia_putq(&nia_unit[0], nia_data.resp_hdr, &nia_data.rec_entry) == 0)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
loop:
|
||||
/* Check if we need to get a packet */
|
||||
if (nia_data.r_pkt == 0) {
|
||||
if (eth_read(&nia_data.etherface, &nia_data.rec_buff, NULL) <= 0)
|
||||
return SCPE_OK;
|
||||
hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]);
|
||||
type = ntohs(hdr->type);
|
||||
nia_packet_debug(&nia_data, "recv", &nia_data.rec_buff);
|
||||
hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]);
|
||||
type = ntohs(hdr->type);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA read packet: %d %04x\n",
|
||||
nia_data.rec_buff.len, type);
|
||||
nia_data.r_pkt = 1;
|
||||
nia_packet_debug(&nia_data, "recv", &nia_data.rec_buff);
|
||||
nia_data.pcnt[NIA_CNT_BR] += nia_data.rec_buff.len;
|
||||
nia_data.pcnt[NIA_CNT_FR] ++;
|
||||
if (hdr->dest[0] & 1) {
|
||||
nia_data.pcnt[NIA_CNT_MCB] += nia_data.rec_buff.len;
|
||||
nia_data.pcnt[NIA_CNT_MCF] ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine which queue to get free packet from */
|
||||
hdr = (struct nia_eth_hdr *)(&nia_data.rec_buff.msg[0]);
|
||||
type = ntohs(hdr->type);
|
||||
|
||||
|
||||
queue = nia_data.unk_hdr;
|
||||
for (i = 0; i < nia_data.ptt_n; i++) {
|
||||
if (nia_data.ptt_proto[i] == type) {
|
||||
@ -1113,17 +1235,20 @@ loop:
|
||||
}
|
||||
|
||||
/* Try to grab place to save packet */
|
||||
if (nia_getq(queue, &nia_data.rec_entry) == 0) {
|
||||
if (nia_getq(queue, &nia_data.rec_entry) == 0)
|
||||
return SCPE_OK; /* Could not get lock, try later */
|
||||
|
||||
if (nia_data.rec_entry == 0) {
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA drop packet\n");
|
||||
nia_data.r_pkt = 0; /* Drop packet it queue empty */
|
||||
if (queue == nia_data.unk_hdr)
|
||||
nia_data.pcnt[NIA_CNT_DUN]++;
|
||||
else
|
||||
nia_data.pcnt[NIA_CNT_D01 + i]++;
|
||||
nia_data.pcnt[NIA_CNT_UBU] += nia_data.rec_buff.len;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
if (nia_data.rec_entry == 0) {
|
||||
if (queue == nia_data.unk_hdr) {
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA drop packet\n");
|
||||
nia_data.r_pkt = 0; /* Drop packet it queue empty */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
/* Got one, now fill in data */
|
||||
M[nia_data.rec_entry + 3] = (uint64)(NIA_CMD_RCV << 12);
|
||||
(void)nia_cpy_from(&nia_unit[0], nia_data.rec_entry + 5, (uint8 *)&hdr->dest, sizeof(ETH_MAC));
|
||||
@ -1145,20 +1270,12 @@ loop:
|
||||
}
|
||||
|
||||
for(i = 0; i < 10; i++)
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA recv: %d %09llx %012llo\n", i, M[nia_data.rec_entry + i],
|
||||
M[nia_data.rec_entry + i]);
|
||||
sim_debug(DEBUG_DETAIL, &nia_dev, "NIA recv: %d %09llx %012llo\n", i, M[nia_data.rec_entry + i],
|
||||
M[nia_data.rec_entry + i]);
|
||||
/* Put on response queue */
|
||||
if (nia_putq(&nia_unit[0], nia_data.resp_hdr, &nia_data.rec_entry) == 0)
|
||||
return SCPE_OK;
|
||||
return SCPE_OK; /* Could not get lock, try again */
|
||||
nia_data.r_pkt = 0;
|
||||
goto loop;
|
||||
// return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat nia_tim_srv(UNIT * uptr)
|
||||
{
|
||||
sim_clock_coschedule(uptr, 1000); /* continue poll */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -1262,8 +1379,7 @@ t_stat nia_detach(UNIT* uptr)
|
||||
free(uptr->filename);
|
||||
uptr->filename = NULL;
|
||||
uptr->flags &= ~UNIT_ATT;
|
||||
sim_cancel (uptr+1); /* stop the packet timing services */
|
||||
sim_cancel (uptr+2); /* stop the clock timer services */
|
||||
sim_cancel (uptr+1); /* stop the packet receiving services */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
@ -1271,7 +1387,7 @@ t_stat nia_detach(UNIT* uptr)
|
||||
t_stat nia_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||
{
|
||||
fprintf (st, "NIA interface\n\n");
|
||||
fprintf (st, "The IMP acted as an interface to the early internet. ");
|
||||
fprintf (st, "The NIA interfaces to the network. Setting MAC defines default MAC address\n");
|
||||
fprint_set_help (st, dptr);
|
||||
fprint_show_help (st, dptr);
|
||||
eth_attach_help(st, dptr, uptr, flag, cptr);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user