diff options
| -rw-r--r-- | sys/src/cmd/nusb/ether/asix.c | 70 | ||||
| -rw-r--r-- | sys/src/cmd/nusb/ether/aue.c | 62 | ||||
| -rw-r--r-- | sys/src/cmd/nusb/ether/cdc.c | 51 | ||||
| -rw-r--r-- | sys/src/cmd/nusb/ether/dat.h | 43 | ||||
| -rw-r--r-- | sys/src/cmd/nusb/ether/ether.c | 218 | ||||
| -rw-r--r-- | sys/src/cmd/nusb/ether/smsc.c | 71 | ||||
| -rw-r--r-- | sys/src/cmd/nusb/ether/url.c | 64 |
7 files changed, 328 insertions, 251 deletions
diff --git a/sys/src/cmd/nusb/ether/asix.c b/sys/src/cmd/nusb/ether/asix.c index 4b725f57c..7ef5df64d 100644 --- a/sys/src/cmd/nusb/ether/asix.c +++ b/sys/src/cmd/nusb/ether/asix.c @@ -207,51 +207,53 @@ eepromread(Dev *d, int i) } static int -asixread(Dev *ep, uchar *p, int plen) +asixreceive(Dev *ep) { - int n, m; + Block *b; uint hd; + int n; - if(nbin < 4) - nbin = read(ep->dfd, bin, sizeof(bin)); - if(nbin < 0) + b = allocb(Maxpkt+4); + if((n = read(ep->dfd, b->wp, b->lim - b->base)) < 0){ + freeb(b); return -1; - if(nbin < 4) - return 0; - hd = GET4(bin); - n = hd & 0xFFFF; - m = n+4; - hd = (hd>>16) ^ 0xFFFF; - if((n != hd) || (n < 6) || (m > nbin)){ - nbin = 0; - return 0; } - if(n > plen) - n = plen; - if(n > 0) - memmove(p, bin+4, n); - if(m < nbin) - memmove(bin, bin+m, nbin - m); - nbin -= m; - return n; + b->wp += n; + while(BLEN(b) >= 4){ + hd = GET4(b->rp); + b->rp += 4; + n = hd & 0xFFFF; + hd = (hd>>16) ^ 0xFFFF; + if((n != hd) || (n > BLEN(b))) + break; + if(n == BLEN(b)){ + etheriq(b, 1); + return 0; + } + etheriq(copyblock(b, n), 1); + b->rp += n; + } + freeb(b); + return 0; } static void -asixwrite(Dev *ep, uchar *p, int n) +asixtransmit(Dev *ep, Block *b) { uint hd; + int n; - if(n > sizeof(bout)-8) - n = sizeof(bout)-8; + n = BLEN(b); hd = n | (n<<16)^0xFFFF0000; - PUT4(bout, hd); - memmove(bout+4, p, n); + b->rp -= 4; + PUT4(b->rp, hd); n += 4; if((n % ep->maxpkt) == 0){ - PUT4(bout+n, 0xFFFF0000); - n += 4; + PUT4(b->wp, 0xFFFF0000); + b->wp += 4; } - write(ep->dfd, bout, n); + write(ep->dfd, b->rp, BLEN(b)); + freeb(b); } static int @@ -312,8 +314,8 @@ a88178init(Dev *d) asixset(d, Cwmedium, Mall178); asixset(d, Cwrxctl, Rxctlso|Rxctlab); - epread = asixread; - epwrite = asixwrite; + epreceive = asixreceive; + eptransmit = asixtransmit; return 0; } @@ -369,7 +371,7 @@ a88772init(Dev *d) if(asixset(d, Cwrxctl, Rxctlso|Rxctlab) < 0) return -1; - epread = asixread; - epwrite = asixwrite; + epreceive = asixreceive; + eptransmit = asixtransmit; return 0; } diff --git a/sys/src/cmd/nusb/ether/aue.c b/sys/src/cmd/nusb/ether/aue.c index 1ee77a3cd..cccfefeaa 100644 --- a/sys/src/cmd/nusb/ether/aue.c +++ b/sys/src/cmd/nusb/ether/aue.c @@ -78,8 +78,6 @@ static int csr16r(Dev *, int); static int csr8w(Dev *, int, int); static int eeprom16r(Dev *, int); static void reset(Dev *); -static int aueread(Dev *, uchar *, int); -static void auewrite(Dev *, uchar *, int); static int csr8r(Dev *d, int reg) @@ -165,49 +163,43 @@ reset(Dev *d) } static int -aueread(Dev *ep, uchar *p, int plen) +auereceive(Dev *ep) { - int n; + Block *b; uint hd; - uchar *q; + int n; - if(nbin < 4) - nbin = read(ep->dfd, bin, sizeof bin); - if(nbin < 0) + b = allocb(Maxpkt+4); + if((n = read(ep->dfd, b->wp, b->lim - b->base)) < 0){ + freeb(b); return -1; - if(nbin < 4) + } + if(n < 4){ + freeb(b); return 0; - q = bin + nbin - 4; - hd = GET4(q); + } + b->wp += n-4; + hd = GET4(b->wp); n = hd & 0xfff; - if(n < 6 || n > nbin) { - nbin = 0; + if((hd & Rxerror) != 0 || n > BLEN(b)){ + freeb(b); return 0; } - if(hd & Rxerror) { - fprint(2, "%s: rx error %#ux\n", - argv0, hd); - n = 0; - } else { - if(n > plen) - n = plen; - if(n > 0) - memmove(p, bin, n); - } - if(n < nbin) - memmove(bin, bin+n, nbin-n); - nbin -= n; - return n; + b->wp = b->rp + n; + etheriq(b, 1); + return 0; } static void -auewrite(Dev *ep, uchar *p, int n) +auetransmit(Dev *ep, Block *b) { - if(n > sizeof bout-2) - n = sizeof bout - 2; - PUT2(bout, n); - memmove(bout+2, p, n); - write(ep->dfd, bout, n+2); + int n; + + n = BLEN(b); + b->rp -= 2; + PUT2(b->rp, n); + write(ep->dfd, b->rp, BLEN(b)); + freeb(b); } int @@ -227,7 +219,7 @@ aueinit(Dev *d) csr8w(d, Ctl0, C0rxstatappend|C0rxen); csr8w(d, Ctl0, csr8r(d, Ctl0)|C0txen); csr8w(d, Ctl2, csr8r(d, Ctl2)|C2ep3clr); - epread = aueread; - epwrite = auewrite; + epreceive = auereceive; + eptransmit = auetransmit; return 0; } diff --git a/sys/src/cmd/nusb/ether/cdc.c b/sys/src/cmd/nusb/ether/cdc.c index 28f56c0ae..c37efe145 100644 --- a/sys/src/cmd/nusb/ether/cdc.c +++ b/sys/src/cmd/nusb/ether/cdc.c @@ -5,33 +5,50 @@ #include <u.h> #include <libc.h> #include <thread.h> -#include <ip.h> #include "usb.h" #include "dat.h" +#include <ip.h> + static int -cdcread(Dev *ep, uchar *p, int n) +cdcreceive(Dev *ep) { - return read(ep->dfd, p, n); + Block *b; + int n; + + b = allocb(Maxpkt); + if((n = read(ep->dfd, b->wp, b->lim - b->base)) < 0){ + freeb(b); + return -1; + } + b->wp += n; + etheriq(b, 1); + return 0; } static void -cdcwrite(Dev *ep, uchar *p, int n) +cdctransmit(Dev *ep, Block *b) { - if(write(ep->dfd, p, n) < 0){ - fprint(2, "cdcwrite: %r\n"); - } else { - /* - * this may not work with all CDC devices. the - * linux driver sends one more random byte - * instead of a zero byte transaction. maybe we - * should do the same? - */ - if(n % ep->maxpkt == 0) - write(ep->dfd, "", 0); + int n; + + n = BLEN(b); + if(write(ep->dfd, b->rp, n) < 0){ + freeb(b); + return; } + freeb(b); + + /* + * this may not work with all CDC devices. the + * linux driver sends one more random byte + * instead of a zero byte transaction. maybe we + * should do the same? + */ + if((n % ep->maxpkt) == 0) + write(ep->dfd, "", 0); } + int cdcinit(Dev *d) { @@ -55,8 +72,8 @@ cdcinit(Dev *d) parseether(macaddr, mac); free(mac); - epread = cdcread; - epwrite = cdcwrite; + epreceive = cdcreceive; + eptransmit = cdctransmit; return 0; } } diff --git a/sys/src/cmd/nusb/ether/dat.h b/sys/src/cmd/nusb/ether/dat.h index 0e5a962ce..180e4596e 100644 --- a/sys/src/cmd/nusb/ether/dat.h +++ b/sys/src/cmd/nusb/ether/dat.h @@ -1,3 +1,36 @@ +typedef struct Block Block; +struct Block +{ + Ref; + + Block *next; + + uchar *rp; + uchar *wp; + uchar *lim; + + uchar base[]; +}; + +#define BLEN(s) ((s)->wp - (s)->rp) + +Block* allocb(int size); +void freeb(Block*); +Block* copyblock(Block*, int); + +typedef struct Ehdr Ehdr; +struct Ehdr +{ + uchar d[6]; + uchar s[6]; + uchar type[2]; +}; + +enum { + Ehdrsz = 6+6+2, + Maxpkt = 2000, +}; + enum { Cdcunion = 6, @@ -10,10 +43,8 @@ int setmac; /* to be filled in by *init() */ uchar macaddr[6]; -int (*epread)(Dev *, uchar *, int); -void (*epwrite)(Dev *, uchar *, int); -/* temporary buffers */ -uchar bout[4*1024]; -uchar bin[4*1024]; -int nbin; +void etheriq(Block*, int wire); + +int (*epreceive)(Dev*); +void (*eptransmit)(Dev*, Block*); diff --git a/sys/src/cmd/nusb/ether/ether.c b/sys/src/cmd/nusb/ether/ether.c index 042edcdcd..c7a622255 100644 --- a/sys/src/cmd/nusb/ether/ether.c +++ b/sys/src/cmd/nusb/ether/ether.c @@ -1,18 +1,17 @@ #include <u.h> #include <libc.h> #include <thread.h> -#include <fcall.h> -#include <9p.h> -#include <ip.h> #include "usb.h" #include "dat.h" +#include <fcall.h> +#include <9p.h> +#include <ip.h> + typedef struct Tab Tab; -typedef struct Qbuf Qbuf; typedef struct Dq Dq; typedef struct Conn Conn; -typedef struct Ehdr Ehdr; typedef struct Stats Stats; enum @@ -48,41 +47,31 @@ Tab tab[] = "type", 0444, }; -struct Qbuf -{ - Qbuf *next; - int ndata; - uchar data[]; -}; - struct Dq { - QLock l; + QLock; + Dq *next; Req *r; Req **rt; - Qbuf *q; - Qbuf **qt; + Block *q; + Block **qt; + + int size; int nb; }; struct Conn { - QLock l; + QLock; + int used; int type; int prom; Dq *dq; }; -struct Ehdr -{ - uchar d[6]; - uchar s[6]; - uchar type[2]; -}; - struct Stats { int in; @@ -104,9 +93,6 @@ static char *uname; #define NUM(path) (((uint)(path) & 0xFFFFFF00)>>8) #define NUMCONN(c) (((long)(c)-(long)&conn[0])/sizeof(conn[0])) -static int -receivepacket(void *buf, int len); - static void fillstat(Dir *d, uvlong path) { @@ -238,24 +224,27 @@ static void matchrq(Dq *d) { Req *r; - Qbuf *b; + Block *b; while(r = d->r){ int n; if((b = d->q) == nil) break; + + d->size -= BLEN(b); if((d->q = b->next) == nil) d->qt = &d->q; if((d->r = (Req*)r->aux) == nil) d->rt = &d->r; n = r->ifcall.count; - if(n > b->ndata) - n = b->ndata; - memmove(r->ofcall.data, b->data, n); - free(b); + if(n > BLEN(b)) + n = BLEN(b); + memmove(r->ofcall.data, b->rp, n); r->ofcall.count = n; + freeb(b); + respond(r, nil); } } @@ -266,19 +255,18 @@ readconndata(Req *r) Dq *d; d = r->fid->aux; - qlock(&d->l); + qlock(d); if(d->q==nil && d->nb){ - qunlock(&d->l); + qunlock(d); r->ofcall.count = 0; respond(r, nil); return; } - // enqueue request r->aux = nil; *d->rt = r; d->rt = (Req**)&r->aux; matchrq(d); - qunlock(&d->l); + qunlock(d); } static void @@ -287,6 +275,7 @@ writeconndata(Req *r) Dq *d; void *p; int n; + Block *b; d = r->fid->aux; p = r->ifcall.data; @@ -295,11 +284,28 @@ writeconndata(Req *r) d->nb = 1; goto out; } - epwrite(epout, p, n); - if(receivepacket(p, n) == 0) - stats.out++; + + /* minimum frame length for rtl8150 */ + if(n < 60) + n = 60; + + /* slack space for header and trailers */ + n += 2*16; + + b = allocb(n); + + /* header space */ + b->wp += 16; + b->rp = b->wp; + + /* copy in the ethernet packet */ + memmove(b->wp, p, r->ifcall.count); + b->wp += r->ifcall.count; + + etheriq(b, 0); + out: - r->ofcall.count = n; + r->ofcall.count = r->ifcall.count; respond(r, nil); } @@ -433,7 +439,6 @@ fsopen(Req *r) Dq *d; Conn *c; - /* * lib9p already handles the blatantly obvious. * we just have to enforce the permissions we have set. @@ -472,7 +477,7 @@ fsopen(Req *r) case Qtype: CaseConn: c = &conn[NUM(path)]; - qlock(&c->l); + qlock(c); if(c->used++ == 0){ c->type = 0; c->prom = 0; @@ -481,7 +486,7 @@ fsopen(Req *r) d->next = c->dq; c->dq = d; } - qunlock(&c->l); + qunlock(c); break; } @@ -501,7 +506,7 @@ fsflush(Req *r) f = o->fid; if(TYPE(f->qid.path) == Qdata){ d = f->aux; - qlock(&d->l); + qlock(d); for(p=&d->r; *p; p=(Req**)&((*p)->aux)){ if(*p == o){ if((*p = (Req*)o->aux) == nil) @@ -511,7 +516,7 @@ fsflush(Req *r) break; } } - qunlock(&d->l); + qunlock(d); } respond(r, nil); } @@ -521,12 +526,12 @@ static void fsdestroyfid(Fid *fid) { Conn *c; - Qbuf *b; Dq **x, *d; + Block *b; if(TYPE(fid->qid.path) >= Qndir){ c = &conn[NUM(fid->qid.path)]; - qlock(&c->l); + qlock(c); if(d = fid->aux){ fid->aux = nil; for(x=&c->dq; *x; x=&((*x)->next)){ @@ -535,17 +540,16 @@ fsdestroyfid(Fid *fid) break; } } - qlock(&d->l); while(b = d->q){ d->q = b->next; - free(b); + freeb(b); } - qunlock(&d->l); + free(d); } if(TYPE(fid->qid.path) == Qctl) c->prom = 0; c->used--; - qunlock(&c->l); + qunlock(c); } } @@ -648,26 +652,26 @@ inote(void *, char *msg) return 0; } -static int -receivepacket(void *buf, int len) +void +etheriq(Block *b, int wire) { - int i; - int t; + int i, t; + Block *q; + Conn *c; + Dq *d; Ehdr *h; - if(len < sizeof(*h)) - return -1; + if(BLEN(b) < Ehdrsz){ + freeb(b); + return; + } - h = (Ehdr*)buf; + h = (Ehdr*)b->rp; t = (h->type[0]<<8)|h->type[1]; for(i=0; i<nconn; i++){ - Qbuf *b; - Conn *c; - Dq *d; - c = &conn[i]; - qlock(&c->l); + qlock(c); if(!c->used) goto next; if(c->type > 0) @@ -677,36 +681,42 @@ receivepacket(void *buf, int len) if(memcmp(h->d, macaddr, sizeof(macaddr))) goto next; for(d=c->dq; d; d=d->next){ - int n; - - n = len; - if(c->type == -2 && n > 64) - n = 64; - - b = emalloc9p(sizeof(*b) + n); - b->ndata = n; - memcpy(b->data, buf, n); - - qlock(&d->l); - // enqueue buffer - b->next = nil; - *d->qt = b; - d->qt = &b->next; + if(d->size > 100000) + continue; + if(c->type == -2) { + q = copyblock(b, 64); + } else if(wire && b->ref == 1) { + incref(b); + q = b; + } else { + q = copyblock(b, BLEN(b)); + } + qlock(d); + q->next = nil; + *d->qt = q; + d->qt = &q->next; + d->size += BLEN(q); matchrq(d); - qunlock(&d->l); + qunlock(d); } next: - qunlock(&c->l); + qunlock(c); + } + if(wire) { + freeb(b); + stats.in++; + } else { + /* transmit frees buffer */ + (*eptransmit)(epout, b); + stats.out++; } - return 0; } static void usbreadproc(void *) { char err[ERRMAX]; - uchar buf[4*1024]; - int n, nerr; + int nerr; atnotify(inote, 1); @@ -714,8 +724,8 @@ usbreadproc(void *) nerr = 0; for(;;){ - n = epread(epin, buf, sizeof(buf)); - if(n < 0){ + /* receive allocates buffer and calls etheriq(b, 1); */ + if((*epreceive)(epin) < 0){ rerrstr(err, sizeof(err)); if(strstr(err, "interrupted") || strstr(err, "timed out")) continue; @@ -725,10 +735,6 @@ usbreadproc(void *) threadexitsall(err); } nerr = 0; - if(n == 0) - continue; - if(receivepacket(buf, n) == 0) - stats.in++; } } @@ -819,7 +825,7 @@ threadmain(int argc, char **argv) werrstr(""); if((*ethertype[et].init)(d) < 0) sysfatal("%s init failed: %r", ethertype[et].name); - if(epread == nil || epwrite == nil) + if(epreceive == nil || eptransmit == nil) sysfatal("bug in init"); if((epin = openep(d, ei)) == nil) @@ -846,3 +852,37 @@ threadmain(int argc, char **argv) threadexits(0); } + +Block* +allocb(int size) +{ + Block *b; + + b = emalloc9p(sizeof(*b) + size); + b->lim = b->base + size; + b->rp = b->base; + b->wp = b->base; + b->next = nil; + b->ref = 1; + return b; +} + +void +freeb(Block *b) +{ + if(decref(b) == 0) + free(b); +} + +Block* +copyblock(Block *b, int count) +{ + Block *nb; + + if(count > BLEN(b)) + count = BLEN(b); + nb = allocb(count); + memmove(nb->wp, b->rp, count); + nb->wp += count; + return nb; +} diff --git a/sys/src/cmd/nusb/ether/smsc.c b/sys/src/cmd/nusb/ether/smsc.c index cefdeb2ed..deb8aef43 100644 --- a/sys/src/cmd/nusb/ether/smsc.c +++ b/sys/src/cmd/nusb/ether/smsc.c @@ -205,48 +205,51 @@ doreset(Dev *d, int reg, int bit) } static int -smscread(Dev *ep, uchar *p, int plen) +smscreceive(Dev *ep) { - int n, m; + Block *b; uint hd; + int n; - if(nbin < 4) - nbin = read(ep->dfd, bin, Doburst ? Hsburst*512: sizeof(bin)); - if(nbin < 0) + if(Doburst) + b = allocb(Hsburst*512); + else + b = allocb(Maxpkt+4); + if((n = read(ep->dfd, b->wp, b->lim - b->base)) < 0){ + freeb(b); return -1; - if(nbin < 4) - return 0; - hd = GET4(bin); - n = hd >> 16; - m = (n + 4 + 3) & ~3; - if(n < 6 || n > nbin-4){ - nbin = 0; - return 0; } - if(hd & Rxerror){ - fprint(2, "smsc rx error %8.8ux\n", hd); - n = 0; - }else{ - if(n > plen) - n = plen; - if(n > 0) - memmove(p, bin+4, n); + b->wp += n; + while(BLEN(b) >= 4){ + hd = GET4(b->rp); + b->rp += 4; + n = hd >> 16; + if(n > BLEN(b)) + break; + if((hd & Rxerror) == 0){ + if(n == BLEN(b)){ + etheriq(b, 1); + return 0; + } + etheriq(copyblock(b, n), 1); + } + b->rp += (n + 3) & ~3; } - if(m < nbin) - memmove(bin, bin+m, nbin - m); - nbin -= m; - return n; + freeb(b); + return 0; } static void -smscwrite(Dev *ep, uchar *p, int n) +smsctransmit(Dev *ep, Block *b) { - if(n > sizeof(bout)-8) - n = sizeof(bout)-8; - PUT4(bout, n | Txfirst | Txlast); - PUT4(bout+4, n); - memmove(bout+8, p, n); - write(ep->dfd, bout, n+8); + int n; + + n = BLEN(b); + b->rp -= 8; + PUT4(b->rp, n | Txfirst | Txlast); + PUT4(b->rp+4, n); + write(ep->dfd, b->rp, BLEN(b)); + freeb(b); } int @@ -284,7 +287,7 @@ smscinit(Dev *d) wr(d, Maccr, rr(d, Maccr)|Txen|Rxen); wr(d, Txcfg, Txon); - epwrite = smscwrite; - epread = smscread; + eptransmit = smsctransmit; + epreceive = smscreceive; return 0; } diff --git a/sys/src/cmd/nusb/ether/url.c b/sys/src/cmd/nusb/ether/url.c index af3cfe7c2..a411c6d4d 100644 --- a/sys/src/cmd/nusb/ether/url.c +++ b/sys/src/cmd/nusb/ether/url.c @@ -164,8 +164,6 @@ static int csr8w(Dev *, int, int); static int csr16w(Dev *, int, int); static int csr32w(Dev *, int, int); static void reset(Dev *); -static int urlread(Dev *, uchar *, int); -static void urlwrite(Dev *, uchar *, int); int urlinit(Dev *); static int @@ -263,49 +261,43 @@ reset(Dev *d) } static int -urlread(Dev *ep, uchar *p, int plen) +urlreceive(Dev *ep) { - int n; + Block *b; uint hd; - uchar *q; + int n; - if(nbin < 4) - nbin = read(ep->dfd, bin, sizeof bin); - if(nbin < 0) + b = allocb(Maxpkt+4); + if((n = read(ep->dfd, b->wp, b->lim - b->base)) < 0){ + freeb(b); return -1; - if(nbin < 4) - return 0; - n = nbin - 4; - if(n < 6) { - nbin = 0; - return 0; } - q = bin + n; - hd = GET2(q); - if((hd & Vpm) == 0) { - fprint(2, "url: rx error: %#.4ux\n", hd); - n = 0; - } else { - if(n > plen) - n = plen; - if(n > 0) - memmove(p, bin, n); + if(n < 4){ + freeb(b); + return 0; } - nbin = 0; - return n; + n -= 4; + b->wp += n; + hd = GET2(b->wp); + if((hd & Vpm) == 0) + freeb(b); + else + etheriq(b, 1); + return 0; } static void -urlwrite(Dev *ep, uchar *p, int n) +urltransmit(Dev *ep, Block *b) { - if(n > sizeof bout) - n = sizeof bout; - memmove(bout, p, n); - if(n < Mfl) { - memset(bout+n, 0, Mfl-n); - n = Mfl; + int n; + + n = BLEN(b); + if(n < Mfl){ + memset(b->wp, 0, Mfl-n); + b->wp += (Mfl-n); } - write(ep->dfd, bout, n); + write(ep->dfd, b->rp, BLEN(b)); + freeb(b); } int @@ -331,7 +323,7 @@ urlinit(Dev *d) csr8w(d, Cr, Te|Re); - epwrite = urlwrite; - epread = urlread; + epreceive = urlreceive; + eptransmit = urltransmit; return 0; } |
