summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/cmd/nusb/serial/ftdi.c18
-rw-r--r--sys/src/cmd/nusb/serial/prolific.c21
-rw-r--r--sys/src/cmd/nusb/serial/serial.c293
-rw-r--r--sys/src/cmd/nusb/serial/serial.h8
-rw-r--r--sys/src/cmd/nusb/serial/silabs.c11
5 files changed, 134 insertions, 217 deletions
diff --git a/sys/src/cmd/nusb/serial/ftdi.c b/sys/src/cmd/nusb/serial/ftdi.c
index fec86ed64..67d28b897 100644
--- a/sys/src/cmd/nusb/serial/ftdi.c
+++ b/sys/src/cmd/nusb/serial/ftdi.c
@@ -1235,12 +1235,9 @@ wait4data(Serialport *p, uchar *data, int count)
count = p->ndata;
p->ndata = 0;
}
- assert(count >= 0);
- assert(p->ndata >= 0);
memmove(data, p->data, count);
if(p->ndata != 0)
memmove(p->data, p->data+count, p->ndata);
-
recvul(p->gotdata);
return count;
}
@@ -1313,7 +1310,6 @@ static void
epreader(void *u)
{
int dfd, rcount, cl, ntries, recov;
- char err[40];
Areader *a;
Channel *c;
Packser *pk;
@@ -1333,7 +1329,7 @@ epreader(void *u)
ntries = 0;
pk = nil;
- do {
+ for(;;) {
if (pk == nil)
pk = emallocz(sizeof(Packser), 1);
Eagain:
@@ -1374,7 +1370,7 @@ Eagain:
ntries = 0;
pk = nil;
}
- } while(rcount >= 0 || (rcount < 0 && strstr(err, "timed out") != nil));
+ }
if(rcount < 0)
fprint(2, "%s: error reading %s: %r\n", argv0, p->name);
@@ -1413,16 +1409,13 @@ statusreader(void *u)
memmove(p->data, pk->b, pk->nb);
p->ndata = pk->nb;
free(pk);
- dsprint(2, "serial %p: status reader %d \n", p, p->ndata);
/* consume it all */
while(p->ndata != 0){
- dsprint(2, "serial %p: status reader to consume: %d\n",
- p, p->ndata);
cl = recvul(p->w4data);
- if(cl < 0)
+ if(cl < 0)
break;
cl = sendul(p->gotdata, 1);
- if(cl < 0)
+ if(cl < 0)
break;
}
}
@@ -1473,9 +1466,6 @@ ftinit(Serialport *p)
return -1;
dsprint(2, "serial: jtag latency timer set to %d\n", timerval);
- /* may be unnecessary */
- devctl(p->epin, "timeout 5000");
- devctl(p->epout, "timeout 5000");
/* 0xb is the mask for lines. plug dependant? */
ftdiwrite(p, BMMPSSE|0x0b, 0, FTSETBITMODE);
}
diff --git a/sys/src/cmd/nusb/serial/prolific.c b/sys/src/cmd/nusb/serial/prolific.c
index a0a489111..4ada08fa9 100644
--- a/sys/src/cmd/nusb/serial/prolific.c
+++ b/sys/src/cmd/nusb/serial/prolific.c
@@ -446,12 +446,13 @@ plinit(Serialport *p)
plgetparam(p);
qunlock(ser);
free(buf);
- st = emallocz(255, 1);
qlock(ser);
- if(serialdebug)
+ if(serialdebug){
+ st = emallocz(255, 1);
serdumpst(p, st, 255);
- dsprint(2, st);
- free(st);
+ dsprint(2, "%s", st);
+ free(st);
+ }
/* p gets freed by closedev, the process has a reference */
incref(ser->dev);
proccreate(statusreader, p, 8*1024);
@@ -528,31 +529,26 @@ static int
plreadstatus(Serialport *p)
{
int nr, dfd;
- char err[40];
+ char err[ERRMAX];
uchar buf[VendorReqSz];
Serial *ser;
ser = p->s;
qlock(ser);
- dsprint(2, "serial: reading from interrupt\n");
dfd = p->epintr->dfd;
-
qunlock(ser);
nr = read(dfd, buf, sizeof buf);
qlock(ser);
- snprint(err, sizeof err, "%r");
- dsprint(2, "serial: interrupt read %d %r\n", nr);
-
+ rerrstr(err, sizeof err);
if(nr < 0 && strstr(err, "timed out") == nil){
- dsprint(2, "serial: need to recover, status read %d %r\n", nr);
if(serialrecover(ser, nil, nil, err) < 0){
qunlock(ser);
return -1;
}
}
if(nr < 0)
- dsprint(2, "serial: reading status: %r");
+ dsprint(2, "serial: reading status: %r\n");
else if(nr >= sizeof buf - 1){
p->dcd = buf[8] & DcdStatus;
p->dsr = buf[8] & DsrStatus;
@@ -567,7 +563,6 @@ plreadstatus(Serialport *p)
p->novererr++;
} else
dsprint(2, "serial: bad status read %d\n", nr);
- dsprint(2, "serial: finished read from interrupt %d\n", nr);
qunlock(ser);
return 0;
}
diff --git a/sys/src/cmd/nusb/serial/serial.c b/sys/src/cmd/nusb/serial/serial.c
index 1fd804bd3..9f570791f 100644
--- a/sys/src/cmd/nusb/serial/serial.c
+++ b/sys/src/cmd/nusb/serial/serial.c
@@ -414,136 +414,109 @@ dstat(Req *req)
respond(req, nil);
}
-enum {
- Serbufsize = 255,
-};
-
static void
-readproc(void *aux)
+procread(Req *req)
{
+ int count, rcount;
+ void *data;
+ Serial *ser;
+ Serialport *p;
+ char err[ERRMAX];
int dfd;
- Req *req;
- long count, rcount;
+
+ p = req->aux;
+ ser = p->s;
+ data = req->ofcall.data;
+ count = req->ifcall.count;
+Again:
+ qlock(ser);
+ if(count > ser->maxread)
+ count = ser->maxread;
+ if(ser->wait4data != nil) {
+ rcount = ser->wait4data(p, data, count);
+ qunlock(ser);
+ } else {
+ dfd = p->epin->dfd;
+ qunlock(ser);
+ rcount = read(dfd, data, count);
+ }
+ if(rcount < 0) {
+ err[0] = 0;
+ errstr(err, sizeof err);
+ if(p->rq->flush == 0 && strstr(err, "timed out") != nil)
+ goto Again;
+ respond(req, err);
+ } else {
+ req->ofcall.count = rcount;
+ respond(req, nil);
+ }
+}
+
+static void
+procwrite(Req *req)
+{
+ int count, wcount;
void *data;
Serial *ser;
Serialport *p;
- static int errrun, good;
- char err[Serbufsize];
+ char err[ERRMAX];
+ int dfd;
- p = aux;
+ p = req->aux;
ser = p->s;
- for(;;){
- qlock(&p->readq);
- while(p->readfirst == nil)
- rsleep(&p->readrend);
- req = p->readfirst;
- p->readfirst = req->aux;
- if(p->readlast == req)
- p->readlast = nil;
- req->aux = nil;
- qunlock(&p->readq);
+ data = req->ifcall.data;
+ count = req->ifcall.count;
+ qlock(ser);
+ if(ser->wait4data != nil) {
+ wcount = ser->wait4write(p, data, count);
+ qunlock(ser);
+ } else {
+ dfd = p->epout->dfd;
+ qunlock(ser);
+ wcount = write(dfd, data, count);
+ }
+ if(wcount != count) {
+ err[0] = 0;
+ errstr(err, sizeof err);
+ respond(req, err);
- count = req->ifcall.count;
- data = req->ofcall.data;
qlock(ser);
- if(count > ser->maxread)
- count = ser->maxread;
- dsprint(2, "serial: reading from data\n");
- do {
- err[0] = 0;
- dfd = p->epin->dfd;
- if(usbdebug >= 3)
- dsprint(2, "serial: reading: %ld\n", count);
-
- assert(count > 0);
- if(ser->wait4data != nil)
- rcount = ser->wait4data(p, data, count);
- else{
- qunlock(ser);
- rcount = read(dfd, data, count);
- qlock(ser);
- }
- /*
- * if we encounter a long run of continuous read
- * errors, do something drastic so that our caller
- * doesn't just spin its wheels forever.
- */
- if(rcount < 0) {
- snprint(err, Serbufsize, "%r");
- ++errrun;
- sleep(20);
- if (good > 0 && errrun > 10000) {
- /* the line has been dropped; give up */
- qunlock(ser);
- fprint(2, "%s: line %s is gone: %r\n",
- argv0, p->name);
- threadexitsall("serial line gone");
- }
- } else {
- errrun = 0;
- good++;
- }
- if(usbdebug >= 3)
- dsprint(2, "serial: read: %s %ld\n", err, rcount);
- } while(rcount < 0 && strstr(err, "timed out") != nil);
-
- dsprint(2, "serial: read from bulk %ld, %10.10s\n", rcount, err);
- if(rcount < 0){
- dsprint(2, "serial: need to recover, data read %ld %r\n",
- count);
- serialrecover(ser, p, p->epin, err);
- }
- dsprint(2, "serial: read from bulk %ld\n", rcount);
- if(rcount >= 0){
- req->ofcall.count = rcount;
- respond(req, nil);
- } else
- responderror(req);
+ serialrecover(p->s, p, p->epout, err);
qunlock(ser);
+ } else {
+ req->ofcall.count = wcount;
+ respond(req, nil);
}
}
static void
dread(Req *req)
{
- char *e; /* change */
- Qid q;
Serial *ser;
- vlong offset;
Serialport *p;
- static char buf[Serbufsize];
-
- q = req->fid->qid;
+ ulong path;
- if(q.path == 0){
+ path = req->fid->qid.path;
+ if(path == 0){
dirread9p(req, dirgen, nil);
respond(req, nil);
return;
}
- p = ports[(q.path - 1) / 2];
+ p = ports[(path - 1) / 2];
ser = p->s;
- offset = req->ifcall.offset;
-
- memset(buf, 0, sizeof buf);
qlock(ser);
- switch((long)((q.path - 1) % 2)){
+ switch((path - 1) % 2){
case 0:
- qlock(&p->readq);
- if(p->readfirst == nil)
- p->readfirst = req;
- else
- p->readlast->aux = req;
- p->readlast = req;
- rwakeup(&p->readrend);
- qunlock(&p->readq);
+ req->aux = p;
+ reqqueuepush(p->rq, req, procread);
break;
case 1:
- if(offset == 0) {
- if(!p->isjtag){
- e = serdumpst(p, buf, Serbufsize);
- readbuf(req, buf, e - buf);
- }
+ req->ofcall.count = 0;
+ if(req->ifcall.offset == 0 && !p->isjtag){
+ char buf[256];
+ serdumpst(p, buf, sizeof buf);
+ readstr(req, buf);
}
respond(req, nil);
break;
@@ -551,85 +524,45 @@ dread(Req *req)
qunlock(ser);
}
-static long
-altwrite(Serialport *p, uchar *buf, long count)
-{
- int nw, dfd;
- char err[128];
- Serial *ser;
-
- ser = p->s;
- do{
- dsprint(2, "serial: write to bulk %ld\n", count);
-
- if(ser->wait4write != nil)
- /* unlocked inside later */
- nw = ser->wait4write(p, buf, count);
- else{
- dfd = p->epout->dfd;
- qunlock(ser);
- nw = write(dfd, buf, count);
- qlock(ser);
- }
- rerrstr(err, sizeof err);
- dsprint(2, "serial: written %s %d\n", err, nw);
- } while(nw < 0 && strstr(err, "timed out") != nil);
-
- if(nw != count){
- dsprint(2, "serial: need to recover, status in write %d %r\n",
- nw);
- snprint(err, sizeof err, "%r");
- serialrecover(p->s, p, p->epout, err);
- }
- return nw;
-}
-
static void
dwrite(Req *req)
{
- ulong path;
- char *cmd;
Serial *ser;
- long count;
- void *buf;
Serialport *p;
+ ulong path;
+ int count;
path = req->fid->qid.path;
- p = ports[(path-1)/2];
+ p = ports[(path-1) / 2];
ser = p->s;
- count = req->ifcall.count;
- buf = req->ifcall.data;
-
qlock(ser);
- switch((long)((path-1)%2)){
+ switch((path-1) % 2){
case 0:
- count = altwrite(p, (uchar *)buf, count);
+ req->aux = p;
+ reqqueuepush(p->wq, req, procwrite);
break;
case 1:
- if(p->isjtag)
- break;
- cmd = emallocz(count+1, 1);
- memmove(cmd, buf, count);
- cmd[count] = 0;
- if(serialctl(p, cmd) < 0){
- qunlock(ser);
+ count = req->ifcall.count;
+ if(!p->isjtag){
+ char *cmd, *buf;
+
+ buf = (char*)req->ifcall.data;
+ cmd = emallocz(count+1, 1);
+ memmove(cmd, buf, count);
+ cmd[count] = 0;
+ if(serialctl(p, cmd) < 0){
+ qunlock(ser);
+ free(cmd);
+ respond(req, "bad control request");
+ return;
+ }
free(cmd);
- respond(req, "bad control request");
- return;
}
- free(cmd);
+ req->ofcall.count = count;
+ respond(req, nil);
break;
}
- if(count >= 0)
- ser->recover = 0;
- else
- serialrecover(ser, p, p->epout, "writing");
qunlock(ser);
- if(count >= 0){
- req->ofcall.count = count;
- respond(req, nil);
- } else
- responderror(req);
}
static int
@@ -653,12 +586,6 @@ openeps(Serialport *p, int epin, int epout, int epintr)
closedev(p->epin);
return -1;
}
-
- if(!p->isjtag){
- devctl(p->epin, "timeout 1000");
- devctl(p->epout, "timeout 1000");
- }
-
if(ser->hasepintr){
p->epintr = openep(ser->dev, epintr);
if(p->epintr == nil){
@@ -739,6 +666,27 @@ findendpoints(Serial *ser, int ifc)
return 0;
}
+static void
+dflush(Req *req)
+{
+ Serialport *p;
+ Req *old;
+ ulong path;
+
+ old = req->oldreq;
+ path = old->fid->qid.path;
+ if(path != 0){
+ p = ports[(path - 1) / 2];
+ if(p != nil){
+ if(old->ifcall.type == Twrite)
+ reqqueueflush(p->wq, old);
+ else
+ reqqueueflush(p->rq, old);
+ }
+ }
+ respond(req, nil);
+}
+
/* keep in sync with main.c */
static void
usage(void)
@@ -759,6 +707,7 @@ static Srv serialfs = {
.read = dread,
.write= dwrite,
.stat = dstat,
+ .flush = dflush,
.end = dend,
};
@@ -821,18 +770,14 @@ threadmain(int argc, char* argv[])
serialreset(ser);
for(i = 0; i < ser->nifcs; i++){
p = &ser->p[i];
- dprint(2, "serial: valid interface, calling serinit\n");
if(serinit(p) < 0)
sysfatal("wserinit: %r");
-
- dsprint(2, "serial: adding interface %d, %p\n", p->interfc, p);
if(ser->nifcs == 1)
snprint(p->name, sizeof p->name, "%s%s", p->isjtag ? "jtag" : "eiaU", dev->hname);
else
snprint(p->name, sizeof p->name, "%s%s.%d", p->isjtag ? "jtag" : "eiaU", dev->hname, i);
- incref(dev);
- p->readrend.l = &p->readq;
- p->readpid = proccreate(readproc, p, mainstacksize);
+ p->rq = reqqueuecreate();
+ p->wq = reqqueuecreate();
ports = realloc(ports, (nports + 1) * sizeof(Serialport*));
ports[nports++] = p;
}
diff --git a/sys/src/cmd/nusb/serial/serial.h b/sys/src/cmd/nusb/serial/serial.h
index 4117e7e95..eb46996f5 100644
--- a/sys/src/cmd/nusb/serial/serial.h
+++ b/sys/src/cmd/nusb/serial/serial.h
@@ -65,11 +65,9 @@ struct Serialport {
Channel *readc; /* to uncouple reads, only used in ftdi... */
int ndata;
uchar data[DataBufSz];
-
- QLock readq;
- Req *readfirst, *readlast; /* read request queue */
- int readpid;
- Rendez readrend;
+
+ Reqqueue *rq;
+ Reqqueue *wq;
};
struct Serial {
diff --git a/sys/src/cmd/nusb/serial/silabs.c b/sys/src/cmd/nusb/serial/silabs.c
index ca2032139..8b624a6a5 100644
--- a/sys/src/cmd/nusb/serial/silabs.c
+++ b/sys/src/cmd/nusb/serial/silabs.c
@@ -114,16 +114,6 @@ slsetparam(Serialport *p)
}
static int
-seteps(Serialport *p)
-{
- if(devctl(p->epin, "timeout 0") < 0){
- fprint(2, "can't set timeout on %s: %r\n", p->epin->dir);
- return -1;
- }
- return 0;
-}
-
-static int
wait4data(Serialport *p, uchar *data, int count)
{
int n;
@@ -139,6 +129,5 @@ static Serialops slops = {
.init = slinit,
.getparam = slgetparam,
.setparam = slsetparam,
- .seteps = seteps,
.wait4data = wait4data,
};