Subject: ether_ioctl()
To: None <tech-net@netbsd.org>
From: Jason R Thorpe <thorpej@zembu.com>
List: tech-net
Date: 10/03/2000 22:27:05
--tjCHc7DPkfUGtrlw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I finally got around to implementing this in a sane way for the
NetBSD network stack.  Attached are ether_ioctl() itself and
changes for several network drivers to use it.

Note that it changes (*if_reset)() to (*if_init)() and adds
an (*if_stop)(), which also takes an argument indicating that
the interface should be disabled (Rx buffers freed, power
removed from the device, etc.).

There's also an unrelated change in there (if_bridge) that is
part of somthing else I'm working on, but if I'm changing the
ifnet, do it once, not N times, right? :-)

Feedback soon, please.

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>

--tjCHc7DPkfUGtrlw
Content-Type: text/plain; charset=us-ascii
Content-Description: ether_ioctl.diff
Content-Disposition: attachment; filename="ether_ioctl.diff"

Index: net/if.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if.c,v
retrieving revision 1.71
diff -c -r1.71 if.c
*** net/if.c	2000/10/01 23:16:07	1.71
--- net/if.c	2000/10/04 05:23:29
***************
*** 213,219 ****
  }
  
  int
! if_nullreset(ifp)
  	struct ifnet *ifp;
  {
  
--- 213,219 ----
  }
  
  int
! if_nullinit(ifp)
  	struct ifnet *ifp;
  {
  
***************
*** 221,226 ****
--- 221,235 ----
  }
  
  void
+ if_nullstop(ifp, disable)
+ 	struct ifnet *ifp;
+ 	int disable;
+ {
+ 
+ 	/* Nothing. */
+ }
+ 
+ void
  if_nullwatchdog(ifp)
  	struct ifnet *ifp;
  {
***************
*** 356,362 ****
  	ifp->if_input	 = if_nullinput;
  	ifp->if_start	 = if_nullstart;
  	ifp->if_ioctl	 = if_nullioctl;
! 	ifp->if_reset	 = if_nullreset;
  	ifp->if_watchdog = if_nullwatchdog;
  	ifp->if_drain	 = if_nulldrain;
  
--- 365,372 ----
  	ifp->if_input	 = if_nullinput;
  	ifp->if_start	 = if_nullstart;
  	ifp->if_ioctl	 = if_nullioctl;
! 	ifp->if_init	 = if_nullinit;
! 	ifp->if_stop	 = if_nullstop;
  	ifp->if_watchdog = if_nullwatchdog;
  	ifp->if_drain	 = if_nulldrain;
  
Index: net/if.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if.h,v
retrieving revision 1.53
diff -c -r1.53 if.h
*** net/if.h	2000/07/20 18:40:27	1.53
--- net/if.h	2000/10/04 05:23:30
***************
*** 240,247 ****
  		__P((struct ifnet *));
  	int	(*if_ioctl)		/* ioctl routine */
  		__P((struct ifnet *, u_long, caddr_t));
! 	int	(*if_reset)		/* XXX bus reset routine */
  		__P((struct ifnet *));
  	void	(*if_watchdog)		/* timer routine */
  		__P((struct ifnet *));
  	void	(*if_drain)		/* routine to release resources */
--- 240,249 ----
  		__P((struct ifnet *));
  	int	(*if_ioctl)		/* ioctl routine */
  		__P((struct ifnet *, u_long, caddr_t));
! 	int	(*if_init)		/* init routine */
  		__P((struct ifnet *));
+ 	void	(*if_stop)		/* stop routine */
+ 		__P((struct ifnet *, int));
  	void	(*if_watchdog)		/* timer routine */
  		__P((struct ifnet *));
  	void	(*if_drain)		/* routine to release resources */
***************
*** 256,261 ****
--- 258,264 ----
  	struct	sockaddr_dl *if_sadl;	/* pointer to our sockaddr_dl */
  	u_int8_t *if_broadcastaddr;	/* linklevel broadcast bytestring */
  	struct ifprefix *if_prefixlist; /* linked list of prefixes per if */
+ 	void *if_bridge;		/* bridge glue */
  };
  #define	if_mtu		if_data.ifi_mtu
  #define	if_type		if_data.ifi_type
***************
*** 628,634 ****
  void	if_nullinput __P((struct ifnet *, struct mbuf *));
  void	if_nullstart __P((struct ifnet *));
  int	if_nullioctl __P((struct ifnet *, u_long, caddr_t));
! int	if_nullreset __P((struct ifnet *));
  void	if_nullwatchdog __P((struct ifnet *));
  void	if_nulldrain __P((struct ifnet *));
  #else
--- 631,638 ----
  void	if_nullinput __P((struct ifnet *, struct mbuf *));
  void	if_nullstart __P((struct ifnet *));
  int	if_nullioctl __P((struct ifnet *, u_long, caddr_t));
! int	if_nullinit __P((struct ifnet *));
! void	if_nullstop __P((struct ifnet *, int));
  void	if_nullwatchdog __P((struct ifnet *));
  void	if_nulldrain __P((struct ifnet *));
  #else
Index: net/if_ether.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_ether.h,v
retrieving revision 1.19
diff -c -r1.19 if_ether.h
*** net/if_ether.h	2000/10/03 23:33:38	1.19
--- net/if_ether.h	2000/10/04 04:42:55
***************
*** 161,166 ****
--- 161,167 ----
  extern u_int8_t ether_ipmulticast_min[ETHER_ADDR_LEN];
  extern u_int8_t ether_ipmulticast_max[ETHER_ADDR_LEN];
  
+ int	ether_ioctl(struct ifnet *, u_long, caddr_t);
  int	ether_addmulti (struct ifreq *, struct ethercom *);
  int	ether_delmulti (struct ifreq *, struct ethercom *);
  int	ether_changeaddr (struct ifreq *, struct ethercom *);
Index: net/if_ethersubr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_ethersubr.c,v
retrieving revision 1.64
diff -c -r1.64 if_ethersubr.c
*** net/if_ethersubr.c	2000/10/03 23:50:52	1.64
--- net/if_ethersubr.c	2000/10/04 04:42:55
***************
*** 1088,1090 ****
--- 1088,1183 ----
  	 */
  	return (ENETRESET);
  }
+ 
+ /*
+  * Common ioctls for Ethernet interfaces.  Note, we must be
+  * called at splnet().
+  */
+ int
+ ether_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+ {
+ 	struct ethercom *ec = (void *) ifp;
+ 	struct ifreq *ifr = (struct ifreq *)data;
+ 	struct ifaddr *ifa = (struct ifaddr *)data;
+ 	int error = 0;
+ 
+ 	switch (cmd) {
+ 	case SIOCSIFADDR:
+ 		ifp->if_flags |= IFF_UP;
+ 		switch (ifa->ifa_addr->sa_family) {
+ #ifdef INET
+ 		case AF_INET:
+ 			if ((error = (*ifp->if_init)(ifp)) != 0)
+ 				break;
+ 			arp_ifinit(ifp, ifa);
+ 			break;
+ #endif /* INET */
+ #ifdef NS
+ 		case AF_NS:
+ 		    {
+ 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
+ 
+ 			if (ns_nullhost(*ina))
+ 				ina->x_host = *(union ns_host *)
+ 				    LLADDR(ifp->if_sadl);
+ 			else
+ 				memcpy(LLADDR(ifp->if_sadl),
+ 				    ina->x_host.c_host, ifp->if_addrlen);
+ 			/* Set new address. */
+ 			error = (*ifp->if_init)(ifp);
+ 			break;
+ 		    }
+ #endif /* NS */
+ 		default:
+ 			error = (*ifp->if_init)(ifp);
+ 			break;
+ 		}
+ 		break;
+ 
+ 	case SIOCGIFADDR:
+ 		memcpy(((struct sockaddr *)&ifr->ifr_data)->sa_data,
+ 		    LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
+ 		break;
+ 
+ 	case SIOCSIFMTU:
+ 		if (ifr->ifr_mtu > ETHERMTU)
+ 			error = EINVAL;
+ 		else
+ 			ifp->if_mtu = ifr->ifr_mtu;
+ 		break;
+ 
+ 	case SIOCSIFFLAGS:
+ 		if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_RUNNING) {
+ 			/*
+ 			 * If interface is marked down and it is running,
+ 			 * then stop and disable it.
+ 			 */
+ 			(*ifp->if_stop)(ifp, 1);
+ 		} else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_UP) {
+ 			/*
+ 			 * If interface is marked up and it is stopped, then
+ 			 * start it.
+ 			 */
+ 			error = (*ifp->if_init)(ifp);
+ 		} else if ((ifp->if_flags & IFF_UP) != 0) {
+ 			/*
+ 			 * Reset the interface to pick up changes in any other
+ 			 * flags that affect the hardware state.
+ 			 */
+ 			error = (*ifp->if_init)(ifp);
+ 		}
+ 		break;
+ 
+ 	case SIOCADDMULTI:
+ 	case SIOCDELMULTI:
+ 		error = (cmd == SIOCADDMULTI) ?
+ 		    ether_addmulti(ifr, ec) :
+ 		    ether_delmulti(ifr, ec);
+ 		break;
+ 
+ 	default:
+ 		error = ENOTTY;
+ 	}
+ 
+ 	return (error);
+ }
Index: dev/ic/i82557.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/i82557.c,v
retrieving revision 1.39
diff -c -r1.39 i82557.c
*** dev/ic/i82557.c	2000/10/03 23:35:02	1.39
--- dev/ic/i82557.c	2000/10/04 04:42:58
***************
*** 177,186 ****
  
  void	fxp_start __P((struct ifnet *));
  int	fxp_ioctl __P((struct ifnet *, u_long, caddr_t));
- int	fxp_init __P((struct fxp_softc *));
- void	fxp_rxdrain __P((struct fxp_softc *));
- void	fxp_stop __P((struct fxp_softc *, int));
  void	fxp_watchdog __P((struct ifnet *));
  int	fxp_add_rfabuf __P((struct fxp_softc *, bus_dmamap_t, int));
  int	fxp_mdi_read __P((struct device *, int, int));
  void	fxp_statchg __P((struct device *));
--- 177,187 ----
  
  void	fxp_start __P((struct ifnet *));
  int	fxp_ioctl __P((struct ifnet *, u_long, caddr_t));
  void	fxp_watchdog __P((struct ifnet *));
+ int	fxp_init __P((struct ifnet *));
+ void	fxp_stop __P((struct ifnet *, int));
+ 
+ void	fxp_rxdrain __P((struct fxp_softc *));
  int	fxp_add_rfabuf __P((struct fxp_softc *, bus_dmamap_t, int));
  int	fxp_mdi_read __P((struct device *, int, int));
  void	fxp_statchg __P((struct device *));
***************
*** 331,336 ****
--- 332,339 ----
  	ifp->if_ioctl = fxp_ioctl;
  	ifp->if_start = fxp_start;
  	ifp->if_watchdog = fxp_watchdog;
+ 	ifp->if_init = fxp_init;
+ 	ifp->if_stop = fxp_stop;
  
  	/*
  	 * We can support 802.1Q VLAN-sized frames.
***************
*** 459,465 ****
  	 * Since the system's going to halt shortly, don't bother
  	 * freeing mbufs.
  	 */
! 	fxp_stop(sc, 0);
  }
  /*
   * Power handler routine. Called when the system is transitioning
--- 462,468 ----
  	 * Since the system's going to halt shortly, don't bother
  	 * freeing mbufs.
  	 */
! 	fxp_stop(&sc->sc_ethercom.ec_if, 0);
  }
  /*
   * Power handler routine. Called when the system is transitioning
***************
*** 473,488 ****
  	void *arg;
  {
  	struct fxp_softc *sc = arg;
! 	struct ifnet *ifp;
  	int s;
  
  	s = splnet();
  	if (why != PWR_RESUME)
! 		fxp_stop(sc, 0);
  	else {
- 		ifp = &sc->sc_ethercom.ec_if;
  		if (ifp->if_flags & IFF_UP)
! 			fxp_init(sc);
  	}
  	splx(s);
  }
--- 476,490 ----
  	void *arg;
  {
  	struct fxp_softc *sc = arg;
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	int s;
  
  	s = splnet();
  	if (why != PWR_RESUME)
! 		fxp_stop(ifp, 0);
  	else {
  		if (ifp->if_flags & IFF_UP)
! 			fxp_init(ifp);
  	}
  	splx(s);
  }
***************
*** 1060,1066 ****
  				 * If we want a re-init, do that now.
  				 */
  				if (sc->sc_flags & FXPF_WANTINIT)
! 					(void) fxp_init(sc);
  			}
  
  			/*
--- 1062,1068 ----
  				 * If we want a re-init, do that now.
  				 */
  				if (sc->sc_flags & FXPF_WANTINIT)
! 					(void) fxp_init(ifp);
  			}
  
  			/*
***************
*** 1139,1145 ****
  	 * speed transition).
  	 */
  	if (sc->sc_rxidle > FXP_MAX_RX_IDLE) {
! 		(void) fxp_init(sc);
  		splx(s);
  		return;
  	}
--- 1141,1147 ----
  	 * speed transition).
  	 */
  	if (sc->sc_rxidle > FXP_MAX_RX_IDLE) {
! 		(void) fxp_init(ifp);
  		splx(s);
  		return;
  	}
***************
*** 1211,1221 ****
   * the interface.
   */
  void
! fxp_stop(sc, drain)
! 	struct fxp_softc *sc;
! 	int drain;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct fxp_txsoft *txs;
  	int i;
  
--- 1213,1223 ----
   * the interface.
   */
  void
! fxp_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
! 	struct fxp_softc *sc = ifp->if_softc;
  	struct fxp_txsoft *txs;
  	int i;
  
***************
*** 1254,1264 ****
  	}
  	sc->sc_txpending = 0;
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		fxp_rxdrain(sc);
  	}
  
  }
--- 1256,1264 ----
  	}
  	sc->sc_txpending = 0;
  
! 	if (disable) {
  		fxp_rxdrain(sc);
+ 		fxp_disable(sc);
  	}
  
  }
***************
*** 1278,1304 ****
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) fxp_init(sc);
  }
  
  /*
   * Initialize the interface.  Must be called at splnet().
   */
  int
! fxp_init(sc)
! 	struct fxp_softc *sc;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct fxp_cb_config *cbp;
  	struct fxp_cb_ias *cb_ias;
  	struct fxp_cb_tx *txd;
  	bus_dmamap_t rxmap;
  	int i, prm, save_bf, allm, error = 0;
  
  	/*
  	 * Cancel any pending I/O
  	 */
! 	fxp_stop(sc, 0);
  
  	/* 
  	 * XXX just setting sc_flags to 0 here clears any FXPF_MII
--- 1278,1307 ----
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) fxp_init(ifp);
  }
  
  /*
   * Initialize the interface.  Must be called at splnet().
   */
  int
! fxp_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct fxp_softc *sc = ifp->if_softc;
  	struct fxp_cb_config *cbp;
  	struct fxp_cb_ias *cb_ias;
  	struct fxp_cb_tx *txd;
  	bus_dmamap_t rxmap;
  	int i, prm, save_bf, allm, error = 0;
  
+ 	if ((error = fxp_enable(sc)) != 0)
+ 		goto out;
+ 
  	/*
  	 * Cancel any pending I/O
  	 */
! 	fxp_stop(ifp, 0);
  
  	/* 
  	 * XXX just setting sc_flags to 0 here clears any FXPF_MII
***************
*** 1529,1536 ****
  	fxp_start(ifp);
  
   out:
! 	if (error)
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
  	return (error);
  }
  
--- 1532,1542 ----
  	fxp_start(ifp);
  
   out:
! 	if (error) {
! 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 		ifp->if_timer = 0;
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
+ 	}
  	return (error);
  }
  
***************
*** 1691,1812 ****
  }
  
  int
! fxp_ioctl(ifp, command, data)
  	struct ifnet *ifp;
! 	u_long command;
  	caddr_t data;
  {
  	struct fxp_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
- 
- 	switch (command) {
- 	case SIOCSIFADDR:
- 		if ((error = fxp_enable(sc)) != 0)
- 			break;
- 		ifp->if_flags |= IFF_UP;
- 
- 		switch (ifa->ifa_addr->sa_family) {
- #ifdef INET
- 		case AF_INET:
- 			if ((error = fxp_init(sc)) != 0)
- 				break;
- 			arp_ifinit(ifp, ifa);
- 			break;
- #endif /* INET */
- #ifdef NS
- 		case AF_NS:
- 		    {
- 			 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
- 
- 			 if (ns_nullhost(*ina))
- 				ina->x_host = *(union ns_host *)
- 				    LLADDR(ifp->if_sadl);
- 			 else
- 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
- 				    ifp->if_addrlen);
- 			 /* Set new address. */
- 			 error = fxp_init(sc);
- 			 break;
- 		    }
- #endif /* NS */
- 		default:
- 			error = fxp_init(sc);
- 			break;
- 		}
- 		break;
  
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			fxp_stop(sc, 1);
! 			fxp_disable(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interface is marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			if((error = fxp_enable(sc)) != 0)
! 				break;
! 			error = fxp_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up change in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			if((error = fxp_enable(sc)) != 0)
! 				break;
! 			error = fxp_init(sc);
! 		}
! 		break;
! 
! 	case SIOCADDMULTI:
! 	case SIOCDELMULTI:
! 		if(sc->sc_enabled == 0) {
! 			error = EIO;
! 			break;
! 		}
! 		error = (command == SIOCADDMULTI) ?
! 		    ether_addmulti(ifr, &sc->sc_ethercom) :
! 		    ether_delmulti(ifr, &sc->sc_ethercom);
! 
! 		if (error == ENETRESET) {
! 			/*
! 			 * Multicast list has changed; set the hardware
! 			 * filter accordingly.
! 			 */
! 			if (sc->sc_txpending) {
! 				sc->sc_flags |= FXPF_WANTINIT;
! 				error = 0;
! 			} else
! 				error = fxp_init(sc);
! 		}
! 		break;
! 
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
  		break;
  
  	default:
! 		error = EINVAL;
  		break;
  	}
  
  	splx(s);
  	return (error);
--- 1697,1741 ----
  }
  
  int
! fxp_ioctl(ifp, cmd, data)
  	struct ifnet *ifp;
! 	u_long cmd;
  	caddr_t data;
  {
  	struct fxp_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
! 	switch (cmd) {
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
  	default:
! 		error = ether_ioctl(ifp, cmd, data);
! 		if (error == ENETRESET) {
! 			if (sc->sc_enabled) {
! 				/*
! 				 * Multicast list has changed; set the
! 				 * hardware filter accordingly.
! 				 */
! 				if (sc->sc_txpending) {
! 					sc->sc_flags |= FXPF_WANTINIT;
! 					error = 0;
! 				} else
! 					error = fxp_init(ifp);
! 			} else
! 				error = 0;
! 		}
  		break;
  	}
+ 
+ 	/* Try to get more packets going. */
+ 	if (sc->sc_enabled)
+ 		fxp_start(ifp);
  
  	splx(s);
  	return (error);
Index: dev/ic/rtl81x9.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/rtl81x9.c,v
retrieving revision 1.14
diff -c -r1.14 rtl81x9.c
*** dev/ic/rtl81x9.c	2000/10/01 23:32:42	1.14
--- dev/ic/rtl81x9.c	2000/10/04 04:42:59
***************
*** 141,148 ****
  STATIC void rtk_txeof		__P((struct rtk_softc *));
  STATIC void rtk_start		__P((struct ifnet *));
  STATIC int rtk_ioctl		__P((struct ifnet *, u_long, caddr_t));
! STATIC void rtk_init		__P((void *));
! STATIC void rtk_stop		__P((struct rtk_softc *));
  STATIC void rtk_watchdog	__P((struct ifnet *));
  STATIC void rtk_shutdown	__P((void *));
  STATIC int rtk_ifmedia_upd	__P((struct ifnet *));
--- 141,149 ----
  STATIC void rtk_txeof		__P((struct rtk_softc *));
  STATIC void rtk_start		__P((struct ifnet *));
  STATIC int rtk_ioctl		__P((struct ifnet *, u_long, caddr_t));
! STATIC int rtk_init		__P((struct ifnet *));
! STATIC void rtk_stop		__P((struct ifnet *, int));
! 
  STATIC void rtk_watchdog	__P((struct ifnet *));
  STATIC void rtk_shutdown	__P((void *));
  STATIC int rtk_ifmedia_upd	__P((struct ifnet *));
***************
*** 167,175 ****
  STATIC void rtk_setmulti	__P((struct rtk_softc *));
  STATIC int rtk_list_tx_init	__P((struct rtk_softc *));
  
- STATIC int rtk_ether_ioctl __P((struct ifnet *, u_long, caddr_t));
- 
- 
  #define EE_SET(x)					\
  	CSR_WRITE_1(sc, RTK_EECMD,			\
  		CSR_READ_1(sc, RTK_EECMD) | (x))
--- 168,173 ----
***************
*** 729,743 ****
  	ifp = &sc->ethercom.ec_if;
  	ifp->if_softc = sc;
  	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
- 	ifp->if_mtu = ETHERMTU;
  	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  	ifp->if_ioctl = rtk_ioctl;
- #if 0
- 	ifp->if_output = ether_output;
- #endif
  	ifp->if_start = rtk_start;
  	ifp->if_watchdog = rtk_watchdog;
! 	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  
  	/*
  	 * Do ifmedia setup.
--- 727,738 ----
  	ifp = &sc->ethercom.ec_if;
  	ifp->if_softc = sc;
  	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
  	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  	ifp->if_ioctl = rtk_ioctl;
  	ifp->if_start = rtk_start;
  	ifp->if_watchdog = rtk_watchdog;
! 	ifp->if_init = rtk_init;
! 	ifp->if_stop = rtk_stop;
  
  	/*
  	 * Do ifmedia setup.
***************
*** 942,954 ****
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		rtk_stop(sc);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		rtk_init(sc);
  	}
  	splx(s);
  
--- 937,949 ----
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		rtk_stop(ifp, 0);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		rtk_init(ifp);
  	}
  	splx(s);
  
***************
*** 1050,1056 ****
  			}
  			break;
  #else
! 			rtk_init(sc);
  			return;
  #endif
  		}
--- 1045,1051 ----
  			}
  			break;
  #else
! 			rtk_init(ifp);
  			return;
  #endif
  		}
***************
*** 1233,1239 ****
  
  		if (status & RTK_ISR_SYSTEM_ERR) {
  			rtk_reset(sc);
! 			rtk_init(sc);
  		}
  
  	}
--- 1228,1234 ----
  
  		if (status & RTK_ISR_SYSTEM_ERR) {
  			rtk_reset(sc);
! 			rtk_init(ifp);
  		}
  
  	}
***************
*** 1353,1372 ****
  	return;
  }
  
! STATIC void rtk_init(xsc)
! 	void			*xsc;
  {
! 	struct rtk_softc	*sc = xsc;
! 	struct ifnet		*ifp = &sc->ethercom.ec_if;
! 	int			s, i;
  	u_int32_t		rxcfg;
  
! 	s = splnet();
  
  	/*
! 	 * Cancel pending I/O and free all RX/TX buffers.
  	 */
! 	rtk_stop(sc);
  
  	/* Init our MAC address */
  	for (i = 0; i < ETHER_ADDR_LEN; i++) {
--- 1348,1367 ----
  	return;
  }
  
! STATIC int rtk_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct rtk_softc	*sc = ifp->if_softc;
! 	int			error = 0, i;
  	u_int32_t		rxcfg;
  
! 	if ((error = rtk_enable(sc)) != 0)
! 		goto out;
  
  	/*
! 	 * Cancel pending I/O.
  	 */
! 	rtk_stop(ifp, 0);
  
  	/* Init our MAC address */
  	for (i = 0; i < ETHER_ADDR_LEN; i++) {
***************
*** 1442,1450 ****
  	ifp->if_flags |= IFF_RUNNING;
  	ifp->if_flags &= ~IFF_OACTIVE;
  
- 	(void)splx(s);
- 
  	callout_reset(&sc->rtk_tick_ch, hz, rtk_tick, sc);
  }
  
  /*
--- 1437,1451 ----
  	ifp->if_flags |= IFF_RUNNING;
  	ifp->if_flags &= ~IFF_OACTIVE;
  
  	callout_reset(&sc->rtk_tick_ch, hz, rtk_tick, sc);
+ 
+  out:
+ 	if (error) {
+ 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+ 		ifp->if_timer = 0;
+ 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
+ 	}
+ 	return (error);
  }
  
  /*
***************
*** 1476,1533 ****
  	ifmr->ifm_active = sc->mii.mii_media_active;
  }
  
- STATIC int
- rtk_ether_ioctl(ifp, cmd, data)
- 	struct ifnet *ifp;
- 	u_long cmd;
- 	caddr_t data;
- {
- 	struct ifaddr *ifa = (struct ifaddr *) data;
- 	struct rtk_softc *sc = ifp->if_softc;
- 	int error = 0;
- 
- 	switch (cmd) {
- 	case SIOCSIFADDR:
- 		if ((error = rtk_enable(sc)) != 0)
- 			break;
- 		ifp->if_flags |= IFF_UP;
- 
- 		switch (ifa->ifa_addr->sa_family) {
- #ifdef INET
- 		case AF_INET:
- 			rtk_init(sc);
- 			arp_ifinit(ifp, ifa);
- 			break;
- #endif
- #ifdef NS
- 		case AF_NS:
- 		    {
- 			 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
- 
- 			 if (ns_nullhost(*ina))
- 				ina->x_host = *(union ns_host *)
- 				    LLADDR(ifp->if_sadl);
- 			 else
- 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
- 				    ifp->if_addrlen);
- 			 /* Set new address. */
- 			 rtk_init(sc);
- 			 break;
- 		    }
- #endif
- 		default:
- 			rtk_init(sc);
- 			break;
- 		}
- 		break;
- 
- 	default:
- 		return (EINVAL);
- 	}
- 
- 	return (error);
- }
- 
  STATIC int rtk_ioctl(ifp, command, data)
  	struct ifnet		*ifp;
  	u_long			command;
--- 1477,1482 ----
***************
*** 1540,1584 ****
  	s = splnet();
  
  	switch (command) {
- 	case SIOCSIFADDR:
- 	case SIOCGIFADDR:
- 	case SIOCSIFMTU:
- 		error = rtk_ether_ioctl(ifp, command, data);
- 		break;
- 	case SIOCSIFFLAGS:
- 		if (ifp->if_flags & IFF_UP) {
- 			if ((error = rtk_enable(sc)) != 0)
- 				break;
- 			rtk_init(sc);
- 		} else {
- 			if (ifp->if_flags & IFF_RUNNING) {
- 				rtk_stop(sc);
- 				rtk_disable(sc);
- 			}
- 		}
- 		error = 0;
- 		break;
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		error = (command == SIOCADDMULTI) ?
- 		    ether_addmulti(ifr, &sc->ethercom) :
- 		    ether_delmulti(ifr, &sc->ethercom);
- 
- 		if (error == ENETRESET) { 
- 			/*
- 			 * Multicast list has changed; set the hardware filter
- 			 * accordingly.
- 			 */
- 			rtk_setmulti(sc);
- 			error = 0;
- 		}
- 		break;
  	case SIOCGIFMEDIA:
  	case SIOCSIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->mii.mii_media, command);
  		break;
  	default:
! 		error = EINVAL;
  		break;
  	}
  
--- 1489,1511 ----
  	s = splnet();
  
  	switch (command) {
  	case SIOCGIFMEDIA:
  	case SIOCSIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->mii.mii_media, command);
  		break;
+ 
  	default:
! 		error = ether_ioctl(ifp, command, data);
! 		if (error == ENETRESET) {
! 			if (RTK_IS_ENABLED(sc)) {
! 				/*
! 				 * Multicast list has changed.  Set the
! 				 * hardware filter accordingly.
! 				 */
! 				rtk_setmulti(sc);
! 			}
! 			error = 0;
! 		}
  		break;
  	}
  
***************
*** 1598,1604 ****
  	ifp->if_oerrors++;
  	rtk_txeof(sc);
  	rtk_rxeof(sc);
! 	rtk_init(sc);
  
  	return;
  }
--- 1525,1531 ----
  	ifp->if_oerrors++;
  	rtk_txeof(sc);
  	rtk_rxeof(sc);
! 	rtk_init(ifp);
  
  	return;
  }
***************
*** 1607,1620 ****
   * Stop the adapter and free any mbufs allocated to the
   * RX and TX lists.
   */
! STATIC void rtk_stop(sc)
! 	struct rtk_softc	*sc;
  {
! 	int			i;
! 	struct ifnet		*ifp;
! 
! 	ifp = &sc->ethercom.ec_if;
! 	ifp->if_timer = 0;
  
  	callout_stop(&sc->rtk_tick_ch);
  
--- 1534,1545 ----
   * Stop the adapter and free any mbufs allocated to the
   * RX and TX lists.
   */
! STATIC void rtk_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
! 	struct rtk_softc *sc = ifp->if_softc;
! 	int i;
  
  	callout_stop(&sc->rtk_tick_ch);
  
***************
*** 1635,1643 ****
  		}
  	}
  
! 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
  
