Subject: port-i386/522: Several bugs in IE ethernet driver
To: None <gnats-admin@sun-lamp.cs.berkeley.edu>
From: None <r-boni@uiuc.edu>
List: netbsd-bugs
Date: 10/17/1994 14:20:04
>Number:         522
>Category:       port-i386
>Synopsis:       if_ie sets promisc mode in wrong place, fouls up TDR commands
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    gnats-admin (GNATS administrator)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Oct 17 14:20:03 1994
>Originator:     Rafal Boni
>Organization:
	Procrastination, Inc.: We'll get to you tomorrow!
>Release:        1.0_Beta, Supped Oct 17th, ~ 3PM Central
>Environment:

System: NetBSD colt-73.slip.uiuc.edu 1.0_BETA NetBSD 1.0_BETA (RAFAL) #9: Fri Oct 14 17:26:08 CDT 1994 rafal@ruger-47.slip.uiuc.edu:/usr/src/sys/arch/i386/compile/RAFAL i386

	2 i386 boxes with EtherLink/16 cards.

>Description:

	[There's two mostly independent probs. here...]

	1) the if_ie driver sets the promisc flag AFTER the card is re-
	   configured, so PROMISC. mode does not get set in the right place,
	   AND/OR can linger on after it should have been turned off.

	2) The if_ie driver also mucks about with stuff in the TDR code, so
	   that a failed TDR command will be reported as an OPEN!

>How-To-Repeat:

	[Match up these statements with prob. descriptions above...]

	1) Run tcpdump and watch machine come to it's knees as the if_ie driver
	   leaves the card in promisc. mode but thinks it isn't... Hence ALL
	   packets off the wire are passed up to the higher-level protocol
           machinery

	2) Dunno... I seem to encounter this pretty much at random, sometimes
	   on bootup, other times it's caused by the card's re-initing itself.

>Fix:

	[NOTE: this patch also cleans out 3-4 lines of dead/pointless code...]

*** if_ie.c.orig	Mon Oct 17 15:48:10 1994
--- if_ie.c	Mon Oct 17 15:51:47 1994
***************
*** 728,738 ****
  		mc_setup(sc, (caddr_t)sc->xmit_cbuffs[0]);
  		sc->want_mcsetup = 0;
  	}
  
- 	/* Wish I knew why this seems to be necessary... */
- 	sc->xmit_cmds[0]->ie_xmit_status |= IE_STAT_COMPL;
- 
  	iestart(&sc->sc_arpcom.ac_if);
  }
  
  /*
--- 728,735 ----
***************
*** 1569,1592 ****
  	
  	cmd->com.ie_cmd_status = 0;
  	cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
  	cmd->com.ie_cmd_link = 0xffff;
- 	cmd->ie_tdr_time = 0;
  	
  	sc->scb->ie_command_list = MK_16(MEM, cmd);
  	cmd->ie_tdr_time = 0;
  	
! 	if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL))
! 		result = 0x2000;
  	else
  		result = cmd->ie_tdr_time;
  	
  	ie_ack(sc, IE_ST_WHENCE);
  	
  	if (result & IE_TDR_SUCCESS)
  		return;
  	
! 	if (result & IE_TDR_XCVR) {
  		printf("%s: transceiver problem\n", sc->sc_dev.dv_xname);
  	} else if (result & IE_TDR_OPEN) {
  		printf("%s: TDR detected an open %d clocks away\n",
  		       sc->sc_dev.dv_xname, result & IE_TDR_TIME);
--- 1566,1591 ----
  	
  	cmd->com.ie_cmd_status = 0;
  	cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
  	cmd->com.ie_cmd_link = 0xffff;
  	
  	sc->scb->ie_command_list = MK_16(MEM, cmd);
  	cmd->ie_tdr_time = 0;
  	
! 	if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
! 	    !(cmd->com.ie_cmd_status & IE_STAT_OK))
! 		result = 0x10000;
  	else
  		result = cmd->ie_tdr_time;
  	
  	ie_ack(sc, IE_ST_WHENCE);
  	
  	if (result & IE_TDR_SUCCESS)
  		return;
  	
! 	if (result & 0x10000) {
! 		printf("%s: TDR command  failed\n", sc->sc_dev.dv_xname);
! 	} else if (result & IE_TDR_XCVR) {
  		printf("%s: transceiver problem\n", sc->sc_dev.dv_xname);
  	} else if (result & IE_TDR_OPEN) {
  		printf("%s: TDR detected an open %d clocks away\n",
  		       sc->sc_dev.dv_xname, result & IE_TDR_TIME);
***************
*** 1806,1818 ****
  		ptr += IE_TBUF_SIZE;
  		ptr = Align(ptr);
  	}
  	
- 	/*
- 	 * This must be coordinated with iestart() and ietint().
- 	 */
- 	sc->xmit_cmds[0]->ie_xmit_status = IE_STAT_COMPL;
- 	
  	sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING; /* tell higher levels that we are here */
  	start_receiver(sc);
  	return 0;
  }
--- 1805,1812 ----
***************
*** 1881,1888 ****
--- 1875,1884 ----
  		}
  		break;
  		
  	case SIOCSIFFLAGS:
+ 		sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
+ 
  		if ((ifp->if_flags & IFF_UP) == 0 &&
  		    (ifp->if_flags & IFF_RUNNING) != 0) {
  			/*
  			 * If interface is marked down and it is running, then
***************
*** 1904,1912 ****
  			 */
  			iestop(sc);
  			ieinit(sc);
  		}
- 		sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
  #ifdef IEDEBUG
  		if (ifp->if_flags & IFF_DEBUG)
  			sc->sc_debug = IED_ALL;
  		else
--- 1900,1907 ----
>Audit-Trail:
>Unformatted: