/* * all uarts must be uartsetup() by this point or inside of uartinstall() */ static void uartreset(void) { int i; Dirtab *dp; uartinstall(); ndir = 1+3*nuart; uartdir = xalloc(ndir * sizeof(Dirtab)); dp = uartdir; strcpy(dp->name, "."); mkqid(&dp->qid, 0, 0, QTDIR); dp->length = 0; dp->perm = DMDIR|0555; dp++; for(i = 0; i < nuart; i++){ /* 3 directory entries per port */ strcpy(dp->name, uart[i]->name); dp->qid.path = NETQID(i, Ndataqid); dp->perm = 0660; dp++; sprint(dp->name, "%sctl", uart[i]->name); dp->qid.path = NETQID(i, Nctlqid); dp->perm = 0660; dp++; sprint(dp->name, "%sstatus", uart[i]->name); dp->qid.path = NETQID(i, Nstatqid); dp->perm = 0444; dp++; } }
static void eiainit(void) { int i, nports; Dirtab *dp; struct stat sb; #ifdef buildsysdev buildsysdev(); #endif /* check to see which ports exist by trying to stat them */ nports = 0; for (i=0; i < nelem(sysdev); i++) { if(stat(sysdev[i], &sb) < 0) break; nports++; } if (!nports) return; ndir = Nqid*nports+1; dp = eiadir = malloc(ndir*sizeof(Dirtab)); if(dp == 0) panic("eiainit"); strcpy(dp->name, "."); dp->qid.path = 0; dp->qid.type = QTDIR; dp->perm = DMDIR|0555; dp++; eia = malloc(nports*sizeof(Eia)); if(eia == 0) panic("eiainit"); for(i = 0; i < nports; i++) { sprint(dp->name, "%s%d", Devname, i); dp->qid.path = NETQID(i, Ndataqid); dp->perm = 0660; dp++; sprint(dp->name, "%s%dctl", Devname, i); dp->qid.path = NETQID(i, Nctlqid); dp->perm = 0660; dp++; sprint(dp->name, "%s%dstatus", Devname, i); dp->qid.path = NETQID(i, Nstatqid); dp->perm = 0660; dp++; eia[i].frame = eia[i].overrun = 0; eia[i].restore = eia[i].dtr = eia[i].rts = eia[i].cts = 0; } }
static int pipegen(Chan *c, char*, Dirtab *tab, int ntab, int i, Dir *dp) { Qid q; int len; Pipe *p; if(i == DEVDOTDOT){ devdir(c, c->qid, "#|", 0, eve, DMDIR|0555, dp); return 1; } i++; /* skip . */ if(tab==0 || i>=ntab) return -1; tab += i; p = c->aux; switch((ulong)tab->qid.path){ case Qdata0: len = qlen(p->q[0]); break; case Qdata1: len = qlen(p->q[1]); break; default: len = tab->length; break; } mkqid(&q, NETQID(NETID(c->qid.path), tab->qid.path), 0, QTFILE); devdir(c, q, tab->name, len, eve, p->perm, dp); return 1; }
static int pipegen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp) { int id, len; Qid qid; Pipe *p; USED(name); if(i == DEVDOTDOT){ devdir(c, c->qid, "#|", 0, eve, 0555, dp); return 1; } i++; /* skip . */ if(tab==0 || i>=ntab) return -1; tab += i; p = c->aux; switch(NETTYPE(tab->qid.path)){ case Qdata0: len = qlen(p->q[0]); break; case Qdata1: len = qlen(p->q[1]); break; default: len = tab->length; break; } id = NETID(c->qid.path); qid.path = NETQID(id, tab->qid.path); qid.vers = 0; qid.type = QTFILE; devdir(c, qid, tab->name, len, eve, tab->perm, dp); return 1; }
/* * create a pipe, no streams are created until an open */ static Chan* pipeattach(char *spec) { Pipe *p; Chan *c; c = devattach('|', spec); p = malloc(sizeof(Pipe)); if(p == 0) exhausted("memory"); p->ref = 1; p->q[0] = qopen(conf.pipeqsize, 0, 0, 0); if(p->q[0] == 0){ free(p); exhausted("memory"); } p->q[1] = qopen(conf.pipeqsize, 0, 0, 0); if(p->q[1] == 0){ free(p->q[0]); free(p); exhausted("memory"); } lock(&pipealloc.lk); p->path = ++pipealloc.path; unlock(&pipealloc.lk); mkqid(&c->qid, NETQID(2*p->path, Qdir), 0, QTDIR); c->aux = p; c->dev = 0; return c; }
/* * create a pipe, no streams are created until an open */ static struct chan *pipeattach(char *spec) { ERRSTACK(2); Pipe *p; struct chan *c; c = devattach(devname(), spec); p = kzmalloc(sizeof(Pipe), 0); if (p == 0) error(ENOMEM, ERROR_FIXME); if (waserror()) { freepipe(p); nexterror(); } p->pipedir = kzmalloc(sizeof(pipedir), 0); if (p->pipedir == 0) error(ENOMEM, ERROR_FIXME); memmove(p->pipedir, pipedir, sizeof(pipedir)); kstrdup(&p->user, current->user); kref_init(&p->ref, pipe_release, 1); qlock_init(&p->qlock); p->q[0] = qopen(pipealloc.pipeqsize, Qcoalesce, 0, 0); if (p->q[0] == 0) error(ENOMEM, ERROR_FIXME); p->q[1] = qopen(pipealloc.pipeqsize, Qcoalesce, 0, 0); if (p->q[1] == 0) error(ENOMEM, ERROR_FIXME); poperror(); spin_lock(&(&pipealloc)->lock); p->path = ++pipealloc.path; spin_unlock(&(&pipealloc)->lock); c->qid.path = NETQID(2 * p->path, Qdir); c->qid.vers = 0; c->qid.type = QTDIR; c->aux = p; c->dev = 0; /* taps. */ SLIST_INIT(&p->data_taps[0]); /* already = 0; set to be futureproof */ SLIST_INIT(&p->data_taps[1]); spinlock_init(&p->tap_lock); return c; }
Chan* netifopen(Netif *nif, Chan *c, int omode) { Proc *up = externup(); int id; Netfile *f; id = 0; if(c->qid.type & QTDIR){ if(omode != OREAD) error(Eperm); } else { switch(NETTYPE(c->qid.path)){ case Ndataqid: case Nctlqid: id = NETID(c->qid.path); openfile(nif, id); break; case Ncloneqid: id = openfile(nif, -1); c->qid.path = NETQID(id, Nctlqid); break; default: if(omode != OREAD) error(Ebadarg); } switch(NETTYPE(c->qid.path)){ case Ndataqid: case Nctlqid: f = nif->f[id]; if(netown(f, up->user, omode&7) < 0){ netifclose(nif, c); error(Eperm); } break; } } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; c->iounit = qiomaxatomic; return c; }
/* * create a pipe, no streams are created until an open */ static Chan* pipeattach(char *spec) { Pipe *p; Chan *c; c = devattach('|', spec); p = malloc(sizeof(Pipe)); if(p == 0) error(Enomem); if(waserror()){ freepipe(p); nexterror(); } p->pipedir = malloc(sizeof(pipedir)); if (p->pipedir == 0) error(Enomem); memmove(p->pipedir, pipedir, sizeof(pipedir)); kstrdup(&p->user, up->env->user); p->ref = 1; p->q[0] = qopen(pipealloc.pipeqsize, 0, 0, 0); if(p->q[0] == 0) error(Enomem); p->q[1] = qopen(pipealloc.pipeqsize, 0, 0, 0); if(p->q[1] == 0) error(Enomem); poperror(); lock(&pipealloc.l); p->path = ++pipealloc.path; unlock(&pipealloc.l); c->qid.path = NETQID(2*p->path, Qdir); c->qid.vers = 0; c->qid.type = QTDIR; c->aux = p; c->dev = 0; return c; }
struct chan *netifopen(struct ether *nif, struct chan *c, int omode) { int id; struct netfile *f; id = 0; if (c->qid.type & QTDIR) { if (!IS_RDONLY(omode)) error(Eperm); } else { switch (NETTYPE(c->qid.path)) { case Ndataqid: case Nctlqid: id = NETID(c->qid.path); openfile(nif, id); break; case Ncloneqid: id = openfile(nif, -1); c->qid.path = NETQID(id, Nctlqid); break; default: if (!IS_RDONLY(omode)) error(Ebadarg); } switch (NETTYPE(c->qid.path)) { case Ndataqid: case Nctlqid: f = nif->f[id]; if (netown(f, current->user, omode & 7) < 0) error(Eperm); break; } } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; c->iounit = qiomaxatomic; return c; }
/* * create a pipe, no streams are created until an open */ static Chan* pipeattach(char *spec) { Pipe *p; Chan *c; c = devattach('|', spec); if(waserror()){ chanfree(c); nexterror(); } p = malloc(sizeof(Pipe)); if(p == 0) exhausted("memory"); p->ref = 1; p->q[0] = qopen(conf.pipeqsize, 0, 0, 0); if(p->q[0] == 0){ free(p); exhausted("memory"); } p->q[1] = qopen(conf.pipeqsize, 0, 0, 0); if(p->q[1] == 0){ qfree(p->q[0]); free(p); exhausted("memory"); } poperror(); lock(&pipealloc); p->path = ++pipealloc.path; unlock(&pipealloc); p->perm = pipedir[Qdata0].perm; mkqid(&c->qid, NETQID(2*p->path, Qdir), 0, QTDIR); c->aux = p; c->dev = 0; return c; }
/* * generate a 3 level directory */ static int netifgen(Chan *c, char* j, Dirtab *vp, int n, int i, Dir *dp) { Proc *up = externup(); Qid q; Netif *nif = (Netif*)vp; Netfile *f; int t; int perm; char *o; q.type = QTFILE; q.vers = 0; /* top level directory contains the name of the network */ if(c->qid.path == 0){ switch(i){ case DEVDOTDOT: q.path = 0; q.type = QTDIR; devdir(c, q, ".", 0, eve, 0555, dp); break; case 0: q.path = N2ndqid; q.type = QTDIR; strcpy(up->genbuf, nif->name); devdir(c, q, up->genbuf, 0, eve, 0555, dp); break; default: return -1; } return 1; } /* second level contains clone plus all the conversations */ t = NETTYPE(c->qid.path); if(t == N2ndqid || t == Ncloneqid || t == Naddrqid || t == Nstatqid || t == Nifstatqid || t == Nmtuqid){ switch(i) { case DEVDOTDOT: q.type = QTDIR; q.path = 0; devdir(c, q, ".", 0, eve, DMDIR|0555, dp); break; case 0: q.path = Ncloneqid; devdir(c, q, "clone", 0, eve, 0666, dp); break; case 1: q.path = Naddrqid; devdir(c, q, "addr", 0, eve, 0666, dp); break; case 2: q.path = Nstatqid; devdir(c, q, "stats", 0, eve, 0444, dp); break; case 3: q.path = Nifstatqid; devdir(c, q, "ifstats", 0, eve, 0444, dp); break; case 4: q.path = Nmtuqid; devdir(c, q, "mtu", 0, eve, 0444, dp); break; default: i -= 5; if(i >= nif->nfile) return -1; if(nif->f[i] == 0) return 0; q.type = QTDIR; q.path = NETQID(i, N3rdqid); snprint(up->genbuf, sizeof up->genbuf, "%d", i); devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp); break; } return 1; } /* third level */ f = nif->f[NETID(c->qid.path)]; if(f == 0) return 0; if(*f->owner){ o = f->owner; perm = f->mode; } else { o = eve; perm = 0666; } switch(i){ case DEVDOTDOT: q.type = QTDIR; q.path = N2ndqid; strcpy(up->genbuf, nif->name); devdir(c, q, up->genbuf, 0, eve, DMDIR|0555, dp); break; case 0: q.path = NETQID(NETID(c->qid.path), Ndataqid); devdir(c, q, "data", 0, o, perm, dp); break; case 1: q.path = NETQID(NETID(c->qid.path), Nctlqid); devdir(c, q, "ctl", 0, o, perm, dp); break; case 2: q.path = NETQID(NETID(c->qid.path), Nstatqid); devdir(c, q, "stats", 0, eve, 0444, dp); break; case 3: q.path = NETQID(NETID(c->qid.path), Ntypeqid); devdir(c, q, "type", 0, eve, 0444, dp); break; case 4: q.path = NETQID(NETID(c->qid.path), Nifstatqid); devdir(c, q, "ifstats", 0, eve, 0444, dp); break; default: return -1; } return 1; }
/* * generate a 3 level directory */ static int netifgen(struct chan *c, char *unused_char_p_t, struct dirtab *vp, int unused_int, int i, struct dir *dp) { struct qid q; struct ether *nif = (struct ether *)vp; struct netfile *f; int perm; char *o; q.type = QTFILE; q.vers = 0; /* top level directory contains the name of the network */ if (c->qid.path == 0) { switch (i) { case DEVDOTDOT: q.path = 0; q.type = QTDIR; devdir(c, q, ".", 0, eve, 0555, dp); break; case 0: q.path = N2ndqid; q.type = QTDIR; strncpy(get_cur_genbuf(), nif->name, GENBUF_SZ); devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp); break; default: return -1; } return 1; } /* second level contains clone plus all the conversations. * * This ancient comment is from plan9. Inferno and nxm both had issues * here. You couldn't ls /net/ether0/ when it didn't have any convs. There * were also issues with nxm where you couldn't stat ether0/x/stats * properly. * * The issue is that if we handle things like Nstatqid, then we will never * pass it down to the third level. And since we just set the path == * Nstatqid, we won't have the NETID muxed in. If someone isn't trying to * generate a chan, but instead is looking it up (devwalk generates, devstat * already has the chan), then they are also looking for a devdir with path * containing ID << 5. So if you stat ether0/1/ifstats, devstat is looking * for path 41, but we return path 9 (41 = 32 + 9). (these numbers are * before we tracked NETID + 1). * * We (akaros and plan9) had a big if here, that would catch things that do * not exist in the subdirs of a netif. Things like clone make sense here. * I guess addr too, though that seems to be added since the original * comment. You can see what the 3rd level was expecting to parse by looking * farther down in the code. * * The root of the problem was that the old code couldn't tell the * difference between no netid and netid 0. Now, we determine if we're at * the second level by the lack of a netid, instead of trying to enumerate * the qid types that the second level could have. The latter approach * allowed for something like ether0/1/stats, but we couldn't actually * devstat ether0/stats directly. It's worth noting that there is no * difference to the content of ether0/stats and ether0/x/stats (when you * read), but they have different chan qids. * * Here's the old if block: t = NETTYPE(c->qid.path); if (t == N2ndqid || t == Ncloneqid || t == Naddrqid) { */ if (NETID(c->qid.path) == -1) { switch (i) { case DEVDOTDOT: q.type = QTDIR; q.path = 0; devdir(c, q, ".", 0, eve, DMDIR | 0555, dp); break; case 0: q.path = Ncloneqid; devdir(c, q, "clone", 0, eve, 0666, dp); break; case 1: q.path = Naddrqid; devdir(c, q, "addr", 0, eve, 0666, dp); break; case 2: q.path = Nstatqid; devdir(c, q, "stats", 0, eve, 0444, dp); break; case 3: q.path = Nifstatqid; devdir(c, q, "ifstats", 0, eve, 0444, dp); break; default: i -= 4; if (i >= nif->nfile) return -1; if (nif->f[i] == 0) return 0; q.type = QTDIR; q.path = NETQID(i, N3rdqid); snprintf(get_cur_genbuf(), GENBUF_SZ, "%d", i); devdir(c, q, get_cur_genbuf(), 0, eve, DMDIR | 0555, dp); break; } return 1; } /* third level */ f = nif->f[NETID(c->qid.path)]; if (f == 0) return 0; if (*f->owner) { o = f->owner; perm = f->mode; } else { o = eve; perm = 0666; } switch (i) { case DEVDOTDOT: q.type = QTDIR; q.path = N2ndqid; strncpy(get_cur_genbuf(), nif->name, GENBUF_SZ); devdir(c, q, get_cur_genbuf(), 0, eve, DMDIR | 0555, dp); break; case 0: q.path = NETQID(NETID(c->qid.path), Ndataqid); devdir(c, q, "data", 0, o, perm, dp); break; case 1: q.path = NETQID(NETID(c->qid.path), Nctlqid); devdir(c, q, "ctl", 0, o, perm, dp); break; case 2: q.path = NETQID(NETID(c->qid.path), Nstatqid); devdir(c, q, "stats", 0, eve, 0444, dp); break; case 3: q.path = NETQID(NETID(c->qid.path), Ntypeqid); devdir(c, q, "type", 0, eve, 0444, dp); break; case 4: q.path = NETQID(NETID(c->qid.path), Nifstatqid); devdir(c, q, "ifstats", 0, eve, 0444, dp); break; default: return -1; } return 1; }
/* * set up the '#t' directory */ static void uartreset(void) { int i; Dirtab *dp; Uart *p, *tail; tail = nil; for(i = 0; physuart[i] != nil; i++){ if(physuart[i]->pnp == nil) continue; if((p = physuart[i]->pnp()) == nil) continue; if(uartlist != nil) tail->next = p; else uartlist = p; for(tail = p; tail->next != nil; tail = tail->next) uartnuart++; uartnuart++; } if(uartnuart) uart = xalloc(uartnuart*sizeof(Uart*)); uartndir = 1 + 3*uartnuart; uartdir = xalloc(uartndir * sizeof(Dirtab)); if (uart == nil || uartdir == nil) panic("uartreset: no memory"); dp = uartdir; strcpy(dp->name, "."); mkqid(&dp->qid, 0, 0, QTDIR); dp->length = 0; dp->perm = DMDIR|0555; dp++; p = uartlist; for(i = 0; i < uartnuart; i++){ /* 3 directory entries per port */ snprint(dp->name, sizeof dp->name, "eia%d", i); dp->qid.path = NETQID(i, Ndataqid); dp->perm = 0660; dp++; snprint(dp->name, sizeof dp->name, "eia%dctl", i); dp->qid.path = NETQID(i, Nctlqid); dp->perm = 0660; dp++; snprint(dp->name, sizeof dp->name, "eia%dstatus", i); dp->qid.path = NETQID(i, Nstatqid); dp->perm = 0444; dp++; uart[i] = p; p->dev = i; if(p->console || p->special){ if(uartenable(p) != nil){ if(p->console && up) serialoq = p->oq; p->opens++; } } p = p->next; } if(uartnuart){ /* * at 115200 baud, the 1024 char buffer takes 56 ms to process, * processing it every 22 ms should be fine. */ uarttimer = addclock0link(uartclock, 22); } }
static void eiainit(void) { int i,x; byte ports; //bitmask of active host ports int nports; //number of active host ports int max; //number of highest port Dirtab *dp; // setup the timeouts; choose carefully timeouts.ReadIntervalTimeout = 2; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = 200; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 400; // check to see which ports exist by trying to open them // keep results in a bitmask ports = nports = max = 0; for(i=0; (sysdev[i] != NULL) && (i<8); i++) { HANDLE comfh = CreateFile(sysdev[i], 0, 0, NULL, /* no security attrs */ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(comfh != INVALID_HANDLE_VALUE) { ports |= 1<<i; CloseHandle(comfh); nports++; max = i; } } if(nports == 0) return; //no ports // allocate directory table and eia structure // for each active port. ndir = Nqid*nports+1; dp = eiadir = malloc(ndir*sizeof(Dirtab)); if(dp == 0) panic("eiainit"); eia = malloc(nports*sizeof(Eia)); if(eia == 0) { free(dp); panic("eiainit"); } // fill in the directory table and initialize // the eia structure. skip inactive ports. sprint(dp->name, "."); dp->qid.path = 0; dp->qid.type = QTDIR; dp->perm = DMDIR|0555; dp++; x = 0; // index in eia[] for(i = 0; i <= max; i++) { if( (ports & (1<<i)) == 0) continue; //port 'i' is not active sprint(dp->name, "eia%d", i); dp->qid.path = NETQID(x, Ndataqid); dp->perm = 0660; dp++; sprint(dp->name, "eia%dctl", i); dp->qid.path = NETQID(x, Nctlqid); dp->perm = 0660; dp++; sprint(dp->name, "eia%dstatus", i); dp->qid.path = NETQID(x, Nstatqid); dp->perm = 0660; dp++; // init the eia structure eia[x].restore = 0; eia[x].id = i; x++; } }