! 	return;
  }
  
  /*
--- 1560,1570 ----
  		}
  	}
  
! 	if (disable)
! 		rtk_disable(sc);
  
! 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 	ifp->if_timer = 0;
  }
  
  /*
***************
*** 1648,1657 ****
  	void			*vsc;
  {
  	struct rtk_softc	*sc = (struct rtk_softc *)vsc;
- 
- 	rtk_stop(sc);
  
! 	return;
  }
  
  STATIC void
--- 1575,1582 ----
  	void			*vsc;
  {
  	struct rtk_softc	*sc = (struct rtk_softc *)vsc;
  
! 	rtk_stop(&sc->ethercom.ec_if, 0);
  }
  
  STATIC void
Index: dev/ic/smc83c170.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/smc83c170.c,v
retrieving revision 1.33
diff -c -r1.33 smc83c170.c
*** dev/ic/smc83c170.c	2000/10/01 23:32:42	1.33
--- dev/ic/smc83c170.c	2000/10/04 04:43:00
***************
*** 87,99 ****
  void	epic_start __P((struct ifnet *));
  void	epic_watchdog __P((struct ifnet *));
  int	epic_ioctl __P((struct ifnet *, u_long, caddr_t));
  
  void	epic_shutdown __P((void *));
  
  void	epic_reset __P((struct epic_softc *));
- int	epic_init __P((struct epic_softc *));
  void	epic_rxdrain __P((struct epic_softc *));
- void	epic_stop __P((struct epic_softc *, int));
  int	epic_add_rxbuf __P((struct epic_softc *, int));
  void	epic_read_eeprom __P((struct epic_softc *, int, int, u_int16_t *));
  void	epic_set_mchash __P((struct epic_softc *));
--- 87,99 ----
  void	epic_start __P((struct ifnet *));
  void	epic_watchdog __P((struct ifnet *));
  int	epic_ioctl __P((struct ifnet *, u_long, caddr_t));
+ int	epic_init __P((struct ifnet *));
+ void	epic_stop __P((struct ifnet *, int));
  
  void	epic_shutdown __P((void *));
  
  void	epic_reset __P((struct epic_softc *));
  void	epic_rxdrain __P((struct epic_softc *));
  int	epic_add_rxbuf __P((struct epic_softc *, int));
  void	epic_read_eeprom __P((struct epic_softc *, int, int, u_int16_t *));
  void	epic_set_mchash __P((struct epic_softc *));
***************
*** 253,258 ****
--- 253,260 ----
  	ifp->if_ioctl = epic_ioctl;
  	ifp->if_start = epic_start;
  	ifp->if_watchdog = epic_watchdog;
+ 	ifp->if_init = epic_init;
+ 	ifp->if_stop = epic_stop;
  
  	/*
  	 * Attach the interface.
***************
*** 310,316 ****
  {
  	struct epic_softc *sc = arg;
  
! 	epic_stop(sc, 1);
  }
  
  /*
--- 312,318 ----
  {
  	struct epic_softc *sc = arg;
  
! 	epic_stop(&sc->sc_ethercom.ec_if, 1);
  }
  
  /*
***************
*** 502,508 ****
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) epic_init(sc);
  }
  
  /*
--- 504,510 ----
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) epic_init(ifp);
  }
  
  /*
***************
*** 517,598 ****
  {
  	struct epic_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFADDR:
! 		ifp->if_flags |= IFF_UP;
! 
! 		switch (ifa->ifa_addr->sa_family) {
! #ifdef INET
! 		case AF_INET:
! 			if ((error = epic_init(sc)) != 0)
! 				break;
! 			arp_ifinit(ifp, ifa);
! 			break;
! #endif /* INET */
! #ifdef NS
! 		case AF_NS:
! 		    {
! 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
! 
! 			if (ns_nullhost(*ina))
! 				ina->x_host = *(union ns_host *)
! 				    LLADDR(ifp->if_sadl);
! 			else
! 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
! 				    ifp->if_addrlen);
! 			/* Set new address. */
! 			error = epic_init(sc);
! 			break;
! 		    }
! #endif /* NS */
! 		default:
! 			error = epic_init(sc);
! 			break;
! 		}
! 		break;
! 
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			epic_stop(sc, 1);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 			   (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interfase it marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			error = epic_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up changes in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			error = epic_init(sc);
! 		}
  		break;
  
! 	case SIOCADDMULTI:
! 	case SIOCDELMULTI:
! 		error = (cmd == SIOCADDMULTI) ?
! 		    ether_addmulti(ifr, &sc->sc_ethercom) :
! 		    ether_delmulti(ifr, &sc->sc_ethercom);
! 
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
--- 519,536 ----
  {
  	struct epic_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFMEDIA:
! 	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
! 	default:
! 		error = ether_ioctl(ifp, cmd, data);
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
***************
*** 604,618 ****
  			error = 0;
  		}
  		break;
- 
- 	case SIOCSIFMEDIA:
- 	case SIOCGIFMEDIA:
- 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
- 		break;
- 
- 	default:
- 		error = EINVAL;
- 		break;
  	}
  
  	splx(s);
--- 542,547 ----
***************
*** 867,873 ****
  		else
  			printf("%s: unknown fatal error\n",
  			    sc->sc_dev.dv_xname);
! 		(void) epic_init(sc);
  	}
  
  	/*
--- 796,802 ----
  		else
  			printf("%s: unknown fatal error\n",
  			    sc->sc_dev.dv_xname);
! 		(void) epic_init(ifp);
  	}
  
  	/*
***************
*** 937,948 ****
   * Initialize the interface.  Must be called at splnet().
   */
  int
! epic_init(sc)
! 	struct epic_softc *sc;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	u_int8_t *enaddr = LLADDR(ifp->if_sadl);
  	struct epic_txdesc *txd;
  	struct epic_descsoft *ds;
--- 866,877 ----
   * Initialize the interface.  Must be called at splnet().
   */
  int
! epic_init(ifp)
! 	struct ifnet *ifp;
  {
+ 	struct epic_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	u_int8_t *enaddr = LLADDR(ifp->if_sadl);
  	struct epic_txdesc *txd;
  	struct epic_descsoft *ds;
***************
*** 952,958 ****
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	epic_stop(sc, 0);
  
  	/*
  	 * Reset the EPIC to a known state.
--- 881,887 ----
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	epic_stop(ifp, 0);
  
  	/*
  	 * Reset the EPIC to a known state.
***************
*** 1118,1130 ****
   * Stop transmission on the interface.
   */
  void
! epic_stop(sc, drain)
! 	struct epic_softc *sc;
! 	int drain;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct epic_descsoft *ds;
  	u_int32_t reg;
  	int i;
--- 1047,1059 ----
   * Stop transmission on the interface.
   */
  void
! epic_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
+ 	struct epic_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	struct epic_descsoft *ds;
  	u_int32_t reg;
  	int i;
***************
*** 1165,1176 ****
  		}
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		epic_rxdrain(sc);
- 	}
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
--- 1094,1101 ----
  		}
  	}
  
! 	if (disable)
  		epic_rxdrain(sc);
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
Index: dev/ic/tulip.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/tulip.c,v
retrieving revision 1.74
diff -c -r1.74 tulip.c
*** dev/ic/tulip.c	2000/10/03 23:35:55	1.74
--- dev/ic/tulip.c	2000/10/04 04:43:03
***************
*** 107,119 ****
  void	tlp_start __P((struct ifnet *));
  void	tlp_watchdog __P((struct ifnet *));
  int	tlp_ioctl __P((struct ifnet *, u_long, caddr_t));
  
  void	tlp_shutdown __P((void *));
  
  void	tlp_reset __P((struct tulip_softc *));
- int	tlp_init __P((struct tulip_softc *));
  void	tlp_rxdrain __P((struct tulip_softc *));
- void	tlp_stop __P((struct tulip_softc *, int));
  int	tlp_add_rxbuf __P((struct tulip_softc *, int));
  void	tlp_idle __P((struct tulip_softc *, u_int32_t));
  void	tlp_srom_idle __P((struct tulip_softc *));
--- 107,119 ----
  void	tlp_start __P((struct ifnet *));
  void	tlp_watchdog __P((struct ifnet *));
  int	tlp_ioctl __P((struct ifnet *, u_long, caddr_t));
+ int	tlp_init __P((struct ifnet *));
+ void	tlp_stop __P((struct ifnet *, int));
  
  void	tlp_shutdown __P((void *));
  
  void	tlp_reset __P((struct tulip_softc *));
  void	tlp_rxdrain __P((struct tulip_softc *));
  int	tlp_add_rxbuf __P((struct tulip_softc *, int));
  void	tlp_idle __P((struct tulip_softc *, u_int32_t));
  void	tlp_srom_idle __P((struct tulip_softc *));
***************
*** 501,506 ****
--- 501,508 ----
  	ifp->if_ioctl = tlp_ioctl;
  	ifp->if_start = tlp_start;
  	ifp->if_watchdog = tlp_watchdog;
+ 	ifp->if_init = tlp_init;
+ 	ifp->if_stop = tlp_stop;
  
  	/*
  	 * We can support 802.1Q VLAN-sized frames.
***************
*** 676,682 ****
  {
  	struct tulip_softc *sc = arg;
  
! 	tlp_stop(sc, 1);
  }
  
  /*
--- 678,684 ----
  {
  	struct tulip_softc *sc = arg;
  
! 	tlp_stop(&sc->sc_ethercom.ec_if, 1);
  }
  
  /*
***************
*** 960,966 ****
  	else
  		printf("%s: spurious watchdog timeout\n", sc->sc_dev.dv_xname);
  
! 	(void) tlp_init(sc);
  
  	/* Try to get more packets going. */
  	tlp_start(ifp);
--- 962,968 ----
  	else
  		printf("%s: spurious watchdog timeout\n", sc->sc_dev.dv_xname);
  
! 	(void) tlp_init(ifp);
  
  	/* Try to get more packets going. */
  	tlp_start(ifp);
***************
*** 979,1088 ****
  {
  	struct tulip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
  
  	switch (cmd) {
- 	case SIOCSIFADDR:
- 		if ((error = tlp_enable(sc)) != 0)
- 			break;
- 		ifp->if_flags |= IFF_UP;
- 
- 		switch (ifa->ifa_addr->sa_family) {
- #ifdef INET
- 		case AF_INET:
- 			if ((error = tlp_init(sc)) != 0)
- 				break;
- 			arp_ifinit(ifp, ifa);
- 			break;
- #endif /* INET */
- #ifdef NS
- 		case AF_NS:
- 		    {
- 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
- 
- 			if (ns_nullhost(*ina))
- 				ina->x_host = *(union ns_host *)
- 				    LLADDR(ifp->if_sadl);
- 			else
- 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
- 				    ifp->if_addrlen);
- 			/* Set new address. */
- 			error = tlp_init(sc);
- 			break;
- 		    }
- #endif /* NS */
- 		default:
- 			error = tlp_init(sc);
- 			break;
- 		}
- 		break;
- 
- 	case SIOCSIFMTU:
- 		if (ifr->ifr_mtu > ETHERMTU)
- 			error = EINVAL;
- 		else
- 			ifp->if_mtu = ifr->ifr_mtu;
- 		break;
- 
- 	case SIOCSIFFLAGS:
- #ifdef TLP_STATS
- 		if (ifp->if_flags & IFF_DEBUG)
- 			tlp_print_stats(sc);
- #endif
- 		if ((ifp->if_flags & IFF_UP) == 0 &&
- 		    (ifp->if_flags & IFF_RUNNING) != 0) {
- 			/*
- 			 * If interface is marked down and it is running, then
- 			 * stop it.
- 			 */
- 			tlp_stop(sc, 1);
- 			tlp_disable(sc);
- 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
- 			   (ifp->if_flags & IFF_RUNNING) == 0) {
- 			/*
- 			 * If interfase it marked up and it is stopped, then
- 			 * start it.
- 			 */
- 			if ((error = tlp_enable(sc)) != 0)
- 				break;
- 			error = tlp_init(sc);
- 		} else if ((ifp->if_flags & IFF_UP) != 0) {
- 			/*
- 			 * Reset the interface to pick up changes in any other
- 			 * flags that affect the hardware state.
- 			 */
- 			if ((error = tlp_enable(sc)) != 0)
- 				break;
- 			error = tlp_init(sc);
- 		}
- 		break;
- 
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		error = (cmd == SIOCADDMULTI) ?
- 		    ether_addmulti(ifr, &sc->sc_ethercom) :
- 		    ether_delmulti(ifr, &sc->sc_ethercom);
- 
- 		if (TULIP_IS_ENABLED(sc) && error == ENETRESET) {
- 			/*
- 			 * Multicast list has changed.  Set the filter
- 			 * accordingly.
- 			 */
- 			(*sc->sc_filter_setup)(sc);
- 			error = 0;
- 		}
- 		break;
- 
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
  	default:
! 		error = EINVAL;
  		break;
  	}
  
--- 981,1008 ----
  {
  	struct tulip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
  	switch (cmd) {
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
  	default:
! 		error = ether_ioctl(ifp, cmd, data);
! 		if (error == ENETRESET) {
! 			if (TULIP_IS_ENABLED(sc)) {
! 				/*
! 				 * Multicast list has changed.  Set the
! 				 * hardware filter accordingly.
! 				 */
! 				(*sc->sc_filter_setup)(sc);
! 			}
! 			error = 0;
! 		}
  		break;
  	}
  
***************
*** 1219,1225 ****
  			if (status & STATUS_RPS)
  				printf("%s: receive process stopped\n",
  				    sc->sc_dev.dv_xname);
! 			(void) tlp_init(sc);
  			break;
  		}
  
--- 1139,1145 ----
  			if (status & STATUS_RPS)
  				printf("%s: receive process stopped\n",
  				    sc->sc_dev.dv_xname);
! 			(void) tlp_init(ifp);
  			break;
  		}
  
***************
*** 1244,1250 ****
  			}
  			printf("%s: fatal system error: %s\n",
  			    sc->sc_dev.dv_xname, str);
! 			(void) tlp_init(sc);
  			break;
  		}
  
--- 1164,1170 ----
  			}
  			printf("%s: fatal system error: %s\n",
  			    sc->sc_dev.dv_xname, str);
! 			(void) tlp_init(ifp);
  			break;
  		}
  
***************
*** 1322,1328 ****
  		    (TDSTAT_Rx_FS|TDSTAT_Rx_LS)) {
  			printf("%s: incoming packet spilled, resetting\n",
  			    sc->sc_dev.dv_xname);
! 			(void) tlp_init(sc);
  			return;
  		}
  
--- 1242,1248 ----
  		    (TDSTAT_Rx_FS|TDSTAT_Rx_LS)) {
  			printf("%s: incoming packet spilled, resetting\n",
  			    sc->sc_dev.dv_xname);
! 			(void) tlp_init(ifp);
  			return;
  		}
  
***************
*** 1633,1655 ****
  }
  
  /*
!  * tlp_init:
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! tlp_init(sc)
! 	struct tulip_softc *sc;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct tulip_txsoft *txs;
  	struct tulip_rxsoft *rxs;
  	int i, error = 0;
  
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	tlp_stop(sc, 0);
  
  	/*
  	 * Initialize `opmode' to 0, and call the pre-init routine, if
--- 1553,1578 ----
  }
  
  /*
!  * tlp_init:		[ ifnet interface function ]
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! tlp_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct tulip_softc *sc = ifp->if_softc;
  	struct tulip_txsoft *txs;
  	struct tulip_rxsoft *rxs;
  	int i, error = 0;
  
+ 	if ((error = tlp_enable(sc)) != 0)
+ 		goto out;
+ 
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	tlp_stop(ifp, 0);
  
  	/*
  	 * Initialize `opmode' to 0, and call the pre-init routine, if
***************
*** 1938,1945 ****
  	ifp->if_flags &= ~IFF_OACTIVE;
  
   out:
! 	if (error)
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
  	return (error);
  }
  
--- 1861,1871 ----
  	ifp->if_flags &= ~IFF_OACTIVE;
  
   out:
! 	if (error) {
! 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 		ifp->if_timer = 0;
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
+ 	}
  	return (error);
  }
  
***************
*** 1996,2008 ****
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		tlp_stop(sc, 0);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		tlp_init(sc);
  	}
  	splx(s);
  }
--- 1922,1934 ----
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		tlp_stop(ifp, 0);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		tlp_init(ifp);
  	}
  	splx(s);
  }
***************
*** 2030,2045 ****
  }
  
  /*
!  * tlp_stop:
   *
   *	Stop transmission on the interface.
   */
  void
! tlp_stop(sc, drain)
! 	struct tulip_softc *sc;
! 	int drain;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct tulip_txsoft *txs;
  
  	if (sc->sc_tick != NULL) {
--- 1956,1971 ----
  }
  
  /*
!  * tlp_stop:		[ ifnet interface function ]
   *
   *	Stop transmission on the interface.
   */
  void
! tlp_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
! 	struct tulip_softc *sc = ifp->if_softc;
  	struct tulip_txsoft *txs;
  
  	if (sc->sc_tick != NULL) {
***************
*** 2074,2084 ****
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		tlp_rxdrain(sc);
  	}
  
  	sc->sc_flags &= ~(TULIPF_WANT_SETUP|TULIPF_DOING_SETUP);
--- 2000,2008 ----
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (disable) {
  		tlp_rxdrain(sc);
+ 		tlp_disable(sc);
  	}
  
  	sc->sc_flags &= ~(TULIPF_WANT_SETUP|TULIPF_DOING_SETUP);
***************
*** 5018,5024 ****
  	 * time through.
  	 */
  	if (TULIP_MEDIA_NEEDSRESET(sc, tm->tm_opmode))
! 		return (tlp_init(sc));
  
  	return ((*tm->tm_set)(sc));
  }
--- 4942,4948 ----
  	 * time through.
  	 */
  	if (TULIP_MEDIA_NEEDSRESET(sc, tm->tm_opmode))
! 		return (tlp_init(&sc->sc_ethercom.ec_if));
  
  	return ((*tm->tm_set)(sc));
  }
Index: dev/pci/if_sip.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_sip.c,v
retrieving revision 1.16
diff -c -r1.16 if_sip.c
*** dev/pci/if_sip.c	2000/10/01 23:32:43	1.16
--- dev/pci/if_sip.c	2000/10/04 04:43:05
***************
*** 255,266 ****
  void	sip_start __P((struct ifnet *));
  void	sip_watchdog __P((struct ifnet *));
  int	sip_ioctl __P((struct ifnet *, u_long, caddr_t));
  
  void	sip_shutdown __P((void *));
  
  void	sip_reset __P((struct sip_softc *));
- int	sip_init __P((struct sip_softc *));
- void	sip_stop __P((struct sip_softc *, int));
  void	sip_rxdrain __P((struct sip_softc *));
  int	sip_add_rxbuf __P((struct sip_softc *, int));
  void	sip_read_eeprom __P((struct sip_softc *, int, int, u_int16_t *));
--- 255,266 ----
  void	sip_start __P((struct ifnet *));
  void	sip_watchdog __P((struct ifnet *));
  int	sip_ioctl __P((struct ifnet *, u_long, caddr_t));
+ int	sip_init __P((struct ifnet *));
+ void	sip_stop __P((struct ifnet *, int));
  
  void	sip_shutdown __P((void *));
  
  void	sip_reset __P((struct sip_softc *));
  void	sip_rxdrain __P((struct sip_softc *));
  int	sip_add_rxbuf __P((struct sip_softc *, int));
  void	sip_read_eeprom __P((struct sip_softc *, int, int, u_int16_t *));
***************
*** 580,585 ****
--- 580,587 ----
  	ifp->if_ioctl = sip_ioctl;
  	ifp->if_start = sip_start;
  	ifp->if_watchdog = sip_watchdog;
+ 	ifp->if_init = sip_init;
+ 	ifp->if_stop = sip_stop;
  
  	/*
  	 * Attach the interface.
***************
*** 639,645 ****
  {
  	struct sip_softc *sc = arg;
  
! 	sip_stop(sc, 1);
  }
  
  /*
--- 641,647 ----
  {
  	struct sip_softc *sc = arg;
  
! 	sip_stop(&sc->sc_ethercom.ec_if, 1);
  }
  
  /*
***************
*** 868,874 ****
  		ifp->if_oerrors++;
  
  		/* Reset the interface. */
! 		(void) sip_init(sc);
  	} else if (ifp->if_flags & IFF_DEBUG)
  		printf("%s: recovered from device timeout\n",
  		    sc->sc_dev.dv_xname);
--- 870,876 ----
  		ifp->if_oerrors++;
  
  		/* Reset the interface. */
! 		(void) sip_init(ifp);
  	} else if (ifp->if_flags & IFF_DEBUG)
  		printf("%s: recovered from device timeout\n",
  		    sc->sc_dev.dv_xname);
***************
*** 890,970 ****
  {
  	struct sip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFADDR:
! 		ifp->if_flags |= IFF_UP;
! 
! 		switch (ifa->ifa_addr->sa_family) {
! #ifdef INET
! 		case AF_INET:
! 			if ((error = sip_init(sc)) != 0)
! 				break;
! 			arp_ifinit(ifp, ifa);
! 			break;
! #endif /* INET */
! #ifdef NS
! 		case AF_NS:
! 		    {
! 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
! 
! 			if (ns_nullhost(*ina))
! 				ina->x_host = *(union ns_host *)
! 				    LLADDR(ifp->if_sadl);
! 			else
! 				memcpy(LLADDR(ifp->if_sadl),
! 				    ina->x_host.c_host, ifp->if_addrlen);
! 			error = sip_init(sc);
! 			break;
! 		    }
! #endif /* NS */
! 		default:
! 			error = sip_init(sc);
! 			break;
! 		}
! 		break;
! 
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			sip_stop(sc, 1);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 			   (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interfase it marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			error = sip_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up changes in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			error = sip_init(sc);
! 		}
  		break;
- 	
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		error = (cmd == SIOCADDMULTI) ?
- 		    ether_addmulti(ifr, &sc->sc_ethercom) :
- 		    ether_delmulti(ifr, &sc->sc_ethercom);
  
  		if (error == ENETRESET) { 
  			/*
  			 * Multicast list has changed; set the hardware filter
--- 892,909 ----
  {
  	struct sip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFMEDIA:
! 	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
+ 	default:
+ 		error = ether_ioctl(ifp, cmd, data);
  		if (error == ENETRESET) { 
  			/*
  			 * Multicast list has changed; set the hardware filter
***************
*** 974,988 ****
  			error = 0;
  		}
  		break;
- 
- 	case SIOCSIFMEDIA:
- 	case SIOCGIFMEDIA:
- 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
- 		break;
- 
- 	default:
- 		error = EINVAL;
- 		break;
  	}
  
  	/* Try to get more packets going. */
--- 913,918 ----
***************
*** 1055,1063 ****
  					    "threshold to %u bytes\n",
  					    thresh * 32);
  					sc->sc_tx_drain_thresh = thresh;
! 					(void) sip_init(sc);
  				} else {
! 					(void) sip_init(sc);
  					printf("\n");
  				}
  			}
--- 985,993 ----
  					    "threshold to %u bytes\n",
  					    thresh * 32);
  					sc->sc_tx_drain_thresh = thresh;
! 					(void) sip_init(ifp);
  				} else {
! 					(void) sip_init(ifp);
  					printf("\n");
  				}
  			}
***************
*** 1083,1089 ****
  			PRINTERR(ISR_RMABT, "master abort");
  			PRINTERR(ISR_RTABT, "target abort");
  			PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
! 			(void) sip_init(sc);
  #undef PRINTERR
  		}
  	}
--- 1013,1019 ----
  			PRINTERR(ISR_RMABT, "master abort");
  			PRINTERR(ISR_RTABT, "target abort");
  			PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
! 			(void) sip_init(ifp);
  #undef PRINTERR
  		}
  	}
***************
*** 1380,1396 ****
  }
  
  /*
!  * sip_init:
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! sip_init(sc)
! 	struct sip_softc *sc;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct sip_txsoft *txs;
  	struct sip_rxsoft *rxs;
  	struct sip_desc *sipd;
--- 1310,1326 ----
  }
  
  /*
!  * sip_init:		[ ifnet interface function ]
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! sip_init(ifp)
! 	struct ifnet *ifp;
  {
+ 	struct sip_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	struct sip_txsoft *txs;
  	struct sip_rxsoft *rxs;
  	struct sip_desc *sipd;
***************
*** 1400,1406 ****
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	sip_stop(sc, 0);
  
  	/*
  	 * Reset the chip to a known state.
--- 1330,1336 ----
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	sip_stop(ifp, 0);
  
  	/*
  	 * Reset the chip to a known state.
***************
*** 1599,1615 ****
  }
  
  /*
!  * sip_stop:
   *
   *	Stop transmission on the interface.
   */
  void
! sip_stop(sc, drain)
! 	struct sip_softc *sc;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct sip_txsoft *txs;
  	u_int32_t cmdsts = 0;		/* DEBUG */
  
--- 1529,1546 ----
  }
  
  /*
!  * sip_stop:		[ ifnet interface function ]
   *
   *	Stop transmission on the interface.
   */
  void
! sip_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
+ 	struct sip_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	struct sip_txsoft *txs;
  	u_int32_t cmdsts = 0;		/* DEBUG */
  
***************
*** 1657,1668 ****
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		sip_rxdrain(sc);
- 	}
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
--- 1588,1595 ----
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (disable)
  		sip_rxdrain(sc);
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
Index: dev/pci/if_vr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_vr.c,v
retrieving revision 1.38
diff -c -r1.38 if_vr.c
*** dev/pci/if_vr.c	2000/10/01 23:32:44	1.38
--- dev/pci/if_vr.c	2000/10/04 04:43:06
***************
*** 301,308 ****
  static int vr_intr		__P((void *));
  static void vr_start		__P((struct ifnet *));
  static int vr_ioctl		__P((struct ifnet *, u_long, caddr_t));
! static int vr_init		__P((struct vr_softc *));
! static void vr_stop		__P((struct vr_softc *, int));
  static void vr_rxdrain		__P((struct vr_softc *));
  static void vr_watchdog		__P((struct ifnet *));
  static void vr_tick		__P((void *));
--- 301,308 ----
  static int vr_intr		__P((void *));
  static void vr_start		__P((struct ifnet *));
  static int vr_ioctl		__P((struct ifnet *, u_long, caddr_t));
! static int vr_init		__P((struct ifnet *));
! static void vr_stop		__P((struct ifnet *, int));
  static void vr_rxdrain		__P((struct vr_softc *));
  static void vr_watchdog		__P((struct ifnet *));
  static void vr_tick		__P((void *));
***************
*** 856,862 ****
  
  	/* Suppress unwanted interrupts. */
  	if ((ifp->if_flags & IFF_UP) == 0) {
! 		vr_stop(sc, 1);
  		return (0);
  	}
  
--- 856,862 ----
  
  	/* Suppress unwanted interrupts. */
  	if ((ifp->if_flags & IFF_UP) == 0) {
! 		vr_stop(ifp, 1);
  		return (0);
  	}
  
***************
*** 906,912 ****
  			printf("%s: PCI bus error\n", sc->vr_dev.dv_xname);
  			/* vr_init() calls vr_start() */
  			dotx = 0;
! 			(void) vr_init(sc);
  		}
  	}
  
--- 906,912 ----
  			printf("%s: PCI bus error\n", sc->vr_dev.dv_xname);
  			/* vr_init() calls vr_start() */
  			dotx = 0;
! 			(void) vr_init(ifp);
  		}
  	}
  
***************
*** 1089,1104 ****
   * Initialize the interface.  Must be called at splnet.
   */
  static int
! vr_init(sc)
! 	struct vr_softc *sc;
  {
! 	struct ifnet *ifp = &sc->vr_ec.ec_if;
  	struct vr_desc *d;
  	struct vr_descsoft *ds;
  	int i, error = 0;
  
  	/* Cancel pending I/O. */
! 	vr_stop(sc, 0);
  
  	/* Reset the Rhine to a known state. */
  	vr_reset(sc);
--- 1089,1104 ----
   * Initialize the interface.  Must be called at splnet.
   */
  static int
! vr_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct vr_softc *sc = ifp->if_softc;
  	struct vr_desc *d;
  	struct vr_descsoft *ds;
  	int i, error = 0;
  
  	/* Cancel pending I/O. */
! 	vr_stop(ifp, 0);
  
  	/* Reset the Rhine to a known state. */
  	vr_reset(sc);
***************
*** 1228,1300 ****
  {
  	struct vr_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
- 	struct ifaddr *ifa = (struct ifaddr *)data;
  	int s, error = 0;
  
  	s = splnet();
  
  	switch (command) {
! 	case SIOCSIFADDR:
! 		ifp->if_flags |= IFF_UP;
! 
! 		switch (ifa->ifa_addr->sa_family) {
! #ifdef INET
! 		case AF_INET:
! 			if ((error = vr_init(sc)) != 0)
! 				break;
! 			arp_ifinit(ifp, ifa);
! 			break;
! #endif /* INET */
! 		default:
! 			error = vr_init(sc);
! 			break;
! 		}
! 		break;
! 
! 	case SIOCGIFADDR:
! 		bcopy((caddr_t) sc->vr_enaddr,
! 			(caddr_t) ((struct sockaddr *)&ifr->ifr_data)->sa_data,
! 			ETHER_ADDR_LEN);
! 		break;
! 
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			vr_stop(sc, 1);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 			   (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interface is marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			error = vr_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up changes in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			error = vr_init(sc);
! 		}
  		break;
- 
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		if (command == SIOCADDMULTI)
- 			error = ether_addmulti(ifr, &sc->vr_ec);
- 		else
- 			error = ether_delmulti(ifr, &sc->vr_ec);
  
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
--- 1228,1245 ----
  {
  	struct vr_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
  	int s, error = 0;
  
  	s = splnet();
  
  	switch (command) {
! 	case SIOCGIFMEDIA:
! 	case SIOCSIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->vr_mii.mii_media, command);
  		break;
  
+ 	default:
+ 		error = ether_ioctl(ifp, command, data);
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
***************
*** 1304,1318 ****
  			error = 0;
  		}
  		break;
- 
- 	case SIOCGIFMEDIA:
- 	case SIOCSIFMEDIA:
- 		error = ifmedia_ioctl(ifp, ifr, &sc->vr_mii.mii_media, command);
- 		break;
- 
- 	default:
- 		error = EINVAL;
- 		break;
  	}
  
  	splx(s);
--- 1249,1254 ----
***************
*** 1328,1334 ****
  	printf("%s: device timeout\n", sc->vr_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) vr_init(sc);
  }
  
  /*
--- 1264,1270 ----
  	printf("%s: device timeout\n", sc->vr_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) vr_init(ifp);
  }
  
  /*
***************
*** 1373,1384 ****
   * transmit lists.
   */
  static void
! vr_stop(sc, drain)
! 	struct vr_softc *sc;
! 	int drain;
  {
  	struct vr_descsoft *ds;
- 	struct ifnet *ifp;
  	int i;
  
  	/* Cancel one second timer. */
--- 1309,1320 ----
   * transmit lists.
   */
  static void
! vr_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
+ 	struct vr_softc *sc = ifp->if_softc;
  	struct vr_descsoft *ds;
  	int i;
  
  	/* Cancel one second timer. */
***************
*** 1408,1419 ****
  		}
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		vr_rxdrain(sc);
- 	}
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
--- 1344,1351 ----
  		}
  	}
  
