shithub: riscv

Download patch

ref: c937aac59bf77b56e665564092e680159a118115
parent: 7bcbef11eb17d0b5f756acd74762d1a285aa134f
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Sep 16 19:21:54 EDT 2016

nusb/ether: experimental pomisc mode and multicast support for smsc and asix

--- a/sys/src/cmd/nusb/ether/asix.c
+++ b/sys/src/cmd/nusb/ether/asix.c
@@ -262,7 +262,7 @@
 	int rxctl;
 
 	rxctl = getrxctl(d);
-	if(on != 0)
+	if(on)
 		rxctl |= Rxctlprom;
 	else
 		rxctl &= ~Rxctlprom;
@@ -269,6 +269,19 @@
 	return asixset(d, Cwrxctl, rxctl);
 }
 
+static int
+asixmulticast(Dev *d, uchar*, int)
+{
+	int rxctl;
+
+	rxctl = getrxctl(d);
+	if(nmulti != 0)
+		rxctl |= Rxctlamall;
+	else
+		rxctl &= ~Rxctlamall;
+	return asixset(d, Cwrxctl, rxctl);
+}
+
 int
 a88178init(Dev *d)
 {
@@ -316,6 +329,9 @@
 
 	epreceive = asixreceive;
 	eptransmit = asixtransmit;
+	eppromiscuous = asixpromiscuous;
+	epmulticast = asixmulticast;
+
 	return 0;
 }
 
@@ -373,5 +389,8 @@
 
 	epreceive = asixreceive;
 	eptransmit = asixtransmit;
+	eppromiscuous = asixpromiscuous;
+	epmulticast = asixmulticast;
+
 	return 0;
 }
--- a/sys/src/cmd/nusb/ether/dat.h
+++ b/sys/src/cmd/nusb/ether/dat.h
@@ -44,7 +44,13 @@
 /* to be filled in by *init() */
 uchar macaddr[6];
 
+int nprom;
+int nmulti;
+uchar multiaddr[32][6];
+
 void	etheriq(Block*, int wire);
 
 int	(*epreceive)(Dev*);
 void	(*eptransmit)(Dev*, Block*);
+int 	(*eppromiscuous)(Dev*, int);
+int	(*epmulticast)(Dev*, uchar*, int);
--- a/sys/src/cmd/nusb/ether/ether.c
+++ b/sys/src/cmd/nusb/ether/ether.c
@@ -82,6 +82,10 @@
 Conn conn[32];
 int nconn = 0;
 
+int nprom = 0;
+int nmulti = 0;
+
+Dev *epctl;
 Dev *epin;
 Dev *epout;
 
@@ -401,9 +405,37 @@
 	case Qctl:
 		n = r->ifcall.count;
 		p = (char*)r->ifcall.data;
-		if((n == 11) && memcmp(p, "promiscuous", 11)==0)
-			conn[NUM(path)].prom = 1;
-		if((n > 8) && memcmp(p, "connect ", 8)==0){
+		if(n == 11 && memcmp(p, "promiscuous", 11)==0){
+			if(conn[NUM(path)].prom == 0){
+				conn[NUM(path)].prom = 1;
+				if(nprom++ == 0 && eppromiscuous != nil)
+					(*eppromiscuous)(epctl, 1);
+			}
+		} else if(n >= 9+12 && (memcmp(p, "addmulti ", 9)==0 || memcmp(p, "remmulti ", 9)==0)){
+			uchar ea[6];
+			int i;
+
+			if(parseether(ea, p+9) < 0){
+				respond(r, "bad ether address");
+				return;
+			}
+			for(i=0; i<nmulti; i++)
+				if(memcmp(ea, multiaddr[i], 6) == 0)
+					break;
+			if(i < nmulti){
+				if(*p == 'r'){
+					memmove(multiaddr[i], multiaddr[--nmulti], 6);
+					if(epmulticast != nil)
+						(*epmulticast)(epctl, ea, 0);
+				}
+			} else if(nmulti < nelem(multiaddr)){
+				if(*p == 'a'){
+					memmove(multiaddr[nmulti++], ea, 6);
+					if(epmulticast != nil)
+						(*epmulticast)(epctl, ea, 1);
+				}
+			}
+		} else if(n > 8 && memcmp(p, "connect ", 8)==0){
 			char x[12];
 
 			if(n - 8 >= sizeof(x)){
@@ -546,8 +578,13 @@
 			}
 			free(d);
 		}
-		if(TYPE(fid->qid.path) == Qctl)
-			c->prom = 0;
+		if(TYPE(fid->qid.path) == Qctl){
+			if(c->prom){
+				c->prom = 0;
+				if(--nprom == 0 && eppromiscuous != nil)
+					(*eppromiscuous)(epctl, 0);
+			}
+		}
 		c->used--;
 		qunlock(c);
 	}
