summaryrefslogtreecommitdiff
path: root/sys/src/cmd/nusb
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-10-18 18:41:27 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-10-18 18:41:27 +0200
commit8ceb100fa4081cc441acc693190ce7da55fcb3af (patch)
treee77b5fe15f378c777981c7ed25bdea2898653b62 /sys/src/cmd/nusb
parent5bfaf253d3ea0f0d60eb12b45b0866a79c5ae66b (diff)
nusb/ether: new driver interface with kernel inspired Block buffers
introduce kernel inspured Block structure with read/write pointers to pass packets arround. the intend is to avoid copying when adding/removing frame headers and simplifying the drivers. the driver now calls etheriq() directly allowing it to queue multiple packets in one pass without having to keep state. transmit gets a buffer passed that has room for frame headers and trailers so no copying is needed. blocks are refcounted avoiding another copy when passed to only one receive queue (common case). receive queues are now limited to 100KB avoiding buffer bloat. Dq* a memory leak in destroyfid has been fixed. lots of minor cleanups.
Diffstat (limited to 'sys/src/cmd/nusb')
-rw-r--r--sys/src/cmd/nusb/ether/asix.c70
-rw-r--r--sys/src/cmd/nusb/ether/aue.c62
-rw-r--r--sys/src/cmd/nusb/ether/cdc.c51
-rw-r--r--sys/src/cmd/nusb/ether/dat.h43
-rw-r--r--sys/src/cmd/nusb/ether/ether.c218
-rw-r--r--sys/src/cmd/nusb/ether/smsc.c71
-rw-r--r--sys/src/cmd/nusb/ether/url.c64
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;
}