! 	if (disable)
  		vr_rxdrain(sc);
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
***************
*** 1469,1475 ****
  {
  	struct vr_softc *sc = (struct vr_softc *)arg;
  
! 	vr_stop(sc, 1);
  }
  
  /*
--- 1401,1407 ----
  {
  	struct vr_softc *sc = (struct vr_softc *)arg;
  
! 	vr_stop(&sc->vr_ec.ec_if, 1);
  }
  
  /*
***************
*** 1694,1699 ****
--- 1626,1633 ----
  	ifp->if_ioctl = vr_ioctl;
  	ifp->if_start = vr_start;
  	ifp->if_watchdog = vr_watchdog;
+ 	ifp->if_init = vr_init;
+ 	ifp->if_stop = vr_stop;
  	bcopy(sc->vr_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
  
  	/*

--tjCHc7DPkfUGtrlw--

From bouyer@antioche.lip6.fr Wed Oct 04 07:47:56 2000
  by mail.netbsd.org with SMTP; 4 Oct 2000 07:47:56 -0000
	by antioche.lip6.fr (8.10.1/8.10.1) with ESMTP id e947lkv09212;
	Wed, 4 Oct 2000 09:47:47 +0200 (MEST)
Date: Wed, 4 Oct 2000 09:47:46 +0200
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
To: Jason R Thorpe <thorpej@zembu.com>, tech-net@netbsd.org, apb@cequrux.com
Subject: Re: 802.1Q & ETHER_MAX_LEN
Message-ID: <20001004094746.D7454@antioche.lip6.fr>
References: <20001001213524.A323@antioche.eu.org> <20001003090922.A340@dr-evil.shagadelic.org> <20001003210125.A546@antioche.eu.org> <20001003124541.G921@dr-evil.z.zembu.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
In-Reply-To: <20001003124541.G921@dr-evil.z.zembu.com>; from Jason R Thorpe on Tue, Oct 03, 2000 at 12:45:41PM -0700

On Tue, Oct 03, 2000 at 12:45:41PM -0700, Jason R Thorpe wrote:
> There would be a different cap flag for each encapsulation type, so for
> Hag's case, there would be a ETHERCAP_ISL_MTU capability.

Ok. But if we have a lot of encapsulation we'll be short of place to store the
flags :)

--
Manuel Bouyer, LIP6, Universite Paris VI.           Manuel.Bouyer@lip6.fr
--

From itojun@itojun.org Wed Oct 04 18:33:12 2000
  by mail.netbsd.org with SMTP; 4 Oct 2000 18:33:12 -0000
	by coconut.itojun.org (8.9.3+3.2W/3.7W) with ESMTP id DAA07016;
	Thu, 5 Oct 2000 03:33:10 +0900 (JST)
To: mellon@netbsd.org
cc: tech-net@netbsd.org
In-reply-to: mellon's message of Mon, 02 Oct 2000 23:54:50 +0300.
      <200010022054.XAA04771@netbsd.hut.fi>
Subject: SIOCGIFCONF behavior change
From: itojun@iijlab.net
Date: Thu, 05 Oct 2000 03:33:10 +0900
Message-ID: <7014.970684390@coconut.itojun.org>
Sender: itojun@itojun.org


>Module Name:	syssrc
>Committed By:	mellon
>Date:		Mon Oct  2 20:54:49 UTC 2000
>
>Modified Files:
>	syssrc/sys/net [netbsd-1-5]: if.c
>
>Log Message:
>Pull up 1.69-1.70 - kernel portion of fix for PR#10968 (jhawk approved)

	(sorry quoted a pullup, not the original)

	is it really safe to change SIOCGIFCONF behavior here?
	are we sure that it won't bite existing programs?
	are there any standard regarding to this ioctl (i believe not)?

itojun

From feyrer@rfhs8012.fh-regensburg.de Wed Oct 04 18:42:16 2000
  by mail.netbsd.org with SMTP; 4 Oct 2000 18:42:15 -0000
	by rfhs8012.fh-regensburg.de (8.10.1/8.10.1) with ESMTP id e94IfR000089
	for <tech-net@netbsd.org>; Wed, 4 Oct 2000 20:41:27 +0200 (MET DST)
Date: Wed, 4 Oct 2000 20:44:24 +0200 (MET DST)
From: Hubert Feyrer <hubert.feyrer@informatik.fh-regensburg.de>
To: tech-net@netbsd.org
Subject: PAT ports?
Message-ID: <Pine.GSO.4.21.0010042042080.24129-100000@rfhpc8320.fh-regensburg.de>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII


Mipan just brought my attention to
http://www.cisco.com/warp/public/701/60.html, and I wonder if that's still
correct for us (NetBSD):

``When translation is required, the new port number is picked out
of the same range as the original following the convention of Berkeley
Software Distributions (BSD): 

    (1-->511, 512-->1023, 1024-->4999, 5000-->65535) ''


 - Hubert

-- 
Hubert Feyrer <hubert.feyrer@informatik.fh-regensburg.de>


From itojun@itojun.org Thu Oct 05 02:43:12 2000
  by mail.netbsd.org with SMTP; 5 Oct 2000 02:43:12 -0000
	by starfruit.itojun.org (Postfix) with ESMTP id 0453D7E29
	for <tech-net@netbsd.org>; Thu,  5 Oct 2000 11:42:43 +0900 (JST)
To: tech-net@netbsd.org
Subject: use of rnd(4) from within the kernel
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
Date: Thu, 05 Oct 2000 11:42:43 +0900
Sender: itojun@itojun.org
Message-Id: <20001005024244.0453D7E29@starfruit.itojun.org>

	I have been trying to migrate from random() to rnd(4), in the
	kernel network processing (including IPsec).
	so my question: is it okay to assume that
		rnd_extract_data(RND_EXTRACT_ANY)
	returns the specified bytes of random bytes?  what will it return
	in entropy-starvation situation?  how good is the randomness in
	entropy-starvation situation?
	(NOTE: in the kernel networking code, we can't wait till entropy
	to be gathered)

	tcp_new_iss() does not check the return value from rnd_extract_data(),
	and assumes that we can get enough randomness from the function.
	is it a safe thing to do?  if so, i'm happy.

itojun

From thorpej@zembu.com Thu Oct 05 22:24:37 2000
  by mail.netbsd.org with SMTP; 5 Oct 2000 22:24:37 -0000
	id 7F01CD221; Thu,  5 Oct 2000 15:24:34 -0700 (PDT)
Date: Thu, 5 Oct 2000 15:24:34 -0700
From: Jason R Thorpe <thorpej@zembu.com>
To: tech-net@netbsd.org
Subject: Multicast routing and unnumbered point-to-point interfaces
Message-ID: <20001005152434.L902@dr-evil.z.zembu.com>
Reply-To: thorpej@zembu.com
Mail-Followup-To: Jason R Thorpe <thorpej@zembu.com>, tech-net@netbsd.org
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="BOKacYhQ+x31HxR3"
Content-Disposition: inline
User-Agent: Mutt/1.2i
Organization: Zembu Labs, Inc.


--BOKacYhQ+x31HxR3
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Folks...

I have routers with a large number of unnumbered point-to-point
interfaces (`gif' tunnels), and I need to do multicast routing
on them.

This required some hacking in mrouted and the kernel in order to
decouple the notion of "IP address" from "interface identifier".

I did this in two stages:

	- Rip out support for mrouted-created v4-in-v4 tunnels.
	  They are wire-compatible with gif(4), which is more
	  generic, so we should just use the generic mechanism.

	- Changed the MRT_ADD_VIF socket option to pass an
	  interface name rather than an IP address.  I left
	  the old version in there as OMRT_ADD_VIF so that
	  old mrouted(8) versions would continue to work, so
	  long as they did not use VIFF_TUNNEL (which could
	  not work, since I ripped out all the kernel support
	  for it :-).

I still have some changes to mrouted(8) to make, and some debugging
and more hacking to do, but I wanted to present this idea here in the
hopes of folding it back into NetBSD, rather than maintaining this
local change forever.

Kernel diff attached.  Please comment.

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>

--BOKacYhQ+x31HxR3
Content-Type: text/plain; charset=us-ascii
Content-Description: ip_mroute.diff
Content-Disposition: attachment; filename=foo

Index: ip_mroute.c
===================================================================
RCS file: /home/cvsfiles/netbsd/src/sys/netinet/ip_mroute.c,v
retrieving revision 1.1.1.2
retrieving revision 1.6
diff -c -r1.1.1.2 -r1.6
*** ip_mroute.c	2000/04/25 00:37:11	1.1.1.2
--- ip_mroute.c	2000/10/05 21:19:52	1.6
***************
*** 10,15 ****
--- 10,16 ----
   * Modified by Ajit Thyagarajan, PARC, August 1993
   * Modified by Bill Fenner, PARC, April 1994
   * Modified by Charles M. Hannum, NetBSD, May 1995.
+  * Modified by Jason R. Thorpe, Zembu Labs, October 2000.
   *
   * MROUTING Revision: 1.2
   */
***************
*** 97,103 ****
--- 98,106 ----
  static int get_version __P((struct mbuf *));
  static int set_assert __P((struct mbuf *));
  static int get_assert __P((struct mbuf *));
+ static int oadd_vif __P((struct mbuf *));
  static int add_vif __P((struct mbuf *));
+ static int add_vif_common __P((struct vifctl *, struct ifnet *));
  static int del_vif __P((struct mbuf *));
  static void update_mfc __P((struct mfcctl *, struct mfc *));
  static void expire_mfc __P((struct mfc *));
***************
*** 115,121 ****
  static int ip_mdq __P((struct mbuf *, struct ifnet *, struct mfc *));
  #endif
  static void phyint_send __P((struct ip *, struct vif *, struct mbuf *));
- static void encap_send __P((struct ip *, struct vif *, struct mbuf *));
  static void tbf_control __P((struct vif *, struct mbuf *, struct ip *,
  			     u_int32_t));
  static void tbf_queue __P((struct vif *, struct mbuf *));
--- 118,123 ----
***************
*** 138,177 ****
  struct ifnet multicast_decap_if[MAXVIFS];
  #endif
  
- #define	ENCAP_TTL	64
- #define	ENCAP_PROTO	IPPROTO_IPIP	/* 4 */
- 
- /* prototype IP hdr for encapsulated packets */
- struct ip multicast_encap_iphdr = {
- #if BYTE_ORDER == LITTLE_ENDIAN
- 	sizeof(struct ip) >> 2, IPVERSION,
- #else
- 	IPVERSION, sizeof(struct ip) >> 2,
- #endif
- 	0,				/* tos */
- 	sizeof(struct ip),		/* total length */
- 	0,				/* id */
- 	0,				/* frag offset */
- 	ENCAP_TTL, ENCAP_PROTO,	
- 	0,				/* checksum */
- };
- 
  /*
   * Private variables.
   */
  static vifi_t	   numvifs = 0;
- static int have_encap_tunnel = 0;
  
  static struct callout expire_upcalls_ch;
  
  /*
-  * one-back cache used by mrt_ipip_input to locate a tunnel's vif
-  * given a datagram's src ip address.
-  */
- static struct in_addr last_encap_src;
- static struct vif *last_encap_vif;
- 
- /*
   * whether or not special PIM assert processing is enabled.
   */
  static int pim_assert;
--- 140,153 ----
***************
*** 250,255 ****
--- 226,234 ----
  		case MRT_DONE:
  			error = ip_mrouter_done();
  			break;
+ 		case OMRT_ADD_VIF:
+ 			error = oadd_vif(*m);
+ 			break;
  		case MRT_ADD_VIF:
  			error = add_vif(*m);
  			break;
***************
*** 444,450 ****
  	/* Clear out all the vifs currently in use. */
  	for (vifi = 0; vifi < numvifs; vifi++) {
  		vifp = &viftable[vifi];
! 		if (!in_nullhost(vifp->v_lcl_addr))
  			reset_vif(vifp);
  	}
  
--- 423,429 ----
  	/* Clear out all the vifs currently in use. */
  	for (vifi = 0; vifi < numvifs; vifi++) {
  		vifp = &viftable[vifi];
! 		if (vifp->v_ifp != NULL)
  			reset_vif(vifp);
  	}
  
***************
*** 469,477 ****
  	free(mfchashtbl, M_MRTABLE);
  	mfchashtbl = 0;
  	
- 	/* Reset de-encapsulation cache. */
- 	have_encap_tunnel = 0;
- 	
  	ip_mrouter = 0;
  	
  	splx(s);
--- 448,453 ----
***************
*** 527,554 ****
  static struct sockaddr_in sin = { sizeof(sin), AF_INET };
  
  /*
!  * Add a vif to the vif table
   */
  static int
! add_vif(m)
  	struct mbuf *m;
  {
! 	struct vifctl *vifcp;
! 	struct vif *vifp;
  	struct ifaddr *ifa;
  	struct ifnet *ifp;
! 	struct ifreq ifr;
! 	int error, s;
! 	
! 	if (m == 0 || m->m_len < sizeof(struct vifctl))
  		return (EINVAL);
  
! 	vifcp = mtod(m, struct vifctl *);
  	if (vifcp->vifc_vifi >= MAXVIFS)
  		return (EINVAL);
  
! 	vifp = &viftable[vifcp->vifc_vifi];
! 	if (!in_nullhost(vifp->v_lcl_addr))
  		return (EADDRINUSE);
  	
  	/* Find the interface with an address in AF_INET family. */
--- 503,534 ----
  static struct sockaddr_in sin = { sizeof(sin), AF_INET };
  
  /*
!  * Add a vif to the vif table.  This supports the older,
!  * IP address-based ioctl.
   */
  static int
! oadd_vif(m)
  	struct mbuf *m;
  {
! 	struct ovifctl *vifcp;
  	struct ifaddr *ifa;
  	struct ifnet *ifp;
! 
! 	if (m == 0 || m->m_len < sizeof(struct ovifctl))
  		return (EINVAL);
  
! 	vifcp = mtod(m, struct ovifctl *);
  	if (vifcp->vifc_vifi >= MAXVIFS)
  		return (EINVAL);
  
! 	/*
! 	 * Tunnel vifs are deprecated.  Do not allow them
! 	 * to be added.
! 	 */
! 	if (vifcp->vifc_flags & (OVIFF_TUNNEL|OVIFF_SRCRT))
! 		return (EINVAL);
! 
! 	if (viftable[vifcp->vifc_vifi].v_ifp != NULL)
  		return (EADDRINUSE);
  	
  	/* Find the interface with an address in AF_INET family. */
***************
*** 556,595 ****
  	ifa = ifa_ifwithaddr(sintosa(&sin));
  	if (ifa == 0)
  		return (EADDRNOTAVAIL);
- 	
- 	if (vifcp->vifc_flags & VIFF_TUNNEL) {
- 		if (vifcp->vifc_flags & VIFF_SRCRT) {
- 			log(LOG_ERR, "Source routed tunnels not supported\n");
- 			return (EOPNOTSUPP);
- 		}
  
! 		/* Create a fake encapsulation interface. */
! 		ifp = (struct ifnet *)malloc(sizeof(*ifp), M_MRTABLE, M_WAITOK);
! 		bzero(ifp, sizeof(*ifp));
! 		sprintf(ifp->if_xname, "mdecap%d", vifcp->vifc_vifi);
  
! 		/* Prepare cached route entry. */
! 		bzero(&vifp->v_route, sizeof(vifp->v_route));
  
! 		/* Tell mrt_ipip_input() to start looking at encapsulated packets. */
! 		have_encap_tunnel = 1;
! 	} else {
! 		/* Use the physical interface associated with the address. */
! 		ifp = ifa->ifa_ifp;
  
! 		/* Make sure the interface supports multicast. */
! 		if ((ifp->if_flags & IFF_MULTICAST) == 0)
! 			return (EOPNOTSUPP);
! 
! 		/* Enable promiscuous reception of all IP multicasts. */
! 		satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
! 		satosin(&ifr.ifr_addr)->sin_family = AF_INET;
! 		satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
! 		error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
! 		if (error)
! 			return (error);
  	}
  
  	s = splsoftnet();
  
  	/* Define parameters for the tbf structure. */
--- 536,625 ----
  	ifa = ifa_ifwithaddr(sintosa(&sin));
  	if (ifa == 0)
  		return (EADDRNOTAVAIL);
  
! 	/* Use the physical interface associated with the address. */
! 	ifp = ifa->ifa_ifp;
  
! 	/* Make sure the interface supports multicast. */
! 	if ((ifp->if_flags & IFF_MULTICAST) == 0)
! 		return (EOPNOTSUPP);
  
! 	/*
! 	 * The portion of the vifctl structre that we are interested in
! 	 * is the same between the old and new versions of the strucutre,
! 	 * so we just access it as if it were the new one.
! 	 */
! 	return (add_vif_common((struct vifctl *)vifcp, ifp));
! }
  
! /*
!  * Add a vif to the vif table.  This is the new,
!  * interface-name based version.
!  */
! static int
! add_vif(m)
! 	struct mbuf *m;
! {
! 	struct vifctl *vifcp;
! 	struct ifnet *ifp;
! 	struct ifaddr *ifa;
! 
! 	if (m == 0 || m->m_len < sizeof(struct vifctl))
! 		return (EINVAL);
! 
! 	vifcp = mtod(m, struct vifctl *);
! 	if (vifcp->vifc_vifi >= MAXVIFS)
! 		return (EINVAL);
! 
! 	if (viftable[vifcp->vifc_vifi].v_ifp != NULL)
! 		return (EADDRINUSE);
! 
! 	/* Find the interface. */
! 	vifcp->vifc_ifname[sizeof(vifcp->vifc_ifname) - 1] = '\0';
! 	ifp = ifunit(vifcp->vifc_ifname);
! 	if (ifp == NULL)
! 		return (ENXIO);
! 
! 	/* Make sure the interface has at least one AF_INET address. */
! 	for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
! 	     ifa = TAILQ_NEXT(ifa, ifa_list)) {
! 		if (ifa->ifa_addr->sa_family == AF_INET)
! 			break;
  	}
+ 	if (ifa == NULL)
+ 		return (EADDRNOTAVAIL);
+ 
+ 	/* Make sure the interface supports multicast. */
+ 	if ((ifp->if_flags & IFF_MULTICAST) == 0)
+ 		return (EOPNOTSUPP);
  
+ 	/*
+ 	 * The portion of the vifctl structre that we are interested in
+ 	 * is the same between the old and new versions of the strucutre,
+ 	 * so we just access it as if it were the new one.
+ 	 */
+ 	return (add_vif_common(vifcp, ifp));
+ }
+ 
+ int
+ add_vif_common(vifcp, ifp)
+ 	struct vifctl *vifcp;
+ 	struct ifnet *ifp;
+ {
+ 	struct ifreq ifr;
+ 	struct vif *vifp;
+ 	int error, s;
+ 
+ 	vifp = &viftable[vifcp->vifc_vifi];
+ 
+ 	/* Enable promiscuous reception of all IP multicasts. */
+ 	satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
+ 	satosin(&ifr.ifr_addr)->sin_family = AF_INET;
+ 	satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
+ 	error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
+ 	if (error)
+ 		return (error);
+ 
  	s = splsoftnet();
  
  	/* Define parameters for the tbf structure. */
***************
*** 604,611 ****
  	vifp->v_threshold = vifcp->vifc_threshold;
  	/* scaling up here allows division by 1024 in critical code */
  	vifp->v_rate_limit = vifcp->vifc_rate_limit * 1024 / 1000;
- 	vifp->v_lcl_addr = vifcp->vifc_lcl_addr;
- 	vifp->v_rmt_addr = vifcp->vifc_rmt_addr;
  	vifp->v_ifp = ifp;
  	/* Initialize per vif pkt counters. */
  	vifp->v_pkt_in = 0;
--- 634,639 ----
***************
*** 621,637 ****
  #endif /* RSVP_ISI */
  
  	splx(s);
! 	
  	/* Adjust numvifs up if the vifi is higher than numvifs. */
  	if (numvifs <= vifcp->vifc_vifi)
  		numvifs = vifcp->vifc_vifi + 1;
! 	
  	if (mrtdebug)
! 		log(LOG_DEBUG, "add_vif #%d, lcladdr %x, %s %x, thresh %x, rate %d\n",
  		    vifcp->vifc_vifi, 
! 		    ntohl(vifcp->vifc_lcl_addr.s_addr),
! 		    (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask",
! 		    ntohl(vifcp->vifc_rmt_addr.s_addr),
  		    vifcp->vifc_threshold,
  		    vifcp->vifc_rate_limit);    
  	
--- 649,664 ----
  #endif /* RSVP_ISI */
  
  	splx(s);
! 
  	/* Adjust numvifs up if the vifi is higher than numvifs. */
  	if (numvifs <= vifcp->vifc_vifi)
  		numvifs = vifcp->vifc_vifi + 1;
! 
  	if (mrtdebug)
! 		log(LOG_DEBUG,
! 		    "add_vif #%d, interface %s, thresh %x, rate %d\n",
  		    vifcp->vifc_vifi, 
! 		    ifp->if_xname,
  		    vifcp->vifc_threshold,
  		    vifcp->vifc_rate_limit);    
  	
***************
*** 653,671 ****
  		m_freem(m);
  	}
  
! 	if (vifp->v_flags & VIFF_TUNNEL) {
! 		free(vifp->v_ifp, M_MRTABLE);
! 		if (vifp == last_encap_vif) {
! 			last_encap_vif = 0;
! 			last_encap_src = zeroin_addr;
! 		}
! 	} else {
! 		satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
! 		satosin(&ifr.ifr_addr)->sin_family = AF_INET;
! 		satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
! 		ifp = vifp->v_ifp;
! 		(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
! 	}
  	bzero((caddr_t)vifp, sizeof(*vifp));
  }
  
--- 680,691 ----
  		m_freem(m);
  	}
  
! 	satosin(&ifr.ifr_addr)->sin_len = sizeof(struct sockaddr_in);
! 	satosin(&ifr.ifr_addr)->sin_family = AF_INET;
! 	satosin(&ifr.ifr_addr)->sin_addr = zeroin_addr;
! 	ifp = vifp->v_ifp;
! 	(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
! 
  	bzero((caddr_t)vifp, sizeof(*vifp));
  }
  
***************
*** 689,695 ****
  		return (EINVAL);
  
  	vifp = &viftable[*vifip];
! 	if (in_nullhost(vifp->v_lcl_addr))
  		return (EADDRNOTAVAIL);
  	
  	s = splsoftnet();
--- 709,715 ----
  		return (EINVAL);
  
  	vifp = &viftable[*vifip];
! 	if (vifp->v_ifp == NULL)
  		return (EADDRNOTAVAIL);
  	
  	s = splsoftnet();
***************
*** 698,704 ****
  	
  	/* Adjust numvifs down */
  	for (vifi = numvifs; vifi > 0; vifi--)
! 		if (!in_nullhost(viftable[vifi-1].v_lcl_addr))
  			break;
  	numvifs = vifi;
  	
--- 718,724 ----
  	
  	/* Adjust numvifs down */
  	for (vifi = numvifs; vifi > 0; vifi--)
! 		if (viftable[vifi - 1].v_ifp != NULL)
  			break;
  	numvifs = vifi;
  	
***************
*** 999,1007 ****
  	    ip->ip_ttl++;	/* compensate for -1 in *_send routines */
  	if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
  	    vifp = viftable + vifi;
! 	    printf("Sending IPPROTO_RSVP from %x to %x on vif %d (%s%s)\n",
  		ntohl(ip->ip_src), ntohl(ip->ip_dst), vifi,
- 		(vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "",
  		vifp->v_ifp->if_xname);
  	}
  	return (ip_mdq(m, ifp, (struct mfc *)0, vifi));
--- 1019,1026 ----
  	    ip->ip_ttl++;	/* compensate for -1 in *_send routines */
  	if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
  	    vifp = viftable + vifi;
! 	    printf("Sending IPPROTO_RSVP from %x to %x on vif %d (%s)\n",
  		ntohl(ip->ip_src), ntohl(ip->ip_dst), vifi,
  		vifp->v_ifp->if_xname);
  	}
  	return (ip_mdq(m, ifp, (struct mfc *)0, vifi));
***************
*** 1234,1239 ****
--- 1253,1259 ----
      vifi_t xmt_vif;
  #endif /* RSVP_ISI */
  {
+     struct in_ifaddr *ia;
      struct ip  *ip = mtod(m, struct ip *);
      vifi_t vifi;
      struct vif *vifp;
***************
*** 1244,1255 ****
   * input, they shouldn't get counted on output, so statistics keeping is
   * seperate.
   */
! #define MC_SEND(ip,vifp,m) {                             \
!                 if ((vifp)->v_flags & VIFF_TUNNEL)	 \
!                     encap_send((ip), (vifp), (m));       \
!                 else                                     \
!                     phyint_send((ip), (vifp), (m));      \
! }
  
  #ifdef RSVP_ISI
      /*
--- 1264,1270 ----
   * input, they shouldn't get counted on output, so statistics keeping is
   * seperate.
   */
! #define MC_SEND(ip,vifp,m)	phyint_send((ip), (vifp), (m))
  
  #ifdef RSVP_ISI
      /*
***************
*** 1280,1287 ****
  	 * interface (and not a tunnel), send a message to the routing daemon.
  	 */
  	if (pim_assert && rt->mfc_ttls[vifi] &&
! 		(ifp->if_flags & IFF_BROADCAST) &&
! 		!(viftable[vifi].v_flags & VIFF_TUNNEL)) {
  	    struct mbuf *mm;
  	    struct igmpmsg *im;
  	    int hlen = ip->ip_hl << 2;
--- 1295,1301 ----
  	 * interface (and not a tunnel), send a message to the routing daemon.
  	 */
  	if (pim_assert && rt->mfc_ttls[vifi] &&
! 		(ifp->if_flags & IFF_BROADCAST)) {
  	    struct mbuf *mm;
  	    struct igmpmsg *im;
  	    int hlen = ip->ip_hl << 2;
***************
*** 1315,1321 ****
      }
  
      /* If I sourced this packet, it counts as output, else it was input. */
!     if (in_hosteq(ip->ip_src, viftable[vifi].v_lcl_addr)) {
  	viftable[vifi].v_pkt_out++;
  	viftable[vifi].v_bytes_out += plen;
      } else {
--- 1329,1336 ----
      }
  
      /* If I sourced this packet, it counts as output, else it was input. */
!     INADDR_TO_IA(ip->ip_src, ia);
!     if (ia != NULL) {
  	viftable[vifi].v_pkt_out++;
  	viftable[vifi].v_bytes_out += plen;
      } else {
***************
*** 1383,1529 ****
  		tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *), ip->ip_len);
  }
  
- static void
- encap_send(ip, vifp, m)
- 	struct ip *ip;
- 	struct vif *vifp;
- 	struct mbuf *m;
- {
- 	struct mbuf *mb_copy;
- 	struct ip *ip_copy;
- 	int i, len = ip->ip_len + sizeof(multicast_encap_iphdr);
- 
- 	/*
- 	 * copy the old packet & pullup it's IP header into the
- 	 * new mbuf so we can modify it.  Try to fill the new
- 	 * mbuf since if we don't the ethernet driver will.
- 	 */
- 	MGETHDR(mb_copy, M_DONTWAIT, MT_DATA);
- 	if (mb_copy == 0)
- 		return;
- 	mb_copy->m_data += max_linkhdr;
- 	mb_copy->m_pkthdr.len = len;
- 	mb_copy->m_len = sizeof(multicast_encap_iphdr);
- 	
- 	if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == 0) {
- 		m_freem(mb_copy);
- 		return;
- 	}
- 	i = MHLEN - max_linkhdr;
- 	if (i > len)
- 		i = len;
- 	mb_copy = m_pullup(mb_copy, i);
- 	if (mb_copy == 0)
- 		return;
- 	
- 	/*
- 	 * fill in the encapsulating IP header.
- 	 */
- 	ip_copy = mtod(mb_copy, struct ip *);
- 	*ip_copy = multicast_encap_iphdr;
- 	ip_copy->ip_id = htons(ip_id++);
- 	ip_copy->ip_len = len;
- 	ip_copy->ip_src = vifp->v_lcl_addr;
- 	ip_copy->ip_dst = vifp->v_rmt_addr;
- 	
- 	/*
- 	 * turn the encapsulated IP header back into a valid one.
- 	 */
- 	ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr));
- 	--ip->ip_ttl;
- 	HTONS(ip->ip_len);
- 	HTONS(ip->ip_off);
- 	ip->ip_sum = 0;
- 	mb_copy->m_data += sizeof(multicast_encap_iphdr);
- 	ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
- 	mb_copy->m_data -= sizeof(multicast_encap_iphdr);
- 	
- 	if (vifp->v_rate_limit <= 0)
- 		tbf_send_packet(vifp, mb_copy);
- 	else
- 		tbf_control(vifp, mb_copy, ip, ip_copy->ip_len);
- }
- 
  /*
-  * De-encapsulate a packet and feed it back through ip input (this
-  * routine is called whenever IP gets a packet with proto type
-  * ENCAP_PROTO and a local destination address).
-  *
-  * Return 1 if we handled the packet, 0 if we did not.
-  *
-  * Called from encap4_input() in sys/netinet/ip_encap.c.
-  */
- int
- mrt_ipip_input(m, hlen)
- 	struct mbuf *m;
- 	int hlen;
- {
- 	struct ip *ip = mtod(m, struct ip *);
- 	int s;
- 	struct ifqueue *ifq;
- 	struct vif *vifp;
- 
- 	if (!have_encap_tunnel)
- 		return (0);
- 
- 	/*
- 	 * dump the packet if it's not to a multicast destination or if
- 	 * we don't have an encapsulating tunnel with the source.
- 	 * Note:  This code assumes that the remote site IP address
- 	 * uniquely identifies the tunnel (i.e., that this site has
- 	 * at most one tunnel with the remote site).
- 	 */
- 	if (!IN_MULTICAST(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr)) {
- 		++mrtstat.mrts_bad_tunnel;
- 		return (0);
- 	}
- 
- 	if (!in_hosteq(ip->ip_src, last_encap_src)) {
- 		struct vif *vife;
- 	
- 		vifp = viftable;
- 		vife = vifp + numvifs;
- 		for (; vifp < vife; vifp++)
- 			if (vifp->v_flags & VIFF_TUNNEL &&
- 			    in_hosteq(vifp->v_rmt_addr, ip->ip_src))
- 				break;
- 		if (vifp == vife) {
- 			mrtstat.mrts_cant_tunnel++; /*XXX*/
- 			if (mrtdebug)
- 				log(LOG_DEBUG,
- 				    "ip_mforward: no tunnel with %x\n",
- 				    ntohl(ip->ip_src.s_addr));
- 			return (0);
- 		}
- 		last_encap_vif = vifp;
- 		last_encap_src = ip->ip_src;
- 	} else
- 		vifp = last_encap_vif;
- 
- 	m->m_data += hlen;
- 	m->m_len -= hlen;
- 	m->m_pkthdr.len -= hlen;
- 	m->m_pkthdr.rcvif = vifp->v_ifp;
- 	ifq = &ipintrq;
- 	s = splimp();
- 	if (IF_QFULL(ifq)) {
- 		IF_DROP(ifq);
- 		m_freem(m);
- 	} else {
- 		IF_ENQUEUE(ifq, m);
- 		/*
- 		 * normally we would need a "schednetisr(NETISR_IP)"
- 		 * here but we were called by ip_input and it is going
- 		 * to loop back & try to dequeue the packet we just
- 		 * queued as soon as we return so we avoid the
- 		 * unnecessary software interrrupt.
- 		 */
- 	}
- 	splx(s);
- 	return (1);
- }
- 
- /*
   * Token bucket filter module
   */
  static void