@@ -783,7 +820,6 @@
 {
 	char s[64], *t;
 	int et, ei, eo;
-	Dev *d;
 
 	fmtinstall('E', eipfmt);
 
@@ -819,18 +855,18 @@
 	if(argc != 1)
 		usage();
 
-	if((d = getdev(*argv)) == nil)
+	if((epctl = getdev(*argv)) == nil)
 		sysfatal("getdev: %r");
-	if(findendpoints(d, &ei, &eo) < 0)
+	if(findendpoints(epctl, &ei, &eo) < 0)
 		sysfatal("no endpoints found");
 
 	werrstr("");
-	if((*ethertype[et].init)(d) < 0)
+	if((*ethertype[et].init)(epctl) < 0)
 		sysfatal("%s init failed: %r", ethertype[et].name);
 	if(epreceive == nil || eptransmit == nil)
 		sysfatal("bug in init");
 
-	if((epin = openep(d, ei)) == nil)
+	if((epin = openep(epctl, ei)) == nil)
 		sysfatal("openep: %r");
 	if(ei == eo){
 		incref(epin);
@@ -837,7 +873,7 @@
 		epout = epin;
 		opendevdata(epin, ORDWR);
 	} else {
-		if((epout = openep(d, eo)) == nil)
+		if((epout = openep(epctl, eo)) == nil)
 			sysfatal("openep: %r");
 		opendevdata(epin, OREAD);
 		opendevdata(epout, OWRITE);
@@ -847,9 +883,9 @@
 
 	atnotify(inote, 1);
 	time0 = time(0);
-	tab[Qiface].name = smprint("etherU%s", d->hname);
-	snprint(s, sizeof(s), "%d.ether", d->id);
-	closedev(d);
+	tab[Qiface].name = smprint("etherU%s", epctl->hname);
+	snprint(s, sizeof(s), "%d.ether", epctl->id);
+
 	threadpostsharesrv(&fs, nil, "usbnet", s);
 
 	threadexits(0);
--- a/sys/src/cmd/nusb/ether/smsc.c
+++ b/sys/src/cmd/nusb/ether/smsc.c
@@ -252,6 +252,32 @@
 	freeb(b);
 }
 
+static int
+smscpromiscuous(Dev *d, int on)
+{
+	int rxctl;
+
+	rxctl = rr(d, Maccr);
+	if(on)
+		rxctl |= Prms;
+	else
+		rxctl &= ~Prms;
+	return wr(d, Maccr, rxctl);
+}
+
+static int
+smscmulticast(Dev *d, uchar *, int)
+{
+	int rxctl;
+
+	rxctl = rr(d, Maccr);
+	if(nmulti != 0)
+		rxctl |= Mcpas;
+	else
+		rxctl &= ~Mcpas;
+	return wr(d, Maccr, rxctl);
+}
+
 int
 smscinit(Dev *d)
 {
@@ -289,5 +315,8 @@
 
 	eptransmit = smsctransmit;
 	epreceive = smscreceive;
+	eppromiscuous = smscpromiscuous;
+	epmulticast = smscmulticast;
+
 	return 0;
 }