Skip site navigation (1)Skip section navigation (2)
Date:      27 Nov 2002 11:22:00 -0600
From:      Craig Boston <craig@xfoil.gank.org>
To:        freebsd-current@freebsd.org
Subject:   Testers needed for if_ex multicast patch
Message-ID:  <1038417716.59621.30.camel@owen1492.it.oot>

next in thread | raw e-mail | index | archive | help

--=-CDQUCZt+cYpQqSWPpYB9
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

The attached patch adds multicast support for the ex (Intel EtherExpress
10/PRO 10 ISA and pccard) driver.  I ported this from the NetBSD driver
so I could do IPv6 on my 486 router at home ;).  It also seems that the
original ex might not have completely supported promiscuous mode, but
that should be functional as well now.

I'd appreciate if it some people who have one or more of these cards
could test it and make sure it doesn't break anything.  If you're using
multicast routing or IPv6 and can give it a try in those environments to
make sure it works as advertised, that would be even better.  It seems
to work fine on my cards which are mostly ISA Intel Pro/10s (00:aa:00)
and a Pro/10+ (00:a0:c9).

The patch should be applied in the sys/dev/ex directory.  Please send me
reports of any problems, no matter how small, along with your board type
and version if available, and the first three MAC address octets.  Code
improvements are of course welcome also :)

I've tried to match the style of the rest of the ex driver.  I don't
think the driver is quite style(9) compliant, but I wanted to keep the
patch as simple as possible.

I'll give it a week or two of testing and then submit to Matthew Dodd
for his review after code freeze is over.

Thanks!

Craig Boston

--=-CDQUCZt+cYpQqSWPpYB9
Content-Disposition: attachment; filename=ex_current_multicast.patch
Content-Type: text/x-patch; name=ex_current_multicast.patch; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: if_ex.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ex/if_ex.c,v
retrieving revision 1.39
diff -u -r1.39 if_ex.c
--- if_ex.c	2002/11/14 23:54:51	1.39
+++ if_ex.c	2002/11/27 16:55:21
@@ -35,6 +35,7 @@
  *
  * Revision history:
  *
+ * dd-mmm-yyyy: Multicast support ported from NetBSD's if_iy driver.
  * 30-Oct-1996: first beta version. Inet and BPF supported, but no multicast.
  */
 
@@ -54,6 +55,7 @@
 
 #include <net/if.h>
 #include <net/if_arp.h>
+#include <net/if_dl.h>
 #include <net/if_media.h> 
 #include <net/ethernet.h>
 #include <net/bpf.h>
@@ -103,6 +105,7 @@
 static int	ex_get_media	(u_int32_t iobase);
 
 static void	ex_reset	(struct ex_softc *);
+static void	ex_setmulti	(struct ex_softc *);
 
 static void	ex_tx_intr	(struct ex_softc *);
 static void	ex_rx_intr	(struct ex_softc *);
@@ -235,7 +238,7 @@
 	ifp->if_unit = unit;
 	ifp->if_name = "ex";
 	ifp->if_mtu = ETHERMTU;
-	ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST /* XXX not done yet. | IFF_MULTICAST */;
+	ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
 	ifp->if_output = ether_output;
 	ifp->if_start = ex_start;
 	ifp->if_ioctl = ex_ioctl;
@@ -349,6 +352,8 @@
 	ifp->if_flags &= ~IFF_OACTIVE;
 	DODEBUG(Status, printf("OIDLE init\n"););
 	
+	ex_setmulti(sc);
+	
 	/*
 	 * Final reset of the board, and enable operation.
 	 */
@@ -809,11 +814,9 @@
 			break;
 #endif
 		case SIOCADDMULTI:
-			DODEBUG(Start_End, printf("SIOCADDMULTI"););
 		case SIOCDELMULTI:
-			DODEBUG(Start_End, printf("SIOCDELMULTI"););
-			/* XXX Support not done yet. */
-			error = EINVAL;
+			ex_init(sc);
+			error = 0;
 			break;
 		case SIOCSIFMEDIA:
 		case SIOCGIFMEDIA:
@@ -831,6 +834,94 @@
 	return(error);
 }
 