--- 1398,1404 ----
***************
*** 1683,1721 ****
  	struct vif *vifp;
  	struct mbuf *m;
  {
  	int error;
  	int s = splsoftnet();
- 
- 	if (vifp->v_flags & VIFF_TUNNEL) {
- 		/* If tunnel options */
- #ifdef IPSEC
- 		/* Don't lookup socket in forwading case */
- 		ipsec_setsocket(m, NULL);
- #endif
- 		ip_output(m, (struct mbuf *)0, &vifp->v_route,
- 			  IP_FORWARDING, (struct ip_moptions *)0);
- 	} else {
- 		/* if physical interface option, extract the options and then send */
- 		struct ip_moptions imo;
  
! 		imo.imo_multicast_ifp = vifp->v_ifp;
! 		imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1;
! 		imo.imo_multicast_loop = 1;
  #ifdef RSVP_ISI
! 		imo.imo_multicast_vif = -1;
  #endif
  
  #ifdef IPSEC
! 		/* Don't lookup socket in forwading case */
! 		ipsec_setsocket(m, NULL);
  #endif
! 		error = ip_output(m, (struct mbuf *)0, (struct route *)0,
! 				  IP_FORWARDING|IP_MULTICASTOPTS, &imo);
  
! 		if (mrtdebug & DEBUG_XMIT)
! 			log(LOG_DEBUG, "phyint_send on vif %ld err %d\n",
! 			    (long)(vifp-viftable), error);
! 	}
  	splx(s);
  }
  
--- 1558,1584 ----
  	struct vif *vifp;
  	struct mbuf *m;
  {
+ 	struct ip_moptions imo;
  	int error;
  	int s = splsoftnet();
  
! 	imo.imo_multicast_ifp = vifp->v_ifp;
! 	imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1;
! 	imo.imo_multicast_loop = 1;
  #ifdef RSVP_ISI
! 	imo.imo_multicast_vif = -1;
  #endif
  
  #ifdef IPSEC
! 	/* Don't lookup socket in forwading case */
! 	ipsec_setsocket(m, NULL);
  #endif
! 	error = ip_output(m, (struct mbuf *)0, (struct route *)0,
! 			  IP_FORWARDING|IP_MULTICASTOPTS, &imo);
  
! 	if (mrtdebug & DEBUG_XMIT)
! 		log(LOG_DEBUG, "phyint_send on vif %ld err %d\n",
! 		    (long)(vifp-viftable), error);
  	splx(s);
  }
  
Index: ip_mroute.h
===================================================================
RCS file: /home/cvsfiles/netbsd/src/sys/netinet/ip_mroute.h,v
retrieving revision 1.1.1.1
retrieving revision 1.6
diff -c -r1.1.1.1 -r1.6
*** ip_mroute.h	2000/03/31 20:00:36	1.1.1.1
--- ip_mroute.h	2000/10/05 21:19:52	1.6
***************
*** 7,12 ****
--- 7,13 ----
   * Modified by Steve Deering, Stanford, February 1989.
   * Modified by Ajit Thyagarajan, PARC, August 1993.
   * Modified by Ajit Thyagarajan, PARC, August 1994.
+  * Modified by Jason R. Thorpe, Zembu Labs, October 2000.
   *
   * MROUTING Revision: 1.2
   */
***************
*** 17,33 ****
  #include <sys/queue.h>
  #include <sys/callout.h>
  
  /*
   * Multicast Routing set/getsockopt commands.
   */
  #define	MRT_INIT		100	/* initialize forwarder */
  #define	MRT_DONE		101	/* shut down forwarder */
! #define	MRT_ADD_VIF		102	/* create virtual interface */
  #define	MRT_DEL_VIF		103	/* delete virtual interface */
  #define	MRT_ADD_MFC		104	/* insert forwarding cache entry */
  #define	MRT_DEL_MFC		105	/* delete forwarding cache entry */
  #define	MRT_VERSION		106	/* get kernel version number */
  #define	MRT_ASSERT		107	/* enable PIM assert processing */
  
  
  /*
--- 18,37 ----
  #include <sys/queue.h>
  #include <sys/callout.h>
  
+ #include <net/if.h>
+ 
  /*
   * Multicast Routing set/getsockopt commands.
   */
  #define	MRT_INIT		100	/* initialize forwarder */
  #define	MRT_DONE		101	/* shut down forwarder */
! #define	OMRT_ADD_VIF		102	/* old create virtual interface */
  #define	MRT_DEL_VIF		103	/* delete virtual interface */
  #define	MRT_ADD_MFC		104	/* insert forwarding cache entry */
  #define	MRT_DEL_MFC		105	/* delete forwarding cache entry */
  #define	MRT_VERSION		106	/* get kernel version number */
  #define	MRT_ASSERT		107	/* enable PIM assert processing */
+ #define	MRT_ADD_VIF		108	/* create virtual interface */
  
  
  /*
***************
*** 45,58 ****
  #define	VIFM_COPY(mfrom, mto)		((mto) = (mfrom))
  #define	VIFM_SAME(m1, m2)		((m1) == (m2))
  
! #define	VIFF_TUNNEL	0x1		/* vif represents a tunnel end-point */
! #define	VIFF_SRCRT	0x2		/* tunnel uses IP src routing */
  
  /*
!  * Argument structure for MRT_ADD_VIF.
   * (MRT_DEL_VIF takes a single vifi_t argument.)
   */
! struct vifctl {
  	vifi_t	  vifc_vifi;	    	/* the index of the vif to be added */
  	u_int8_t  vifc_flags;     	/* VIFF_ flags defined below */
  	u_int8_t  vifc_threshold; 	/* min ttl required to forward on vif */
--- 49,68 ----
  #define	VIFM_COPY(mfrom, mto)		((mto) = (mfrom))
  #define	VIFM_SAME(m1, m2)		((m1) == (m2))
  
! #ifdef _KERNEL
! /*
!  * These flags were used for "tunnel" vifs, and are deprecated.  We
!  * rename them to break old source, but keep them around in order
!  * to return sane errors to userland routing daemons.
!  */
! #define	OVIFF_TUNNEL		0x01
! #define	OVIFF_SRCRT		0x02
  
  /*
!  * Argument structure for OMRT_ADD_VIF.
   * (MRT_DEL_VIF takes a single vifi_t argument.)
   */
! struct ovifctl {
  	vifi_t	  vifc_vifi;	    	/* the index of the vif to be added */
  	u_int8_t  vifc_flags;     	/* VIFF_ flags defined below */
  	u_int8_t  vifc_threshold; 	/* min ttl required to forward on vif */
***************
*** 60,65 ****
--- 70,88 ----
  	struct	  in_addr vifc_lcl_addr;/* local interface address */
  	struct	  in_addr vifc_rmt_addr;/* remote address (tunnels only) */
  };
+ #endif /* _KERNEL */
+ 
+ /*
+  * Argument structure for MRT_ADD_VIF.
+  * (MRT_DEL_VIF takes a single vifi_t argument.)
+  */
+ struct vifctl {
+ 	vifi_t    vifc_vifi;		/* the index of the vif to be added */
+ 	u_int8_t  vifc_flags;		/* VIFF_ flags */
+ 	u_int8_t  vifc_threshold;	/* min ttl required to forward on vif */
+ 	u_int32_t vifc_rate_limit;	/* max rate */
+ 	char      vifc_ifname[IFNAMSIZ];/* interface name */
+ };
  
  /*
   * Argument structure for MRT_ADD_MFC and MRT_DEL_MFC.
***************
*** 130,143 ****
  	u_int8_t  v_flags;		/* VIFF_ flags defined above */
  	u_int8_t  v_threshold;		/* min ttl required to forward on vif */
  	u_int32_t v_rate_limit;		/* max rate */
- 	struct	  in_addr v_lcl_addr;	/* local interface address */
- 	struct	  in_addr v_rmt_addr;	/* remote address (tunnels only) */
  	struct	  ifnet *v_ifp;		/* pointer to interface */
  	u_long	  v_pkt_in;		/* # pkts in on interface */
  	u_long	  v_pkt_out;		/* # pkts out on interface */
  	u_long	  v_bytes_in;		/* # bytes in on interface */
  	u_long	  v_bytes_out;		/* # bytes out on interface */
- 	struct	  route v_route;	/* cached route if this is a tunnel */
  	struct	  callout v_repq_ch;	/* for tbf_reprocess_q() */
  #ifdef RSVP_ISI
  	int	  v_rsvp_on;		/* # RSVP listening on this vif */
--- 153,163 ----
***************
*** 218,224 ****
  #else
  int ip_mforward __P((struct mbuf *, struct ifnet *));
  #endif
- int mrt_ipip_input __P((struct mbuf *, int));
  
  #endif /* _KERNEL */
  
--- 238,243 ----

--BOKacYhQ+x31HxR3--

From asaeda@yamato.ibm.co.jp Fri Oct 06 07:51:13 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 07:51:13 -0000
	by cindy.yamato.ibm.co.jp (8.9.3/3.7W/GW3.3) with ESMTP id QAA04002;
	Fri, 6 Oct 2000 16:50:50 +0900
To: thorpej@zembu.com
Cc: tech-net@netbsd.org
Subject: Re: Multicast routing and unnumbered point-to-point interfaces
In-Reply-To: Your message of "Thu, 5 Oct 2000 15:24:34 -0700"
	<20001005152434.L902@dr-evil.z.zembu.com>
References: <20001005152434.L902@dr-evil.z.zembu.com>
Mime-Version: 1.0
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Message-Id: <20001006164941F.asaeda@yamato.ibm.com>
Date: Fri, 06 Oct 2000 16:49:41 +0900 (JST)
From: Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>
Lines: 36

> This required some hacking in mrouted and the kernel in order to
> decouple the notion of "IP address" from "interface identifier".

I'll see if this change might be ok, though..

> I did this in two stages:
> 
> 	- Rip out support for mrouted-created v4-in-v4 tunnels.
> 	  They are wire-compatible with gif(4), which is more
> 	  generic, so we should just use the generic mechanism.

I for one would say ok.

> 	- Changed the MRT_ADD_VIF socket option to pass an
> 	  interface name rather than an IP address.  I left
> 	  the old version in there as OMRT_ADD_VIF so that
> 	  old mrouted(8) versions would continue to work, so
> 	  long as they did not use VIFF_TUNNEL (which could
> 	  not work, since I ripped out all the kernel support
> 	  for it :-).

I agree that we don't use VIFF_TUNNEL as an interface (vif) flag
anymore. However, VIFF_TUNNEL and VIFF_SRCRT aren't needed to be
changed to OVIFF_TUNNEL and OVIFF_SRCRT.
Because daemon codes, mrouted, pimd etc. have these flags and adding
"O" doesn't have any effectiveness, these can be still kept in
ip_mroute.h without change, I think.
(As for pimd, there are entries of VIFF_TUNNEL and VIFF_SRCRT, but
they have no meanings anymore. Even so, retaining a portability
between other OSes must be cared...)
(pimd newly defines VIFF_REGISTER for a pseudo interface to handle PIM 
Register messages. just fyi.:)

Regards.
--
Hitoshi Asaeda

From asaeda@yamato.ibm.co.jp Fri Oct 06 09:08:53 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 09:08:53 -0000
	by cindy.yamato.ibm.co.jp (8.9.3/3.7W/GW3.3) with ESMTP id SAA36438;
	Fri, 6 Oct 2000 18:08:31 +0900
To: thorpej@zembu.com
Cc: tech-net@netbsd.org
Subject: Re: Multicast routing and unnumbered point-to-point interfaces
In-Reply-To: Your message of "Thu, 5 Oct 2000 15:24:34 -0700"
	<20001005152434.L902@dr-evil.z.zembu.com>
References: <20001005152434.L902@dr-evil.z.zembu.com>
Mime-Version: 1.0
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Message-Id: <20001006180737W.asaeda@yamato.ibm.com>
Date: Fri, 06 Oct 2000 18:07:37 +0900 (JST)
From: Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>
Lines: 15

> This required some hacking in mrouted and the kernel in order to
> decouple the notion of "IP address" from "interface identifier".

I'd like to ask you a very simple question.

Why don't you define another vif flag, e.g., VIFF_LOGICAL, instead of
an obsolete VIFF_TUNNEL?
gif, gre etc. have each if_type, then you can distinguish the
interface is physical or logical (virtual) interface.
If you distinguish the interface's attribute, then you can skip
routines of unneed check for a logical interface.

Something unwilling?
--
Hitoshi Asaeda

From thorpej@zembu.com Fri Oct 06 16:25:32 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 16:25:32 -0000
	id 8F027D221; Fri,  6 Oct 2000 09:25:32 -0700 (PDT)
Date: Fri, 6 Oct 2000 09:25:32 -0700
From: Jason R Thorpe <thorpej@zembu.com>
To: Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>
Cc: tech-net@netbsd.org
Subject: Re: Multicast routing and unnumbered point-to-point interfaces
Message-ID: <20001006092532.D991@dr-evil.z.zembu.com>
Reply-To: thorpej@zembu.com
Mail-Followup-To: Jason R Thorpe <thorpej@zembu.com>,
	Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>, tech-net@netbsd.org
References: <20001005152434.L902@dr-evil.z.zembu.com> <20001006164941F.asaeda@yamato.ibm.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.2i
In-Reply-To: <20001006164941F.asaeda@yamato.ibm.com>; from asaeda@yamato.ibm.co.jp on Fri, Oct 06, 2000 at 04:49:41PM +0900
Organization: Zembu Labs, Inc.

On Fri, Oct 06, 2000 at 04:49:41PM +0900, Hitoshi Asaeda wrote:

 > I agree that we don't use VIFF_TUNNEL as an interface (vif) flag
 > anymore. However, VIFF_TUNNEL and VIFF_SRCRT aren't needed to be
 > changed to OVIFF_TUNNEL and OVIFF_SRCRT.
 > Because daemon codes, mrouted, pimd etc. have these flags and adding
 > "O" doesn't have any effectiveness, these can be still kept in
 > ip_mroute.h without change, I think.

The reason for this is to make it obvious that they're "obsolete" or
"old" .. and I want to keep the defns around so I can return a sane
error condition.

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>

From thorpej@zembu.com Fri Oct 06 16:26:59 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 16:26:58 -0000
	id 08DF5D221; Fri,  6 Oct 2000 09:26:59 -0700 (PDT)
Date: Fri, 6 Oct 2000 09:26:59 -0700
From: Jason R Thorpe <thorpej@zembu.com>
To: Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>
Cc: tech-net@netbsd.org
Subject: Re: Multicast routing and unnumbered point-to-point interfaces
Message-ID: <20001006092659.E991@dr-evil.z.zembu.com>
Reply-To: thorpej@zembu.com
Mail-Followup-To: Jason R Thorpe <thorpej@zembu.com>,
	Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>, tech-net@netbsd.org
References: <20001005152434.L902@dr-evil.z.zembu.com> <20001006180737W.asaeda@yamato.ibm.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.2i
In-Reply-To: <20001006180737W.asaeda@yamato.ibm.com>; from asaeda@yamato.ibm.co.jp on Fri, Oct 06, 2000 at 06:07:37PM +0900
Organization: Zembu Labs, Inc.

On Fri, Oct 06, 2000 at 06:07:37PM +0900, Hitoshi Asaeda wrote:

 > Why don't you define another vif flag, e.g., VIFF_LOGICAL, instead of
 > an obsolete VIFF_TUNNEL?
 > gif, gre etc. have each if_type, then you can distinguish the
 > interface is physical or logical (virtual) interface.
 > If you distinguish the interface's attribute, then you can skip
 > routines of unneed check for a logical interface.

I'm not sure I understand.  The VIFF_TUNNEL checks were to handle the
special-case of ip_mroute.c doing the encap.  "Logical" interfaces such
as gif, gre, etc. can simply be treated as normal network interfaces,
as can e.g. vlan interfaces.

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>

From asaeda@yamato.ibm.co.jp Fri Oct 06 17:09:46 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 17:09:46 -0000
	by cindy.yamato.ibm.co.jp (8.9.3/3.7W/GW3.3) with ESMTP id CAA36752;
	Sat, 7 Oct 2000 02:09:27 +0900
To: thorpej@zembu.com
Cc: tech-net@netbsd.org
Subject: Re: Multicast routing and unnumbered point-to-point interfaces
In-Reply-To: Your message of "Fri, 6 Oct 2000 09:25:32 -0700"
	<20001006092532.D991@dr-evil.z.zembu.com>
References: <20001006092532.D991@dr-evil.z.zembu.com>
Mime-Version: 1.0
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Message-Id: <20001007020923A.asaeda@yamato.ibm.com>
Date: Sat, 07 Oct 2000 02:09:23 +0900 (JST)
From: Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>
Lines: 20

>  > I agree that we don't use VIFF_TUNNEL as an interface (vif) flag
>  > anymore. However, VIFF_TUNNEL and VIFF_SRCRT aren't needed to be
>  > changed to OVIFF_TUNNEL and OVIFF_SRCRT.
>  > Because daemon codes, mrouted, pimd etc. have these flags and adding
>  > "O" doesn't have any effectiveness, these can be still kept in
>  > ip_mroute.h without change, I think.
> 
> The reason for this is to make it obvious that they're "obsolete" or
> "old" .. and I want to keep the defns around so I can return a sane
> error condition.

Yes, I know the meaning of "O".:) But I think you don't need to change
the name to make it be obvious.
(If you do so, mrouted and pimd must be changed. If adding "O" is so
reasonable, of course, I can agree to change from VIFF_... to
OVIFF_... and these daemon codes. However, I cannot understand the
benefits.)
Is it not enough for you only to put a comment, "obsoleted"?
--
Hitoshi Asaeda

From thorpej@zembu.com Fri Oct 06 17:13:32 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 17:13:32 -0000
	id AC6DFD221; Fri,  6 Oct 2000 10:13:32 -0700 (PDT)
Date: Fri, 6 Oct 2000 10:13:32 -0700
From: Jason R Thorpe <thorpej@zembu.com>
To: Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>
Cc: tech-net@netbsd.org
Subject: Re: Multicast routing and unnumbered point-to-point interfaces
Message-ID: <20001006101332.V991@dr-evil.z.zembu.com>
Reply-To: thorpej@zembu.com
Mail-Followup-To: Jason R Thorpe <thorpej@zembu.com>,
	Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>, tech-net@netbsd.org
References: <20001006092532.D991@dr-evil.z.zembu.com> <20001007020923A.asaeda@yamato.ibm.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.2i
In-Reply-To: <20001007020923A.asaeda@yamato.ibm.com>; from asaeda@yamato.ibm.co.jp on Sat, Oct 07, 2000 at 02:09:23AM +0900
Organization: Zembu Labs, Inc.

On Sat, Oct 07, 2000 at 02:09:23AM +0900, Hitoshi Asaeda wrote:

 > Yes, I know the meaning of "O".:) But I think you don't need to change
 > the name to make it be obvious.
 > (If you do so, mrouted and pimd must be changed. If adding "O" is so
 > reasonable, of course, I can agree to change from VIFF_... to
 > OVIFF_... and these daemon codes. However, I cannot understand the
 > benefits.)
 > Is it not enough for you only to put a comment, "obsoleted"?

It is also the intent to cause old source to fail to compile with the
new kernel headers.

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>

From asaeda@yamato.ibm.co.jp Fri Oct 06 17:57:10 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 17:57:10 -0000
	by cindy.yamato.ibm.co.jp (8.9.3/3.7W/GW3.3) with ESMTP id CAA36718;
	Sat, 7 Oct 2000 02:56:51 +0900
To: thorpej@zembu.com
Cc: tech-net@netbsd.org
Subject: Re: Multicast routing and unnumbered point-to-point interfaces
In-Reply-To: Your message of "Fri, 6 Oct 2000 10:13:32 -0700"
	<20001006101332.V991@dr-evil.z.zembu.com>
References: <20001006101332.V991@dr-evil.z.zembu.com>
Mime-Version: 1.0
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Message-Id: <20001007025704B.asaeda@yamato.ibm.com>
Date: Sat, 07 Oct 2000 02:57:04 +0900 (JST)
From: Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>
Lines: 15

>  > Yes, I know the meaning of "O".:) But I think you don't need to change
>  > the name to make it be obvious.
>  > (If you do so, mrouted and pimd must be changed. If adding "O" is so
>  > reasonable, of course, I can agree to change from VIFF_... to
>  > OVIFF_... and these daemon codes. However, I cannot understand the
>  > benefits.)
>  > Is it not enough for you only to put a comment, "obsoleted"?
> 
> It is also the intent to cause old source to fail to compile with the
> new kernel headers.

I'm afraid I can't understand why you insist to cause errors by
force.
--
Hitoshi Asaeda

From asaeda@yamato.ibm.co.jp Fri Oct 06 18:09:37 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 18:09:37 -0000
	by cindy.yamato.ibm.co.jp (8.9.3/3.7W/GW3.3) with ESMTP id DAA07956;
	Sat, 7 Oct 2000 03:09:18 +0900
To: thorpej@zembu.com
Cc: tech-net@netbsd.org
Subject: Re: Multicast routing and unnumbered point-to-point interfaces
In-Reply-To: Your message of "Fri, 6 Oct 2000 09:26:59 -0700"
	<20001006092659.E991@dr-evil.z.zembu.com>
References: <20001006092659.E991@dr-evil.z.zembu.com>
Mime-Version: 1.0
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Message-Id: <20001007030935U.asaeda@yamato.ibm.com>
Date: Sat, 07 Oct 2000 03:09:35 +0900 (JST)
From: Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>
Lines: 27

> I'm not sure I understand.  The VIFF_TUNNEL checks were to handle the
> special-case of ip_mroute.c doing the encap.  "Logical" interfaces such
> as gif, gre, etc. can simply be treated as normal network interfaces,
> as can e.g. vlan interfaces.

Yes, you are right.
The reason why I asked you is that if you handle all of available
interfaces without checking these attributes (i.e. vif flags), you
have to change members of vifctl structure, like your change. However,
if you can distinguish each interface by each vif flag which is gotten 
from if_type, IFT_..., then you don't need to change vifctl
structure. (I mean your kernel patch eliminates vifc_lcl_addr and
vifc_rmt_addr from vifctl.)

Following is what I want to say.
Since you are complaining about using local/remote address, the patch
tries to use ifp instead of the address. But when you can see the
interface is a phisical or logical (virtual) after mrouting
initiation, you can skip checking these addresses for logical
interfaces. I feel this is reasonable rather than that.
And newly defined vif flag (e.g. VIFF_LOGICAL) by above policy stands
completely different meaning from VIFF_TUNNEL. 

(Because I've not checked your codes deeply yet, I may miss some
point around this. If so, please correct me.)
--
Hitoshi Asaeda

From thorpej@zembu.com Fri Oct 06 18:21:09 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 18:21:09 -0000
	id 3DD35D221; Fri,  6 Oct 2000 11:21:09 -0700 (PDT)
Date: Fri, 6 Oct 2000 11:21:09 -0700
From: Jason R Thorpe <thorpej@zembu.com>
To: Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>
Cc: tech-net@netbsd.org
Subject: Re: Multicast routing and unnumbered point-to-point interfaces
Message-ID: <20001006112109.B991@dr-evil.z.zembu.com>
Reply-To: thorpej@zembu.com
Mail-Followup-To: Jason R Thorpe <thorpej@zembu.com>,
	Hitoshi Asaeda <asaeda@yamato.ibm.co.jp>, tech-net@netbsd.org
References: <20001006101332.V991@dr-evil.z.zembu.com> <20001007025704B.asaeda@yamato.ibm.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.2i
In-Reply-To: <20001007025704B.asaeda@yamato.ibm.com>; from asaeda@yamato.ibm.co.jp on Sat, Oct 07, 2000 at 02:57:04AM +0900
Organization: Zembu Labs, Inc.

On Sat, Oct 07, 2000 at 02:57:04AM +0900, Hitoshi Asaeda wrote:

 > > It is also the intent to cause old source to fail to compile with the
 > > new kernel headers.
 > 
 > I'm afraid I can't understand why you insist to cause errors by
 > force.

A multicast routing daemon which compiles fine but then fails to
function isn't the greatest thing, IMO.  Preserving the binary
compatibility was a goal, but changing the API like that is really
the only way to force programs to get fixed (and, sometimes, even
notice that they're broken in the first place).

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>

From thorpej@zembu.com Fri Oct 06 21:17:29 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 21:17:29 -0000
	id D91A6D221; Fri,  6 Oct 2000 14:17:27 -0700 (PDT)
Date: Tue, 3 Oct 2000 22:27:05 -0700
From: Jason R Thorpe <thorpej@zembu.com>
To: tech-net@netbsd.org
Subject: ether_ioctl()
Message-ID: <20001003222705.H712@dr-evil.shagadelic.org>
Reply-To: thorpej@zembu.com
Mail-Followup-To: Jason R Thorpe <thorpej@zembu.com>, tech-net@netbsd.org
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="tjCHc7DPkfUGtrlw"
Content-Disposition: inline
User-Agent: Mutt/1.2i
Organization: Zembu Labs, Inc.
Resent-From: thorpej@dr-evil.z.zembu.com
Resent-Date: Fri, 6 Oct 2000 14:17:27 -0700
Resent-To: tech-net@netbsd.org
Resent-Message-Id: <20001006211727.D91A6D221@dr-evil.shagadelic.org>
Resent-Sender: thorpej@zembu.com


--tjCHc7DPkfUGtrlw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I finally got around to implementing this in a sane way for the
NetBSD network stack.  Attached are ether_ioctl() itself and
changes for several network drivers to use it.

Note that it changes (*if_reset)() to (*if_init)() and adds
an (*if_stop)(), which also takes an argument indicating that
the interface should be disabled (Rx buffers freed, power
removed from the device, etc.).

There's also an unrelated change in there (if_bridge) that is
part of somthing else I'm working on, but if I'm changing the
ifnet, do it once, not N times, right? :-)

Feedback soon, please.

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>

--tjCHc7DPkfUGtrlw
Content-Type: text/plain; charset=us-ascii
Content-Description: ether_ioctl.diff
Content-Disposition: attachment; filename="ether_ioctl.diff"

Index: net/if.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if.c,v
retrieving revision 1.71
diff -c -r1.71 if.c
*** net/if.c	2000/10/01 23:16:07	1.71
--- net/if.c	2000/10/04 05:23:29
***************
*** 213,219 ****
  }
  
  int
! if_nullreset(ifp)
  	struct ifnet *ifp;
  {
  
--- 213,219 ----
  }
  
  int
! if_nullinit(ifp)
  	struct ifnet *ifp;
  {
  
***************
*** 221,226 ****
--- 221,235 ----
  }
  
  void
+ if_nullstop(ifp, disable)
+ 	struct ifnet *ifp;
+ 	int disable;
+ {
+ 
+ 	/* Nothing. */
+ }
+ 
+ void
  if_nullwatchdog(ifp)
  	struct ifnet *ifp;
  {
***************
*** 356,362 ****
  	ifp->if_input	 = if_nullinput;
  	ifp->if_start	 = if_nullstart;
  	ifp->if_ioctl	 = if_nullioctl;
! 	ifp->if_reset	 = if_nullreset;
  	ifp->if_watchdog = if_nullwatchdog;
  	ifp->if_drain	 = if_nulldrain;
  
--- 365,372 ----
  	ifp->if_input	 = if_nullinput;
  	ifp->if_start	 = if_nullstart;
  	ifp->if_ioctl	 = if_nullioctl;
! 	ifp->if_init	 = if_nullinit;
! 	ifp->if_stop	 = if_nullstop;
  	ifp->if_watchdog = if_nullwatchdog;
  	ifp->if_drain	 = if_nulldrain;
  
Index: net/if.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if.h,v
retrieving revision 1.53
diff -c -r1.53 if.h
*** net/if.h	2000/07/20 18:40:27	1.53
--- net/if.h	2000/10/04 05:23:30
***************
*** 240,247 ****
  		__P((struct ifnet *));
  	int	(*if_ioctl)		/* ioctl routine */
  		__P((struct ifnet *, u_long, caddr_t));
! 	int	(*if_reset)		/* XXX bus reset routine */
  		__P((struct ifnet *));
  	void	(*if_watchdog)		/* timer routine */
  		__P((struct ifnet *));
  	void	(*if_drain)		/* routine to release resources */
--- 240,249 ----
  		__P((struct ifnet *));
  	int	(*if_ioctl)		/* ioctl routine */
  		__P((struct ifnet *, u_long, caddr_t));
! 	int	(*if_init)		/* init routine */
  		__P((struct ifnet *));
+ 	void	(*if_stop)		/* stop routine */
+ 		__P((struct ifnet *, int));
  	void	(*if_watchdog)		/* timer routine */
  		__P((struct ifnet *));
  	void	(*if_drain)		/* routine to release resources */
***************
*** 256,261 ****
--- 258,264 ----
  	struct	sockaddr_dl *if_sadl;	/* pointer to our sockaddr_dl */
  	u_int8_t *if_broadcastaddr;	/* linklevel broadcast bytestring */
  	struct ifprefix *if_prefixlist; /* linked list of prefixes per if */
+ 	void *if_bridge;		/* bridge glue */
  };
  #define	if_mtu		if_data.ifi_mtu
  #define	if_type		if_data.ifi_type
***************
*** 628,634 ****
  void	if_nullinput __P((struct ifnet *, struct mbuf *));
  void	if_nullstart __P((struct ifnet *));
  int	if_nullioctl __P((struct ifnet *, u_long, caddr_t));
! int	if_nullreset __P((struct ifnet *));
  void	if_nullwatchdog __P((struct ifnet *));
  void	if_nulldrain __P((struct ifnet *));
  #else
