From fdf17b80a1725a0d5c14beb89bd9ee1dd5d5f696 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 3 Jan 2021 21:28:29 -0500 Subject: [PATCH] SEL32: EC controller now passes more diagnostics. --- SEL32/sel32_ec.c | 407 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 319 insertions(+), 88 deletions(-) diff --git a/SEL32/sel32_ec.c b/SEL32/sel32_ec.c index 1d28f1d..cd1bca6 100644 --- a/SEL32/sel32_ec.c +++ b/SEL32/sel32_ec.c @@ -196,19 +196,22 @@ struct ec_device { ETH_MAC mac; /* Hardware MAC addresses */ ETH_DEV etherface; ETH_QUE ReadQ; - ETH_PACK rec_buff; /* Buffer for recieved packet */ + ETH_PACK rec_buff[64]; /* Buffer for recieved packet */ ETH_PACK snd_buff; /* Buffer for sending packet */ int macs_n; /* Number of multi-cast addresses */ ETH_MAC macs[67]; /* Watched Multi-cast addresses */ int amc; /* Recieve all multicast packets */ uint32 rx_count; /* Packets received */ uint32 tx_count; /* Packets sent */ + uint16 drop_cnt; /* Packets dropped */ int r_pkt; /* Packet pending */ int poll; /* Need to poll receiver */ + int lp_rdy; /* Loop back packet ready */ + int rec_ptr; /* Receive pointer */ + int xtr_ptr; /* Extract pointer */ + uint8 conf[12]; /* user specified configuration */ } ec_data; -uint8 conf[12] = {0}; /* user specified configuration */ - extern int32 tmxr_poll; extern uint32 readfull(CHANP *chp, uint32 maddr, uint32 *word); @@ -219,6 +222,7 @@ static CONST ETH_MAC broadcast_ethaddr = {0xff,0xff,0xff,0xff,0xff,0xff}; CHANP ec_chp[NUM_UNITS_ETHER] = {0}; uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd); +t_stat ec_rec_srv(UNIT *uptr); t_stat ec_srv(UNIT *uptr); uint16 ec_haltio(UNIT *uptr); uint16 ec_iocl(CHANP *chp, int32 tic_ok); @@ -237,7 +241,7 @@ const char *ec_description (DEVICE *dptr); #define ec_master_uptr (&ec_unit[0]) /* Unit doing receive digestion */ UNIT ec_unit[] = { - {UDATA(ec_srv, UNIT_IDLE|UNIT_ATTABLE, 0), 0, UNIT_ADDR(0xE00)}, /* 0 */ + {UDATA(ec_rec_srv, UNIT_IDLE|UNIT_ATTABLE, 0), 0, UNIT_ADDR(0xE00)}, /* 0 */ #ifdef FOR_DIAG {UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE01)}, /* 1 */ {UDATA(ec_srv, UNIT_IDLE|UNIT_DIS|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE02)}, /* 2 */ @@ -256,6 +260,7 @@ UNIT ec_unit[] = { {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE07)}, /* 7 */ {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE08)}, /* 8 */ {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE09)}, /* 9 */ +// {UDATA(ec_srv, UNIT_IDLE|UNIT_SUBCHAN, 0), 0, UNIT_ADDR(0xE0A)}, /* A */ #endif }; @@ -301,6 +306,7 @@ DEBTAB ec_debug[] = { {"DETAIL", DEBUG_DETAIL, "Show details about device"}, {"EXP", DEBUG_EXP, "Show exception information"}, {"IRQ", DEBUG_IRQ, "Show IRQ requests"}, + {"XIO", DEBUG_XIO, "Show XIO I/O instructions"}, #define DEBUG_ARP (DEBUG_IRQ<<1) {"ARP", DEBUG_ARP, "Show ARP activities"}, #define DEBUG_TCP (DEBUG_ARP<<1) @@ -345,7 +351,6 @@ uint16 ec_iocl(CHANP *chp, int32 tic_ok) chan, chp->chan_caw); chp->ccw_addr = chp->chan_caw; /* set the bad iocl address */ chp->chan_status |= STATUS_PCHK; /* program check for invalid iocd addr */ -// uptr->SNS |= SNS_INAD; /* invalid address status */ return 1; /* error return */ } } @@ -382,7 +387,26 @@ loop: chp->chan_caw, chan, word1, word2, uptr->SNS); chp->chan_caw = (chp->chan_caw & 0xfffffc) + 8; /* point to next IOCD */ + +#ifndef NOT_HERE + /* Check if we had data chaining in previous iocd */ + /* if we did, use previous cmd value */ + if (((chp->chan_info & INFO_SIOCD) == 0) && /* see if 1st IOCD in channel prog */ + (chp->ccw_flags & FLAG_DC)) { /* last IOCD have DC set? */ + sim_debug(DEBUG_CMD, dptr, + "ec_iocl @%06x DO DC, ccw_flags %04x cmd %02x\n", + chp->chan_caw, chp->ccw_flags, chp->ccw_cmd); +// chp->ccw_flags = (word2 >> 16) & 0xf800;/* get flags from bits 0-4 of WD 2 of IOCD */ +// if (chp->ccw_cmd == EC_READ) /* Force SLI on READ */ +// chp->ccw_flags |= FLAG_SLI; +// chp->ccw_count = word2 & 0xffff; /* get 16 bit byte count from IOCD WD 2 */ +// return 0; + } else + chp->ccw_cmd = (word1 >> 24) & 0xff; /* set new command from IOCD wd 1 */ +#else chp->ccw_cmd = (word1 >> 24) & 0xff; /* set command from IOCD wd 1 */ +#endif + chp->ccw_count = 0; if (!MEM_ADDR_OK(word1 & MASK24)) { /* see if memory address invalid */ chp->chan_status |= STATUS_PCHK; /* bad, program check */ @@ -392,8 +416,6 @@ loop: return 1; /* error return */ } - chp->ccw_count = 0; - /* this switch is here to satisify the SEL diag who wants a program */ /* check error instead of a unit check error for these cmd values??? */ /* validate the commands for the ethernet */ @@ -412,9 +434,20 @@ loop: chp->chan_status |= STATUS_PCHK; /* program check for invalid cmd */ return 1; /* error return */ - case EC_INCH: case EC_WRITE: case EC_READ: case EC_NOP: case EC_SNS: - case EC_LIA: case EC_TIC: case EC_CGA: case EC_LGA: case EC_LCC: + case EC_INCH: case EC_WRITE: case EC_READ: case EC_LIA: + case EC_TIC: case EC_CGA: case EC_LGA: case EC_LCC: case EC_STATS: case EC_CSTATS: + uptr->SNS = 0; + break; + case EC_SNS: + break; + case EC_NOP: + uptr->SNS = 0; + /* nop must have non zero count */ + if ((word2 & 0xffff) == 0) { + chp->chan_status |= STATUS_PCHK; /* program check for invalid cmd */ + return 1; /* error return */ + } break; default: uptr->SNS |= SNS_CMDREJ; @@ -464,8 +497,6 @@ loop: chp->chan_caw = word1 & MASK24; /* get new IOCD address */ chp->chan_status |= STATUS_PCHK; /* program check for invalid tic */ uptr->SNS |= SNS_CMDREJ; /* cmd rejected status */ -// if (((word1 & MASK24) == 0) || (word1 & 0x3)) -// uptr->SNS |= SNS_INAD; /* invalid address status */ sim_debug(DEBUG_EXP, dptr, "ec_iocl TIC ERROR chan_status[%04x] %04x\n", chan, chp->chan_status); return 1; /* error return */ @@ -506,6 +537,9 @@ loop: } } +// if (chp->ccw_cmd == EC_READ) /* Force SLI on READ */ + // chp->ccw_flags |= FLAG_SLI; + chp->chan_byte = BUFF_BUSY; /* busy & no bytes transferred yet */ sim_debug(DEBUG_XIO, dptr, @@ -593,9 +627,12 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) /* Unit is online, so process a command */ switch (cmd) { + case EC_WRITE: /* Write command 0x01 */ + uptr->CMD |= cmd|EC_BUSY; /* save cmd */ + sim_activate(uptr, 5000); /* start things off */ + return 0; case EC_INCH: /* INCH cmd 0x0 */ cmd = EC_INCH2; /* set dummy INCH cmd 0xf0 */ - case EC_WRITE: /* Write command 0x01 */ case EC_READ: /* Read command 0x02 */ case EC_TIC: /* Transfer in channel */ case EC_CGA: /* Disable multicast address */ @@ -605,18 +642,20 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) case EC_NOP: /* NOP 0x03 */ case EC_LIA: /* Load individual address */ case EC_LGA: /* Load Multicast address */ - uptr->SNS &= 0xffff0000; + uptr->SNS &= 0xffff0000; /* remove invalid cmd status */ // uptr->SNS &= 0x7fff0000; /* remove invalid cmd status */ // uptr->SNS &= ~SNS_CMDREJ; /* remove CMD reject status */ /* Fall through */ case EC_SNS: /* Sense 0x04 */ +#if 0 /* nop must have non zero count */ if (cmd == EC_NOP) { if (chp->ccw_count == 0) return SNS_CHNEND|SNS_DEVEND|STATUS_PCHK; /* diags want prog check */ } +#endif uptr->CMD |= cmd|EC_BUSY; /* save cmd */ - sim_activate(uptr, 300); /* start things off */ + sim_activate(uptr, 100); /* start things off */ return 0; } @@ -627,6 +666,35 @@ uint16 ec_startcmd(UNIT *uptr, uint16 chan, uint8 cmd) return SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK; /* diags want unit check */ } +/* Handle processing of ethernet requests. */ +t_stat ec_rec_srv(UNIT *uptr) +{ + DEVICE *dptr = get_dev(uptr); + int cmd = uptr->CMD & EC_CMDMSK; + + /* If not in loopback try and receive a packet */ + if ((ec_data.conf[0] & 0x40) == 0) { + if (eth_read(&ec_data.etherface, &ec_data.rec_buff[ec_data.rec_ptr], + NULL) > 0) { + if (((ec_data.rec_ptr + 1) & 0xf) == ec_data.xtr_ptr) { + ec_data.drop_cnt++; + } else { + ec_data.rec_ptr = (ec_data.rec_ptr + 1) & 0xf; + ec_data.rx_count++; + sim_debug(DEBUG_DETAIL, dptr, + "ec_rec_srv received packet %08x\n", + ec_data.rx_count); + } + } + } + + /* If there is a command on this subchannel, do it */ + if (cmd != 0) + return ec_srv(uptr); + + return SCPE_OK; +} + /* Handle processing of ethernet requests. */ t_stat ec_srv(UNIT *uptr) { @@ -637,6 +705,7 @@ t_stat ec_srv(UNIT *uptr) uint32 mema; int i; int n, len; + int pirq; uint8 ch; uint8 buf[1520]; uint8 *pck; @@ -653,10 +722,9 @@ t_stat ec_srv(UNIT *uptr) sim_debug(DEBUG_CMD, dptr, "ec_srv starting INCH %06x cmd, chsa %04x addr %06x cnt %04x\n", chp->chan_inch_addr, chsa, chp->ccw_addr, chp->ccw_count); - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - /* now call set_inch() function to write and test inch buffer addresses */ i = set_inch(uptr, mema); /* new address */ + ec_ini(uptr, 0); if ((i == SCPE_MEM) || (i == SCPE_ARG)) { /* any error */ /* we have error, bail out */ uptr->SNS |= SNS_CMDREJ|SNS_EQUCHK; @@ -689,14 +757,13 @@ t_stat ec_srv(UNIT *uptr) memcpy(&ec_data.mac, &buf[0], sizeof (ETH_MAC)); eth_mac_fmt(&ec_data.mac, (char *)&buf[0]); sim_debug(DEBUG_CMD, dptr, "ec_srv setting mac %s\n", buf); - i = buf[0] & 1; /* set/reset promiscuous mode */ n = ec_data.macs_n + 2; memcpy(&ec_data.macs[0], &ec_data.mac, sizeof (ETH_MAC)); memcpy(&ec_data.macs[1], &broadcast_ethaddr, sizeof (ETH_MAC)); if (ec_master_uptr->flags & UNIT_ATT) -//DIAGS eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, 0); /* set promiscuous if bit 7 of byte zero of mac address is set */ - eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, i); + eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, + ec_data.macs[0][0] & 1); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; @@ -705,14 +772,19 @@ t_stat ec_srv(UNIT *uptr) ec_data.macs_n = 0; ec_data.amc = 0; if (ec_master_uptr->flags & UNIT_ATT) - eth_filter (&ec_data.etherface, 1, ec_data.macs, ec_data.amc, 0); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + eth_filter (&ec_data.etherface, 2, ec_data.macs, ec_data.amc, + ec_data.macs[0][0] & 1); + if (chan_read_byte(chsa, &ch)) + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; case EC_LGA: /* Load Multicast address */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ ec_data.macs_n = 0; - for(n = 2; n < (int)(sizeof(ec_data.macs_n) / sizeof (ETH_MAC)); n++) { + len = 2; + for(n = 2; n < (int)(sizeof(ec_data.macs) / sizeof (ETH_MAC)); n++) { for(i = 0; i < sizeof (ETH_MAC); i++) { if (chan_read_byte(chsa, &buf[i])) { break; @@ -720,33 +792,34 @@ t_stat ec_srv(UNIT *uptr) } if (i != sizeof (ETH_MAC)) break; - memcpy(&ec_data.macs[n], &buf[0], sizeof (ETH_MAC)); + memcpy(&ec_data.macs[len++], &buf[0], sizeof (ETH_MAC)); } - ec_data.macs_n = n - 2; + ec_data.macs_n = len - 2; ec_data.amc = 1; - for (i = 0; i< n; i++) { + for (i = 0; i< len; i++) { eth_mac_fmt(&ec_data.macs[i], (char *)&buf[0]); sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv load mcast%d: %s\n",i,buf); } if (ec_master_uptr->flags & UNIT_ATT) -//DIAGS eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, 0); /* multicast on means promiscous is too */ - eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, ec_data.amc); + eth_filter (&ec_data.etherface, n, ec_data.macs, ec_data.amc, + ec_data.macs[0][0] & 1); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; case EC_WRITE: /* Write command 0x01 */ - ec_data.tx_count++; + pirq = 0; + uptr->CMD &= LMASK; /* remove old status bits & cmd */ hdr = (struct ec_eth_hdr *)(&ec_data.snd_buff.msg[0]); pck = (uint8 *)(&ec_data.snd_buff.msg[0]); - uptr->CMD &= LMASK; /* remove old status bits & cmd */ switch (GET_MODE(ec_master_uptr->flags)) { case 0: for(i = 0; i < sizeof (struct ec_eth_hdr); i++) { if (chan_read_byte(chsa, &pck[i])) { - goto runt; + pirq = 1; + goto wr_end; } } break; @@ -754,124 +827,237 @@ t_stat ec_srv(UNIT *uptr) case 2: for(i = 0; i < sizeof (ETH_MAC); i++) { if (chan_read_byte(chsa, &pck[i])) { - goto runt; + pirq = 1; + goto wr_end; } } memcpy(&hdr->src, ec_data.mac, sizeof (ETH_MAC)); - for(i += 6; i < sizeof(struct ec_eth_hdr); i++) { + for(i = sizeof(ETH_MAC) * 2; i < sizeof(struct ec_eth_hdr); i++) { if (chan_read_byte(chsa, &pck[i])) { - goto runt; + pirq = 1; + goto wr_end; } } break; case 3: for(i = 0; i < sizeof (ETH_MAC); i++) { if (chan_read_byte(chsa, &pck[i])) { - goto runt; + pirq = 1; + goto wr_end; } } memcpy(&hdr->src, ec_data.mac, sizeof (ETH_MAC)); hdr->type = htons(ETHTYPE_IP); break; } - pck = (uint8 *)(&ec_data.snd_buff.msg[sizeof(struct ec_eth_hdr)]); - for(i = 0; i < (ETH_FRAME_SIZE - sizeof(struct ec_eth_hdr)); i++) { - if (chan_read_byte(chsa, &pck[i])) { - break; + i = sizeof(struct ec_eth_hdr); + while (chan_read_byte(chsa, &ch) == 0) { + if (i < ETH_MAX_PACKET) { + sim_debug(DEBUG_DATA, &ec_dev, "ec_srv data: %06x %02x\n", + chp->ccw_addr, ch); + pck[i] = ch; } + i++; } - /* see if too many bytes */ - if (chp->ccw_count != 0) { +wr_end: + ec_data.snd_buff.len = i; + ec_packet_debug(&ec_data, "send", &ec_data.snd_buff); + + /* see if too few bytes */ + if (ec_data.snd_buff.len < ec_data.conf[9]) { + sim_debug(DEBUG_DETAIL, &ec_dev, + "ec_srv WRITE error user small packet %d %d\n", chp->ccw_count, ec_data.conf[9]); + /* diags wants prog check instead of unit check */ + pirq = 1; + } + /* see if too many bytes, did not get channel end before packet filled */ + if (ec_data.snd_buff.len > ETH_MAX_PACKET) { sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv WRITE error user 2manybytes %0x\n", chp->ccw_count); - goto runt; - } - ec_data.snd_buff.len = i + sizeof(struct ec_eth_hdr); - ec_packet_debug(&ec_data, "send", &ec_data.snd_buff); - if (eth_write(&ec_data.etherface, &ec_data.snd_buff, NULL) != SCPE_OK) { -runt: - sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv short packet %d\n",i); -//DIAGS chan_end(chsa, SNS_CHNEND|SNS_DEVEND|SNS_UNITEXP); /* diags wants prog check instead of unit check */ chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); break; } - sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv sent packet %d bytes\n",i); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + + if ((ec_data.conf[0] & 0x40) != 0) { + if (((ec_data.rec_ptr + 1) & 0xf) == ec_data.xtr_ptr) { + ec_data.drop_cnt++; + } else { + memcpy(&ec_data.rec_buff[ec_data.rec_ptr], + &ec_data.snd_buff, sizeof(ETH_PACK)); + sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv queued %d\n",ec_data.rec_ptr); + ec_data.rec_ptr = (ec_data.rec_ptr + 1) & 0xf; + ec_data.rx_count++; + ec_data.tx_count++; + } + } + + sim_debug(DEBUG_DETAIL, &ec_dev, + "ec_srv sent packet %d bytes count=%08x\n", + ec_data.snd_buff.len, ec_data.tx_count); + if ((ec_data.conf[0] & 0x40) == 0) { + /* Pad the packet */ + while(i < ETH_MIN_PACKET) { + ec_data.snd_buff.len++; + pck[i++] = 0; + } + if (eth_write(&ec_data.etherface, &ec_data.snd_buff, NULL) != SCPE_OK) { + sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv short packet %d\n",i); + /* diags wants prog check instead of unit check */ + pirq = 1; + ec_data.tx_count++; + } + } + if (pirq) + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else { + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + } break; case EC_READ: /* Read command 0x02 */ - /* min size is 78 */ - if (chp->ccw_count < (ETH_MIN_PACKET+sizeof(struct ec_eth_hdr))) { - sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv short read size %x\n",chp->ccw_count); - uptr->CMD &= LMASK; /* remove old status bits & cmd */ - /* diags wants prog check instead of unit check */ - chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); - break; - } - ec_master_uptr->SNS |= SNS_RCV_RDY; - if (eth_read(&ec_data.etherface, &ec_data.rec_buff, NULL) <= 0) { + /* If no data to receive wait for some more */ + if (ec_data.xtr_ptr == ec_data.rec_ptr) { sim_clock_coschedule(uptr, 1000); /* continue poll */ return SCPE_OK; } + pirq = 0; + sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv read %d %d size=%d\n", ec_data.xtr_ptr, + ec_data.rec_ptr, ec_data.conf[9]); uptr->CMD &= LMASK; /* remove old status bits & cmd */ - ec_packet_debug(&ec_data, "recv", &ec_data.rec_buff); - ec_data.rx_count++; - hdr = (struct ec_eth_hdr *)(&ec_data.rec_buff.msg[0]); - pck = (uint8 *)(&ec_data.rec_buff.msg[0]); + /* Read must be word bounded */ + if (chp->ccw_addr & 0x3) { + sim_debug(DEBUG_EXP, dptr, + "ec_iocl iocd bad address caw %06x ccw %06x\n", + chp->chan_caw, chp->ccw_addr); + ec_data.xtr_ptr = (ec_data.xtr_ptr + 1) & 0xf; +// chp->ccw_flags &= ~FLAG_SLI; + chp->ccw_count = 0; + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_LENGTH|STATUS_PCHK); + break; + } + + ec_master_uptr->SNS |= SNS_RCV_RDY; + ec_packet_debug(&ec_data, "recv", &ec_data.rec_buff[ec_data.xtr_ptr]); + pck = (uint8 *)(&ec_data.rec_buff[ec_data.xtr_ptr].msg[0]); + len = (int)(ec_data.rec_buff[ec_data.xtr_ptr].len); + if (len < ec_data.conf[9]) { + sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv short read size %x %x %x\n",chp->ccw_count, i, ec_data.conf[9]); + ec_data.xtr_ptr = (ec_data.xtr_ptr + 1) & 0xf; + chp->ccw_count = 0; + /* diags wants prog check instead of unit check */ + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + break; + } switch (GET_MODE(ec_master_uptr->flags)) { case 0: for(i = 0; i < sizeof (struct ec_eth_hdr); i++) { if (chan_write_byte(chsa, &pck[i])) { - goto runt; + pirq = 1; + break; } } break; case 1: case 2: - case 3: for(i = 0; i < sizeof (ETH_MAC); i++) { if (chan_write_byte(chsa, &pck[i])) { - goto runt; + pirq = 1; + break; } } - ch = (ec_data.rec_buff.len >> 8) & 0xff; + ch = (len >> 8) & 0xff; if (chan_write_byte(chsa, &ch)) { - goto runt; + pirq = 1; + break; } - ch = ec_data.rec_buff.len & 0xff; + ch = len & 0xff; if (chan_write_byte(chsa, &ch)) { - goto runt; + pirq = 1; + break; } for(; i < sizeof(struct ec_eth_hdr); i++) { if (chan_write_byte(chsa, &pck[i])) { - goto runt; + pirq = 1; + break; } } break; + case 3: + for(i = 0; i < sizeof (ETH_MAC); i++) { + if (chan_write_byte(chsa, &pck[i])) { + pirq = 1; + break; + } + } + ch = (len >> 8) & 0xff; + if (chan_write_byte(chsa, &ch)) { + pirq = 1; + break; + } + ch = len & 0xff; + if (chan_write_byte(chsa, &ch)) { + pirq = 1; + break; + } + for(; i < sizeof(ETH_MAC) * 2; i++) { + if (chan_write_byte(chsa, &pck[i])) { + pirq = 1; + break; + } + } + ch = (len >> 8) & 0xff; + if (chan_write_byte(chsa, &ch)) { + pirq = 1; + break; + } + ch = len & 0xff; + if (chan_write_byte(chsa, &ch)) { + pirq = 1; + break; + } + break; } - pck = (uint8 *)(&ec_data.rec_buff.msg[sizeof(struct ec_eth_hdr)]); - for(i = 0; i < (int)(ec_data.rec_buff.len - sizeof(struct ec_eth_hdr)); i++) { + for(i = sizeof(struct ec_eth_hdr); i < len; i++) { if (chan_write_byte(chsa, &pck[i])) { - break; +// if (len < ec_data.conf[9]) { +// sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv short read size %x %x %x\n",chp->ccw_count, i, ec_data.conf[9]); +// /* diags wants prog check instead of unit check */ +// pirq = 1; + // } + ec_data.xtr_ptr = (ec_data.xtr_ptr + 1) & 0xf; + ec_data.rx_count++; + sim_debug(DEBUG_DETAIL, &ec_dev, + "ec_srv received bytes %d of %d count=%08x\n" ,i, + len, ec_data.rx_count); + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_LENGTH); + return SCPE_OK; } } - sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv received bytes %d\n",i); - chan_end(chsa, SNS_CHNEND|SNS_DEVEND); + chp->ccw_flags |= FLAG_SLI; +// chp->ccw_cmd = 0; /* This is to kill SLI indicator */ + ec_data.xtr_ptr = (ec_data.xtr_ptr + 1) & 0xf; + sim_debug(DEBUG_DETAIL, &ec_dev, + "ec_srv received bytes %d count=%08x\n" ,len, ec_data.rx_count); + if (pirq) + chan_end(chsa, SNS_CHNEND|SNS_DEVEND|STATUS_PCHK); + else + chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; case EC_LCC: /* Configure LCC 0x10 */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ /* Read up to 12 bytes of configuration data */ for (i = 0; i < 12; i++) { - if (chan_read_byte(chsa, &conf[0])) { + if (chan_read_byte(chsa, &ec_data.conf[i])) { break; } } sim_debug(DEBUG_CMD, &ec_dev, "ec_srv LCC CONF: %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n", - conf[0], conf[1], conf[2], conf[3], conf[4], conf[5], conf[6], conf[7], - conf[8], conf[9], conf[10], conf[11]); + ec_data.conf[0], ec_data.conf[1], ec_data.conf[2], ec_data.conf[3], + ec_data.conf[4], ec_data.conf[5], ec_data.conf[6], ec_data.conf[7], + ec_data.conf[8], ec_data.conf[9], ec_data.conf[10], ec_data.conf[11]); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; @@ -880,6 +1066,12 @@ runt: /* First 5 words are always zero since these errors are not supported */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ for (i = 0; i < STAT_LEN * 2; i++) { + if (i == 6) + ch = (ec_data.drop_cnt >> 8) & 0xff; + if (i == 7) + ch = ec_data.drop_cnt & 0xff; + if (i == 8) + ch = 0; if (chan_write_byte(chsa, &ch)) { break; } @@ -908,6 +1100,10 @@ runt: case EC_CSTATS: /* Clear software counters */ uptr->CMD &= LMASK; /* remove old status bits & cmd */ ec_data.rx_count = ec_data.tx_count = 0; + (void)chan_read_byte(chsa, &ch); + sim_debug(DEBUG_CMD, dptr, + "ec_srv cmd clear counters chsa %04x count %04x completed\n", + chsa, chp->ccw_count); chan_end(chsa, SNS_CHNEND|SNS_DEVEND); break; @@ -936,6 +1132,11 @@ runt: } } + len = ec_data.rec_buff[ec_data.xtr_ptr].len; +// if (ec_data.xtr_ptr == ec_data.rec_ptr) + // len = 0; + sim_debug(DEBUG_DETAIL, &ec_dev, "ec_srv SNS %d %d\n", ec_data.xtr_ptr, + ec_data.rec_ptr); ch = (uptr->SNS >> 24) & 0xfc; ch |= GET_MODE(ec_master_uptr->flags); sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b0 1 %02x\n", ch); @@ -943,10 +1144,10 @@ runt: ch = (ec_master_uptr->SNS >> 16) & 0xff; sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b1 2 %02x\n", ch); chan_write_byte(chsa, &ch); - ch = (ec_data.rec_buff.len >> 8) & 0xff; + ch = (len >> 8) & 0xff; sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b2 3 %02x\n", ch); chan_write_byte(chsa, &ch); - ch = ec_data.rec_buff.len & 0xff; + ch = len & 0xff; sim_debug(DEBUG_DETAIL, dptr, "ec_srv sense b3 4 %02x\n", ch); chan_write_byte(chsa, &ch); @@ -961,6 +1162,7 @@ runt: "ec_startcmd CMD sense excess cnt %02x\n", chp->ccw_count); break; } +/*JB*/ ec_data.rec_buff[ec_data.xtr_ptr].len = 0; /* reset last buffer length */ uptr->SNS &= ~(SNS_CMDREJ|SNS_EQUCHK); /* clear old status */ @@ -1003,7 +1205,7 @@ uint16 ec_haltio(UNIT *uptr) { chp->ccw_count = 0; /* zero the count */ chp->ccw_flags &= ~(FLAG_DC|FLAG_CC);/* stop any chaining */ uptr->CMD &= LMASK; /* make non-busy */ -//12 uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ + uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ sim_cancel(uptr); /* clear the input timer */ sim_debug(DEBUG_CMD, dptr, "ec_haltio HIO I/O stop chsa %04x cmd = %02x\n", chsa, cmd); @@ -1011,7 +1213,7 @@ uint16 ec_haltio(UNIT *uptr) { return SCPE_IOERR; } uptr->CMD &= LMASK; /* make non-busy */ -//12uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ + uptr->SNS = SNS_RCV_RDY; /* status is online & ready */ sim_debug(DEBUG_CMD, dptr, "ec_haltio HIO I/O not busy chsa %04x cmd = %02x\n", chsa, cmd); return SCPE_OK; /* not busy */ @@ -1024,7 +1226,18 @@ void ec_ini(UNIT *uptr, t_bool f) uptr->CMD &= LMASK; /* remove old status bits & cmd */ uptr->SNS = 0; /* save mode value */ - + memset(&ec_data.conf[0], 0, sizeof(ec_data.conf)); + ec_data.macs_n = 0; + ec_data.tx_count = 0; + ec_data.rx_count = 0; + ec_data.rec_ptr = 0; + ec_data.xtr_ptr = 0; + ec_data.drop_cnt = 0; + ec_data.amc = 0; + if (ec_master_uptr->flags & UNIT_ATT) + /* multicast on means promiscous is too */ + eth_filter (&ec_data.etherface, ec_data.macs_n + 2, ec_data.macs, + ec_data.amc, ec_data.macs[0][0] & 1); sim_debug(DEBUG_EXP, dptr, "EC init device %s on unit EC%04X\n", dptr->name, GET_UADDR(uptr->CMD)); } @@ -1150,8 +1363,8 @@ void ec_packet_debug(struct ec_device *ec, const char *action, return; } if (ntohs(eth->type) != ETHTYPE_IP) { - payload = (uint8 *)&packet->msg[sizeof(struct ec_eth_hdr)]; - len = packet->len - sizeof(struct ec_eth_hdr); + payload = (uint8 *)&packet->msg[0]; + len = packet->len; sim_data_trace(&ec_dev, ec_unit, payload, "", len, "", DEBUG_DATA); return; } @@ -1264,6 +1477,21 @@ t_stat ec_reset (DEVICE *dptr) /* Set a default MAC address in a BBN assigned OID range no longer in use */ ec_set_mac (dptr->units, 0, "00:00:02:00:00:00/24", NULL); } + memset(&ec_data.conf[0], 0, sizeof(ec_data.conf)); + ec_data.macs_n = 0; + ec_data.tx_count = 0; + ec_data.rx_count = 0; + ec_data.rec_ptr = 0; + ec_data.xtr_ptr = 0; + ec_data.drop_cnt = 0; + ec_data.amc = 0; + if (ec_master_uptr->flags & UNIT_ATT) + /* multicast on means promiscous is too */ + eth_filter (&ec_data.etherface, ec_data.macs_n + 2, ec_data.macs, + ec_data.amc, ec_data.macs[0][0] & 1); + sim_debug(DEBUG_EXP, dptr, + "EC reset device %s on unit EC%04X\n", dptr->name, + GET_UADDR(dptr->units->CMD)); return SCPE_OK; } @@ -1304,7 +1532,7 @@ t_stat ec_attach(UNIT* uptr, CONST char* cptr) uptr->filename = tptr; uptr->flags |= UNIT_ATT; - eth_setcrc(&ec_data.etherface, 1); /* Enable CRC */ + eth_setcrc(&ec_data.etherface, 0); /* Enable CRC */ /* init read queue (first time only) */ status = ethq_init(&ec_data.ReadQ, 8); @@ -1316,6 +1544,9 @@ t_stat ec_attach(UNIT* uptr, CONST char* cptr) ec_dev.name); } + eth_set_async (&ec_data.etherface, 0); + + return SCPE_OK; }