static void etherfree(Ether *e) { int i; Buf *bp; if(e->free != nil) e->free(e); closedev(e->epin); closedev(e->epout); if(e->rc == nil){ /* not really started */ free(e); return; } for(i = 0; i < e->nconns; i++) if(e->conns[i] != nil){ while((bp = nbrecvp(e->conns[i]->rc)) != nil) free(bp); chanfree(e->conns[i]->rc); free(e->conns[i]); } shutdownchan(e->bc); shutdownchan(e->rc); shutdownchan(e->wc); e->epin = e->epout = nil; devctl(e->dev, "detach"); free(e); }
void fswrite(Req *r) { char msg[256], *f[4]; int nf, speed; snprint(msg, sizeof(msg), "%.*s", r->ifcall.count, r->ifcall.data); nf = tokenize(msg, f, nelem(f)); if(nf < 2){ respond(r, "invalid ctl message"); return; } if(strcmp(f[0], "speed") == 0){ Dev *d; speed = atoi(f[1]); Setup: if((d = setupep(audiodev, audioepout, speed)) == nil){ responderror(r); return; } closedev(d); if(audioepin != nil && audioepin != audioepout){ if(d = setupep(audiodev, audioepin, speed)) closedev(d); } audiofreq = speed; } else if(strcmp(f[0], "delay") == 0){ audiodelay = atoi(f[1]); speed = audiofreq; goto Setup; } r->ofcall.count = r->ifcall.count; respond(r, nil); }
static int fsopen(Usbfs*_1, Fid *fid, int mode) { int qd; int rc; Dev *dev; int (*xfsopen)(Usbfs *fs, Fid *f, int mode); qd = qiddev(fid->qid.path); if(qd == Dtop) return 0; qlock(&fslck); if(fs[qd] == nil){ qunlock(&fslck); werrstr(Eio); return -1; } dev = fs[qd]->dev; if(dev != nil) incref(&dev->Ref); xfsopen = fs[qd]->open; qunlock(&fslck); if(xfsopen != nil) rc = xfsopen(fs[qd], fid, mode); else rc = 0; if(dev != nil) closedev(dev); return rc; }
static int dirgen(Usbfs*_1, Qid _2, int n, Dir *d, void *_3) { int i; Dev *dev; char *nm; qlock(&fslck); for(i = 0; i < nfs; i++) if(fs[i] != nil && n-- == 0){ d->qid.type = QTDIR; d->qid.path = mkqid(i, Qdir); d->qid.vers = 0; dev = fs[i]->dev; if(dev != nil) incref(&dev->Ref); nm = d->name; fs[i]->stat(fs[i], d->qid, d); d->name = nm; strncpy(d->name, fs[i]->name, Namesz); if(dev != nil) closedev(dev); qunlock(&fslck); return 0; } qunlock(&fslck); return -1; }
static void etherwriteproc(void *a) { Ether *e = a; Buf *bp; Channel *wc; threadsetname("etherwrite"); wc = e->wc; while(e->exiting == 0){ bp = recvp(wc); if(bp == nil || e->exiting != 0){ free(bp); break; } e->nout++; if(e->bwrite(e, bp) < 0) e->noerrs++; if(isloopback(e, bp) && e->exiting == 0) sendp(e->rc, bp); /* send to input queue */ else freebuf(e, bp); } deprint(2, "%s: writeproc exiting\n", argv0); closedev(e->dev); }
static void portdetach(Hub *h, int p) { Dev *d; Port *pp; extern void usbfsgone(char*); d = h->dev; pp = &h->port[p]; /* * Clear present, so that we detect an attach on reconnects. */ pp->sts &= ~(PSpresent|PSenable); if(pp->state == Pdisabled) return; pp->state = Pdisabled; dprint(2, "%s: %s: port %d: detached\n", argv0, d->dir, p); if(pp->hub != nil){ closehub(pp->hub); pp->hub = nil; } if(pp->devmaskp != nil) putdevnb(pp->devmaskp, pp->devnb); pp->devmaskp = nil; if(pp->dev != nil){ devctl(pp->dev, "detach"); usbfsgone(pp->dev->dir); closedev(pp->dev); pp->dev = nil; } }
static int32_t fsread(Usbfs*_1, Fid *fid, void *data, int32_t cnt, int64_t off) { int qd; int rc; Dev *dev; Qid q; int32_t (*xfsread)(Usbfs *fs, Fid *f, void *data, int32_t count, int64_t ); q = fid->qid; qd = qiddev(q.path); if(qd == Dtop) return usbdirread(nil, q, data, cnt, off, dirgen, nil); qlock(&fslck); if(fs[qd] == nil){ qunlock(&fslck); werrstr(Eio); return -1; } dev = fs[qd]->dev; if(dev != nil) incref(&dev->Ref); xfsread = fs[qd]->read; qunlock(&fslck); rc = xfsread(fs[qd], fid, data, cnt, off); if(dev != nil) closedev(dev); return rc; }
static int32_t fswrite(Usbfs*_1, Fid *fid, void *data, int32_t cnt, int64_t off) { int qd; int rc; Dev *dev; int32_t (*xfswrite)(Usbfs *fs, Fid *f, void *data, int32_t count, int64_t ); qd = qiddev(fid->qid.path); if(qd == Dtop) sysfatal("fswrite: not for usbd /"); qlock(&fslck); if(fs[qd] == nil){ qunlock(&fslck); werrstr(Eio); return -1; } dev = fs[qd]->dev; if(dev != nil) incref(&dev->Ref); xfswrite = fs[qd]->write; qunlock(&fslck); rc = xfswrite(fs[qd], fid, data, cnt, off); if(dev != nil) closedev(dev); return rc; }
static int fsstat(Usbfs*_1, Qid qid, Dir *d) { int qd; int rc; Dev *dev; int (*xfsstat)(Usbfs *fs, Qid q, Dir *d); qd = qiddev(qid.path); if(qd == Dtop){ d->qid = qid; d->name = "usb"; d->length = 0; d->mode = 0555|DMDIR; return 0; } qlock(&fslck); if(fs[qd] == nil){ qunlock(&fslck); werrstr(Eio); return -1; } xfsstat = fs[qd]->stat; dev = fs[qd]->dev; if(dev != nil) incref(&dev->Ref); qunlock(&fslck); rc = xfsstat(fs[qd], qid, d); if(dev != nil) closedev(dev); return rc; }
UART::~UART() { if (_isOpen==TRUE) closedev(); _file=0; _tty=-1; _isOpen=FALSE; }
static void etherreadproc(void *a) { int i, n, nwants; Buf *bp, *dbp; Ether *e = a; threadsetname("etherread"); while(e->exiting == 0){ bp = nbrecvp(e->rc); if(bp == nil){ bp = allocbuf(e); /* leak() may think we leak */ if(e->bread(e, bp) < 0){ freebuf(e, bp); break; } if(bp->ndata == 0){ /* may be a short packet; continue */ if(0)dprint(2, "%s: read: short\n", argv0); freebuf(e, bp); continue; }else setbuftype(bp); } e->nin++; nwants = 0; for(i = 0; i < e->nconns; i++) nwants += cwantsbp(e->conns[i], bp); for(i = 0; nwants > 0 && i < e->nconns; i++) if(cwantsbp(e->conns[i], bp)){ n = bp->ndata; if(e->conns[i]->type == -2 && n > 64) n = 64; if(nwants-- == 1){ bp->ndata = n; dbp = bp; bp = nil; }else{ dbp = allocbuf(e); memmove(dbp->rp, bp->rp, n); dbp->ndata = n; dbp->type = bp->type; } if(nbsendp(e->conns[i]->rc, dbp) == 0){ deprint(2, "%s: (in) packet lost\n", argv0); e->nierrs++; freebuf(e, dbp); } } freebuf(e, bp); } deprint(2, "%s: writeproc exiting\n", argv0); etherexiting(e); closedev(e->dev); usbfsdel(&e->fs); }
static int openeps(Ether *e, int epin, int epout) { e->epin = openep(e->dev, epin); if(e->epin == nil){ fprint(2, "ether: in: openep %d: %r\n", epin); return -1; } if(epout == epin){ incref(e->epin); e->epout = e->epin; }else e->epout = openep(e->dev, epout); if(e->epout == nil){ fprint(2, "ether: out: openep %d: %r\n", epout); closedev(e->epin); return -1; } if(e->epin == e->epout) opendevdata(e->epin, ORDWR); else{ opendevdata(e->epin, OREAD); opendevdata(e->epout, OWRITE); } if(e->epin->dfd < 0 || e->epout->dfd < 0){ fprint(2, "ether: open i/o ep data: %r\n"); closedev(e->epin); closedev(e->epout); return -1; } dprint(2, "ether: ep in %s maxpkt %d; ep out %s maxpkt %d\n", e->epin->dir, e->epin->maxpkt, e->epout->dir, e->epout->maxpkt); /* time outs are not activated for I/O endpoints */ if(usbdebug > 2 || etherdebug > 2){ devctl(e->epin, "debug 1"); devctl(e->epout, "debug 1"); devctl(e->dev, "debug 1"); } return 0; }
static void portreset(Hub *h, int p) { int sts; Dev *d, *nd; Port *pp; d = h->dev; pp = &h->port[p]; nd = pp->dev; dprint(2, "%s: %s: port %d: resetting\n", argv0, d->dir, p); if(hubfeature(h, p, Fportreset, 1) < 0){ dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p); goto Fail; } sleep(Resetdelay); sts = portstatus(h, p); if(sts < 0) goto Fail; if((sts & PSenable) == 0){ dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p); hubfeature(h, p, Fportenable, 1); sts = portstatus(h, p); if((sts & PSenable) == 0) goto Fail; } nd = pp->dev; opendevdata(nd, ORDWR); if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetaddress, nd->id, 0, nil, 0) < 0){ dprint(2, "%s: %s: port %d: setaddress: %r\n", argv0, d->dir, p); goto Fail; } if(devctl(nd, "address") < 0){ dprint(2, "%s: %s: port %d: set address: %r\n", argv0, d->dir, p); goto Fail; } if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0){ dprint(2, "%s: %s: port %d: setconf: %r\n", argv0, d->dir, p); unstall(nd, nd, Eout); if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0) goto Fail; } if(nd->dfd >= 0) close(nd->dfd); return; Fail: pp->state = Pdisabled; pp->sts = 0; if(pp->hub != nil) pp->hub = nil; /* hub closed by enumhub */ hubfeature(h, p, Fportenable, 0); if(nd != nil) devctl(nd, "detach"); closedev(nd); }
static int fswalk(Usbfs*_1, Fid *fid, char *name) { Qid q; int qd, qf; int i; int rc; Dev *dev; Dir d; int (*xfswalk)(Usbfs *fs, Fid *f, char *name); q = fid->qid; qd = qiddev(q.path); qf = qidfile(q.path); q.type = QTDIR; q.vers = 0; if(strcmp(name, "..") == 0) if(qd == Dtop || qf == Qdir){ q.path = mkqid(Dtop, Qdir); fid->qid = q; return 0; } if(qd != 0){ qlock(&fslck); if(fs[qd] == nil){ qunlock(&fslck); werrstr(Eio); return -1; } dev = fs[qd]->dev; if(dev != nil) incref(&dev->Ref); xfswalk = fs[qd]->walk; qunlock(&fslck); rc = xfswalk(fs[qd], fid, name); if(dev != nil) closedev(dev); return rc; } qlock(&fslck); for(i = 0; i < nfs; i++) if(fs[i] != nil && strcmp(name, fs[i]->name) == 0){ q.path = mkqid(i, Qdir); fs[i]->stat(fs[i], q, &d); /* may be a file */ fid->qid = d.qid; qunlock(&fslck); return 0; } qunlock(&fslck); werrstr(Enotfound); return -1; }
static void statusreader(void *u) { Serialport *p; Serial *ser; p = u; ser = p->s; threadsetname("statusreaderproc"); while(plreadstatus(p) >= 0) ; fprint(2, "serial: statusreader exiting\n"); closedev(ser->dev); }
void threadmain(int argc, char **argv) { Dev *yd; char *devdir = nil; Ep *ep; int csps[] = {YurexCSP, 0}; int i; if(finddevs(matchdevcsp, csps, &devdir, 1) < 1){ fprint(2, "No yurex device\n"); threadexitsall("yurex not found"); } yd = opendev(devdir); if(yd == nil) sysfatal("opendev: %r"); if(configdev(yd)<0) sysfatal("configdev: %r"); for(i = 0; i < nelem(yd->usb->ep); i++){ if((ep = yd->usb->ep[i]) == nil) break; if(ep->type == Eintr && ep->dir == Ein) if(ep->iface->csp == YurexCSP){ yc.ep = openep(yd, ep->id); if(yc.ep == nil) sysfatal("YUREX: %s: openep %d: %r\n", yd->dir, ep->id); if(opendevdata(yc.ep, OREAD) < 0){ fprint(2, "YUERX: %s: opendevdata: %r\n", yc.ep->dir); closedev(yc.ep); yc.ep = nil; break; } fs.tree = alloctree(nil, nil, DMDIR|0777, destroyfile); createfile(fs.tree->root, "bbu", nil, 0444, nil); createfile(fs.tree->root, "mbbups", nil, 0444, nil); threadpostmountsrv(&fs, "yurex", nil, MREPL|MCREATE); proccreate(yurexwork, nil, Stack); } } threadexits(nil); }
static void statusreader(void *u) { Areader *a; Channel *c; Packser *pk; Serialport *p; Serial *ser; int cl; p = u; ser = p->s; threadsetname("statusreader thread"); /* big buffering, fewer bytes lost */ c = chancreate(sizeof(Packser *), 128); a = emallocz(sizeof(Areader), 1); a->p = p; a->c = c; incref(ser->dev); proccreate(epreader, a, 16*1024); while((pk = recvp(c)) != nil){ 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) break; cl = sendul(p->gotdata, 1); if(cl < 0) break; } } shutdownchan(c); devctl(ser->dev, "detach"); closedev(ser->dev); usbfsdel(&p->fs); }
static void closehub(Hub *h) { Hub **hl; dprint(2, "%s: closing hub %#p\n", argv0, h); for(hl = &hubs; *hl != nil; hl = &(*hl)->next) if(*hl == h) break; if(*hl == nil) sysfatal("closehub: no hub"); *hl = h->next; nhubs--; hubfail(h); /* detach all ports */ free(h->port); assert(h->dev != nil); devctl(h->dev, "detach"); closedev(h->dev); free(h); }
static void usbfsdelnth(int i) { if(fs[i] != nil){ dprint(2, "%s: fsdel %s", argv0, fs[i]->name); if(fs[i]->dev != nil){ dprint(2, " dev %#p ref %ld\n", fs[i]->dev, fs[i]->dev->Ref.ref); }else dprint(2, "no dev\n"); if(fs[i]->end != nil) fs[i]->end(fs[i]); closedev(fs[i]->dev); fsused--; } fs[i] = nil; if(fsused == 0 && exitonclose != 0){ fprint(2, "%s: all file systems gone: exiting\n", argv0); threadexitsall(nil); } }
static void fsclunk(Usbfs*_1, Fid* fid) { int qd; Dev *dev; void (*xfsclunk)(Usbfs *fs, Fid *f); dev = nil; qd = qiddev(fid->qid.path); qlock(&fslck); if(qd != Dtop && fs[qd] != nil){ dev=fs[qd]->dev; if(dev != nil) incref(&dev->Ref); xfsclunk = fs[qd]->clunk; }else xfsclunk = nil; qunlock(&fslck); if(xfsclunk != nil){ xfsclunk(fs[qd], fid); } if(dev != nil) closedev(dev); }
static void fsclone(Usbfs*_1, Fid *o, Fid *n) { int qd; Dev *dev; void (*xfsclone)(Usbfs *fs, Fid *of, Fid *nf); xfsclone = nil; dev = nil; qd = qiddev(o->qid.path); qlock(&fslck); if(qd != Dtop && fs[qd] != nil && fs[qd]->clone != nil){ dev = fs[qd]->dev; if(dev != nil) incref(&dev->Ref); xfsclone = fs[qd]->clone; } qunlock(&fslck); if(xfsclone != nil){ xfsclone(fs[qd], o, n); } if(dev != nil) closedev(dev); }
void main(int argc, char *argv[]) { char buf[32]; Dev *d, *ed; Ep *e; int i; ARGBEGIN { case 'D': chatty9p++; break; case 'd': usbdebug++; break; } ARGEND; if(argc == 0) usage(); if((d = getdev(*argv)) == nil) sysfatal("getdev: %r"); audiodev = d; /* parse descriptors, mark valid altc */ for(i = 0; i < nelem(d->usb->ddesc); i++) parsedescr(d->usb->ddesc[i]); for(i = 0; i < nelem(d->usb->ep); i++){ e = d->usb->ep[i]; if(e != nil && e->type == Eiso && e->iface != nil && e->iface->csp == CSP(Claudio, 2, 0)){ switch(e->dir){ case Ein: if(audioepin != nil) continue; audioepin = e; break; case Eout: if(audioepout != nil) continue; audioepout = e; break; case Eboth: if(audioepin != nil && audioepout != nil) continue; if(audioepin == nil) audioepin = e; if(audioepout == nil) audioepout = e; break; } if((ed = setupep(audiodev, e, audiofreq)) == nil){ fprint(2, "setupep: %r\n"); if(e == audioepin) audioepin = nil; if(e == audioepout) audioepout = nil; continue; } closedev(ed); } } if(audioepout == nil) sysfatal("no endpoints found"); fs.tree = alloctree(user, "usb", DMDIR|0555, nil); createfile(fs.tree->root, "volume", user, 0666, nil); snprint(buf, sizeof buf, "%d.audio", audiodev->id); postsharesrv(&fs, nil, "usb", buf); exits(0); }
/* * BUG: does not consider max. power avail. */ static Dev* portattach(Hub *h, int p, int sts) { Dev *d; Port *pp; Dev *nd; char fname[80]; char buf[40]; char *sp; int mp; int nr; d = h->dev; pp = &h->port[p]; nd = nil; pp->state = Pattached; dprint(2, "%s: %s: port %d attach sts %#x\n", argv0, d->dir, p, sts); sleep(Connectdelay); if(hubfeature(h, p, Fportenable, 1) < 0) dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p); sleep(Enabledelay); if(hubfeature(h, p, Fportreset, 1) < 0){ dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p); goto Fail; } sleep(Resetdelay); sts = portstatus(h, p); if(sts < 0) goto Fail; if((sts & PSenable) == 0){ dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p); hubfeature(h, p, Fportenable, 1); sts = portstatus(h, p); if((sts & PSenable) == 0) goto Fail; } sp = "full"; if(sts & PSslow) sp = "low"; if(sts & PShigh) sp = "high"; dprint(2, "%s: %s: port %d: attached status %#x\n", argv0, d->dir, p, sts); if(devctl(d, "newdev %s %d", sp, p) < 0){ fprint(2, "%s: %s: port %d: newdev: %r\n", argv0, d->dir, p); goto Fail; } seek(d->cfd, 0, 0); nr = read(d->cfd, buf, sizeof(buf)-1); if(nr == 0){ fprint(2, "%s: %s: port %d: newdev: eof\n", argv0, d->dir, p); goto Fail; } if(nr < 0){ fprint(2, "%s: %s: port %d: newdev: %r\n", argv0, d->dir, p); goto Fail; } buf[nr] = 0; snprint(fname, sizeof(fname), "/dev/usb/%s", buf); nd = opendev(fname); if(nd == nil){ fprint(2, "%s: %s: port %d: opendev: %r\n", argv0, d->dir, p); goto Fail; } if(usbdebug > 2) devctl(nd, "debug 1"); if(opendevdata(nd, ORDWR) < 0){ fprint(2, "%s: %s: opendevdata: %r\n", argv0, nd->dir); goto Fail; } if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetaddress, nd->id, 0, nil, 0) < 0){ dprint(2, "%s: %s: port %d: setaddress: %r\n", argv0, d->dir, p); goto Fail; } if(devctl(nd, "address") < 0){ dprint(2, "%s: %s: port %d: set address: %r\n", argv0, d->dir, p); goto Fail; } mp=getmaxpkt(nd, strcmp(sp, "low") == 0); if(mp < 0){ dprint(2, "%s: %s: port %d: getmaxpkt: %r\n", argv0, d->dir, p); goto Fail; }else{ dprint(2, "%s; %s: port %d: maxpkt %d\n", argv0, d->dir, p, mp); devctl(nd, "maxpkt %d", mp); } if((sts & PSslow) != 0 && strcmp(sp, "full") == 0) dprint(2, "%s: %s: port %d: %s is full speed when port is low\n", argv0, d->dir, p, nd->dir); if(configdev(nd) < 0){ dprint(2, "%s: %s: port %d: configdev: %r\n", argv0, d->dir, p); goto Fail; } /* * We always set conf #1. BUG. */ if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0){ dprint(2, "%s: %s: port %d: setconf: %r\n", argv0, d->dir, p); unstall(nd, nd, Eout); if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0) goto Fail; } dprint(2, "%s: %U\n", argv0, nd); pp->state = Pconfiged; dprint(2, "%s: %s: port %d: configed: %s\n", argv0, d->dir, p, nd->dir); return pp->dev = nd; Fail: pp->state = Pdisabled; pp->sts = 0; if(pp->hub != nil) pp->hub = nil; /* hub closed by enumhub */ hubfeature(h, p, Fportenable, 0); if(nd != nil) devctl(nd, "detach"); closedev(nd); return nil; }
static void epreader(void *u) { int dfd, rcount, cl, ntries, recov; Areader *a; Channel *c; Packser *pk; Serial *ser; Serialport *p; threadsetname("epreader proc"); a = u; p = a->p; ser = p->s; c = a->c; free(a); qlock(ser); /* this makes the reader wait end of initialization too */ dfd = p->epin->dfd; qunlock(ser); ntries = 0; pk = nil; for(;;) { if (pk == nil) pk = emallocz(sizeof(Packser), 1); Eagain: rcount = read(dfd, pk->b, sizeof pk->b); if(serialdebug > 5) dsprint(2, "%d %#ux%#ux ", rcount, p->data[0], p->data[1]); if(rcount < 0) { if(ntries++ > 100) break; qlock(ser); recov = serialrecover(ser, p, nil, "epreader: bulkin error"); qunlock(ser); if(recov >= 0) goto Eagain; } if(rcount == 0) continue; if(rcount >= ser->inhdrsz) { rcount = cpdata(ser, p, pk->b, pk->b, rcount); if(rcount != 0) { pk->nb = rcount; cl = sendp(c, pk); if(cl < 0) { /* * if it was a time-out, I don't want * to give back an error. */ rcount = 0; break; } } else free(pk); qlock(ser); ser->recover = 0; qunlock(ser); ntries = 0; pk = nil; } } if(rcount < 0) fprint(2, "%s: error reading %s: %r\n", argv0, p->name); free(pk); nbsendp(c, nil); if(p->w4data != nil) chanclose(p->w4data); if(p->gotdata != nil) chanclose(p->gotdata); devctl(ser->dev, "detach"); closedev(ser->dev); }
static void startdevproc(void *a) { Sarg *sa = a; Dev *d; Devtab *dt; int argc; char *args, *argse, **argv; char *fname; threadsetgrp(threadid()); d = sa->pp->dev; dt = sa->dt; args = sa->args; argse = sa->args + sizeof sa->args; argv = sa->argv; fname = sa->fname; sa->pp->devmaskp = &dt->devmask; sa->pp->devnb = getdevnb(&dt->devmask); if(sa->pp->devnb < 0){ sa->pp->devmaskp = nil; sa->pp->devnb = 0; }else args = seprint(args, argse, "-N %d", sa->pp->devnb); if(dt->args != nil) seprint(args, argse, " %s", dt->args); args = sa->args; dprint(2, "%s: start: %s %s\n", argv0, dt->name, args); argv[0] = dt->name; argc = 1; if(args[0] != 0) argc += tokenize(args, argv+1, nelem(sa->argv)-2); argv[argc] = nil; if(dt->init == nil){ if(d->dfd > 0 ){ close(d->dfd); d->dfd = -1; } rfork(RFCFDG); open("/dev/null", OREAD); open("/dev/cons", OWRITE); open("/dev/cons", OWRITE); xexec(sa->rc, argv[0], argv); snprint(fname, sizeof(sa->fname), "/bin/usb/%s", dt->name); xexec(sa->rc, fname, argv); snprint(fname, sizeof(sa->fname), "/boot/%s", dt->name); xexec(sa->rc, fname, argv); if(cputype == nil) cputype = getenv("cputype"); if(cputype != nil){ snprint(fname, sizeof(sa->fname), "/%s/bin/%s", cputype, dt->name); argv[0] = fname; xexec(sa->rc, fname, argv); } fprint(2, "%s: %s: not found. can't exec\n", argv0, dt->name); sendul(sa->rc, -1); threadexits("exec"); }else{ sa->pp->dev = opendev(d->dir); sendul(sa->rc, 0); if(dt->init(d, argc, argv) < 0) fprint(2, "%s: %s: %r\n", argv0, dt->name); closedev(d); free(sa); } threadexits(nil); }