--- 631,638 ----
  void	if_nullinput __P((struct ifnet *, struct mbuf *));
  void	if_nullstart __P((struct ifnet *));
  int	if_nullioctl __P((struct ifnet *, u_long, caddr_t));
! int	if_nullinit __P((struct ifnet *));
! void	if_nullstop __P((struct ifnet *, int));
  void	if_nullwatchdog __P((struct ifnet *));
  void	if_nulldrain __P((struct ifnet *));
  #else
Index: net/if_ether.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_ether.h,v
retrieving revision 1.19
diff -c -r1.19 if_ether.h
*** net/if_ether.h	2000/10/03 23:33:38	1.19
--- net/if_ether.h	2000/10/04 04:42:55
***************
*** 161,166 ****
--- 161,167 ----
  extern u_int8_t ether_ipmulticast_min[ETHER_ADDR_LEN];
  extern u_int8_t ether_ipmulticast_max[ETHER_ADDR_LEN];
  
+ int	ether_ioctl(struct ifnet *, u_long, caddr_t);
  int	ether_addmulti (struct ifreq *, struct ethercom *);
  int	ether_delmulti (struct ifreq *, struct ethercom *);
  int	ether_changeaddr (struct ifreq *, struct ethercom *);
Index: net/if_ethersubr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_ethersubr.c,v
retrieving revision 1.64
diff -c -r1.64 if_ethersubr.c
*** net/if_ethersubr.c	2000/10/03 23:50:52	1.64
--- net/if_ethersubr.c	2000/10/04 04:42:55
***************
*** 1088,1090 ****
--- 1088,1183 ----
  	 */
  	return (ENETRESET);
  }
+ 
+ /*
+  * Common ioctls for Ethernet interfaces.  Note, we must be
+  * called at splnet().
+  */
+ int
+ ether_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+ {
+ 	struct ethercom *ec = (void *) ifp;
+ 	struct ifreq *ifr = (struct ifreq *)data;
+ 	struct ifaddr *ifa = (struct ifaddr *)data;
+ 	int error = 0;
+ 
+ 	switch (cmd) {
+ 	case SIOCSIFADDR:
+ 		ifp->if_flags |= IFF_UP;
+ 		switch (ifa->ifa_addr->sa_family) {
+ #ifdef INET
+ 		case AF_INET:
+ 			if ((error = (*ifp->if_init)(ifp)) != 0)
+ 				break;
+ 			arp_ifinit(ifp, ifa);
+ 			break;
+ #endif /* INET */
+ #ifdef NS
+ 		case AF_NS:
+ 		    {
+ 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
+ 
+ 			if (ns_nullhost(*ina))
+ 				ina->x_host = *(union ns_host *)
+ 				    LLADDR(ifp->if_sadl);
+ 			else
+ 				memcpy(LLADDR(ifp->if_sadl),
+ 				    ina->x_host.c_host, ifp->if_addrlen);
+ 			/* Set new address. */
+ 			error = (*ifp->if_init)(ifp);
+ 			break;
+ 		    }
+ #endif /* NS */
+ 		default:
+ 			error = (*ifp->if_init)(ifp);
+ 			break;
+ 		}
+ 		break;
+ 
+ 	case SIOCGIFADDR:
+ 		memcpy(((struct sockaddr *)&ifr->ifr_data)->sa_data,
+ 		    LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
+ 		break;
+ 
+ 	case SIOCSIFMTU:
+ 		if (ifr->ifr_mtu > ETHERMTU)
+ 			error = EINVAL;
+ 		else
+ 			ifp->if_mtu = ifr->ifr_mtu;
+ 		break;
+ 
+ 	case SIOCSIFFLAGS:
+ 		if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_RUNNING) {
+ 			/*
+ 			 * If interface is marked down and it is running,
+ 			 * then stop and disable it.
+ 			 */
+ 			(*ifp->if_stop)(ifp, 1);
+ 		} else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_UP) {
+ 			/*
+ 			 * If interface is marked up and it is stopped, then
+ 			 * start it.
+ 			 */
+ 			error = (*ifp->if_init)(ifp);
+ 		} else if ((ifp->if_flags & IFF_UP) != 0) {
+ 			/*
+ 			 * Reset the interface to pick up changes in any other
+ 			 * flags that affect the hardware state.
+ 			 */
+ 			error = (*ifp->if_init)(ifp);
+ 		}
+ 		break;
+ 
+ 	case SIOCADDMULTI:
+ 	case SIOCDELMULTI:
+ 		error = (cmd == SIOCADDMULTI) ?
+ 		    ether_addmulti(ifr, ec) :
+ 		    ether_delmulti(ifr, ec);
+ 		break;
+ 
+ 	default:
+ 		error = ENOTTY;
+ 	}
+ 
+ 	return (error);
+ }
Index: dev/ic/i82557.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/i82557.c,v
retrieving revision 1.39
diff -c -r1.39 i82557.c
*** dev/ic/i82557.c	2000/10/03 23:35:02	1.39
--- dev/ic/i82557.c	2000/10/04 04:42:58
***************
*** 177,186 ****
  
  void	fxp_start __P((struct ifnet *));
  int	fxp_ioctl __P((struct ifnet *, u_long, caddr_t));
- int	fxp_init __P((struct fxp_softc *));
- void	fxp_rxdrain __P((struct fxp_softc *));
- void	fxp_stop __P((struct fxp_softc *, int));
  void	fxp_watchdog __P((struct ifnet *));
  int	fxp_add_rfabuf __P((struct fxp_softc *, bus_dmamap_t, int));
  int	fxp_mdi_read __P((struct device *, int, int));
  void	fxp_statchg __P((struct device *));
--- 177,187 ----
  
  void	fxp_start __P((struct ifnet *));
  int	fxp_ioctl __P((struct ifnet *, u_long, caddr_t));
  void	fxp_watchdog __P((struct ifnet *));
+ int	fxp_init __P((struct ifnet *));
+ void	fxp_stop __P((struct ifnet *, int));
+ 
+ void	fxp_rxdrain __P((struct fxp_softc *));
  int	fxp_add_rfabuf __P((struct fxp_softc *, bus_dmamap_t, int));
  int	fxp_mdi_read __P((struct device *, int, int));
  void	fxp_statchg __P((struct device *));
***************
*** 331,336 ****
--- 332,339 ----
  	ifp->if_ioctl = fxp_ioctl;
  	ifp->if_start = fxp_start;
  	ifp->if_watchdog = fxp_watchdog;
+ 	ifp->if_init = fxp_init;
+ 	ifp->if_stop = fxp_stop;
  
  	/*
  	 * We can support 802.1Q VLAN-sized frames.
***************
*** 459,465 ****
  	 * Since the system's going to halt shortly, don't bother
  	 * freeing mbufs.
  	 */
! 	fxp_stop(sc, 0);
  }
  /*
   * Power handler routine. Called when the system is transitioning
--- 462,468 ----
  	 * Since the system's going to halt shortly, don't bother
  	 * freeing mbufs.
  	 */
! 	fxp_stop(&sc->sc_ethercom.ec_if, 0);
  }
  /*
   * Power handler routine. Called when the system is transitioning
***************
*** 473,488 ****
  	void *arg;
  {
  	struct fxp_softc *sc = arg;
! 	struct ifnet *ifp;
  	int s;
  
  	s = splnet();
  	if (why != PWR_RESUME)
! 		fxp_stop(sc, 0);
  	else {
- 		ifp = &sc->sc_ethercom.ec_if;
  		if (ifp->if_flags & IFF_UP)
! 			fxp_init(sc);
  	}
  	splx(s);
  }
--- 476,490 ----
  	void *arg;
  {
  	struct fxp_softc *sc = arg;
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	int s;
  
  	s = splnet();
  	if (why != PWR_RESUME)
! 		fxp_stop(ifp, 0);
  	else {
  		if (ifp->if_flags & IFF_UP)
! 			fxp_init(ifp);
  	}
  	splx(s);
  }
***************
*** 1060,1066 ****
  				 * If we want a re-init, do that now.
  				 */
  				if (sc->sc_flags & FXPF_WANTINIT)
! 					(void) fxp_init(sc);
  			}
  
  			/*
--- 1062,1068 ----
  				 * If we want a re-init, do that now.
  				 */
  				if (sc->sc_flags & FXPF_WANTINIT)
! 					(void) fxp_init(ifp);
  			}
  
  			/*
***************
*** 1139,1145 ****
  	 * speed transition).
  	 */
  	if (sc->sc_rxidle > FXP_MAX_RX_IDLE) {
! 		(void) fxp_init(sc);
  		splx(s);
  		return;
  	}
--- 1141,1147 ----
  	 * speed transition).
  	 */
  	if (sc->sc_rxidle > FXP_MAX_RX_IDLE) {
! 		(void) fxp_init(ifp);
  		splx(s);
  		return;
  	}
***************
*** 1211,1221 ****
   * the interface.
   */
  void
! fxp_stop(sc, drain)
! 	struct fxp_softc *sc;
! 	int drain;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct fxp_txsoft *txs;
  	int i;
  
--- 1213,1223 ----
   * the interface.
   */
  void
! fxp_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
! 	struct fxp_softc *sc = ifp->if_softc;
  	struct fxp_txsoft *txs;
  	int i;
  
***************
*** 1254,1264 ****
  	}
  	sc->sc_txpending = 0;
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		fxp_rxdrain(sc);
  	}
  
  }
--- 1256,1264 ----
  	}
  	sc->sc_txpending = 0;
  
! 	if (disable) {
  		fxp_rxdrain(sc);
+ 		fxp_disable(sc);
  	}
  
  }
***************
*** 1278,1304 ****
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) fxp_init(sc);
  }
  
  /*
   * Initialize the interface.  Must be called at splnet().
   */
  int
! fxp_init(sc)
! 	struct fxp_softc *sc;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct fxp_cb_config *cbp;
  	struct fxp_cb_ias *cb_ias;
  	struct fxp_cb_tx *txd;
  	bus_dmamap_t rxmap;
  	int i, prm, save_bf, allm, error = 0;
  
  	/*
  	 * Cancel any pending I/O
  	 */
! 	fxp_stop(sc, 0);
  
  	/* 
  	 * XXX just setting sc_flags to 0 here clears any FXPF_MII
--- 1278,1307 ----
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) fxp_init(ifp);
  }
  
  /*
   * Initialize the interface.  Must be called at splnet().
   */
  int
! fxp_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct fxp_softc *sc = ifp->if_softc;
  	struct fxp_cb_config *cbp;
  	struct fxp_cb_ias *cb_ias;
  	struct fxp_cb_tx *txd;
  	bus_dmamap_t rxmap;
  	int i, prm, save_bf, allm, error = 0;
  
+ 	if ((error = fxp_enable(sc)) != 0)
+ 		goto out;
+ 
  	/*
  	 * Cancel any pending I/O
  	 */
! 	fxp_stop(ifp, 0);
  
  	/* 
  	 * XXX just setting sc_flags to 0 here clears any FXPF_MII
***************
*** 1529,1536 ****
  	fxp_start(ifp);
  
   out:
! 	if (error)
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
  	return (error);
  }
  
--- 1532,1542 ----
  	fxp_start(ifp);
  
   out:
! 	if (error) {
! 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 		ifp->if_timer = 0;
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
+ 	}
  	return (error);
  }
  
***************
*** 1691,1812 ****
  }
  
  int
! fxp_ioctl(ifp, command, data)
  	struct ifnet *ifp;
! 	u_long command;
  	caddr_t data;
  {
  	struct fxp_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
- 
- 	switch (command) {
- 	case SIOCSIFADDR:
- 		if ((error = fxp_enable(sc)) != 0)
- 			break;
- 		ifp->if_flags |= IFF_UP;
- 
- 		switch (ifa->ifa_addr->sa_family) {
- #ifdef INET
- 		case AF_INET:
- 			if ((error = fxp_init(sc)) != 0)
- 				break;
- 			arp_ifinit(ifp, ifa);
- 			break;
- #endif /* INET */
- #ifdef NS
- 		case AF_NS:
- 		    {
- 			 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
- 
- 			 if (ns_nullhost(*ina))
- 				ina->x_host = *(union ns_host *)
- 				    LLADDR(ifp->if_sadl);
- 			 else
- 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
- 				    ifp->if_addrlen);
- 			 /* Set new address. */
- 			 error = fxp_init(sc);
- 			 break;
- 		    }
- #endif /* NS */
- 		default:
- 			error = fxp_init(sc);
- 			break;
- 		}
- 		break;
  
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			fxp_stop(sc, 1);
! 			fxp_disable(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interface is marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			if((error = fxp_enable(sc)) != 0)
! 				break;
! 			error = fxp_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up change in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			if((error = fxp_enable(sc)) != 0)
! 				break;
! 			error = fxp_init(sc);
! 		}
! 		break;
! 
! 	case SIOCADDMULTI:
! 	case SIOCDELMULTI:
! 		if(sc->sc_enabled == 0) {
! 			error = EIO;
! 			break;
! 		}
! 		error = (command == SIOCADDMULTI) ?
! 		    ether_addmulti(ifr, &sc->sc_ethercom) :
! 		    ether_delmulti(ifr, &sc->sc_ethercom);
! 
! 		if (error == ENETRESET) {
! 			/*
! 			 * Multicast list has changed; set the hardware
! 			 * filter accordingly.
! 			 */
! 			if (sc->sc_txpending) {
! 				sc->sc_flags |= FXPF_WANTINIT;
! 				error = 0;
! 			} else
! 				error = fxp_init(sc);
! 		}
! 		break;
! 
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
  		break;
  
  	default:
! 		error = EINVAL;
  		break;
  	}
  
  	splx(s);
  	return (error);
--- 1697,1741 ----
  }
  
  int
! fxp_ioctl(ifp, cmd, data)
  	struct ifnet *ifp;
! 	u_long cmd;
  	caddr_t data;
  {
  	struct fxp_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
! 	switch (cmd) {
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
  	default:
! 		error = ether_ioctl(ifp, cmd, data);
! 		if (error == ENETRESET) {
! 			if (sc->sc_enabled) {
! 				/*
! 				 * Multicast list has changed; set the
! 				 * hardware filter accordingly.
! 				 */
! 				if (sc->sc_txpending) {
! 					sc->sc_flags |= FXPF_WANTINIT;
! 					error = 0;
! 				} else
! 					error = fxp_init(ifp);
! 			} else
! 				error = 0;
! 		}
  		break;
  	}
+ 
+ 	/* Try to get more packets going. */
+ 	if (sc->sc_enabled)
+ 		fxp_start(ifp);
  
  	splx(s);
  	return (error);
Index: dev/ic/rtl81x9.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/rtl81x9.c,v
retrieving revision 1.14
diff -c -r1.14 rtl81x9.c
*** dev/ic/rtl81x9.c	2000/10/01 23:32:42	1.14
--- dev/ic/rtl81x9.c	2000/10/04 04:42:59
***************
*** 141,148 ****
  STATIC void rtk_txeof		__P((struct rtk_softc *));
  STATIC void rtk_start		__P((struct ifnet *));
  STATIC int rtk_ioctl		__P((struct ifnet *, u_long, caddr_t));
! STATIC void rtk_init		__P((void *));
! STATIC void rtk_stop		__P((struct rtk_softc *));
  STATIC void rtk_watchdog	__P((struct ifnet *));
  STATIC void rtk_shutdown	__P((void *));
  STATIC int rtk_ifmedia_upd	__P((struct ifnet *));
--- 141,149 ----
  STATIC void rtk_txeof		__P((struct rtk_softc *));
  STATIC void rtk_start		__P((struct ifnet *));
  STATIC int rtk_ioctl		__P((struct ifnet *, u_long, caddr_t));
! STATIC int rtk_init		__P((struct ifnet *));
! STATIC void rtk_stop		__P((struct ifnet *, int));
! 
  STATIC void rtk_watchdog	__P((struct ifnet *));
  STATIC void rtk_shutdown	__P((void *));
  STATIC int rtk_ifmedia_upd	__P((struct ifnet *));
***************
*** 167,175 ****
  STATIC void rtk_setmulti	__P((struct rtk_softc *));
  STATIC int rtk_list_tx_init	__P((struct rtk_softc *));
  
- STATIC int rtk_ether_ioctl __P((struct ifnet *, u_long, caddr_t));
- 
- 
  #define EE_SET(x)					\
  	CSR_WRITE_1(sc, RTK_EECMD,			\
  		CSR_READ_1(sc, RTK_EECMD) | (x))
--- 168,173 ----
***************
*** 729,743 ****
  	ifp = &sc->ethercom.ec_if;
  	ifp->if_softc = sc;
  	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
- 	ifp->if_mtu = ETHERMTU;
  	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  	ifp->if_ioctl = rtk_ioctl;
- #if 0
- 	ifp->if_output = ether_output;
- #endif
  	ifp->if_start = rtk_start;
  	ifp->if_watchdog = rtk_watchdog;
! 	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  
  	/*
  	 * Do ifmedia setup.
--- 727,738 ----
  	ifp = &sc->ethercom.ec_if;
  	ifp->if_softc = sc;
  	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
  	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  	ifp->if_ioctl = rtk_ioctl;
  	ifp->if_start = rtk_start;
  	ifp->if_watchdog = rtk_watchdog;
! 	ifp->if_init = rtk_init;
! 	ifp->if_stop = rtk_stop;
  
  	/*
  	 * Do ifmedia setup.
***************
*** 942,954 ****
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		rtk_stop(sc);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		rtk_init(sc);
  	}
  	splx(s);
  
--- 937,949 ----
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		rtk_stop(ifp, 0);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		rtk_init(ifp);
  	}
  	splx(s);
  
***************
*** 1050,1056 ****
  			}
  			break;
  #else
! 			rtk_init(sc);
  			return;
  #endif
  		}
--- 1045,1051 ----
  			}
  			break;
  #else
! 			rtk_init(ifp);
  			return;
  #endif
  		}
***************
*** 1233,1239 ****
  
  		if (status & RTK_ISR_SYSTEM_ERR) {
  			rtk_reset(sc);
! 			rtk_init(sc);
  		}
  
  	}
--- 1228,1234 ----
  
  		if (status & RTK_ISR_SYSTEM_ERR) {
  			rtk_reset(sc);
! 			rtk_init(ifp);
  		}
  
  	}
***************
*** 1353,1372 ****
  	return;
  }
  
! STATIC void rtk_init(xsc)
! 	void			*xsc;
  {
! 	struct rtk_softc	*sc = xsc;
! 	struct ifnet		*ifp = &sc->ethercom.ec_if;
! 	int			s, i;
  	u_int32_t		rxcfg;
  
! 	s = splnet();
  
  	/*
! 	 * Cancel pending I/O and free all RX/TX buffers.
  	 */
! 	rtk_stop(sc);
  
  	/* Init our MAC address */
  	for (i = 0; i < ETHER_ADDR_LEN; i++) {
--- 1348,1367 ----
  	return;
  }
  
! STATIC int rtk_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct rtk_softc	*sc = ifp->if_softc;
! 	int			error = 0, i;
  	u_int32_t		rxcfg;
  
! 	if ((error = rtk_enable(sc)) != 0)
! 		goto out;
  
  	/*
! 	 * Cancel pending I/O.
  	 */
! 	rtk_stop(ifp, 0);
  
  	/* Init our MAC address */
  	for (i = 0; i < ETHER_ADDR_LEN; i++) {
***************
*** 1442,1450 ****
  	ifp->if_flags |= IFF_RUNNING;
  	ifp->if_flags &= ~IFF_OACTIVE;
  
- 	(void)splx(s);
- 
  	callout_reset(&sc->rtk_tick_ch, hz, rtk_tick, sc);
  }
  
  /*
--- 1437,1451 ----
  	ifp->if_flags |= IFF_RUNNING;
  	ifp->if_flags &= ~IFF_OACTIVE;
  
  	callout_reset(&sc->rtk_tick_ch, hz, rtk_tick, sc);
+ 
+  out:
+ 	if (error) {
+ 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+ 		ifp->if_timer = 0;
+ 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
+ 	}
+ 	return (error);
  }
  
  /*
***************
*** 1476,1533 ****
  	ifmr->ifm_active = sc->mii.mii_media_active;
  }
  
- STATIC int
- rtk_ether_ioctl(ifp, cmd, data)
- 	struct ifnet *ifp;
- 	u_long cmd;
- 	caddr_t data;
- {
- 	struct ifaddr *ifa = (struct ifaddr *) data;
- 	struct rtk_softc *sc = ifp->if_softc;
- 	int error = 0;
- 
- 	switch (cmd) {
- 	case SIOCSIFADDR:
- 		if ((error = rtk_enable(sc)) != 0)
- 			break;
- 		ifp->if_flags |= IFF_UP;
- 
- 		switch (ifa->ifa_addr->sa_family) {
- #ifdef INET
- 		case AF_INET:
- 			rtk_init(sc);
- 			arp_ifinit(ifp, ifa);
- 			break;
- #endif
- #ifdef NS
- 		case AF_NS:
- 		    {
- 			 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
- 
- 			 if (ns_nullhost(*ina))
- 				ina->x_host = *(union ns_host *)
- 				    LLADDR(ifp->if_sadl);
- 			 else
- 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
- 				    ifp->if_addrlen);
- 			 /* Set new address. */
- 			 rtk_init(sc);
- 			 break;
- 		    }
- #endif
- 		default:
- 			rtk_init(sc);
- 			break;
- 		}
- 		break;
- 
- 	default:
- 		return (EINVAL);
- 	}
- 
- 	return (error);
- }
- 
  STATIC int rtk_ioctl(ifp, command, data)
  	struct ifnet		*ifp;
  	u_long			command;
--- 1477,1482 ----
***************
*** 1540,1584 ****
  	s = splnet();
  
  	switch (command) {
- 	case SIOCSIFADDR:
- 	case SIOCGIFADDR:
- 	case SIOCSIFMTU:
- 		error = rtk_ether_ioctl(ifp, command, data);
- 		break;
- 	case SIOCSIFFLAGS:
- 		if (ifp->if_flags & IFF_UP) {
- 			if ((error = rtk_enable(sc)) != 0)
- 				break;
- 			rtk_init(sc);
- 		} else {
- 			if (ifp->if_flags & IFF_RUNNING) {
- 				rtk_stop(sc);
- 				rtk_disable(sc);
- 			}
- 		}
- 		error = 0;
- 		break;
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		error = (command == SIOCADDMULTI) ?
- 		    ether_addmulti(ifr, &sc->ethercom) :
- 		    ether_delmulti(ifr, &sc->ethercom);
- 
- 		if (error == ENETRESET) { 
- 			/*
- 			 * Multicast list has changed; set the hardware filter
- 			 * accordingly.
- 			 */
- 			rtk_setmulti(sc);
- 			error = 0;
- 		}
- 		break;
  	case SIOCGIFMEDIA:
  	case SIOCSIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->mii.mii_media, command);
  		break;
  	default:
! 		error = EINVAL;
  		break;
  	}
  
--- 1489,1511 ----
  	s = splnet();
  
  	switch (command) {
  	case SIOCGIFMEDIA:
  	case SIOCSIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->mii.mii_media, command);
  		break;
+ 
  	default:
! 		error = ether_ioctl(ifp, command, data);
! 		if (error == ENETRESET) {
! 			if (RTK_IS_ENABLED(sc)) {
! 				/*
! 				 * Multicast list has changed.  Set the
! 				 * hardware filter accordingly.
! 				 */
! 				rtk_setmulti(sc);
! 			}
! 			error = 0;
! 		}
  		break;
  	}
  
***************
*** 1598,1604 ****
  	ifp->if_oerrors++;
  	rtk_txeof(sc);
  	rtk_rxeof(sc);
! 	rtk_init(sc);
  
  	return;
  }
--- 1525,1531 ----
  	ifp->if_oerrors++;
  	rtk_txeof(sc);
  	rtk_rxeof(sc);
! 	rtk_init(ifp);
  
  	return;
  }
***************
*** 1607,1620 ****
   * Stop the adapter and free any mbufs allocated to the
   * RX and TX lists.
   */
! STATIC void rtk_stop(sc)
! 	struct rtk_softc	*sc;
  {
! 	int			i;
! 	struct ifnet		*ifp;
! 
! 	ifp = &sc->ethercom.ec_if;
! 	ifp->if_timer = 0;
  
  	callout_stop(&sc->rtk_tick_ch);
  
--- 1534,1545 ----
   * Stop the adapter and free any mbufs allocated to the
   * RX and TX lists.
   */
! STATIC void rtk_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
! 	struct rtk_softc *sc = ifp->if_softc;
! 	int i;
  
  	callout_stop(&sc->rtk_tick_ch);
  
***************
*** 1635,1643 ****
  		}
  	}
  
! 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
  
! 	return;
  }
  
  /*
--- 1560,1570 ----
  		}
  	}
  
! 	if (disable)
! 		rtk_disable(sc);
  
! 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 	ifp->if_timer = 0;
  }
  
  /*
***************
*** 1648,1657 ****
  	void			*vsc;
  {
  	struct rtk_softc	*sc = (struct rtk_softc *)vsc;
- 
- 	rtk_stop(sc);
  
! 	return;
  }
  
  STATIC void
--- 1575,1582 ----
  	void			*vsc;
  {
  	struct rtk_softc	*sc = (struct rtk_softc *)vsc;
  
! 	rtk_stop(&sc->ethercom.ec_if, 0);
  }
  
  STATIC void
Index: dev/ic/smc83c170.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/smc83c170.c,v
retrieving revision 1.33
diff -c -r1.33 smc83c170.c
*** dev/ic/smc83c170.c	2000/10/01 23:32:42	1.33
--- dev/ic/smc83c170.c	2000/10/04 04:43:00
***************
*** 87,99 ****
  void	epic_start __P((struct ifnet *));
  void	epic_watchdog __P((struct ifnet *));
  int	epic_ioctl __P((struct ifnet *, u_long, caddr_t));
  
  void	epic_shutdown __P((void *));
  
  void	epic_reset __P((struct epic_softc *));
- int	epic_init __P((struct epic_softc *));
  void	epic_rxdrain __P((struct epic_softc *));
- void	epic_stop __P((struct epic_softc *, int));
  int	epic_add_rxbuf __P((struct epic_softc *, int));
  void	epic_read_eeprom __P((struct epic_softc *, int, int, u_int16_t *));
  void	epic_set_mchash __P((struct epic_softc *));
--- 87,99 ----
  void	epic_start __P((struct ifnet *));
  void	epic_watchdog __P((struct ifnet *));
  int	epic_ioctl __P((struct ifnet *, u_long, caddr_t));
+ int	epic_init __P((struct ifnet *));
+ void	epic_stop __P((struct ifnet *, int));
  
  void	epic_shutdown __P((void *));
  
  void	epic_reset __P((struct epic_softc *));
  void	epic_rxdrain __P((struct epic_softc *));
  int	epic_add_rxbuf __P((struct epic_softc *, int));
  void	epic_read_eeprom __P((struct epic_softc *, int, int, u_int16_t *));
  void	epic_set_mchash __P((struct epic_softc *));
***************
*** 253,258 ****
--- 253,260 ----
  	ifp->if_ioctl = epic_ioctl;
  	ifp->if_start = epic_start;
  	ifp->if_watchdog = epic_watchdog;
+ 	ifp->if_init = epic_init;
+ 	ifp->if_stop = epic_stop;
  
  	/*
  	 * Attach the interface.
***************
*** 310,316 ****
  {
  	struct epic_softc *sc = arg;
  
! 	epic_stop(sc, 1);
  }
  
  /*
--- 312,318 ----
  {
  	struct epic_softc *sc = arg;
  
! 	epic_stop(&sc->sc_ethercom.ec_if, 1);
  }
  
  /*
***************
*** 502,508 ****
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) epic_init(sc);
  }
  
  /*
--- 504,510 ----
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) epic_init(ifp);
  }
  
  /*
***************
*** 517,598 ****
  {
  	struct epic_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFADDR:
! 		ifp->if_flags |= IFF_UP;
! 
! 		switch (ifa->ifa_addr->sa_family) {
! #ifdef INET
! 		case AF_INET:
! 			if ((error = epic_init(sc)) != 0)
! 				break;
! 			arp_ifinit(ifp, ifa);
! 			break;
! #endif /* INET */
! #ifdef NS
! 		case AF_NS:
! 		    {
! 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
! 
! 			if (ns_nullhost(*ina))
! 				ina->x_host = *(union ns_host *)
! 				    LLADDR(ifp->if_sadl);
! 			else
! 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
! 				    ifp->if_addrlen);
! 			/* Set new address. */
! 			error = epic_init(sc);
! 			break;
! 		    }
! #endif /* NS */
! 		default:
! 			error = epic_init(sc);
! 			break;
! 		}
! 		break;
! 
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			epic_stop(sc, 1);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 			   (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interfase it marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			error = epic_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up changes in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			error = epic_init(sc);
! 		}
  		break;
  
! 	case SIOCADDMULTI:
! 	case SIOCDELMULTI:
! 		error = (cmd == SIOCADDMULTI) ?
! 		    ether_addmulti(ifr, &sc->sc_ethercom) :
! 		    ether_delmulti(ifr, &sc->sc_ethercom);
! 
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
--- 519,536 ----
  {
  	struct epic_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFMEDIA:
! 	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
! 	default:
! 		error = ether_ioctl(ifp, cmd, data);
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
***************
*** 604,618 ****
  			error = 0;
  		}
  		break;
- 
- 	case SIOCSIFMEDIA:
- 	case SIOCGIFMEDIA:
- 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
- 		break;
- 
- 	default:
- 		error = EINVAL;
- 		break;
  	}
  
  	splx(s);
--- 542,547 ----
***************
*** 867,873 ****
  		else
  			printf("%s: unknown fatal error\n",
  			    sc->sc_dev.dv_xname);
! 		(void) epic_init(sc);
  	}
  
  	/*
--- 796,802 ----
  		else
  			printf("%s: unknown fatal error\n",
  			    sc->sc_dev.dv_xname);
! 		(void) epic_init(ifp);
  	}
  
  	/*
***************
*** 937,948 ****
   * Initialize the interface.  Must be called at splnet().
   */
  int
! epic_init(sc)
! 	struct epic_softc *sc;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	u_int8_t *enaddr = LLADDR(ifp->if_sadl);
  	struct epic_txdesc *txd;
  	struct epic_descsoft *ds;
--- 866,877 ----
   * Initialize the interface.  Must be called at splnet().
   */
  int