+static void
+ex_setmulti(struct ex_softc *sc)
+{
+	struct ifnet *ifp;
+	struct ifmultiaddr *maddr;
+	u_int16_t *addr;
+	int iobase = sc->iobase;
+	int count;
+	int timeout, status;
+	
+	ifp = &sc->arpcom.ac_if;
+	maddr = ifp->if_multiaddrs.lh_first;
+
+	for (count = 0; maddr != NULL; maddr = maddr->ifma_link.le_next, count++);
+
+	if ((ifp->if_flags & IFF_PROMISC) || (ifp->if_flags & IFF_ALLMULTI)
+			|| count > 63) {
+		/* Interface is in promiscuous mode or there are too many
+		 * multicast addresses for the card to handle */
+		outb(iobase + CMD_REG, Bank2_Sel);
+		outb(iobase + REG2, inb(iobase + REG2) | Promisc_Mode);
+		outb(iobase + REG3, inb(iobase + REG3));
+		outb(iobase + CMD_REG, Bank0_Sel);
+	}
+	else if ((ifp->if_flags & IFF_MULTICAST) && (count > 0)) {
+		/* Program multicast addresses plus our MAC address
+		 * into the filter */
+		outb(iobase + CMD_REG, Bank2_Sel);
+		outb(iobase + REG2, inb(iobase + REG2) | Multi_IA);
+		outb(iobase + REG3, inb(iobase + REG3));
+		outb(iobase + CMD_REG, Bank0_Sel);
+
+		/* Borrow space from TX buffer; this should be safe
+		 * as this is only called from ex_init */
+		
+		outw(iobase + HOST_ADDR_REG, sc->tx_lower_limit);
+		outw(iobase + IO_PORT_REG, MC_Setup_CMD);
+		outw(iobase + IO_PORT_REG, 0);
+		outw(iobase + IO_PORT_REG, 0);
+		outw(iobase + IO_PORT_REG, (count + 1) * 6);
+		
+        	for (maddr = ifp->if_multiaddrs.lh_first; maddr != NULL;
+				maddr = maddr->ifma_link.le_next)
+		{
+			addr = (u_int16_t*)LLADDR((struct sockaddr_dl *)
+					maddr->ifma_addr);
+			outw(iobase + IO_PORT_REG, *addr++);
+			outw(iobase + IO_PORT_REG, *addr++);
+			outw(iobase + IO_PORT_REG, *addr++);
+		}
+
+		/* Program our MAC address as well */
+		/* XXX: Is this necessary?  The Linux driver does this
+		 * but the NetBSD driver does not */
+		addr = (u_int16_t*)(&sc->arpcom.ac_enaddr);
+		outw(iobase + IO_PORT_REG, *addr++);
+		outw(iobase + IO_PORT_REG, *addr++);
+		outw(iobase + IO_PORT_REG, *addr++);
+
+		inw(iobase + IO_PORT_REG);
+		outw(iobase + XMT_BAR, sc->tx_lower_limit);
+		outb(iobase + CMD_REG, MC_Setup_CMD);
+
+		sc->tx_head = sc->tx_lower_limit;
+		sc->tx_tail = sc->tx_head + XMT_HEADER_LEN + (count + 1) * 6;
+
+		for (timeout=0; timeout<100; timeout++) {
+			DELAY(2);
+			if ((inb(iobase + STATUS_REG) & Exec_Int) == 0)
+				continue;
+
+			status = inb(iobase + CMD_REG);
+			outb(iobase + STATUS_REG, Exec_Int);
+			break;
+		}
+
+		sc->tx_head = sc->tx_tail;
+	}
+	else
+	{
+		/* No multicast or promiscuous mode */
+		outb(iobase + CMD_REG, Bank2_Sel);
+		outb(iobase + REG2, inb(iobase + REG2) & 0xDE);
+			/* ~(Multi_IA | Promisc_Mode) */
+		outb(iobase + REG3, inb(iobase + REG3));
+		outb(iobase + CMD_REG, Bank0_Sel);
+	}
+}
 
 static void
 ex_reset(struct ex_softc *sc)
Index: if_exreg.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/ex/if_exreg.h,v
retrieving revision 1.3
diff -u -r1.3 if_exreg.h
--- if_exreg.h	2000/05/01 09:05:18	1.3
+++ if_exreg.h	2002/11/27 16:55:21
@@ -119,8 +119,10 @@
 #define Disc_Bad_Fr 0x80
 #define Tx_Chn_ErStp 0x40
 #define Tx_Chn_Int_Md 0x20
+#define Multi_IA 0x20
 #define No_SA_Ins 0x10
 #define RX_CRC_InMem 0x04
+#define Promisc_Mode 0x01
 #define BNC_bit 0x20
 #define TPE_bit 0x04
 #define I_ADDR_REG0 4

--=-CDQUCZt+cYpQqSWPpYB9--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1038417716.59621.30.camel>