Subject: Re: wi driver: initialization order
To: <>
From: None <itojun@iijlab.net>
List: tech-net
Date: 09/08/1999 19:23:36
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <3676.936786191.1@coconut.itojun.org>
Content-Transfer-Encoding: 7bit

>	I'm now testing wi driver with wavelan turbo card.
>	I noticed that, if I use wiconfig before ifconfig, like
>	# wiconfig -i wi0 -p 1
>	# wiconfig -i wi0 -n 0100
>	# ifconfig wi0 up
>	kernel will display "wi0: device timeout" onto the console.
>	This is because, on invocation of /usr/sbin/wiconfig, IFF_RUNNING
>	is raised prior to call to wi_enable() (this is done in wi_init()
>	called via wi_setdef()).  I'm not sure how to fix this.
>
>	Transmission/reception of IPv6 datagram can be done if you add
>	ETHERTYPE_IPV6 into one "if" statement in if_wi.c.  However, 
>	wi interface cannot seem to receive ethernet multicast datagrams
>	on non-promiscuous mode (therefore, IPv6 will not work properly
>	as it uses multicast packets throughout the protocol spec).

	The attached patch fixes the following problems:
	- IPv6 packet was not transmitted to the air
	- IFF_RUNNING will be raised mistakingly on invocation of
	  /usr/sbin/wiconfig before "ifconfig up"
	- multicast datagrams will not be received on non-promiscuous mode.
	The diff was made against NetBSD-current, as of this morning JST.

	You can now enjoy IPv6 on wi driver.
	Does it look sane enough?

	(sorry if you received this twice, this overrides the previous
	patch and is more complete)

itojun


------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <3676.936786191.2@coconut.itojun.org>
Content-Transfer-Encoding: 7bit

*** /home/itojun/NetBSD/syssrc/sys/dev/pcmcia/if_wi.c	Thu Jul 15 08:07:29 1999
--- if_wi.c	Wed Sep  8 17:39:06 1999
***************
*** 437,443 ****
--- 437,454 ----
  #endif
  
  	/* Receive packet. */
+ #if 1
+ 	/* NetBSD-current */
  	(*ifp->if_input)(ifp, m);
+ #else
+     {
+ 	/* NetBSD 1.4.1 */
+ 	struct ether_header *eh;
+ 	eh = mtod(m, struct ether_header *);
+ 	m_adj(m, sizeof(struct ether_header));
+ 	ether_input(ifp, eh, m);
+     }
+ #endif
  }
  
  static void wi_txeof(sc, status)
***************
*** 973,979 ****
  	if (sc->wi_gone)
  		return(ENODEV);
  
! 	switch(command) {
  	case SIOCSIFADDR:
  		if (!(ifp->if_flags & IFF_RUNNING) &&
  		    (error = wi_enable(sc)) != 0)
--- 984,990 ----
  	if (sc->wi_gone)
  		return(ENODEV);
  
! 	switch (command) {
  	case SIOCSIFADDR:
  		if (!(ifp->if_flags & IFF_RUNNING) &&
  		    (error = wi_enable(sc)) != 0)
***************
*** 982,996 ****
  		switch (ifa->ifa_addr->sa_family) {
  #ifdef INET
  		case AF_INET:
  			arp_ifinit(&sc->sc_ethercom.ec_if, ifa);
  			break;
  #endif
  		}
! 		break;
! 
! 
! 
! 
  		break;
  #if 0
  	case SIOCSIFMTU:
--- 993,1007 ----
  		switch (ifa->ifa_addr->sa_family) {
  #ifdef INET
  		case AF_INET:
+ 			wi_init(sc);
  			arp_ifinit(&sc->sc_ethercom.ec_if, ifa);
  			break;
  #endif
+ 		default:
+ 			wi_init(sc);
+ 			break;
  		}
! 		error = 0;
  		break;
  #if 0
  	case SIOCSIFMTU:
***************
*** 1022,1029 ****
  		break;
  	case SIOCADDMULTI:
  	case SIOCDELMULTI:
! 		wi_setmulti(sc);
! 		error = 0;
  		break;
  	case SIOCGWAVELAN:
  		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
--- 1033,1047 ----
  		break;
  	case SIOCADDMULTI:
  	case SIOCDELMULTI:
! 		/* Update our multicast list. */
! 		error = (command == SIOCADDMULTI) ?
! 		    ether_addmulti(ifr, &sc->sc_ethercom) :
! 		    ether_delmulti(ifr, &sc->sc_ethercom);
! 		if (error == ENETRESET || error == 0) {
! 			/* Configure list onto the chip. */
! 			wi_setmulti(sc);
! 			error = 0;
! 		}
  		break;
  	case SIOCGWAVELAN:
  		error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
***************
*** 1075,1087 ****
  	int			s;
  	struct wi_ltv_macaddr	mac;
  	int			id = 0;
  
  	if (sc->wi_gone)
  		return;
  
  	s = splimp();
  
! 	if (ifp->if_flags & IFF_RUNNING)
  		wi_stop(sc);
  
  	wi_reset(sc);
--- 1093,1107 ----
  	int			s;
  	struct wi_ltv_macaddr	mac;
  	int			id = 0;
+ 	int			running;
  
  	if (sc->wi_gone)
  		return;
  
  	s = splimp();
  
! 	running = ifp->if_flags & IFF_RUNNING;
! 	if (running)
  		wi_stop(sc);
  
  	wi_reset(sc);
***************
*** 1156,1162 ****
  
  	splx(s);
  
! 	ifp->if_flags |= IFF_RUNNING;
  	ifp->if_flags &= ~IFF_OACTIVE;
  
  	timeout(wi_inquire, sc, hz * 60);
--- 1176,1183 ----
  
  	splx(s);
  
! 	if (running)
! 		ifp->if_flags |= IFF_RUNNING;
  	ifp->if_flags &= ~IFF_OACTIVE;
  
  	timeout(wi_inquire, sc, hz * 60);
***************
*** 1195,1201 ****
  	 */
  	if (ntohs(eh->ether_type) == ETHERTYPE_IP ||
  	    ntohs(eh->ether_type) == ETHERTYPE_ARP ||
! 	    ntohs(eh->ether_type) == ETHERTYPE_REVARP) {
  		bcopy((char *)&eh->ether_dhost,
  		    (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
  		bcopy((char *)&eh->ether_shost,
--- 1216,1223 ----
  	 */
  	if (ntohs(eh->ether_type) == ETHERTYPE_IP ||
  	    ntohs(eh->ether_type) == ETHERTYPE_ARP ||
! 	    ntohs(eh->ether_type) == ETHERTYPE_REVARP ||
! 	    ntohs(eh->ether_type) == ETHERTYPE_IPV6) {
  		bcopy((char *)&eh->ether_dhost,
  		    (char *)&tx_frame.wi_addr1, ETHER_ADDR_LEN);
  		bcopy((char *)&eh->ether_shost,

------- =_aaaaaaaaaa0--