! epic_init(ifp)
! 	struct ifnet *ifp;
  {
+ 	struct epic_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	u_int8_t *enaddr = LLADDR(ifp->if_sadl);
  	struct epic_txdesc *txd;
  	struct epic_descsoft *ds;
***************
*** 952,958 ****
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	epic_stop(sc, 0);
  
  	/*
  	 * Reset the EPIC to a known state.
--- 881,887 ----
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	epic_stop(ifp, 0);
  
  	/*
  	 * Reset the EPIC to a known state.
***************
*** 1118,1130 ****
   * Stop transmission on the interface.
   */
  void
! epic_stop(sc, drain)
! 	struct epic_softc *sc;
! 	int drain;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct epic_descsoft *ds;
  	u_int32_t reg;
  	int i;
--- 1047,1059 ----
   * Stop transmission on the interface.
   */
  void
! epic_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
+ 	struct epic_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	struct epic_descsoft *ds;
  	u_int32_t reg;
  	int i;
***************
*** 1165,1176 ****
  		}
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		epic_rxdrain(sc);
- 	}
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
--- 1094,1101 ----
  		}
  	}
  
! 	if (disable)
  		epic_rxdrain(sc);
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
Index: dev/ic/tulip.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/tulip.c,v
retrieving revision 1.74
diff -c -r1.74 tulip.c
*** dev/ic/tulip.c	2000/10/03 23:35:55	1.74
--- dev/ic/tulip.c	2000/10/04 04:43:03
***************
*** 107,119 ****
  void	tlp_start __P((struct ifnet *));
  void	tlp_watchdog __P((struct ifnet *));
  int	tlp_ioctl __P((struct ifnet *, u_long, caddr_t));
  
  void	tlp_shutdown __P((void *));
  
  void	tlp_reset __P((struct tulip_softc *));
- int	tlp_init __P((struct tulip_softc *));
  void	tlp_rxdrain __P((struct tulip_softc *));
- void	tlp_stop __P((struct tulip_softc *, int));
  int	tlp_add_rxbuf __P((struct tulip_softc *, int));
  void	tlp_idle __P((struct tulip_softc *, u_int32_t));
  void	tlp_srom_idle __P((struct tulip_softc *));
--- 107,119 ----
  void	tlp_start __P((struct ifnet *));
  void	tlp_watchdog __P((struct ifnet *));
  int	tlp_ioctl __P((struct ifnet *, u_long, caddr_t));
+ int	tlp_init __P((struct ifnet *));
+ void	tlp_stop __P((struct ifnet *, int));
  
  void	tlp_shutdown __P((void *));
  
  void	tlp_reset __P((struct tulip_softc *));
  void	tlp_rxdrain __P((struct tulip_softc *));
  int	tlp_add_rxbuf __P((struct tulip_softc *, int));
  void	tlp_idle __P((struct tulip_softc *, u_int32_t));
  void	tlp_srom_idle __P((struct tulip_softc *));
***************
*** 501,506 ****
--- 501,508 ----
  	ifp->if_ioctl = tlp_ioctl;
  	ifp->if_start = tlp_start;
  	ifp->if_watchdog = tlp_watchdog;
+ 	ifp->if_init = tlp_init;
+ 	ifp->if_stop = tlp_stop;
  
  	/*
  	 * We can support 802.1Q VLAN-sized frames.
***************
*** 676,682 ****
  {
  	struct tulip_softc *sc = arg;
  
! 	tlp_stop(sc, 1);
  }
  
  /*
--- 678,684 ----
  {
  	struct tulip_softc *sc = arg;
  
! 	tlp_stop(&sc->sc_ethercom.ec_if, 1);
  }
  
  /*
***************
*** 960,966 ****
  	else
  		printf("%s: spurious watchdog timeout\n", sc->sc_dev.dv_xname);
  
! 	(void) tlp_init(sc);
  
  	/* Try to get more packets going. */
  	tlp_start(ifp);
--- 962,968 ----
  	else
  		printf("%s: spurious watchdog timeout\n", sc->sc_dev.dv_xname);
  
! 	(void) tlp_init(ifp);
  
  	/* Try to get more packets going. */
  	tlp_start(ifp);
***************
*** 979,1088 ****
  {
  	struct tulip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
  
  	switch (cmd) {
- 	case SIOCSIFADDR:
- 		if ((error = tlp_enable(sc)) != 0)
- 			break;
- 		ifp->if_flags |= IFF_UP;
- 
- 		switch (ifa->ifa_addr->sa_family) {
- #ifdef INET
- 		case AF_INET:
- 			if ((error = tlp_init(sc)) != 0)
- 				break;
- 			arp_ifinit(ifp, ifa);
- 			break;
- #endif /* INET */
- #ifdef NS
- 		case AF_NS:
- 		    {
- 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
- 
- 			if (ns_nullhost(*ina))
- 				ina->x_host = *(union ns_host *)
- 				    LLADDR(ifp->if_sadl);
- 			else
- 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
- 				    ifp->if_addrlen);
- 			/* Set new address. */
- 			error = tlp_init(sc);
- 			break;
- 		    }
- #endif /* NS */
- 		default:
- 			error = tlp_init(sc);
- 			break;
- 		}
- 		break;
- 
- 	case SIOCSIFMTU:
- 		if (ifr->ifr_mtu > ETHERMTU)
- 			error = EINVAL;
- 		else
- 			ifp->if_mtu = ifr->ifr_mtu;
- 		break;
- 
- 	case SIOCSIFFLAGS:
- #ifdef TLP_STATS
- 		if (ifp->if_flags & IFF_DEBUG)
- 			tlp_print_stats(sc);
- #endif
- 		if ((ifp->if_flags & IFF_UP) == 0 &&
- 		    (ifp->if_flags & IFF_RUNNING) != 0) {
- 			/*
- 			 * If interface is marked down and it is running, then
- 			 * stop it.
- 			 */
- 			tlp_stop(sc, 1);
- 			tlp_disable(sc);
- 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
- 			   (ifp->if_flags & IFF_RUNNING) == 0) {
- 			/*
- 			 * If interfase it marked up and it is stopped, then
- 			 * start it.
- 			 */
- 			if ((error = tlp_enable(sc)) != 0)
- 				break;
- 			error = tlp_init(sc);
- 		} else if ((ifp->if_flags & IFF_UP) != 0) {
- 			/*
- 			 * Reset the interface to pick up changes in any other
- 			 * flags that affect the hardware state.
- 			 */
- 			if ((error = tlp_enable(sc)) != 0)
- 				break;
- 			error = tlp_init(sc);
- 		}
- 		break;
- 
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		error = (cmd == SIOCADDMULTI) ?
- 		    ether_addmulti(ifr, &sc->sc_ethercom) :
- 		    ether_delmulti(ifr, &sc->sc_ethercom);
- 
- 		if (TULIP_IS_ENABLED(sc) && error == ENETRESET) {
- 			/*
- 			 * Multicast list has changed.  Set the filter
- 			 * accordingly.
- 			 */
- 			(*sc->sc_filter_setup)(sc);
- 			error = 0;
- 		}
- 		break;
- 
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
  	default:
! 		error = EINVAL;
  		break;
  	}
  
--- 981,1008 ----
  {
  	struct tulip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
  	switch (cmd) {
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
  	default:
! 		error = ether_ioctl(ifp, cmd, data);
! 		if (error == ENETRESET) {
! 			if (TULIP_IS_ENABLED(sc)) {
! 				/*
! 				 * Multicast list has changed.  Set the
! 				 * hardware filter accordingly.
! 				 */
! 				(*sc->sc_filter_setup)(sc);
! 			}
! 			error = 0;
! 		}
  		break;
  	}
  
***************
*** 1219,1225 ****
  			if (status & STATUS_RPS)
  				printf("%s: receive process stopped\n",
  				    sc->sc_dev.dv_xname);
! 			(void) tlp_init(sc);
  			break;
  		}
  
--- 1139,1145 ----
  			if (status & STATUS_RPS)
  				printf("%s: receive process stopped\n",
  				    sc->sc_dev.dv_xname);
! 			(void) tlp_init(ifp);
  			break;
  		}
  
***************
*** 1244,1250 ****
  			}
  			printf("%s: fatal system error: %s\n",
  			    sc->sc_dev.dv_xname, str);
! 			(void) tlp_init(sc);
  			break;
  		}
  
--- 1164,1170 ----
  			}
  			printf("%s: fatal system error: %s\n",
  			    sc->sc_dev.dv_xname, str);
! 			(void) tlp_init(ifp);
  			break;
  		}
  
***************
*** 1322,1328 ****
  		    (TDSTAT_Rx_FS|TDSTAT_Rx_LS)) {
  			printf("%s: incoming packet spilled, resetting\n",
  			    sc->sc_dev.dv_xname);
! 			(void) tlp_init(sc);
  			return;
  		}
  
--- 1242,1248 ----
  		    (TDSTAT_Rx_FS|TDSTAT_Rx_LS)) {
  			printf("%s: incoming packet spilled, resetting\n",
  			    sc->sc_dev.dv_xname);
! 			(void) tlp_init(ifp);
  			return;
  		}
  
***************
*** 1633,1655 ****
  }
  
  /*
!  * tlp_init:
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! tlp_init(sc)
! 	struct tulip_softc *sc;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct tulip_txsoft *txs;
  	struct tulip_rxsoft *rxs;
  	int i, error = 0;
  
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	tlp_stop(sc, 0);
  
  	/*
  	 * Initialize `opmode' to 0, and call the pre-init routine, if
--- 1553,1578 ----
  }
  
  /*
!  * tlp_init:		[ ifnet interface function ]
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! tlp_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct tulip_softc *sc = ifp->if_softc;
  	struct tulip_txsoft *txs;
  	struct tulip_rxsoft *rxs;
  	int i, error = 0;
  
+ 	if ((error = tlp_enable(sc)) != 0)
+ 		goto out;
+ 
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	tlp_stop(ifp, 0);
  
  	/*
  	 * Initialize `opmode' to 0, and call the pre-init routine, if
***************
*** 1938,1945 ****
  	ifp->if_flags &= ~IFF_OACTIVE;
  
   out:
! 	if (error)
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
  	return (error);
  }
  
--- 1861,1871 ----
  	ifp->if_flags &= ~IFF_OACTIVE;
  
   out:
! 	if (error) {
! 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 		ifp->if_timer = 0;
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
+ 	}
  	return (error);
  }
  
***************
*** 1996,2008 ****
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		tlp_stop(sc, 0);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		tlp_init(sc);
  	}
  	splx(s);
  }
--- 1922,1934 ----
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		tlp_stop(ifp, 0);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		tlp_init(ifp);
  	}
  	splx(s);
  }
***************
*** 2030,2045 ****
  }
  
  /*
!  * tlp_stop:
   *
   *	Stop transmission on the interface.
   */
  void
! tlp_stop(sc, drain)
! 	struct tulip_softc *sc;
! 	int drain;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct tulip_txsoft *txs;
  
  	if (sc->sc_tick != NULL) {
--- 1956,1971 ----
  }
  
  /*
!  * tlp_stop:		[ ifnet interface function ]
   *
   *	Stop transmission on the interface.
   */
  void
! tlp_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
! 	struct tulip_softc *sc = ifp->if_softc;
  	struct tulip_txsoft *txs;
  
  	if (sc->sc_tick != NULL) {
***************
*** 2074,2084 ****
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		tlp_rxdrain(sc);
  	}
  
  	sc->sc_flags &= ~(TULIPF_WANT_SETUP|TULIPF_DOING_SETUP);
--- 2000,2008 ----
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (disable) {
  		tlp_rxdrain(sc);
+ 		tlp_disable(sc);
  	}
  
  	sc->sc_flags &= ~(TULIPF_WANT_SETUP|TULIPF_DOING_SETUP);
***************
*** 5018,5024 ****
  	 * time through.
  	 */
  	if (TULIP_MEDIA_NEEDSRESET(sc, tm->tm_opmode))
! 		return (tlp_init(sc));
  
  	return ((*tm->tm_set)(sc));
  }
--- 4942,4948 ----
  	 * time through.
  	 */
  	if (TULIP_MEDIA_NEEDSRESET(sc, tm->tm_opmode))
! 		return (tlp_init(&sc->sc_ethercom.ec_if));
  
  	return ((*tm->tm_set)(sc));
  }
Index: dev/pci/if_sip.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_sip.c,v
retrieving revision 1.16
diff -c -r1.16 if_sip.c
*** dev/pci/if_sip.c	2000/10/01 23:32:43	1.16
--- dev/pci/if_sip.c	2000/10/04 04:43:05
***************
*** 255,266 ****
  void	sip_start __P((struct ifnet *));
  void	sip_watchdog __P((struct ifnet *));
  int	sip_ioctl __P((struct ifnet *, u_long, caddr_t));
  
  void	sip_shutdown __P((void *));
  
  void	sip_reset __P((struct sip_softc *));
- int	sip_init __P((struct sip_softc *));
- void	sip_stop __P((struct sip_softc *, int));
  void	sip_rxdrain __P((struct sip_softc *));
  int	sip_add_rxbuf __P((struct sip_softc *, int));
  void	sip_read_eeprom __P((struct sip_softc *, int, int, u_int16_t *));
--- 255,266 ----
  void	sip_start __P((struct ifnet *));
  void	sip_watchdog __P((struct ifnet *));
  int	sip_ioctl __P((struct ifnet *, u_long, caddr_t));
+ int	sip_init __P((struct ifnet *));
+ void	sip_stop __P((struct ifnet *, int));
  
  void	sip_shutdown __P((void *));
  
  void	sip_reset __P((struct sip_softc *));
  void	sip_rxdrain __P((struct sip_softc *));
  int	sip_add_rxbuf __P((struct sip_softc *, int));
  void	sip_read_eeprom __P((struct sip_softc *, int, int, u_int16_t *));
***************
*** 580,585 ****
--- 580,587 ----
  	ifp->if_ioctl = sip_ioctl;
  	ifp->if_start = sip_start;
  	ifp->if_watchdog = sip_watchdog;
+ 	ifp->if_init = sip_init;
+ 	ifp->if_stop = sip_stop;
  
  	/*
  	 * Attach the interface.
***************
*** 639,645 ****
  {
  	struct sip_softc *sc = arg;
  
! 	sip_stop(sc, 1);
  }
  
  /*
--- 641,647 ----
  {
  	struct sip_softc *sc = arg;
  
! 	sip_stop(&sc->sc_ethercom.ec_if, 1);
  }
  
  /*
***************
*** 868,874 ****
  		ifp->if_oerrors++;
  
  		/* Reset the interface. */
! 		(void) sip_init(sc);
  	} else if (ifp->if_flags & IFF_DEBUG)
  		printf("%s: recovered from device timeout\n",
  		    sc->sc_dev.dv_xname);
--- 870,876 ----
  		ifp->if_oerrors++;
  
  		/* Reset the interface. */
! 		(void) sip_init(ifp);
  	} else if (ifp->if_flags & IFF_DEBUG)
  		printf("%s: recovered from device timeout\n",
  		    sc->sc_dev.dv_xname);
***************
*** 890,970 ****
  {
  	struct sip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFADDR:
! 		ifp->if_flags |= IFF_UP;
! 
! 		switch (ifa->ifa_addr->sa_family) {
! #ifdef INET
! 		case AF_INET:
! 			if ((error = sip_init(sc)) != 0)
! 				break;
! 			arp_ifinit(ifp, ifa);
! 			break;
! #endif /* INET */
! #ifdef NS
! 		case AF_NS:
! 		    {
! 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
! 
! 			if (ns_nullhost(*ina))
! 				ina->x_host = *(union ns_host *)
! 				    LLADDR(ifp->if_sadl);
! 			else
! 				memcpy(LLADDR(ifp->if_sadl),
! 				    ina->x_host.c_host, ifp->if_addrlen);
! 			error = sip_init(sc);
! 			break;
! 		    }
! #endif /* NS */
! 		default:
! 			error = sip_init(sc);
! 			break;
! 		}
! 		break;
! 
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			sip_stop(sc, 1);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 			   (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interfase it marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			error = sip_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up changes in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			error = sip_init(sc);
! 		}
  		break;
- 	
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		error = (cmd == SIOCADDMULTI) ?
- 		    ether_addmulti(ifr, &sc->sc_ethercom) :
- 		    ether_delmulti(ifr, &sc->sc_ethercom);
  
  		if (error == ENETRESET) { 
  			/*
  			 * Multicast list has changed; set the hardware filter
--- 892,909 ----
  {
  	struct sip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFMEDIA:
! 	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
+ 	default:
+ 		error = ether_ioctl(ifp, cmd, data);
  		if (error == ENETRESET) { 
  			/*
  			 * Multicast list has changed; set the hardware filter
***************
*** 974,988 ****
  			error = 0;
  		}
  		break;
- 
- 	case SIOCSIFMEDIA:
- 	case SIOCGIFMEDIA:
- 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
- 		break;
- 
- 	default:
- 		error = EINVAL;
- 		break;
  	}
  
  	/* Try to get more packets going. */
--- 913,918 ----
***************
*** 1055,1063 ****
  					    "threshold to %u bytes\n",
  					    thresh * 32);
  					sc->sc_tx_drain_thresh = thresh;
! 					(void) sip_init(sc);
  				} else {
! 					(void) sip_init(sc);
  					printf("\n");
  				}
  			}
--- 985,993 ----
  					    "threshold to %u bytes\n",
  					    thresh * 32);
  					sc->sc_tx_drain_thresh = thresh;
! 					(void) sip_init(ifp);
  				} else {
! 					(void) sip_init(ifp);
  					printf("\n");
  				}
  			}
***************
*** 1083,1089 ****
  			PRINTERR(ISR_RMABT, "master abort");
  			PRINTERR(ISR_RTABT, "target abort");
  			PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
! 			(void) sip_init(sc);
  #undef PRINTERR
  		}
  	}
--- 1013,1019 ----
  			PRINTERR(ISR_RMABT, "master abort");
  			PRINTERR(ISR_RTABT, "target abort");
  			PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
! 			(void) sip_init(ifp);
  #undef PRINTERR
  		}
  	}
***************
*** 1380,1396 ****
  }
  
  /*
!  * sip_init:
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! sip_init(sc)
! 	struct sip_softc *sc;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct sip_txsoft *txs;
  	struct sip_rxsoft *rxs;
  	struct sip_desc *sipd;
--- 1310,1326 ----
  }
  
  /*
!  * sip_init:		[ ifnet interface function ]
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! sip_init(ifp)
! 	struct ifnet *ifp;
  {
+ 	struct sip_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	struct sip_txsoft *txs;
  	struct sip_rxsoft *rxs;
  	struct sip_desc *sipd;
***************
*** 1400,1406 ****
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	sip_stop(sc, 0);
  
  	/*
  	 * Reset the chip to a known state.
--- 1330,1336 ----
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	sip_stop(ifp, 0);
  
  	/*
  	 * Reset the chip to a known state.
***************
*** 1599,1615 ****
  }
  
  /*
!  * sip_stop:
   *
   *	Stop transmission on the interface.
   */
  void
! sip_stop(sc, drain)
! 	struct sip_softc *sc;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct sip_txsoft *txs;
  	u_int32_t cmdsts = 0;		/* DEBUG */
  
--- 1529,1546 ----
  }
  
  /*
!  * sip_stop:		[ ifnet interface function ]
   *
   *	Stop transmission on the interface.
   */
  void
! sip_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
+ 	struct sip_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	struct sip_txsoft *txs;
  	u_int32_t cmdsts = 0;		/* DEBUG */
  
***************
*** 1657,1668 ****
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		sip_rxdrain(sc);
- 	}
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
--- 1588,1595 ----
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (disable)
  		sip_rxdrain(sc);
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
Index: dev/pci/if_vr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_vr.c,v
retrieving revision 1.38
diff -c -r1.38 if_vr.c
*** dev/pci/if_vr.c	2000/10/01 23:32:44	1.38
--- dev/pci/if_vr.c	2000/10/04 04:43:06
***************
*** 301,308 ****
  static int vr_intr		__P((void *));
  static void vr_start		__P((struct ifnet *));
  static int vr_ioctl		__P((struct ifnet *, u_long, caddr_t));
! static int vr_init		__P((struct vr_softc *));
! static void vr_stop		__P((struct vr_softc *, int));
  static void vr_rxdrain		__P((struct vr_softc *));
  static void vr_watchdog		__P((struct ifnet *));
  static void vr_tick		__P((void *));
--- 301,308 ----
  static int vr_intr		__P((void *));
  static void vr_start		__P((struct ifnet *));
  static int vr_ioctl		__P((struct ifnet *, u_long, caddr_t));
! static int vr_init		__P((struct ifnet *));
! static void vr_stop		__P((struct ifnet *, int));
  static void vr_rxdrain		__P((struct vr_softc *));
  static void vr_watchdog		__P((struct ifnet *));
  static void vr_tick		__P((void *));
***************
*** 856,862 ****
  
  	/* Suppress unwanted interrupts. */
  	if ((ifp->if_flags & IFF_UP) == 0) {
! 		vr_stop(sc, 1);
  		return (0);
  	}
  
--- 856,862 ----
  
  	/* Suppress unwanted interrupts. */
  	if ((ifp->if_flags & IFF_UP) == 0) {
! 		vr_stop(ifp, 1);
  		return (0);
  	}
  
***************
*** 906,912 ****
  			printf("%s: PCI bus error\n", sc->vr_dev.dv_xname);
  			/* vr_init() calls vr_start() */
  			dotx = 0;
! 			(void) vr_init(sc);
  		}
  	}
  
--- 906,912 ----
  			printf("%s: PCI bus error\n", sc->vr_dev.dv_xname);
  			/* vr_init() calls vr_start() */
  			dotx = 0;
! 			(void) vr_init(ifp);
  		}
  	}
  
***************
*** 1089,1104 ****
   * Initialize the interface.  Must be called at splnet.
   */
  static int
! vr_init(sc)
! 	struct vr_softc *sc;
  {
! 	struct ifnet *ifp = &sc->vr_ec.ec_if;
  	struct vr_desc *d;
  	struct vr_descsoft *ds;
  	int i, error = 0;
  
  	/* Cancel pending I/O. */
! 	vr_stop(sc, 0);
  
  	/* Reset the Rhine to a known state. */
  	vr_reset(sc);
--- 1089,1104 ----
   * Initialize the interface.  Must be called at splnet.
   */
  static int
! vr_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct vr_softc *sc = ifp->if_softc;
  	struct vr_desc *d;
  	struct vr_descsoft *ds;
  	int i, error = 0;
  
  	/* Cancel pending I/O. */
! 	vr_stop(ifp, 0);
  
  	/* Reset the Rhine to a known state. */
  	vr_reset(sc);
***************
*** 1228,1300 ****
  {
  	struct vr_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
- 	struct ifaddr *ifa = (struct ifaddr *)data;
  	int s, error = 0;
  
  	s = splnet();
  
  	switch (command) {
! 	case SIOCSIFADDR:
! 		ifp->if_flags |= IFF_UP;
! 
! 		switch (ifa->ifa_addr->sa_family) {
! #ifdef INET
! 		case AF_INET:
! 			if ((error = vr_init(sc)) != 0)
! 				break;
! 			arp_ifinit(ifp, ifa);
! 			break;
! #endif /* INET */
! 		default:
! 			error = vr_init(sc);
! 			break;
! 		}
! 		break;
! 
! 	case SIOCGIFADDR:
! 		bcopy((caddr_t) sc->vr_enaddr,
! 			(caddr_t) ((struct sockaddr *)&ifr->ifr_data)->sa_data,
! 			ETHER_ADDR_LEN);
! 		break;
! 
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			vr_stop(sc, 1);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 			   (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interface is marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			error = vr_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up changes in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			error = vr_init(sc);
! 		}
  		break;
- 
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		if (command == SIOCADDMULTI)
- 			error = ether_addmulti(ifr, &sc->vr_ec);
- 		else
- 			error = ether_delmulti(ifr, &sc->vr_ec);
  
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
--- 1228,1245 ----
  {
  	struct vr_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
  	int s, error = 0;
  
  	s = splnet();
  
  	switch (command) {
! 	case SIOCGIFMEDIA:
! 	case SIOCSIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->vr_mii.mii_media, command);
  		break;
  
+ 	default:
+ 		error = ether_ioctl(ifp, command, data);
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
***************
*** 1304,1318 ****
  			error = 0;
  		}
  		break;
- 
- 	case SIOCGIFMEDIA:
- 	case SIOCSIFMEDIA:
- 		error = ifmedia_ioctl(ifp, ifr, &sc->vr_mii.mii_media, command);
- 		break;
- 
- 	default:
- 		error = EINVAL;
- 		break;
  	}
  
  	splx(s);
--- 1249,1254 ----
***************
*** 1328,1334 ****
  	printf("%s: device timeout\n", sc->vr_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) vr_init(sc);
  }
  
  /*
--- 1264,1270 ----
  	printf("%s: device timeout\n", sc->vr_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) vr_init(ifp);
  }
  
  /*
***************
*** 1373,1384 ****
   * transmit lists.
   */
  static void
! vr_stop(sc, drain)
! 	struct vr_softc *sc;
! 	int drain;
  {
  	struct vr_descsoft *ds;
- 	struct ifnet *ifp;
  	int i;
  
  	/* Cancel one second timer. */
--- 1309,1320 ----
   * transmit lists.
   */
  static void
! vr_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
+ 	struct vr_softc *sc = ifp->if_softc;
  	struct vr_descsoft *ds;
  	int i;
  
  	/* Cancel one second timer. */
***************
*** 1408,1419 ****
  		}
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		vr_rxdrain(sc);
- 	}
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
--- 1344,1351 ----
  		}
  	}
  
! 	if (disable)
  		vr_rxdrain(sc);
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
***************
*** 1469,1475 ****
  {
  	struct vr_softc *sc = (struct vr_softc *)arg;
  
! 	vr_stop(sc, 1);
  }
  
  /*
--- 1401,1407 ----
  {
  	struct vr_softc *sc = (struct vr_softc *)arg;
  
! 	vr_stop(&sc->vr_ec.ec_if, 1);
  }
  
  /*
***************
*** 1694,1699 ****
--- 1626,1633 ----
  	ifp->if_ioctl = vr_ioctl;
  	ifp->if_start = vr_start;
  	ifp->if_watchdog = vr_watchdog;
+ 	ifp->if_init = vr_init;
+ 	ifp->if_stop = vr_stop;
  	bcopy(sc->vr_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
  
  	/*

--tjCHc7DPkfUGtrlw--

From thorpej@zembu.com Fri Oct 06 22:12:52 2000
  by mail.netbsd.org with SMTP; 6 Oct 2000 22:12:52 -0000
	id AE059D221; Fri,  6 Oct 2000 15:12:50 -0700 (PDT)
Date: Tue, 3 Oct 2000 22:27:05 -0700
From: Jason R Thorpe <thorpej@zembu.com>
To: tech-net@netbsd.org
Subject: ether_ioctl()
Message-ID: <20001003222705.H712@dr-evil.shagadelic.org>
Reply-To: thorpej@zembu.com
Mail-Followup-To: Jason R Thorpe <thorpej@zembu.com>, tech-net@netbsd.org
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="tjCHc7DPkfUGtrlw"
Content-Disposition: inline
User-Agent: Mutt/1.2i
Organization: Zembu Labs, Inc.
Resent-From: thorpej@dr-evil.z.zembu.com
Resent-Date: Fri, 6 Oct 2000 15:12:50 -0700
Resent-To: tech-net@netbsd.org
Resent-Message-Id: <20001006221250.AE059D221@dr-evil.shagadelic.org>
Resent-Sender: thorpej@zembu.com


--tjCHc7DPkfUGtrlw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

I finally got around to implementing this in a sane way for the
NetBSD network stack.  Attached are ether_ioctl() itself and
changes for several network drivers to use it.

Note that it changes (*if_reset)() to (*if_init)() and adds
an (*if_stop)(), which also takes an argument indicating that
the interface should be disabled (Rx buffers freed, power
removed from the device, etc.).

There's also an unrelated change in there (if_bridge) that is
part of somthing else I'm working on, but if I'm changing the
ifnet, do it once, not N times, right? :-)

Feedback soon, please.

-- 
        -- Jason R. Thorpe <thorpej@zembu.com>

--tjCHc7DPkfUGtrlw
Content-Type: text/plain; charset=us-ascii
Content-Description: ether_ioctl.diff
Content-Disposition: attachment; filename="ether_ioctl.diff"

Index: net/if.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if.c,v
retrieving revision 1.71
diff -c -r1.71 if.c
*** net/if.c	2000/10/01 23:16:07	1.71
--- net/if.c	2000/10/04 05:23:29
***************
*** 213,219 ****
  }
  
  int
! if_nullreset(ifp)
  	struct ifnet *ifp;
  {
  
--- 213,219 ----
  }
  
  int
! if_nullinit(ifp)
  	struct ifnet *ifp;
  {
  
***************
*** 221,226 ****
--- 221,235 ----
  }
  
  void
+ if_nullstop(ifp, disable)
+ 	struct ifnet *ifp;
+ 	int disable;
+ {
+ 
+ 	/* Nothing. */
+ }
+ 
+ void
  if_nullwatchdog(ifp)
  	struct ifnet *ifp;
  {
***************
*** 356,362 ****
  	ifp->if_input	 = if_nullinput;
  	ifp->if_start	 = if_nullstart;
  	ifp->if_ioctl	 = if_nullioctl;
! 	ifp->if_reset	 = if_nullreset;
  	ifp->if_watchdog = if_nullwatchdog;
  	ifp->if_drain	 = if_nulldrain;
  
--- 365,372 ----
  	ifp->if_input	 = if_nullinput;
  	ifp->if_start	 = if_nullstart;
  	ifp->if_ioctl	 = if_nullioctl;
! 	ifp->if_init	 = if_nullinit;
! 	ifp->if_stop	 = if_nullstop;
  	ifp->if_watchdog = if_nullwatchdog;
  	ifp->if_drain	 = if_nulldrain;
  
Index: net/if.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if.h,v
retrieving revision 1.53
diff -c -r1.53 if.h
*** net/if.h	2000/07/20 18:40:27	1.53
--- net/if.h	2000/10/04 05:23:30
***************
*** 240,247 ****
  		__P((struct ifnet *));
  	int	(*if_ioctl)		/* ioctl routine */
  		__P((struct ifnet *, u_long, caddr_t));
! 	int	(*if_reset)		/* XXX bus reset routine */
  		__P((struct ifnet *));
  	void	(*if_watchdog)		/* timer routine */
  		__P((struct ifnet *));
  	void	(*if_drain)		/* routine to release resources */
--- 240,249 ----
  		__P((struct ifnet *));
  	int	(*if_ioctl)		/* ioctl routine */
  		__P((struct ifnet *, u_long, caddr_t));
! 	int	(*if_init)		/* init routine */
  		__P((struct ifnet *));
+ 	void	(*if_stop)		/* stop routine */
+ 		__P((struct ifnet *, int));
  	void	(*if_watchdog)		/* timer routine */
  		__P((struct ifnet *));
  	void	(*if_drain)		/* routine to release resources */
***************
*** 256,261 ****
--- 258,264 ----
  	struct	sockaddr_dl *if_sadl;	/* pointer to our sockaddr_dl */
  	u_int8_t *if_broadcastaddr;	/* linklevel broadcast bytestring */
  	struct ifprefix *if_prefixlist; /* linked list of prefixes per if */
+ 	void *if_bridge;		/* bridge glue */
  };
  #define	if_mtu		if_data.ifi_mtu
  #define	if_type		if_data.ifi_type
***************
*** 628,634 ****
  void	if_nullinput __P((struct ifnet *, struct mbuf *));
  void	if_nullstart __P((struct ifnet *));
  int	if_nullioctl __P((struct ifnet *, u_long, caddr_t));
! int	if_nullreset __P((struct ifnet *));
  void	if_nullwatchdog __P((struct ifnet *));
  void	if_nulldrain __P((struct ifnet *));
  #else
--- 631,638 ----
  void	if_nullinput __P((struct ifnet *, struct mbuf *));
  void	if_nullstart __P((struct ifnet *));
  int	if_nullioctl __P((struct ifnet *, u_long, caddr_t));
! int	if_nullinit __P((struct ifnet *));
! void	if_nullstop __P((struct ifnet *, int));
  void	if_nullwatchdog __P((struct ifnet *));
  void	if_nulldrain __P((struct ifnet *));
  #else
Index: net/if_ether.h
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_ether.h,v
retrieving revision 1.19
diff -c -r1.19 if_ether.h
*** net/if_ether.h	2000/10/03 23:33:38	1.19
--- net/if_ether.h	2000/10/04 04:42:55
***************
*** 161,166 ****
--- 161,167 ----
  extern u_int8_t ether_ipmulticast_min[ETHER_ADDR_LEN];
  extern u_int8_t ether_ipmulticast_max[ETHER_ADDR_LEN];
  
+ int	ether_ioctl(struct ifnet *, u_long, caddr_t);
  int	ether_addmulti (struct ifreq *, struct ethercom *);
  int	ether_delmulti (struct ifreq *, struct ethercom *);
  int	ether_changeaddr (struct ifreq *, struct ethercom *);
Index: net/if_ethersubr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/if_ethersubr.c,v
retrieving revision 1.64
diff -c -r1.64 if_ethersubr.c
*** net/if_ethersubr.c	2000/10/03 23:50:52	1.64
--- net/if_ethersubr.c	2000/10/04 04:42:55
***************
*** 1088,1090 ****
--- 1088,1183 ----
  	 */
  	return (ENETRESET);
  }
+ 
+ /*
+  * Common ioctls for Ethernet interfaces.  Note, we must be
+  * called at splnet().
+  */
+ int
+ ether_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+ {
+ 	struct ethercom *ec = (void *) ifp;
+ 	struct ifreq *ifr = (struct ifreq *)data;
+ 	struct ifaddr *ifa = (struct ifaddr *)data;
+ 	int error = 0;
+ 
+ 	switch (cmd) {
+ 	case SIOCSIFADDR:
+ 		ifp->if_flags |= IFF_UP;
+ 		switch (ifa->ifa_addr->sa_family) {
+ #ifdef INET
+ 		case AF_INET:
+ 			if ((error = (*ifp->if_init)(ifp)) != 0)
+ 				break;
+ 			arp_ifinit(ifp, ifa);
+ 			break;
+ #endif /* INET */
+ #ifdef NS
+ 		case AF_NS:
+ 		    {
+ 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
+ 
+ 			if (ns_nullhost(*ina))
+ 				ina->x_host = *(union ns_host *)
+ 				    LLADDR(ifp->if_sadl);
+ 			else
+ 				memcpy(LLADDR(ifp->if_sadl),
+ 				    ina->x_host.c_host, ifp->if_addrlen);
+ 			/* Set new address. */
+ 			error = (*ifp->if_init)(ifp);
+ 			break;
+ 		    }
+ #endif /* NS */
+ 		default:
+ 			error = (*ifp->if_init)(ifp);
+ 			break;
+ 		}
+ 		break;
+ 
+ 	case SIOCGIFADDR:
+ 		memcpy(((struct sockaddr *)&ifr->ifr_data)->sa_data,
+ 		    LLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
+ 		break;
+ 
+ 	case SIOCSIFMTU:
+ 		if (ifr->ifr_mtu > ETHERMTU)
+ 			error = EINVAL;
+ 		else
+ 			ifp->if_mtu = ifr->ifr_mtu;
+ 		break;
+ 
+ 	case SIOCSIFFLAGS:
+ 		if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_RUNNING) {
+ 			/*
+ 			 * If interface is marked down and it is running,
+ 			 * then stop and disable it.
+ 			 */
+ 			(*ifp->if_stop)(ifp, 1);
+ 		} else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) == IFF_UP) {
+ 			/*
+ 			 * If interface is marked up and it is stopped, then
+ 			 * start it.
+ 			 */
+ 			error = (*ifp->if_init)(ifp);
+ 		} else if ((ifp->if_flags & IFF_UP) != 0) {
+ 			/*
+ 			 * Reset the interface to pick up changes in any other
+ 			 * flags that affect the hardware state.
+ 			 */
+ 			error = (*ifp->if_init)(ifp);
+ 		}
+ 		break;
+ 
+ 	case SIOCADDMULTI:
+ 	case SIOCDELMULTI:
+ 		error = (cmd == SIOCADDMULTI) ?
+ 		    ether_addmulti(ifr, ec) :
+ 		    ether_delmulti(ifr, ec);
+ 		break;
+ 
+ 	default:
+ 		error = ENOTTY;
+ 	}
+ 
+ 	return (error);
+ }
Index: dev/ic/i82557.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/i82557.c,v
retrieving revision 1.39
diff -c -r1.39 i82557.c
*** dev/ic/i82557.c	2000/10/03 23:35:02	1.39
--- dev/ic/i82557.c	2000/10/04 04:42:58
***************
*** 177,186 ****
  
  void	fxp_start __P((struct ifnet *));
  int	fxp_ioctl __P((struct ifnet *, u_long, caddr_t));
- int	fxp_init __P((struct fxp_softc *));
- void	fxp_rxdrain __P((struct fxp_softc *));
- void	fxp_stop __P((struct fxp_softc *, int));
  void	fxp_watchdog __P((struct ifnet *));
  int	fxp_add_rfabuf __P((struct fxp_softc *, bus_dmamap_t, int));
  int	fxp_mdi_read __P((struct device *, int, int));
  void	fxp_statchg __P((struct device *));
--- 177,187 ----
  
  void	fxp_start __P((struct ifnet *));
  int	fxp_ioctl __P((struct ifnet *, u_long, caddr_t));
  void	fxp_watchdog __P((struct ifnet *));
+ int	fxp_init __P((struct ifnet *));
+ void	fxp_stop __P((struct ifnet *, int));
+ 
+ void	fxp_rxdrain __P((struct fxp_softc *));
  int	fxp_add_rfabuf __P((struct fxp_softc *, bus_dmamap_t, int));
  int	fxp_mdi_read __P((struct device *, int, int));
  void	fxp_statchg __P((struct device *));
***************
*** 331,336 ****
--- 332,339 ----
  	ifp->if_ioctl = fxp_ioctl;
  	ifp->if_start = fxp_start;
  	ifp->if_watchdog = fxp_watchdog;
+ 	ifp->if_init = fxp_init;
+ 	ifp->if_stop = fxp_stop;
  
  	/*
  	 * We can support 802.1Q VLAN-sized frames.
***************
*** 459,465 ****
  	 * Since the system's going to halt shortly, don't bother
  	 * freeing mbufs.
  	 */
! 	fxp_stop(sc, 0);
  }
  /*
   * Power handler routine. Called when the system is transitioning
--- 462,468 ----
  	 * Since the system's going to halt shortly, don't bother
  	 * freeing mbufs.
  	 */
! 	fxp_stop(&sc->sc_ethercom.ec_if, 0);
  }
  /*
   * Power handler routine. Called when the system is transitioning
***************
*** 473,488 ****
  	void *arg;
  {
  	struct fxp_softc *sc = arg;
! 	struct ifnet *ifp;
  	int s;
  
  	s = splnet();
  	if (why != PWR_RESUME)
! 		fxp_stop(sc, 0);
  	else {
- 		ifp = &sc->sc_ethercom.ec_if;
  		if (ifp->if_flags & IFF_UP)
! 			fxp_init(sc);
  	}
  	splx(s);
  }
--- 476,490 ----
  	void *arg;
  {
  	struct fxp_softc *sc = arg;
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	int s;
  
  	s = splnet();
  	if (why != PWR_RESUME)
! 		fxp_stop(ifp, 0);
  	else {
  		if (ifp->if_flags & IFF_UP)
! 			fxp_init(ifp);
  	}
  	splx(s);
  }
***************
*** 1060,1066 ****
  				 * If we want a re-init, do that now.
  				 */
  				if (sc->sc_flags & FXPF_WANTINIT)
! 					(void) fxp_init(sc);
  			}
  
  			/*
--- 1062,1068 ----
  				 * If we want a re-init, do that now.
  				 */
  				if (sc->sc_flags & FXPF_WANTINIT)
! 					(void) fxp_init(ifp);
  			}
  
  			/*
***************
*** 1139,1145 ****
  	 * speed transition).
  	 */
  	if (sc->sc_rxidle > FXP_MAX_RX_IDLE) {
! 		(void) fxp_init(sc);
  		splx(s);
  		return;
  	}
--- 1141,1147 ----
  	 * speed transition).
  	 */
  	if (sc->sc_rxidle > FXP_MAX_RX_IDLE) {
! 		(void) fxp_init(ifp);
  		splx(s);
  		return;
  	}
***************
*** 1211,1221 ****
   * the interface.
   */
  void
! fxp_stop(sc, drain)
! 	struct fxp_softc *sc;
! 	int drain;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct fxp_txsoft *txs;
  	int i;
  
--- 1213,1223 ----
   * the interface.
   */
  void
! fxp_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
! 	struct fxp_softc *sc = ifp->if_softc;
  	struct fxp_txsoft *txs;
  	int i;
  
***************
*** 1254,1264 ****
  	}
  	sc->sc_txpending = 0;
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		fxp_rxdrain(sc);
  	}
  
  }
--- 1256,1264 ----
  	}
  	sc->sc_txpending = 0;
  
! 	if (disable) {
  		fxp_rxdrain(sc);
+ 		fxp_disable(sc);
  	}
  
  }
***************
*** 1278,1304 ****
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) fxp_init(sc);
  }
  
  /*
   * Initialize the interface.  Must be called at splnet().
   */
  int
! fxp_init(sc)
! 	struct fxp_softc *sc;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct fxp_cb_config *cbp;
  	struct fxp_cb_ias *cb_ias;
  	struct fxp_cb_tx *txd;
  	bus_dmamap_t rxmap;
  	int i, prm, save_bf, allm, error = 0;
  
  	/*
  	 * Cancel any pending I/O
  	 */
! 	fxp_stop(sc, 0);
  
  	/* 
  	 * XXX just setting sc_flags to 0 here clears any FXPF_MII
--- 1278,1307 ----
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) fxp_init(ifp);
  }
  
  /*
   * Initialize the interface.  Must be called at splnet().
   */
  int
! fxp_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct fxp_softc *sc = ifp->if_softc;
  	struct fxp_cb_config *cbp;
  	struct fxp_cb_ias *cb_ias;
  	struct fxp_cb_tx *txd;
  	bus_dmamap_t rxmap;
  	int i, prm, save_bf, allm, error = 0;
  
+ 	if ((error = fxp_enable(sc)) != 0)
+ 		goto out;
+ 
  	/*
  	 * Cancel any pending I/O
  	 */
! 	fxp_stop(ifp, 0);
  
  	/* 
  	 * XXX just setting sc_flags to 0 here clears any FXPF_MII
***************
*** 1529,1536 ****
  	fxp_start(ifp);
  
   out:
! 	if (error)
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
  	return (error);
  }
  
--- 1532,1542 ----
  	fxp_start(ifp);
  
   out:
! 	if (error) {
! 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 		ifp->if_timer = 0;
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
+ 	}
  	return (error);
  }
  
***************
*** 1691,1812 ****
  }
  
  int
! fxp_ioctl(ifp, command, data)
  	struct ifnet *ifp;
! 	u_long command;
  	caddr_t data;
  {
  	struct fxp_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
- 
- 	switch (command) {
- 	case SIOCSIFADDR:
- 		if ((error = fxp_enable(sc)) != 0)
- 			break;
- 		ifp->if_flags |= IFF_UP;
- 
- 		switch (ifa->ifa_addr->sa_family) {
- #ifdef INET
- 		case AF_INET:
- 			if ((error = fxp_init(sc)) != 0)
- 				break;
- 			arp_ifinit(ifp, ifa);
- 			break;
- #endif /* INET */
- #ifdef NS
- 		case AF_NS:
- 		    {
- 			 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
- 
- 			 if (ns_nullhost(*ina))
- 				ina->x_host = *(union ns_host *)
- 				    LLADDR(ifp->if_sadl);
- 			 else
- 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
- 				    ifp->if_addrlen);
- 			 /* Set new address. */
- 			 error = fxp_init(sc);
- 			 break;
- 		    }
- #endif /* NS */
- 		default:
- 			error = fxp_init(sc);
- 			break;
- 		}
- 		break;
  
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			fxp_stop(sc, 1);
! 			fxp_disable(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interface is marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			if((error = fxp_enable(sc)) != 0)
! 				break;
! 			error = fxp_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up change in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			if((error = fxp_enable(sc)) != 0)
! 				break;
! 			error = fxp_init(sc);
! 		}
! 		break;
! 
! 	case SIOCADDMULTI:
! 	case SIOCDELMULTI:
! 		if(sc->sc_enabled == 0) {
! 			error = EIO;
! 			break;
! 		}
! 		error = (command == SIOCADDMULTI) ?
! 		    ether_addmulti(ifr, &sc->sc_ethercom) :
! 		    ether_delmulti(ifr, &sc->sc_ethercom);
! 
! 		if (error == ENETRESET) {
! 			/*
! 			 * Multicast list has changed; set the hardware
! 			 * filter accordingly.
! 			 */
! 			if (sc->sc_txpending) {
! 				sc->sc_flags |= FXPF_WANTINIT;
! 				error = 0;
! 			} else
! 				error = fxp_init(sc);
! 		}
! 		break;
! 
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
  		break;
  
  	default:
! 		error = EINVAL;
  		break;
  	}
  
  	splx(s);
  	return (error);
--- 1697,1741 ----
  }
  
  int
! fxp_ioctl(ifp, cmd, data)
  	struct ifnet *ifp;
! 	u_long cmd;
  	caddr_t data;
  {
  	struct fxp_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
! 	switch (cmd) {
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
  	default:
! 		error = ether_ioctl(ifp, cmd, data);
! 		if (error == ENETRESET) {
! 			if (sc->sc_enabled) {
! 				/*
! 				 * Multicast list has changed; set the
! 				 * hardware filter accordingly.
! 				 */
! 				if (sc->sc_txpending) {
! 					sc->sc_flags |= FXPF_WANTINIT;
! 					error = 0;
! 				} else
! 					error = fxp_init(ifp);
! 			} else
! 				error = 0;
! 		}
  		break;
  	}
+ 
+ 	/* Try to get more packets going. */
+ 	if (sc->sc_enabled)
+ 		fxp_start(ifp);
  
  	splx(s);
  	return (error);
Index: dev/ic/rtl81x9.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/rtl81x9.c,v
retrieving revision 1.14
diff -c -r1.14 rtl81x9.c
*** dev/ic/rtl81x9.c	2000/10/01 23:32:42	1.14
--- dev/ic/rtl81x9.c	2000/10/04 04:42:59
***************
*** 141,148 ****
  STATIC void rtk_txeof		__P((struct rtk_softc *));
  STATIC void rtk_start		__P((struct ifnet *));
  STATIC int rtk_ioctl		__P((struct ifnet *, u_long, caddr_t));
! STATIC void rtk_init		__P((void *));
! STATIC void rtk_stop		__P((struct rtk_softc *));
  STATIC void rtk_watchdog	__P((struct ifnet *));
  STATIC void rtk_shutdown	__P((void *));
  STATIC int rtk_ifmedia_upd	__P((struct ifnet *));
--- 141,149 ----
  STATIC void rtk_txeof		__P((struct rtk_softc *));
  STATIC void rtk_start		__P((struct ifnet *));
  STATIC int rtk_ioctl		__P((struct ifnet *, u_long, caddr_t));
! STATIC int rtk_init		__P((struct ifnet *));
! STATIC void rtk_stop		__P((struct ifnet *, int));
! 
  STATIC void rtk_watchdog	__P((struct ifnet *));
  STATIC void rtk_shutdown	__P((void *));
  STATIC int rtk_ifmedia_upd	__P((struct ifnet *));
***************
*** 167,175 ****
  STATIC void rtk_setmulti	__P((struct rtk_softc *));
  STATIC int rtk_list_tx_init	__P((struct rtk_softc *));
  
- STATIC int rtk_ether_ioctl __P((struct ifnet *, u_long, caddr_t));
- 
- 
  #define EE_SET(x)					\
  	CSR_WRITE_1(sc, RTK_EECMD,			\
  		CSR_READ_1(sc, RTK_EECMD) | (x))
--- 168,173 ----
***************
*** 729,743 ****
  	ifp = &sc->ethercom.ec_if;
  	ifp->if_softc = sc;
  	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
- 	ifp->if_mtu = ETHERMTU;
  	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  	ifp->if_ioctl = rtk_ioctl;
- #if 0
- 	ifp->if_output = ether_output;
- #endif
  	ifp->if_start = rtk_start;
  	ifp->if_watchdog = rtk_watchdog;
! 	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  
  	/*
  	 * Do ifmedia setup.
--- 727,738 ----
  	ifp = &sc->ethercom.ec_if;
  	ifp->if_softc = sc;
  	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
  	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  	ifp->if_ioctl = rtk_ioctl;
  	ifp->if_start = rtk_start;
  	ifp->if_watchdog = rtk_watchdog;
! 	ifp->if_init = rtk_init;
! 	ifp->if_stop = rtk_stop;
  
  	/*
  	 * Do ifmedia setup.
***************
*** 942,954 ****
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		rtk_stop(sc);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		rtk_init(sc);
  	}
  	splx(s);
  
--- 937,949 ----
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		rtk_stop(ifp, 0);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		rtk_init(ifp);
  	}
  	splx(s);
  
***************
*** 1050,1056 ****
  			}
  			break;
  #else
! 			rtk_init(sc);
  			return;
  #endif
  		}
--- 1045,1051 ----
  			}
  			break;
  #else
! 			rtk_init(ifp);
  			return;
  #endif
  		}
***************
*** 1233,1239 ****
  
  		if (status & RTK_ISR_SYSTEM_ERR) {
  			rtk_reset(sc);
! 			rtk_init(sc);
  		}
  
  	}
--- 1228,1234 ----
  
  		if (status & RTK_ISR_SYSTEM_ERR) {
  			rtk_reset(sc);
! 			rtk_init(ifp);
  		}
  
  	}
***************
*** 1353,1372 ****
  	return;
  }
  
! STATIC void rtk_init(xsc)
! 	void			*xsc;
  {
! 	struct rtk_softc	*sc = xsc;
! 	struct ifnet		*ifp = &sc->ethercom.ec_if;
! 	int			s, i;
  	u_int32_t		rxcfg;
  
! 	s = splnet();
  
  	/*
! 	 * Cancel pending I/O and free all RX/TX buffers.
  	 */
! 	rtk_stop(sc);
  
  	/* Init our MAC address */
  	for (i = 0; i < ETHER_ADDR_LEN; i++) {
--- 1348,1367 ----
  	return;
  }
  
! STATIC int rtk_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct rtk_softc	*sc = ifp->if_softc;
! 	int			error = 0, i;
  	u_int32_t		rxcfg;
  
! 	if ((error = rtk_enable(sc)) != 0)
! 		goto out;
  
  	/*
! 	 * Cancel pending I/O.
  	 */
! 	rtk_stop(ifp, 0);
  
  	/* Init our MAC address */
  	for (i = 0; i < ETHER_ADDR_LEN; i++) {
***************
*** 1442,1450 ****
  	ifp->if_flags |= IFF_RUNNING;
  	ifp->if_flags &= ~IFF_OACTIVE;
  
- 	(void)splx(s);
- 
  	callout_reset(&sc->rtk_tick_ch, hz, rtk_tick, sc);
  }
  
  /*
--- 1437,1451 ----
  	ifp->if_flags |= IFF_RUNNING;
  	ifp->if_flags &= ~IFF_OACTIVE;
  
  	callout_reset(&sc->rtk_tick_ch, hz, rtk_tick, sc);
+ 
+  out:
+ 	if (error) {
+ 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+ 		ifp->if_timer = 0;
+ 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
+ 	}
+ 	return (error);
  }
  
  /*
***************
*** 1476,1533 ****
  	ifmr->ifm_active = sc->mii.mii_media_active;
  }
  
- STATIC int
- rtk_ether_ioctl(ifp, cmd, data)
- 	struct ifnet *ifp;
- 	u_long cmd;
- 	caddr_t data;
- {
- 	struct ifaddr *ifa = (struct ifaddr *) data;
- 	struct rtk_softc *sc = ifp->if_softc;
- 	int error = 0;
- 
- 	switch (cmd) {
- 	case SIOCSIFADDR:
- 		if ((error = rtk_enable(sc)) != 0)
- 			break;
- 		ifp->if_flags |= IFF_UP;
- 
- 		switch (ifa->ifa_addr->sa_family) {
- #ifdef INET
- 		case AF_INET:
- 			rtk_init(sc);
- 			arp_ifinit(ifp, ifa);
- 			break;
- #endif
- #ifdef NS
- 		case AF_NS:
- 		    {
- 			 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
- 
- 			 if (ns_nullhost(*ina))
- 				ina->x_host = *(union ns_host *)
- 				    LLADDR(ifp->if_sadl);
- 			 else
- 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
- 				    ifp->if_addrlen);
- 			 /* Set new address. */
- 			 rtk_init(sc);
- 			 break;
- 		    }
- #endif
- 		default:
- 			rtk_init(sc);
- 			break;
- 		}
- 		break;
- 
- 	default:
- 		return (EINVAL);
- 	}
- 
- 	return (error);
- }
- 
  STATIC int rtk_ioctl(ifp, command, data)
  	struct ifnet		*ifp;
  	u_long			command;
--- 1477,1482 ----
***************
*** 1540,1584 ****
  	s = splnet();
  
  	switch (command) {
- 	case SIOCSIFADDR:
- 	case SIOCGIFADDR:
- 	case SIOCSIFMTU:
- 		error = rtk_ether_ioctl(ifp, command, data);
- 		break;
- 	case SIOCSIFFLAGS:
- 		if (ifp->if_flags & IFF_UP) {
- 			if ((error = rtk_enable(sc)) != 0)
- 				break;
- 			rtk_init(sc);
- 		} else {
- 			if (ifp->if_flags & IFF_RUNNING) {
- 				rtk_stop(sc);
- 				rtk_disable(sc);
- 			}
- 		}
- 		error = 0;
- 		break;
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		error = (command == SIOCADDMULTI) ?
- 		    ether_addmulti(ifr, &sc->ethercom) :
- 		    ether_delmulti(ifr, &sc->ethercom);
- 
- 		if (error == ENETRESET) { 
- 			/*
- 			 * Multicast list has changed; set the hardware filter
- 			 * accordingly.
- 			 */
- 			rtk_setmulti(sc);
- 			error = 0;
- 		}
- 		break;
  	case SIOCGIFMEDIA:
  	case SIOCSIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->mii.mii_media, command);
  		break;
  	default:
! 		error = EINVAL;
  		break;
  	}
  
--- 1489,1511 ----
  	s = splnet();
  
  	switch (command) {
  	case SIOCGIFMEDIA:
  	case SIOCSIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->mii.mii_media, command);
  		break;
+ 
  	default:
! 		error = ether_ioctl(ifp, command, data);
! 		if (error == ENETRESET) {
! 			if (RTK_IS_ENABLED(sc)) {
! 				/*
! 				 * Multicast list has changed.  Set the
! 				 * hardware filter accordingly.
! 				 */
! 				rtk_setmulti(sc);
! 			}
! 			error = 0;
! 		}
  		break;
  	}
  
***************
*** 1598,1604 ****
  	ifp->if_oerrors++;
  	rtk_txeof(sc);
  	rtk_rxeof(sc);
! 	rtk_init(sc);
  
  	return;
  }
--- 1525,1531 ----
  	ifp->if_oerrors++;
  	rtk_txeof(sc);
  	rtk_rxeof(sc);
! 	rtk_init(ifp);
  
  	return;
  }
***************
*** 1607,1620 ****
   * Stop the adapter and free any mbufs allocated to the
   * RX and TX lists.
   */
! STATIC void rtk_stop(sc)
! 	struct rtk_softc	*sc;
  {
! 	int			i;
! 	struct ifnet		*ifp;
! 
! 	ifp = &sc->ethercom.ec_if;
! 	ifp->if_timer = 0;
  
  	callout_stop(&sc->rtk_tick_ch);
  
--- 1534,1545 ----
   * Stop the adapter and free any mbufs allocated to the
   * RX and TX lists.
   */
! STATIC void rtk_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
! 	struct rtk_softc *sc = ifp->if_softc;
! 	int i;
  
  	callout_stop(&sc->rtk_tick_ch);
  
***************
*** 1635,1643 ****
  		}
  	}
  
! 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
  
! 	return;
  }
  
  /*
--- 1560,1570 ----
  		}
  	}
  
! 	if (disable)
! 		rtk_disable(sc);
  
! 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 	ifp->if_timer = 0;
  }
  
  /*
***************
*** 1648,1657 ****
  	void			*vsc;
  {
  	struct rtk_softc	*sc = (struct rtk_softc *)vsc;
- 
- 	rtk_stop(sc);
  
! 	return;
  }
  
  STATIC void
--- 1575,1582 ----
  	void			*vsc;
  {
  	struct rtk_softc	*sc = (struct rtk_softc *)vsc;
  
! 	rtk_stop(&sc->ethercom.ec_if, 0);
  }
  
  STATIC void
Index: dev/ic/smc83c170.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/smc83c170.c,v
retrieving revision 1.33
diff -c -r1.33 smc83c170.c
*** dev/ic/smc83c170.c	2000/10/01 23:32:42	1.33
--- dev/ic/smc83c170.c	2000/10/04 04:43:00
***************
*** 87,99 ****
  void	epic_start __P((struct ifnet *));
  void	epic_watchdog __P((struct ifnet *));
  int	epic_ioctl __P((struct ifnet *, u_long, caddr_t));
  
  void	epic_shutdown __P((void *));
  
  void	epic_reset __P((struct epic_softc *));
- int	epic_init __P((struct epic_softc *));
  void	epic_rxdrain __P((struct epic_softc *));
- void	epic_stop __P((struct epic_softc *, int));
  int	epic_add_rxbuf __P((struct epic_softc *, int));
  void	epic_read_eeprom __P((struct epic_softc *, int, int, u_int16_t *));
  void	epic_set_mchash __P((struct epic_softc *));
--- 87,99 ----
  void	epic_start __P((struct ifnet *));
  void	epic_watchdog __P((struct ifnet *));
  int	epic_ioctl __P((struct ifnet *, u_long, caddr_t));
+ int	epic_init __P((struct ifnet *));
+ void	epic_stop __P((struct ifnet *, int));
  
  void	epic_shutdown __P((void *));
  
  void	epic_reset __P((struct epic_softc *));
  void	epic_rxdrain __P((struct epic_softc *));
  int	epic_add_rxbuf __P((struct epic_softc *, int));
  void	epic_read_eeprom __P((struct epic_softc *, int, int, u_int16_t *));
  void	epic_set_mchash __P((struct epic_softc *));
***************
*** 253,258 ****
--- 253,260 ----
  	ifp->if_ioctl = epic_ioctl;
  	ifp->if_start = epic_start;
  	ifp->if_watchdog = epic_watchdog;
+ 	ifp->if_init = epic_init;
+ 	ifp->if_stop = epic_stop;
  
  	/*
  	 * Attach the interface.
***************
*** 310,316 ****
  {
  	struct epic_softc *sc = arg;
  
! 	epic_stop(sc, 1);
  }
  
  /*
--- 312,318 ----
  {
  	struct epic_softc *sc = arg;
  
! 	epic_stop(&sc->sc_ethercom.ec_if, 1);
  }
  
  /*
***************
*** 502,508 ****
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) epic_init(sc);
  }
  
  /*
--- 504,510 ----
  	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) epic_init(ifp);
  }
  
  /*
***************
*** 517,598 ****
  {
  	struct epic_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFADDR:
! 		ifp->if_flags |= IFF_UP;
! 
! 		switch (ifa->ifa_addr->sa_family) {
! #ifdef INET
! 		case AF_INET:
! 			if ((error = epic_init(sc)) != 0)
! 				break;
! 			arp_ifinit(ifp, ifa);
! 			break;
! #endif /* INET */
! #ifdef NS
! 		case AF_NS:
! 		    {
! 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
! 
! 			if (ns_nullhost(*ina))
! 				ina->x_host = *(union ns_host *)
! 				    LLADDR(ifp->if_sadl);
! 			else
! 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
! 				    ifp->if_addrlen);
! 			/* Set new address. */
! 			error = epic_init(sc);
! 			break;
! 		    }
! #endif /* NS */
! 		default:
! 			error = epic_init(sc);
! 			break;
! 		}
! 		break;
! 
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			epic_stop(sc, 1);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 			   (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interfase it marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			error = epic_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up changes in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			error = epic_init(sc);
! 		}
  		break;
  
! 	case SIOCADDMULTI:
! 	case SIOCDELMULTI:
! 		error = (cmd == SIOCADDMULTI) ?
! 		    ether_addmulti(ifr, &sc->sc_ethercom) :
! 		    ether_delmulti(ifr, &sc->sc_ethercom);
! 
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
--- 519,536 ----
  {
  	struct epic_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFMEDIA:
! 	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
! 	default:
! 		error = ether_ioctl(ifp, cmd, data);
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
***************
*** 604,618 ****
  			error = 0;
  		}
  		break;
- 
- 	case SIOCSIFMEDIA:
- 	case SIOCGIFMEDIA:
- 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
- 		break;
- 
- 	default:
- 		error = EINVAL;
- 		break;
  	}
  
  	splx(s);
--- 542,547 ----
***************
*** 867,873 ****
  		else
  			printf("%s: unknown fatal error\n",
  			    sc->sc_dev.dv_xname);
! 		(void) epic_init(sc);
  	}
  
  	/*
--- 796,802 ----
  		else
  			printf("%s: unknown fatal error\n",
  			    sc->sc_dev.dv_xname);
! 		(void) epic_init(ifp);
  	}
  
  	/*
***************
*** 937,948 ****
   * Initialize the interface.  Must be called at splnet().
   */
  int
! epic_init(sc)
! 	struct epic_softc *sc;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	u_int8_t *enaddr = LLADDR(ifp->if_sadl);
  	struct epic_txdesc *txd;
  	struct epic_descsoft *ds;
--- 866,877 ----
   * Initialize the interface.  Must be called at splnet().
   */
  int
! epic_init(ifp)
! 	struct ifnet *ifp;
  {
+ 	struct epic_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	u_int8_t *enaddr = LLADDR(ifp->if_sadl);
  	struct epic_txdesc *txd;
  	struct epic_descsoft *ds;
***************
*** 952,958 ****
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	epic_stop(sc, 0);
  
  	/*
  	 * Reset the EPIC to a known state.
--- 881,887 ----
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	epic_stop(ifp, 0);
  
  	/*
  	 * Reset the EPIC to a known state.
***************
*** 1118,1130 ****
   * Stop transmission on the interface.
   */
  void
! epic_stop(sc, drain)
! 	struct epic_softc *sc;
! 	int drain;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct epic_descsoft *ds;
  	u_int32_t reg;
  	int i;
--- 1047,1059 ----
   * Stop transmission on the interface.
   */
  void
! epic_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
+ 	struct epic_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	struct epic_descsoft *ds;
  	u_int32_t reg;
  	int i;
***************
*** 1165,1176 ****
  		}
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		epic_rxdrain(sc);
- 	}
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
--- 1094,1101 ----
  		}
  	}
  
! 	if (disable)
  		epic_rxdrain(sc);
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
Index: dev/ic/tulip.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/tulip.c,v
retrieving revision 1.74
diff -c -r1.74 tulip.c
*** dev/ic/tulip.c	2000/10/03 23:35:55	1.74
--- dev/ic/tulip.c	2000/10/04 04:43:03
***************
*** 107,119 ****
  void	tlp_start __P((struct ifnet *));
  void	tlp_watchdog __P((struct ifnet *));
  int	tlp_ioctl __P((struct ifnet *, u_long, caddr_t));
  
  void	tlp_shutdown __P((void *));
  
  void	tlp_reset __P((struct tulip_softc *));
- int	tlp_init __P((struct tulip_softc *));
  void	tlp_rxdrain __P((struct tulip_softc *));
- void	tlp_stop __P((struct tulip_softc *, int));
  int	tlp_add_rxbuf __P((struct tulip_softc *, int));
  void	tlp_idle __P((struct tulip_softc *, u_int32_t));
  void	tlp_srom_idle __P((struct tulip_softc *));
--- 107,119 ----
  void	tlp_start __P((struct ifnet *));
  void	tlp_watchdog __P((struct ifnet *));
  int	tlp_ioctl __P((struct ifnet *, u_long, caddr_t));
+ int	tlp_init __P((struct ifnet *));
+ void	tlp_stop __P((struct ifnet *, int));
  
  void	tlp_shutdown __P((void *));
  
  void	tlp_reset __P((struct tulip_softc *));
  void	tlp_rxdrain __P((struct tulip_softc *));
  int	tlp_add_rxbuf __P((struct tulip_softc *, int));
  void	tlp_idle __P((struct tulip_softc *, u_int32_t));
  void	tlp_srom_idle __P((struct tulip_softc *));
***************
*** 501,506 ****
--- 501,508 ----
  	ifp->if_ioctl = tlp_ioctl;
  	ifp->if_start = tlp_start;
  	ifp->if_watchdog = tlp_watchdog;
+ 	ifp->if_init = tlp_init;
+ 	ifp->if_stop = tlp_stop;
  
  	/*
  	 * We can support 802.1Q VLAN-sized frames.
***************
*** 676,682 ****
  {
  	struct tulip_softc *sc = arg;
  
! 	tlp_stop(sc, 1);
  }
  
  /*
--- 678,684 ----
  {
  	struct tulip_softc *sc = arg;
  
! 	tlp_stop(&sc->sc_ethercom.ec_if, 1);
  }
  
  /*
***************
*** 960,966 ****
  	else
  		printf("%s: spurious watchdog timeout\n", sc->sc_dev.dv_xname);
  
! 	(void) tlp_init(sc);
  
  	/* Try to get more packets going. */
  	tlp_start(ifp);
--- 962,968 ----
  	else
  		printf("%s: spurious watchdog timeout\n", sc->sc_dev.dv_xname);
  
! 	(void) tlp_init(ifp);
  
  	/* Try to get more packets going. */
  	tlp_start(ifp);
***************
*** 979,1088 ****
  {
  	struct tulip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
  
  	switch (cmd) {
- 	case SIOCSIFADDR:
- 		if ((error = tlp_enable(sc)) != 0)
- 			break;
- 		ifp->if_flags |= IFF_UP;
- 
- 		switch (ifa->ifa_addr->sa_family) {
- #ifdef INET
- 		case AF_INET:
- 			if ((error = tlp_init(sc)) != 0)
- 				break;
- 			arp_ifinit(ifp, ifa);
- 			break;
- #endif /* INET */
- #ifdef NS
- 		case AF_NS:
- 		    {
- 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
- 
- 			if (ns_nullhost(*ina))
- 				ina->x_host = *(union ns_host *)
- 				    LLADDR(ifp->if_sadl);
- 			else
- 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
- 				    ifp->if_addrlen);
- 			/* Set new address. */
- 			error = tlp_init(sc);
- 			break;
- 		    }
- #endif /* NS */
- 		default:
- 			error = tlp_init(sc);
- 			break;
- 		}
- 		break;
- 
- 	case SIOCSIFMTU:
- 		if (ifr->ifr_mtu > ETHERMTU)
- 			error = EINVAL;
- 		else
- 			ifp->if_mtu = ifr->ifr_mtu;
- 		break;
- 
- 	case SIOCSIFFLAGS:
- #ifdef TLP_STATS
- 		if (ifp->if_flags & IFF_DEBUG)
- 			tlp_print_stats(sc);
- #endif
- 		if ((ifp->if_flags & IFF_UP) == 0 &&
- 		    (ifp->if_flags & IFF_RUNNING) != 0) {
- 			/*
- 			 * If interface is marked down and it is running, then
- 			 * stop it.
- 			 */
- 			tlp_stop(sc, 1);
- 			tlp_disable(sc);
- 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
- 			   (ifp->if_flags & IFF_RUNNING) == 0) {
- 			/*
- 			 * If interfase it marked up and it is stopped, then
- 			 * start it.
- 			 */
- 			if ((error = tlp_enable(sc)) != 0)
- 				break;
- 			error = tlp_init(sc);
- 		} else if ((ifp->if_flags & IFF_UP) != 0) {
- 			/*
- 			 * Reset the interface to pick up changes in any other
- 			 * flags that affect the hardware state.
- 			 */
- 			if ((error = tlp_enable(sc)) != 0)
- 				break;
- 			error = tlp_init(sc);
- 		}
- 		break;
- 
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		error = (cmd == SIOCADDMULTI) ?
- 		    ether_addmulti(ifr, &sc->sc_ethercom) :
- 		    ether_delmulti(ifr, &sc->sc_ethercom);
- 
- 		if (TULIP_IS_ENABLED(sc) && error == ENETRESET) {
- 			/*
- 			 * Multicast list has changed.  Set the filter
- 			 * accordingly.
- 			 */
- 			(*sc->sc_filter_setup)(sc);
- 			error = 0;
- 		}
- 		break;
- 
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
  	default:
! 		error = EINVAL;
  		break;
  	}
  
--- 981,1008 ----
  {
  	struct tulip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
  	switch (cmd) {
  	case SIOCSIFMEDIA:
  	case SIOCGIFMEDIA:
  		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
  	default:
! 		error = ether_ioctl(ifp, cmd, data);
! 		if (error == ENETRESET) {
! 			if (TULIP_IS_ENABLED(sc)) {
! 				/*
! 				 * Multicast list has changed.  Set the
! 				 * hardware filter accordingly.
! 				 */
! 				(*sc->sc_filter_setup)(sc);
! 			}
! 			error = 0;
! 		}
  		break;
  	}
  
***************
*** 1219,1225 ****
  			if (status & STATUS_RPS)
  				printf("%s: receive process stopped\n",
  				    sc->sc_dev.dv_xname);
! 			(void) tlp_init(sc);
  			break;
  		}
  
--- 1139,1145 ----
  			if (status & STATUS_RPS)
  				printf("%s: receive process stopped\n",
  				    sc->sc_dev.dv_xname);
! 			(void) tlp_init(ifp);
  			break;
  		}
  
***************
*** 1244,1250 ****
  			}
  			printf("%s: fatal system error: %s\n",
  			    sc->sc_dev.dv_xname, str);
! 			(void) tlp_init(sc);
  			break;
  		}
  
--- 1164,1170 ----
  			}
  			printf("%s: fatal system error: %s\n",
  			    sc->sc_dev.dv_xname, str);
! 			(void) tlp_init(ifp);
  			break;
  		}
  
***************
*** 1322,1328 ****
  		    (TDSTAT_Rx_FS|TDSTAT_Rx_LS)) {
  			printf("%s: incoming packet spilled, resetting\n",
  			    sc->sc_dev.dv_xname);
! 			(void) tlp_init(sc);
  			return;
  		}
  
--- 1242,1248 ----
  		    (TDSTAT_Rx_FS|TDSTAT_Rx_LS)) {
  			printf("%s: incoming packet spilled, resetting\n",
  			    sc->sc_dev.dv_xname);
! 			(void) tlp_init(ifp);
  			return;
  		}
  
***************
*** 1633,1655 ****
  }
  
  /*
!  * tlp_init:
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! tlp_init(sc)
! 	struct tulip_softc *sc;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct tulip_txsoft *txs;
  	struct tulip_rxsoft *rxs;
  	int i, error = 0;
  
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	tlp_stop(sc, 0);
  
  	/*
  	 * Initialize `opmode' to 0, and call the pre-init routine, if
--- 1553,1578 ----
  }
  
  /*
!  * tlp_init:		[ ifnet interface function ]
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! tlp_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct tulip_softc *sc = ifp->if_softc;
  	struct tulip_txsoft *txs;
  	struct tulip_rxsoft *rxs;
  	int i, error = 0;
  
+ 	if ((error = tlp_enable(sc)) != 0)
+ 		goto out;
+ 
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	tlp_stop(ifp, 0);
  
  	/*
  	 * Initialize `opmode' to 0, and call the pre-init routine, if
***************
*** 1938,1945 ****
  	ifp->if_flags &= ~IFF_OACTIVE;
  
   out:
! 	if (error)
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
  	return (error);
  }
  
--- 1861,1871 ----
  	ifp->if_flags &= ~IFF_OACTIVE;
  
   out:
! 	if (error) {
! 		ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 		ifp->if_timer = 0;
  		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
+ 	}
  	return (error);
  }
  
***************
*** 1996,2008 ****
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		tlp_stop(sc, 0);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		tlp_init(sc);
  	}
  	splx(s);
  }
--- 1922,1934 ----
  
  	s = splnet();
  	if (why != PWR_RESUME) {
! 		tlp_stop(ifp, 0);
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
  	} else if (ifp->if_flags & IFF_UP) {
  		if (sc->sc_power != NULL)
  			(*sc->sc_power)(sc, why);
! 		tlp_init(ifp);
  	}
  	splx(s);
  }
***************
*** 2030,2045 ****
  }
  
  /*
!  * tlp_stop:
   *
   *	Stop transmission on the interface.
   */
  void
! tlp_stop(sc, drain)
! 	struct tulip_softc *sc;
! 	int drain;
  {
! 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct tulip_txsoft *txs;
  
  	if (sc->sc_tick != NULL) {
--- 1956,1971 ----
  }
  
  /*
!  * tlp_stop:		[ ifnet interface function ]
   *
   *	Stop transmission on the interface.
   */
  void
! tlp_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
! 	struct tulip_softc *sc = ifp->if_softc;
  	struct tulip_txsoft *txs;
  
  	if (sc->sc_tick != NULL) {
***************
*** 2074,2084 ****
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		tlp_rxdrain(sc);
  	}
  
  	sc->sc_flags &= ~(TULIPF_WANT_SETUP|TULIPF_DOING_SETUP);
--- 2000,2008 ----
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (disable) {
  		tlp_rxdrain(sc);
+ 		tlp_disable(sc);
  	}
  
  	sc->sc_flags &= ~(TULIPF_WANT_SETUP|TULIPF_DOING_SETUP);
***************
*** 5018,5024 ****
  	 * time through.
  	 */
  	if (TULIP_MEDIA_NEEDSRESET(sc, tm->tm_opmode))
! 		return (tlp_init(sc));
  
  	return ((*tm->tm_set)(sc));
  }
--- 4942,4948 ----
  	 * time through.
  	 */
  	if (TULIP_MEDIA_NEEDSRESET(sc, tm->tm_opmode))
! 		return (tlp_init(&sc->sc_ethercom.ec_if));
  
  	return ((*tm->tm_set)(sc));
  }
Index: dev/pci/if_sip.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_sip.c,v
retrieving revision 1.16
diff -c -r1.16 if_sip.c
*** dev/pci/if_sip.c	2000/10/01 23:32:43	1.16
--- dev/pci/if_sip.c	2000/10/04 04:43:05
***************
*** 255,266 ****
  void	sip_start __P((struct ifnet *));
  void	sip_watchdog __P((struct ifnet *));
  int	sip_ioctl __P((struct ifnet *, u_long, caddr_t));
  
  void	sip_shutdown __P((void *));
  
  void	sip_reset __P((struct sip_softc *));
- int	sip_init __P((struct sip_softc *));
- void	sip_stop __P((struct sip_softc *, int));
  void	sip_rxdrain __P((struct sip_softc *));
  int	sip_add_rxbuf __P((struct sip_softc *, int));
  void	sip_read_eeprom __P((struct sip_softc *, int, int, u_int16_t *));
--- 255,266 ----
  void	sip_start __P((struct ifnet *));
  void	sip_watchdog __P((struct ifnet *));
  int	sip_ioctl __P((struct ifnet *, u_long, caddr_t));
+ int	sip_init __P((struct ifnet *));
+ void	sip_stop __P((struct ifnet *, int));
  
  void	sip_shutdown __P((void *));
  
  void	sip_reset __P((struct sip_softc *));
  void	sip_rxdrain __P((struct sip_softc *));
  int	sip_add_rxbuf __P((struct sip_softc *, int));
  void	sip_read_eeprom __P((struct sip_softc *, int, int, u_int16_t *));
***************
*** 580,585 ****
--- 580,587 ----
  	ifp->if_ioctl = sip_ioctl;
  	ifp->if_start = sip_start;
  	ifp->if_watchdog = sip_watchdog;
+ 	ifp->if_init = sip_init;
+ 	ifp->if_stop = sip_stop;
  
  	/*
  	 * Attach the interface.
***************
*** 639,645 ****
  {
  	struct sip_softc *sc = arg;
  
! 	sip_stop(sc, 1);
  }
  
  /*
--- 641,647 ----
  {
  	struct sip_softc *sc = arg;
  
! 	sip_stop(&sc->sc_ethercom.ec_if, 1);
  }
  
  /*
***************
*** 868,874 ****
  		ifp->if_oerrors++;
  
  		/* Reset the interface. */
! 		(void) sip_init(sc);
  	} else if (ifp->if_flags & IFF_DEBUG)
  		printf("%s: recovered from device timeout\n",
  		    sc->sc_dev.dv_xname);
--- 870,876 ----
  		ifp->if_oerrors++;
  
  		/* Reset the interface. */
! 		(void) sip_init(ifp);
  	} else if (ifp->if_flags & IFF_DEBUG)
  		printf("%s: recovered from device timeout\n",
  		    sc->sc_dev.dv_xname);
***************
*** 890,970 ****
  {
  	struct sip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	struct ifaddr *ifa = (struct ifaddr *)data;
! 	int s, error = 0;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFADDR:
! 		ifp->if_flags |= IFF_UP;
! 
! 		switch (ifa->ifa_addr->sa_family) {
! #ifdef INET
! 		case AF_INET:
! 			if ((error = sip_init(sc)) != 0)
! 				break;
! 			arp_ifinit(ifp, ifa);
! 			break;
! #endif /* INET */
! #ifdef NS
! 		case AF_NS:
! 		    {
! 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
! 
! 			if (ns_nullhost(*ina))
! 				ina->x_host = *(union ns_host *)
! 				    LLADDR(ifp->if_sadl);
! 			else
! 				memcpy(LLADDR(ifp->if_sadl),
! 				    ina->x_host.c_host, ifp->if_addrlen);
! 			error = sip_init(sc);
! 			break;
! 		    }
! #endif /* NS */
! 		default:
! 			error = sip_init(sc);
! 			break;
! 		}
! 		break;
! 
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			sip_stop(sc, 1);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 			   (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interfase it marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			error = sip_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up changes in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			error = sip_init(sc);
! 		}
  		break;
- 	
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		error = (cmd == SIOCADDMULTI) ?
- 		    ether_addmulti(ifr, &sc->sc_ethercom) :
- 		    ether_delmulti(ifr, &sc->sc_ethercom);
  
  		if (error == ENETRESET) { 
  			/*
  			 * Multicast list has changed; set the hardware filter
--- 892,909 ----
  {
  	struct sip_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
! 	int s, error;
  
  	s = splnet();
  
  	switch (cmd) {
! 	case SIOCSIFMEDIA:
! 	case SIOCGIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
  		break;
  
+ 	default:
+ 		error = ether_ioctl(ifp, cmd, data);
  		if (error == ENETRESET) { 
  			/*
  			 * Multicast list has changed; set the hardware filter
***************
*** 974,988 ****
  			error = 0;
  		}
  		break;
- 
- 	case SIOCSIFMEDIA:
- 	case SIOCGIFMEDIA:
- 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
- 		break;
- 
- 	default:
- 		error = EINVAL;
- 		break;
  	}
  
  	/* Try to get more packets going. */
--- 913,918 ----
***************
*** 1055,1063 ****
  					    "threshold to %u bytes\n",
  					    thresh * 32);
  					sc->sc_tx_drain_thresh = thresh;
! 					(void) sip_init(sc);
  				} else {
! 					(void) sip_init(sc);
  					printf("\n");
  				}
  			}
--- 985,993 ----
  					    "threshold to %u bytes\n",
  					    thresh * 32);
  					sc->sc_tx_drain_thresh = thresh;
! 					(void) sip_init(ifp);
  				} else {
! 					(void) sip_init(ifp);
  					printf("\n");
  				}
  			}
***************
*** 1083,1089 ****
  			PRINTERR(ISR_RMABT, "master abort");
  			PRINTERR(ISR_RTABT, "target abort");
  			PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
! 			(void) sip_init(sc);
  #undef PRINTERR
  		}
  	}
--- 1013,1019 ----
  			PRINTERR(ISR_RMABT, "master abort");
  			PRINTERR(ISR_RTABT, "target abort");
  			PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
! 			(void) sip_init(ifp);
  #undef PRINTERR
  		}
  	}
***************
*** 1380,1396 ****
  }
  
  /*
!  * sip_init:
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! sip_init(sc)
! 	struct sip_softc *sc;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct sip_txsoft *txs;
  	struct sip_rxsoft *rxs;
  	struct sip_desc *sipd;
--- 1310,1326 ----
  }
  
  /*
!  * sip_init:		[ ifnet interface function ]
   *
   *	Initialize the interface.  Must be called at splnet().
   */
  int
! sip_init(ifp)
! 	struct ifnet *ifp;
  {
+ 	struct sip_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	struct sip_txsoft *txs;
  	struct sip_rxsoft *rxs;
  	struct sip_desc *sipd;
***************
*** 1400,1406 ****
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	sip_stop(sc, 0);
  
  	/*
  	 * Reset the chip to a known state.
--- 1330,1336 ----
  	/*
  	 * Cancel any pending I/O.
  	 */
! 	sip_stop(ifp, 0);
  
  	/*
  	 * Reset the chip to a known state.
***************
*** 1599,1615 ****
  }
  
  /*
!  * sip_stop:
   *
   *	Stop transmission on the interface.
   */
  void
! sip_stop(sc, drain)
! 	struct sip_softc *sc;
  {
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
- 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  	struct sip_txsoft *txs;
  	u_int32_t cmdsts = 0;		/* DEBUG */
  
--- 1529,1546 ----
  }
  
  /*
!  * sip_stop:		[ ifnet interface function ]
   *
   *	Stop transmission on the interface.
   */
  void
! sip_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
+ 	struct sip_softc *sc = ifp->if_softc;
  	bus_space_tag_t st = sc->sc_st;
  	bus_space_handle_t sh = sc->sc_sh;
  	struct sip_txsoft *txs;
  	u_int32_t cmdsts = 0;		/* DEBUG */
  
***************
*** 1657,1668 ****
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		sip_rxdrain(sc);
- 	}
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
--- 1588,1595 ----
  		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
  	}
  
! 	if (disable)
  		sip_rxdrain(sc);
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
Index: dev/pci/if_vr.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_vr.c,v
retrieving revision 1.38
diff -c -r1.38 if_vr.c
*** dev/pci/if_vr.c	2000/10/01 23:32:44	1.38
--- dev/pci/if_vr.c	2000/10/04 04:43:06
***************
*** 301,308 ****
  static int vr_intr		__P((void *));
  static void vr_start		__P((struct ifnet *));
  static int vr_ioctl		__P((struct ifnet *, u_long, caddr_t));
! static int vr_init		__P((struct vr_softc *));
! static void vr_stop		__P((struct vr_softc *, int));
  static void vr_rxdrain		__P((struct vr_softc *));
  static void vr_watchdog		__P((struct ifnet *));
  static void vr_tick		__P((void *));
--- 301,308 ----
  static int vr_intr		__P((void *));
  static void vr_start		__P((struct ifnet *));
  static int vr_ioctl		__P((struct ifnet *, u_long, caddr_t));
! static int vr_init		__P((struct ifnet *));
! static void vr_stop		__P((struct ifnet *, int));
  static void vr_rxdrain		__P((struct vr_softc *));
  static void vr_watchdog		__P((struct ifnet *));
  static void vr_tick		__P((void *));
***************
*** 856,862 ****
  
  	/* Suppress unwanted interrupts. */
  	if ((ifp->if_flags & IFF_UP) == 0) {
! 		vr_stop(sc, 1);
  		return (0);
  	}
  
--- 856,862 ----
  
  	/* Suppress unwanted interrupts. */
  	if ((ifp->if_flags & IFF_UP) == 0) {
! 		vr_stop(ifp, 1);
  		return (0);
  	}
  
***************
*** 906,912 ****
  			printf("%s: PCI bus error\n", sc->vr_dev.dv_xname);
  			/* vr_init() calls vr_start() */
  			dotx = 0;
! 			(void) vr_init(sc);
  		}
  	}
  
--- 906,912 ----
  			printf("%s: PCI bus error\n", sc->vr_dev.dv_xname);
  			/* vr_init() calls vr_start() */
  			dotx = 0;
! 			(void) vr_init(ifp);
  		}
  	}
  
***************
*** 1089,1104 ****
   * Initialize the interface.  Must be called at splnet.
   */
  static int
! vr_init(sc)
! 	struct vr_softc *sc;
  {
! 	struct ifnet *ifp = &sc->vr_ec.ec_if;
  	struct vr_desc *d;
  	struct vr_descsoft *ds;
  	int i, error = 0;
  
  	/* Cancel pending I/O. */
! 	vr_stop(sc, 0);
  
  	/* Reset the Rhine to a known state. */
  	vr_reset(sc);
--- 1089,1104 ----
   * Initialize the interface.  Must be called at splnet.
   */
  static int
! vr_init(ifp)
! 	struct ifnet *ifp;
  {
! 	struct vr_softc *sc = ifp->if_softc;
  	struct vr_desc *d;
  	struct vr_descsoft *ds;
  	int i, error = 0;
  
  	/* Cancel pending I/O. */
! 	vr_stop(ifp, 0);
  
  	/* Reset the Rhine to a known state. */
  	vr_reset(sc);
***************
*** 1228,1300 ****
  {
  	struct vr_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
- 	struct ifaddr *ifa = (struct ifaddr *)data;
  	int s, error = 0;
  
  	s = splnet();
  
  	switch (command) {
! 	case SIOCSIFADDR:
! 		ifp->if_flags |= IFF_UP;
! 
! 		switch (ifa->ifa_addr->sa_family) {
! #ifdef INET
! 		case AF_INET:
! 			if ((error = vr_init(sc)) != 0)
! 				break;
! 			arp_ifinit(ifp, ifa);
! 			break;
! #endif /* INET */
! 		default:
! 			error = vr_init(sc);
! 			break;
! 		}
! 		break;
! 
! 	case SIOCGIFADDR:
! 		bcopy((caddr_t) sc->vr_enaddr,
! 			(caddr_t) ((struct sockaddr *)&ifr->ifr_data)->sa_data,
! 			ETHER_ADDR_LEN);
! 		break;
! 
! 	case SIOCSIFMTU:
! 		if (ifr->ifr_mtu > ETHERMTU)
! 			error = EINVAL;
! 		else
! 			ifp->if_mtu = ifr->ifr_mtu;
! 		break;
! 
! 	case SIOCSIFFLAGS:
! 		if ((ifp->if_flags & IFF_UP) == 0 &&
! 		    (ifp->if_flags & IFF_RUNNING) != 0) {
! 			/*
! 			 * If interface is marked down and it is running, then
! 			 * stop it.
! 			 */
! 			vr_stop(sc, 1);
! 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
! 			   (ifp->if_flags & IFF_RUNNING) == 0) {
! 			/*
! 			 * If interface is marked up and it is stopped, then
! 			 * start it.
! 			 */
! 			error = vr_init(sc);
! 		} else if ((ifp->if_flags & IFF_UP) != 0) {
! 			/*
! 			 * Reset the interface to pick up changes in any other
! 			 * flags that affect the hardware state.
! 			 */
! 			error = vr_init(sc);
! 		}
  		break;
- 
- 	case SIOCADDMULTI:
- 	case SIOCDELMULTI:
- 		if (command == SIOCADDMULTI)
- 			error = ether_addmulti(ifr, &sc->vr_ec);
- 		else
- 			error = ether_delmulti(ifr, &sc->vr_ec);
  
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
--- 1228,1245 ----
  {
  	struct vr_softc *sc = ifp->if_softc;
  	struct ifreq *ifr = (struct ifreq *)data;
  	int s, error = 0;
  
  	s = splnet();
  
  	switch (command) {
! 	case SIOCGIFMEDIA:
! 	case SIOCSIFMEDIA:
! 		error = ifmedia_ioctl(ifp, ifr, &sc->vr_mii.mii_media, command);
  		break;
  
+ 	default:
+ 		error = ether_ioctl(ifp, command, data);
  		if (error == ENETRESET) {
  			/*
  			 * Multicast list has changed; set the hardware filter
***************
*** 1304,1318 ****
  			error = 0;
  		}
  		break;
- 
- 	case SIOCGIFMEDIA:
- 	case SIOCSIFMEDIA:
- 		error = ifmedia_ioctl(ifp, ifr, &sc->vr_mii.mii_media, command);
- 		break;
- 
- 	default:
- 		error = EINVAL;
- 		break;
  	}
  
  	splx(s);
--- 1249,1254 ----
***************
*** 1328,1334 ****
  	printf("%s: device timeout\n", sc->vr_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) vr_init(sc);
  }
  
  /*
--- 1264,1270 ----
  	printf("%s: device timeout\n", sc->vr_dev.dv_xname);
  	ifp->if_oerrors++;
  
! 	(void) vr_init(ifp);
  }
  
  /*
***************
*** 1373,1384 ****
   * transmit lists.
   */
  static void
! vr_stop(sc, drain)
! 	struct vr_softc *sc;
! 	int drain;
  {
  	struct vr_descsoft *ds;
- 	struct ifnet *ifp;
  	int i;
  
  	/* Cancel one second timer. */
--- 1309,1320 ----
   * transmit lists.
   */
  static void
! vr_stop(ifp, disable)
! 	struct ifnet *ifp;
! 	int disable;
  {
+ 	struct vr_softc *sc = ifp->if_softc;
  	struct vr_descsoft *ds;
  	int i;
  
  	/* Cancel one second timer. */
***************
*** 1408,1419 ****
  		}
  	}
  
! 	if (drain) {
! 		/*
! 		 * Release the receive buffers.
! 		 */
  		vr_rxdrain(sc);
- 	}
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
--- 1344,1351 ----
  		}
  	}
  
! 	if (disable)
  		vr_rxdrain(sc);
  
  	/*
  	 * Mark the interface down and cancel the watchdog timer.
***************
*** 1469,1475 ****
  {
  	struct vr_softc *sc = (struct vr_softc *)arg;
  
! 	vr_stop(sc, 1);
  }
  
  /*
--- 1401,1407 ----
  {
  	struct vr_softc *sc = (struct vr_softc *)arg;
  
! 	vr_stop(&sc->vr_ec.ec_if, 1);
  }
  
  /*
***************
*** 1694,1699 ****
--- 1626,1633 ----
  	ifp->if_ioctl = vr_ioctl;
  	ifp->if_start = vr_start;
  	ifp->if_watchdog = vr_watchdog;
+ 	ifp->if_init = vr_init;
+ 	ifp->if_stop = vr_stop;
  	bcopy(sc->vr_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
  
  	/*

--tjCHc7DPkfUGtrlw--