## diffname port/devdk.c 1990/0312 ## diff -e /dev/null /n/bootesdump/1990/0312/sys/src/9/mips/devdk.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "errno.h" #define NOW (MACHP(0)->ticks) #define DPRINT if(0) enum { /* * configuration parameters */ Ndk = 2, /* max dks */ /* * relative or immutable */ Nline = 256, /* max lines per dk */ Ndir = Nline + 1, /* entries in the dk directory */ Nsubdir = 5, /* entries in the sub directory */ }; typedef struct Dkmsg Dkmsg; typedef struct Line Line; typedef struct Dk Dk; /* * types of possible dkcalls */ enum { Dial, Announce, Redial }; /* * format of messages to/from the datakit controller on the common * signalling line */ struct Dkmsg { uchar type; uchar srv; uchar param0l; uchar param0h; uchar param1l; uchar param1h; uchar param2l; uchar param2h; uchar param3l; uchar param3h; uchar param4l; uchar param4h; }; /* * message codes (T_xxx == dialin.type, D_xxx == dialin.srv) */ #define T_SRV 1 /* service request */ #define D_SERV 1 /* (host to dkmux) announce a service */ #define D_DIAL 2 /* (host to dkmux) connect to a service */ #define D_XINIT 7 /* (dkmux to host) line has been spliced */ #define T_REPLY 2 /* reply to T_SRV/D_SERV or T_SRV/D_DIAL */ #define D_OK 1 /* not used */ #define D_OPEN 2 /* (dkmux to host) connection established */ #define D_FAIL 3 /* (dkmux to host) connection failed */ #define T_CHG 3 /* linege the status of a connection */ #define D_CLOSE 1 /* close the connection */ #define D_ISCLOSED 2 /* (dkmux to host) confirm a close */ #define D_CLOSEALL 3 /* (dkmux to host) close all connections */ #define D_REDIAL 6 /* (host to dkmux) redial a call */ #define T_ALIVE 4 /* (host to dkmux) keep alive message */ #define D_CONTINUE 0 /* host has not died since last msg */ #define D_RESTART 1 /* host has restarted */ #define D_MAXCHAN 2 /* request maximum line number */ #define T_RESTART 8 /* (dkmux to host) datakit restarted */ /* * macros for cracking/forming the window negotiation parameter */ #define MIN(x,y) (x < y ? x : y) #define W_WINDOW(o,d,t) ((o<<8) | (d<<4) | t | 0100000) #define W_VALID(x) ((x) & 0100000) #define W_ORIG(x) (((x)>>8) & 017) #define W_DEST(x) (((x)>>4) & 017) #define W_TRAF(x) ((x) & 017) #define W_DESTMAX(x,y) (W_WINDOW(W_ORIG(x),MIN(W_DEST(x),y),W_TRAF(x))) #define W_LIMIT(x,y) (W_WINDOW(MIN(W_ORIG(x),y),MIN(W_DEST(x),y),W_TRAF(x))) #define W_VALUE(x) (1<<((x)+4)) #define WS_2K 7 /* * one per datakit line */ struct Line { QLock; Rendez r; /* wait here for dial */ int state; /* dial state */ int err; /* dialing error (if non zero) */ int window; /* negotiated window */ int timestamp; /* timestamp of last call received on this line */ int calltolive; /* multiple of 15 seconds for dialing state to last */ Queue *rq; char addr[64]; char raddr[64]; char ruser[32]; char other[64]; Dk *dp; /* interface contianing this line */ }; /* * a dkmux dk. one exists for every stream that a * dkmux line disilpline is pushed onto. */ struct Dk { QLock; int ref; char name[64]; /* dk name */ Queue *wq; /* dk output queue */ int lines; /* number of lines */ int ncsc; /* csc line number */ Chan *csc; /* common signalling line */ Line line[Nline]; }; static Dk dk[Ndk]; /* * conversation states (for Line.state) */ typedef enum { Lclosed=0, Lopened, /* opened but no call out */ Lconnected, /* opened and a call set up on htis line */ Lrclose, /* remote end has closed down */ Llclose, /* local end has closed down */ Ldialing, /* dialing a new call */ Llistening, /* this line listening for calls */ Lackwait, /* incoming call waiting for ack/nak */ Laccepting, /* waiting for user to accept or reject the call */ } Lstate; /* * datakit error to errno */ enum { DKok, DKbusy, DKnetotl, DKdestotl, DKbadnet, DKnetbusy, DKinuse, DKreject, }; int dkerr[]={ [DKok]Egreg, [DKbusy]Einuse, /* destination busy */ [DKnetotl]Enetotl, /* network not answering */ [DKdestotl]Edestotl, /* destination not answering */ [DKbadnet]Ebadnet, /* unassigned destination */ [DKnetbusy]Enetbusy, /* network overload */ [DKinuse]Einuse, /* server already exists */ [DKreject]Erejected /* call rejected by destination */ }; #define DKERRS sizeof(dkerr)/sizeof(int) /* * imported */ extern Qinfo urpinfo; /* * predeclared */ Chan* dkattach(char*); static void dkmuxconfig(Dk*, Block*); static int dkmesg(Dk*, int, int, int, int); static void dkcsckproc(void*); static int dklisten(Chan*); static void dkanswer(Chan*, int, int); static void dkwindow(Chan*); static void dkcall(int, Chan*, char*, char*, char*); static void dktimer(void*); static void dkchgmesg(Dk*, Dkmsg*, int); static void dkreplymesg(Dk*, Dkmsg*, int); Chan* dkopen(Chan*, int); /* * the datakit multiplexor stream module definition */ static void dkmuxopen(Queue *, Stream *); static void dkmuxclose(Queue *); static void dkmuxoput(Queue *, Block *); static void dkmuxiput(Queue *, Block *); Qinfo dkmuxinfo = { dkmuxiput, dkmuxoput, dkmuxopen, dkmuxclose, "dkmux" }; /* * a new dkmux. find a free dk structure and assign it to this queue. */ static void dkmuxopen(Queue *q, Stream *s) { Dk *dp; int i; for(dp = dk; dp < &dk[Ndk]; dp++){ if(dp->wq == 0){ qlock(dp); if(dp->wq) { /* someone was faster than us */ qunlock(dp); continue; } q->ptr = q->other->ptr = (void *)dp; dp->csc = 0; dp->ncsc = 4; dp->lines = 16; dp->name[0] = 0; dp->wq = WR(q); qunlock(dp); return; } } error(0, Enoifc); } /* * close down a dkmux */ static void dkmuxclose(Queue *q) { Dk *dp; dp = (Dk *)q->ptr; qlock(dp); if(dp->csc) close(dp->csc); dp->wq = 0; qunlock(dp); } /* * handle configuration */ static void dkmuxoput(Queue *q, Block *bp) { Dk *dp; dp = (Dk *)q->ptr; if(bp->type != M_DATA){ if(streamparse("config", bp)) dkmuxconfig(dp, bp); else PUTNEXT(q, bp); return; } PUTNEXT(q, bp); } /* * gather a message and send it up the appropriate stream * * The first two bytes of each message contains the channel * number, low order byte first. * * Simplifying assumption: one put == one message && the channel number * is in the first block. If this isn't true, demultiplexing will not * work. */ static void dkmuxiput(Queue *q, Block *bp) { Dk *dp; Line *lp; int line; dp = (Dk *)q->ptr; if(bp->type != M_DATA){ PUTNEXT(q, bp); return; } line = *bp->rptr++ | (*bp->rptr++<<8); if(line<0 || line>=dp->lines){ print("dkmuxiput bad line %d\n", line); freeb(bp); return; } lp = &dp->line[line]; if(canqlock(lp)){ if(lp->rq) PUTNEXT(lp->rq, bp); else{ print("dkmuxiput unopened line %d\n", line); freeb(bp); } qunlock(lp); } else { print("dkmuxiput unopened line %d\n", line); freeb(bp); } } /* * the datakit line stream module definition */ static void dkstopen(Queue *, Stream *); static void dkstclose(Queue *); static void dkoput(Queue *, Block *); static void dkiput(Queue *, Block *); Qinfo dkinfo = { dkiput, dkoput, dkstopen, dkstclose, "dk" }; /* * open and save a pointer to the conversation */ static void dkstopen(Queue *q, Stream *s) { Dk *dp; Line *lp; dp = &dk[s->dev]; q->other->ptr = q->ptr = lp = &dp->line[s->id]; lp->dp = dp; lp->rq = q; } /* * close down a datakit conversation */ static void dkstclose(Queue *q) { Dk *dp; Line *lp; lp = (Line *)q->ptr; dp = lp->dp; /* * shake hands with dk */ switch(lp->state){ case Lclosed: case Llclose: break; case Lrclose: dkmesg(dp, T_CHG, D_CLOSE, lp - dp->line, 0); lp->state = Lclosed; break; case Lackwait: dkmesg(dp, T_CHG, D_CLOSE, lp - dp->line, 0); lp->state = Llclose; break; case Llistening: dkmesg(dp, T_CHG, D_CLOSE, lp - dp->line, 0); lp->state = Llclose; break; case Lconnected: dkmesg(dp, T_CHG, D_CLOSE, lp - dp->line, 0); lp->state = Llclose; break; case Lopened: lp->state = Lclosed; } qlock(lp); lp->rq = 0; qunlock(lp); } /* * this is only called by hangup */ static void dkiput(Queue *q, Block *bp) { PUTNEXT(q, bp); } /* * we assume that each put is a message. * * add a 2 byte channel number to the start of each message */ static void dkoput(Queue *q, Block *bp) { Line *lp; Dk *dp; int line; if(bp->type != M_DATA){ freeb(bp); error(0, Ebadarg); } lp = (Line *)q->ptr; dp = lp->dp; line = lp - dp->line; if(bp->base && bp->rptr - bp->base >= 2) bp->rptr -= 2; bp->rptr[0] = line; bp->rptr[1] = line>>8; PUTNEXT(dp->wq, bp); } /* * configure a datakit multiplexor. this takes 3 arguments separated * by spaces: * the line number of the common signalling channel (must be > 0) * the number of lines in the device (optional) * the name of the dk (optional) * * we can configure only once */ static void dkmuxconfig(Dk *dp, Block *bp) { Chan *c; char *fields[3]; int n; char buf[64]; static int dktimeron; if(dp->csc != 0){ freeb(bp); error(0, Ebadarg); } /* * parse */ n = getfields((char *)bp->rptr, fields, 3, ' '); switch(n){ case 3: strncpy(dp->name, fields[2], sizeof(dp->name)); case 2: dp->lines = strtoul(fields[1], 0, 0); case 1: dp->ncsc = strtoul(fields[0], 0, 0); break; default: freeb(bp); error(0, Ebadarg); } freeb(bp); if(dp->ncsc <= 0 || dp->lines <= dp->ncsc){ dp->lines = 16; error(0, Ebadarg); } /* * open a stream for the csc and push urp onto it */ c = 0; if(waserror()){ if(c) close(c); nexterror(); } c = dkattach(dp->name); c->qid = STREAMQID(dp->ncsc, Sdataqid); dkopen(c, ORDWR); dp->csc = c; /* * start a process to deal with it */ sprint(buf, "**csckproc%d**", dp->ncsc); kproc(buf, dkcsckproc, dp); poperror(); /* * start a keepalive process if one doesn't exist */ if(dktimeron == 0){ dktimeron = 1; kproc("**dktimer**", dktimer, 0); } } /* * qid's */ enum { /* * per line */ Daddrqid, Dlistenqid, Draddrqid, Duserqid, Dotherqid, Dlineqid, /* * per device */ Dcloneqid, }; /* * the dk directory */ Dirtab dkdir[Ndir]; /* * the per stream directory structure */ Dirtab dksubdir[]={ "addr", Daddrqid, 0, 0600, "listen", Dlistenqid, 0, 0600, "other", Dotherqid, 0, 0600, "raddr", Draddrqid, 0, 0600, "ruser", Duserqid, 0, 0600, }; /* * dk file system. most of the calls use dev.c to access the dk * directory and stream.c to access the dk devices. */ void dkreset(void) { } /* * create the dk directory. the files are `clone' and stream * directories '1' to '32' (or whatever Nline is in decimal) */ void dkinit(void) { int i; /* * create the directory. */ /* * the circuits */ for(i = 1; i < Nline; i++) { sprint(dkdir[i].name, "%d", i); dkdir[i].qid = CHDIR|STREAMQID(i, Dlineqid); dkdir[i].length = 0; dkdir[i].perm = 0600; } /* * the clone device */ strcpy(dkdir[0].name, "clone"); dkdir[0].qid = Dcloneqid; dkdir[0].length = 0; dkdir[0].perm = 0600; } Chan* dkattach(char *spec) { Chan *c; Dk *dp; /* * find a multiplexor with the same name */ for(dp = dk; dp < &dk[Ndk]; dp++){ qlock(dp); if(dp->wq && strcmp(spec, dp->name)==0) { dp->ref++; qunlock(dp); break; } qunlock(dp); } if(dp == &dk[Ndk]) error(0, Enoifc); c = devattach('k', spec); c->dev = dp - dk; return c; } Chan* dkclone(Chan *c, Chan *nc) { Dk *dp; dp = &dk[c->dev]; qlock(dp); dp->ref++; qunlock(dp); return devclone(c, nc); } int dkwalk(Chan *c, char *name) { if(c->qid == CHDIR) return devwalk(c, name, dkdir, dk[c->dev].lines, devgen); else return devwalk(c, name, dksubdir, Nsubdir, streamgen); } void dkstat(Chan *c, char *dp) { if(c->qid == CHDIR) devstat(c, dp, dkdir, dk[c->dev].lines, devgen); else devstat(c, dp, dksubdir, Nsubdir, streamgen); } /* * opening a dk device allocates a Line. Opening the `clone' * device is a ``macro'' for finding a free Line and opening * it's ctl file. * * opening the `listen' sub device is a macro for listening for * a new call. Lile `clone' the ctl file of the new channel is * returned. */ Chan* dkopen(Chan *c, int omode) { extern Qinfo dkinfo; Stream *s; Line *lp, *end; Dk *dp; int line; if(c->qid == Dcloneqid){ /* * get an unused device and open it's control file */ dp = &dk[c->dev]; end = &dp->line[dp->lines]; for(lp = &dp->line[dp->ncsc+1]; lp < end; lp++){ if(lp->state == Lclosed && canqlock(lp)){ if(lp->state != Lclosed){ qunlock(lp); continue; } c->qid = STREAMQID(lp-dp->line, Sctlqid); qunlock(lp); break; } } if(lp == end) error(0, Enodev); streamopen(c, &dkinfo); pushq(c->stream, &urpinfo); } else if(STREAMTYPE(c->qid) == Dlistenqid){ /* * listen for a call and open the control file for the * channel on which the call arrived. */ line = dklisten(c); c->qid = STREAMQID(line, Sctlqid); streamopen(c, &dkinfo); pushq(c->stream, &urpinfo); dkwindow(c); } else if(c->qid != CHDIR){ /* * open whatever c points to, make sure it has an urp */ streamopen(c, &dkinfo); if(strcmp(c->stream->procq->next->info->name, "urp")!=0) pushq(c->stream, &urpinfo); } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void dkcreate(Chan *c, char *name, int omode, ulong perm) { error(0, Eperm); } void dkclose(Chan *c) { Dk *dp; /* real closing happens in lancestclose */ if(c->qid != CHDIR) streamclose(c); dp = &dk[c->dev]; qlock(dp); dp->ref--; qunlock(dp); } long dkread(Chan *c, void *a, long n) { int t; Line *lp; t = STREAMTYPE(c->qid); if(t>=Slowqid || t==Dlineqid) return streamread(c, a, n); if(c->qid == CHDIR) return devdirread(c, a, n, dkdir, dk[c->dev].lines, devgen); lp = &dk[c->dev].line[STREAMID(c->qid)]; switch(t){ case Daddrqid: return stringread(c, a, n, lp->addr); case Draddrqid: return stringread(c, a, n, lp->raddr); case Duserqid: return stringread(c, a, n, lp->ruser); } error(0, Eperm); } long dkwrite(Chan *c, void *a, long n) { int t; char buf[256]; char *field[5]; int m; t = STREAMTYPE(c->qid); /* * get data dispatched as quickly as possible */ if(t == Sdataqid) return streamwrite(c, a, n, 0); /* * easier to do here than in dkoput */ if(t == Sctlqid){ strncpy(buf, a, sizeof buf); m = getfields(buf, field, 5, ' '); if(strcmp(field[0], "connect")==0){ if(m < 2) error(0, Ebadarg); dkcall(Dial, c, field[1], 0, 0); } else if(strcmp(field[0], "announce")==0){ if(m < 2) error(0, Ebadarg); dkcall(Announce, c, field[1], 0, 0); } else if(strcmp(field[0], "redial")==0){ if(m < 4) error(0, Ebadarg); dkcall(Redial, c, field[1], field[2], field[3]); } else if(strcmp(field[0], "accept")==0){ if(m < 2) error(0, Ebadarg); dkanswer(c, strtoul(field[1], 0, 0), 0); } else if(strcmp(field[0], "reject")==0){ if(m < 3) error(0, Ebadarg); dkanswer(c, strtoul(field[1], 0, 0), strtoul(field[2], 0, 0)); } else return streamwrite(c, a, n, 0); return n; } if(t >= Slowqid) return streamwrite(c, a, n, 0); error(0, Eperm); } void dkremove(Chan *c) { error(0, Eperm); } void dkwstat(Chan *c, char *dp) { error(0, Eperm); } void dkerrstr(Error *e, char *buf) { rooterrstr(e, buf); } void dkuserstr(Error *e, char *buf) { extern consuserstr(Error *, char *); consuserstr(e, buf); } /* * send a message to the datakit on the common signaling line */ static int dkmesg(Dk *dp, int type, int srv, int p0, int p1) { Dkmsg d; Block *bp; if(dp->csc == 0) return -1; if(waserror()) return -1; d.type = type; d.srv = srv; d.param0l = p0; d.param0h = p0>>8; d.param1l = p1; d.param1h = p1>>8; d.param2l = 0; d.param2h = 0; d.param3l = 0; d.param3h = 0; d.param4l = 0; d.param4h = 0; streamwrite(dp->csc, (char *)&d, sizeof(Dkmsg), 1); poperror(); return 0; } /* * call out on a datakit */ static int calldone(void *a) { Line *lp; lp = (Line *)a; return lp->state != Ldialing; } static void dkcall(int type, Chan *c, char *addr, char *nuser, char *machine) { char dialstr[66]; int line; char dialtone; int t_val, d_val; Dk *dp; Line *lp; Chan *dc; line = STREAMID(c->qid); dp = &dk[c->dev]; lp = &dp->line[line]; /* * only dial on virgin lines */ if(lp->state != Lclosed) error(0, Ebadarg); DPRINT("dkcall(line=%d, type=%d, dest=%s)\n", line, type, addr); /* * build dial string (guard against new lines) */ if(strchr(addr, '\n')) error(0, Ebadarg); if(strlen(addr)+strlen(u->p->pgrp->user)+2 >= sizeof(dialstr)) error(0, Ebadarg); strcpy(dialstr, addr); switch(type){ case Dial: t_val = T_SRV; d_val = D_DIAL; strcat(dialstr, "\n"); strcat(dialstr, u->p->pgrp->user); strcat(dialstr, "\n"); break; case Announce: t_val = T_SRV; d_val = D_SERV; break; case Redial: t_val = T_CHG; d_val = D_REDIAL; strcat(dialstr, "\n"); strcat(dialstr, nuser); strcat(dialstr, "\n"); strcat(dialstr, machine); strcat(dialstr, "\n"); break; } /* * open the data file */ dc = dkattach(dp->name); if(waserror()){ close(dc); nexterror(); } dc->qid = STREAMQID(line, Sdataqid); dkopen(dc, ORDWR); lp->calltolive = 4; lp->state = Ldialing; /* * tell the controller we want to make a call */ DPRINT("dialout\n"); dkmesg(dp, t_val, d_val, line, W_WINDOW(WS_2K,WS_2K,2)); /* * if redial, wait for a dial tone (otherwise we might send * the dialstr to the previous other end and not the controller) */ if(type==Redial){ if(streamread(dc, &dialtone, 1L) != 1L){ lp->state = Lconnected; error(0, Ebadarg); } } /* * make the call */ DPRINT("dialstr %s\n", dialstr); streamwrite(dc, dialstr, (long)strlen(dialstr), 1); close(dc); poperror(); /* * redial's never get a reply, assume it worked */ if(type == Redial) { lp->state = Lconnected; return; } /* * wait for a reply */ DPRINT("reply wait\n"); sleep(&lp->r, calldone, lp); /* * if there was an error, translate it to a plan 9 * errno and report it to the user. */ DPRINT("got reply %d\n", lp->state); if(lp->state != Lconnected) { if(lp->err >= DKERRS) error(0, dkerr[0]); else error(0, dkerr[lp->err]); } /* * linege state if serving */ if(type == D_SERV){ lp->state = Llistening; } DPRINT("connected!\n"); /* * decode the window size */ if (W_VALID(lp->window)){ /* * a 1127 window negotiation */ lp->window = W_VALUE(W_DEST(lp->window)); } else if(lp->window>2 && lp->window<31){ /* * a generic window negotiation */ lp->window = 1<window; } else lp->window = 0; /* * tag the connection */ strncpy(lp->addr, addr, sizeof(lp->addr)-1); strncpy(lp->raddr, addr, sizeof(lp->raddr)-1); /* * reset the protocol */ dkwindow(c); } /* * listen for a call, reflavor the */ static int dklisten(Chan *c) { char dialstr[512]; char *line[12]; char *field[8]; Line *lp; Dk *dp; int n, lineno, ts, window; Chan *dc; dp = &dk[c->dev]; /* * open the data file */ dc = dkattach(dp->name); if(waserror()){ close(dc); nexterror(); } dc->qid = STREAMQID(STREAMID(c->qid), Sdataqid); dkopen(dc, ORDWR); /* * wait for a call in */ for(;;){ /* * read the dialstring and null terminate it */ n = streamread(dc, dialstr, sizeof(dialstr)-1); DPRINT("returns %d\n", n); if(n <= 0) error(0, Eio); dialstr[n] = 0; DPRINT("dialstr = %s\n", dialstr); /* * break the dial string into lines */ n = getfields(dialstr, line, 12, '\n'); if (n < 2) { DPRINT("bad dialstr from dk (1 line)\n"); error(0, Eio); } /* * line 0 is `line.tstamp.traffic[.urpparms.window]' */ window = 0; switch(getfields(line[0], field, 5, '.')){ case 5: /* * generic way of passing window */ window = strtoul(field[4], 0, 0); if(window > 0 && window <31) window = 1<= dp->lines){ print("dklisten: illegal line %d\n", lineno); continue; } lp = &dp->line[lineno]; ts = strtoul(field[1], 0, 0); /* * this could be a duplicate request */ if(ts == lp->timestamp){ print("dklisten: repeat timestamp %d\n", lineno); continue; } /* * take care of glare (datakit picked an inuse channel * for the call to come in on). */ if(!canqlock(lp)){ print("DKbusy1\n"); dkanswer(c, lineno, DKbusy); continue; } else { if(lp->state != Lclosed){ qunlock(lp); print("DKbusy2 %ux\n", lp->state); dkanswer(c, lineno, DKbusy); continue; } } lp->window = window; /* * Line 1 is `my-dk-name.service[.more-things]'. * Special characters are escaped by '\'s. */ strncpy(lp->addr, line[1], sizeof(lp->addr)-1); /* * the rest is variable length */ switch(n) { case 2: /* no more lines */ lp->ruser[0] = 0; lp->raddr[0] = 0; break; case 3: /* line 2 is `source.user.param1.param2' */ getfields(line[2], field, 3, '.'); strncpy(lp->raddr, field[0], sizeof(lp->raddr)-1); strncpy(lp->ruser, field[1], sizeof(lp->ruser)-1); break; case 4: /* line 2 is `user.param1.param2' */ getfields(line[2], field, 2, '.'); strncpy(lp->ruser, field[0], sizeof(lp->ruser)-1); /* line 3 is `source.node.mod.line' */ strncpy(lp->raddr, line[3], sizeof(lp->raddr)-1); break; default: print("bad message from dk(>4 line)\n"); qunlock(lp); error(0, Ebadarg); } sprint(lp->other, "w(%d)", W_TRAF(lp->window)); DPRINT("src(%s)user(%s)dest(%s)other(%s)\n", lp->raddr, lp->ruser, lp->addr, lp->other); lp->timestamp = ts; lp->state = Lconnected; qunlock(lp); close(dc); poperror(); DPRINT("dklisten returns %d\n", lineno); return lineno; } } /* * answer a call */ static void dkanswer(Chan *c, int line, int code) { char reply[64]; Dk *dp; Chan *dc; Line *lp; dp = &dk[c->dev]; lp = &dp->line[line]; /* * open the data file (c is a control file) */ dc = dkattach(dp->name); if(waserror()){ close(dc); nexterror(); } dc->qid = STREAMQID(STREAMID(c->qid), Sdataqid); dkopen(dc, ORDWR); /* * send the reply */ sprint(reply, "%ud.%ud.%ud", line, lp->timestamp, code); DPRINT("dkanswer %s\n", reply); streamwrite(dc, reply, strlen(reply), 1); close(dc); poperror(); } /* * set the window size and reset the protocol */ static void dkwindow(Chan *c) { char buf[64]; long wins; Line *lp; lp = &dk[c->dev].line[STREAMID(c->qid)]; if(lp->window == 0) lp->window = 64; sprint(buf, "init %d %d", lp->window, Streamhi); streamwrite(c, buf, strlen(buf), 1); } /* * hangup a datakit connection */ static void dkhangup(Line *lp) { Block *bp; qlock(lp); if(lp->rq){ bp = allocb(0); bp->type = M_HANGUP; PUTNEXT(lp->rq, bp); } qunlock(lp); } /* * A process which listens to all input on a csc line */ static void dkcsckproc(void *a) { long n; Dk *dp; Dkmsg d; int line; int i; dp = (Dk *)a; /* * loop forever listening */ for(;;){ n = streamread(dp->csc, (char *)&d, (long)sizeof(d)); if(n != sizeof(d)){ print("strange csc message %d\n", n); continue; } line = (d.param0h<<8) + d.param0l; /* print("t(%d)s(%d)l(%d)\n", d.type, d.srv, line); /**/ switch (d.type) { case T_CHG: /* controller wants to close a line */ dkchgmesg(dp, &d, line); break; case T_REPLY: /* reply to a dial request */ dkreplymesg(dp, &d, line); break; case T_SRV: /* ignore it, it's useless */ print("dksrvmesg(%d)\n", line); break; case T_RESTART: /* datakit reboot */ print("dk restart\n"); if(line >=0 && linelines){ print("maxlines=%d\n", line+1); dp->lines=line+1; } break; default: DPRINT("unrecognized csc message %o(%o)\n", d.type, line); break; } } } /* * datakit requests or confirms closing a line */ static void dkchgmesg(Dk *dp, Dkmsg *dialp, int line) { Line *lp; if (line <= 0 || line >= dp->lines) { /* tell controller this line is not in use */ dkmesg(dp, T_CHG, D_CLOSE, line, 0); return; } lp = &dp->line[line]; switch (dialp->srv) { case D_CLOSE: /* remote shutdown */ switch (lp->state) { case Ldialing: /* simulate a failed connection */ dkreplymesg(dp, (Dkmsg *)0, line); lp->state = Lrclose; break; case Lrclose: case Lconnected: case Llistening: case Lackwait: dkhangup(lp); lp->state = Lrclose; break; case Lopened: dkmesg(dp, T_CHG, D_CLOSE, line, 0); break; case Llclose: case Lclosed: dkhangup(lp); dkmesg(dp, T_CHG, D_CLOSE, line, 0); lp->state = Lclosed; break; } break; case D_ISCLOSED: /* acknowledging a local shutdown */ switch (lp->state) { case Llclose: case Lclosed: lp->state = Lclosed; break; case Lrclose: case Lconnected: case Llistening: case Lackwait: break; } break; default: print("unrecognized T_CHG\n"); } } /* * datakit replies to a dialout. capture reply code and traffic parameters */ static void dkreplymesg(Dk *dp, Dkmsg *dialp, int line) { Proc *p; Line *lp; DPRINT("dkreplymesg(%d)\n", line); if(line < 0 || line >= dp->lines) return; lp=&dp->line[line]; if(lp->state != Ldialing) return; if(dialp){ /* * a reply from the dk */ lp->state = (dialp->srv==D_OPEN) ? Lconnected : Lrclose; lp->err = (dialp->param1h<<8) + dialp->param1l; lp->window = lp->err; DPRINT("dkreplymesg: %d\n", lp->state); } else { /* * a local abort */ lp->state = Lrclose; lp->err = 0; } if(lp->state==Lrclose){ dkhangup(lp); } wakeup(&lp->r); } /* * 15-second timer for all interfaces */ static Rendez dkt; static int fuckit(void *a) { return 0; } static void dktimer(void *a) { int dki, i; Dk *dp; Line *lp; waserror(); for(;;){ /* * loop through the active dks */ for(dki=0; dkicsc==0) continue; /* * send keep alive */ dkmesg(dp, T_ALIVE, D_CONTINUE, 0, 0); /* * remind controller of dead lines and * timeout calls that take to long */ for (i=0; ilines; i++){ lp = &dp->line[i]; switch(lp->state){ case Llclose: dkmesg(dp, T_CHG, D_CLOSE, i, 0); break; case Ldialing: if(lp->calltolive==0 || --lp->calltolive!=0) break; dkreplymesg(dp, (Dkmsg *)0, i); break; } } } tsleep(&dkt, fuckit, 0, 7500); } } . ## diffname port/devdk.c 1990/0315 ## diff -e /n/bootesdump/1990/0312/sys/src/9/mips/devdk.c /n/bootesdump/1990/0315/sys/src/9/mips/devdk.c 1121c DPRINT("DKbusy2 %ux\n", lp->state); . 1115c DPRINT("DKbusy1\n"); . 593d 413a else panic("dkoput"); . 304c DPRINT("dkmuxiput unopened line %d\n", line); . 299c DPRINT("dkmuxiput unopened line %d\n", line); . 289c DPRINT("dkmuxiput bad line %d\n", line); . 287c line = bp->rptr[0] | (bp->rptr[1]<<8); bp->rptr += 2; . 115c * dkmux line discipline is pushed onto. . ## diffname port/devdk.c 1990/0319 ## diff -e /n/bootesdump/1990/0315/sys/src/9/mips/devdk.c /n/bootesdump/1990/0319/sys/src/9/mips/devdk.c 784,786d 727c switch(STREAMTYPE(c->qid)){ . 725a if(c->qid & CHDIR){ if(c->qid == CHDIR) return devdirread(c, a, n, dkdir, dk[c->dev].lines, devgen); else return devdirread(c, a, n, dksubdir, Nsubdir, streamgen); } . 723,724d 720,721c if(c->stream) . 717d 705c if(c->stream) . 684a break; . 679a * read only files */ if(omode != OREAD) error(0, Ebadarg); break; default: /* . 678c break; case Daddrqid: case Draddrqid: case Duserqid: case Dotherqid: . 668c break; case Dlistenqid: . 648a * directories are read only */ if(omode != OREAD) error(0, Ebadarg); } else switch(STREAMTYPE(c->qid)){ case Dcloneqid: /* . 647c if(c->qid & CHDIR){ . ## diffname port/devdk.c 1990/0321 ## diff -e /n/bootesdump/1990/0319/sys/src/9/mips/devdk.c /n/bootesdump/1990/0321/sys/src/9/mips/devdk.c 540a newqinfo(&dkmuxinfo); newqinfo(&urpinfo); . ## diffname port/devdk.c 1990/0403 ## diff -e /n/bootesdump/1990/0321/sys/src/9/mips/devdk.c /n/bootesdump/1990/0403/sys/src/9/mips/devdk.c 1130a if(lp->state != Lconnected) dkanswer(c, lineno, DKbusy); . ## diffname port/devdk.c 1990/0509 ## diff -e /n/bootesdump/1990/0403/sys/src/9/mips/devdk.c /n/bootesdump/1990/0509/sys/src/9/mips/devdk.c 420c if(QFULL(dp->wq->next)){ print("dk wq full\n"); freeb(bp); } else PUTNEXT(dp->wq, bp); . ## diffname port/devdk.c 1990/0511 ## diff -e /n/bootesdump/1990/0509/sys/src/9/mips/devdk.c /n/bootesdump/1990/0511/sys/src/9/mips/devdk.c 1204a panic("dklisten terminates strangely\n"); . 902c if(lp->state != Lopened) . 730c /* real closing happens in dkstclose */ . 680a qunlock(lp); . 673d 331a if(lp->state == Lclosed) lp->state = Lopened; . ## diffname port/devdk.c 1990/0617 ## diff -e /n/bootesdump/1990/0511/sys/src/9/mips/devdk.c /n/bootesdump/1990/0617/sys/src/9/mips/devdk.c 1291a /* * tell datakit we've rebooted. It should close all channels. */ dkmesg(dp, T_ALIVE, D_RESTART, 0, 0); /* do this on mips but not 68020 */ dkmesg(dp, T_CHG, D_CLOSEALL, 0, 0); . 1087a print("bad dialstr %d '%s'\n", n, dialstr); . 1078a } . 1077a {print("bad n\n"); . 1006c * change state if serving . 69c #define T_CHG 3 /* change the status of a connection */ . ## diffname port/devdk.c 1990/0707 ## diff -e /n/bootesdump/1990/0617/sys/src/9/mips/devdk.c /n/bootesdump/1990/0707/sys/src/9/mips/devdk.c 1299c if(dp->restart) dkmesg(dp, T_ALIVE, D_RESTART, 0, 0); . 916a bang = strchr(dialstr, '!'); if(bang){ dot = strchr(dialstr, '.'); if(dot==0 || dot > bang) *bang = '.'; } . 910c * build dial string * - guard against new lines * - change ! into . to delimit service . 895a char *bang, *dot; . 458c if(strcmp(fields[2], "restart")!=0) dp->restart = 0; . 456a case 4: strncpy(dp->name, fields[3], sizeof(dp->name)); . 455c dp->restart = 1; n = getfields((char *)bp->rptr, fields, 4, ' '); . 442c char *fields[4]; . 433a * the word `restart' or `norestart' (optional/default==restart) . 430c * configure a datakit multiplexor. this takes 4 arguments separated . 125a int restart; . ## diffname port/devdk.c 1990/0717 ## diff -e /n/bootesdump/1990/0707/sys/src/9/mips/devdk.c /n/bootesdump/1990/0717/sys/src/9/mips/devdk.c 554c urpreset(); . ## diffname port/devdk.c 1990/0722 ## diff -e /n/bootesdump/1990/0717/sys/src/9/mips/devdk.c /n/bootesdump/1990/0722/sys/src/9/mips/devdk.c 596a if(*spec == 0) spec = "dk"; . 595c * find a multiplexor with the same name (default dk) . 506c kproc("dktimer", dktimer, 0); . 497c sprint(buf, "csckproc%d", dp->ncsc); . 458a strcpy(dp->name, "dk"); . ## diffname port/devdk.c 1990/0830 ## diff -e /n/bootesdump/1990/0722/sys/src/9/mips/devdk.c /n/bootesdump/1990/0830/sys/src/9/mips/devdk.c 418,419c else { print("dkoput l %d b %ux r %ux w %ux\n", line, bp->base, bp->rptr, bp->wptr); freeb(bp); return; } . ## diffname port/devdk.c 1990/0911 ## diff -e /n/bootesdump/1990/0830/sys/src/9/mips/devdk.c /n/bootesdump/1990/0911/sys/src/9/mips/devdk.c 1487c while(waserror()) print("dktimer: error\n"); . 1322a } DPRINT("dkcsckproc: closeall %s\n", dp->name); . 1321c if(dp->restart) { DPRINT("dkcsckproc: restart %s\n", dp->name); . 980c dkmesg(dp, t_val, d_val, line, W_WINDOW(dp->urpwindow,dp->urpwindow,2)); . 870a } . 869c if(waserror()){ print("dkmesg: error\n"); . 559d 502c sprint(buf, "csc.%s.%d", dp->name, dp->ncsc); . 483a DPRINT("dkmuxconfig: ncsc=%d, lines=%d, restart=%d, name=\"%s\"\n", dp->ncsc, dp->lines, dp->restart, dp->name); . 464a case 5: dp->urpwindow = strtoul(fields[4], 0, 0); . 463a dp->urpwindow = WS_2K; . 462c n = getfields((char *)bp->rptr, fields, 5, ' '); . 448c char *fields[5]; . 440c * the name of the dk (default==dk) * the urp window size (default==WS_2K) . 435c * configure a datakit multiplexor. this takes 5 arguments separated . 416,423c bp = padb(bp, 2); . 398c * add a 2 byte channel number to the start of each message, * low order byte first. . 126a int urpwindow; . 11a #define NOW (MACHP(0)->ticks) . 9,10c #define DPRINT if(0) /*kprint*/ . ## diffname port/devdk.c 1990/0925 ## diff -e /n/bootesdump/1990/0911/sys/src/9/mips/devdk.c /n/bootesdump/1990/0925/sys/src/9/mips/devdk.c 1115d 1105d 1103d ## diffname port/devdk.c 1990/1004 ## diff -e /n/bootesdump/1990/0925/sys/src/9/mips/devdk.c /n/bootesdump/1990/1004/sys/src/9/mips/devdk.c 1317,1326d 501a * tell datakit we've rebooted. It should close all channels. */ if(dp->restart) { DPRINT("dkmuxconfig: restart %s\n", dp->name); dkmesg(dp, T_ALIVE, D_RESTART, 0, 0); } /* . ## diffname port/devdk.c 1990/1011 ## diff -e /n/bootesdump/1990/1004/sys/src/9/mips/devdk.c /n/bootesdump/1990/1011/sys/src/9/mips/devdk.c 424c /* print("dk wq full\n");/**/ . ## diffname port/devdk.c 1990/1018 ## diff -e /n/bootesdump/1990/1011/sys/src/9/mips/devdk.c /n/bootesdump/1990/1018/sys/src/9/mips/devdk.c 423,427c FLOWCTL(dp->wq); PUTNEXT(dp->wq, bp); . 121c char name[64]; /* dk name */ . ## diffname port/devdk.c 1990/1022 ## diff -e /n/bootesdump/1990/1018/sys/src/9/mips/devdk.c /n/bootesdump/1990/1022/sys/src/9/mips/devdk.c 1506c for (i=dp->ncsc+1; ilines; i++){ . 1423a case D_CLOSEALL: for(line = dp->ncsc+1; line < dp->lines; line++){ lp = &dp->line[line]; switch (lp->state) { case Ldialing: /* simulate a failed connection */ dkreplymesg(dp, (Dkmsg *)0, line); lp->state = Lrclose; break; case Lrclose: case Lconnected: case Llistening: case Lackwait: dkhangup(lp); lp->state = Lrclose; break; case Lopened: break; case Llclose: case Lclosed: lp->state = Lclosed; break; } } break; . 1409a if (line <= 0 || line >= dp->lines) { /* tell controller this line is not in use */ dkmesg(dp, T_CHG, D_CLOSE, line, 0); return; } lp = &dp->line[line]; . 1379a if (line <= 0 || line >= dp->lines) { /* tell controller this line is not in use */ dkmesg(dp, T_CHG, D_CLOSE, line, 0); return; } lp = &dp->line[line]; . 1371,1376d 224a for(lp = dp->line; lp < &dp->line[Nline]; lp++) if(lp->state != 0) panic("dkmuxopen l %d s %lux", lp-dp->line, lp->state); . 208a Line *lp; . ## diffname port/devdk.c 1990/1024 ## diff -e /n/bootesdump/1990/1022/sys/src/9/mips/devdk.c /n/bootesdump/1990/1024/sys/src/9/mips/devdk.c 226,228d 209d ## diffname port/devdk.c 1990/1101 ## diff -e /n/bootesdump/1990/1024/sys/src/9/mips/devdk.c /n/bootesdump/1990/1101/sys/src/9/mips/devdk.c 1557c tsleep(&dp->timer, return0, 0, 7500); . 1548,1554c dkreplymesg(dp, (Dkmsg *)0, i); break; . 1538,1546c case Ldialing: if(lp->calltolive==0 || --lp->calltolive!=0) . 1533,1536c /* * remind controller of dead lines and * timeout calls that take to long */ for (i=dp->ncsc+1; ilines; i++){ lp = &dp->line[i]; switch(lp->state){ case Llclose: dkmesg(c, T_CHG, D_CLOSE, i, 0); break; . 1528,1531c dkmesg(c, T_ALIVE, D_CONTINUE, 0, 0); . 1526c * send keep alive . 1524a if(dp->opened==0) error(0, Ehungup); . 1523a case Ldialing: dkreplymesg(dp, (Dkmsg *)0, i); break; } } if(c) close(c); return; } /* * open csc */ dp = (Dk *)a; c = dkopenline(dp, dp->ncsc); . 1521,1522c c = 0; if(waserror()){ /* * hang up any calls waiting for the dk */ for (i=dp->ncsc+1; ilines; i++){ lp = &dp->line[i]; switch(lp->state){ case Llclose: lp->state = Lclosed; break; . 1519a Chan *c; . 1508,1513d 1506c * send a I'm alive message every 7.5 seconds and remind the dk of * any closed channels it hasn't acknowledged. . 1446a dkhangup(lp); . 1445d 1430a /* * datakit wants us to close all lines */ . 1412c dkmesg(c, T_CHG, D_CLOSE, line, 0); . 1403c dkmesg(c, T_CHG, D_CLOSE, line, 0); . 1397c dkmesg(c, T_CHG, D_CLOSE, line, 0); . 1376c dkmesg(c, T_CHG, D_CLOSE, line, 0); . 1367c dkchgmesg(Chan *c, Dk *dp, Dkmsg *dialp, int line) . 1353d 1349,1351c if(line >=0 && linelines) . 1337c dkchgmesg(dp->csc, dp, &d, line); . 1328a if(n == 0) error(0, Ehungup); . 1322a if(waserror()){ close(dp->csc); return; } . 1321c dp = a; . 1319d 1095,1096d 1090c dc = dkopenline(dp, STREAMID(c->qid)); . 988c csc = dkopenline(dp, dp->ncsc); dkmesg(csc, t_val, d_val, line, W_WINDOW(dp->urpwindow,dp->urpwindow,2)); close(csc); csc = 0; . 980a /* * open the data file */ dc = dkopenline(dp, line); . 978,979d 975c if(csc) close(csc); if(dc) close(dc); . 973c dc = 0; csc = 0; . 971c * close temporary channels on error . 918c . 916a Chan *csc; . 891c streamwrite(c, (char *)&d, sizeof(Dkmsg), 1); . 873,874d 871d 868c dkmesg(Chan *c, int type, int srv, int p0, int p1) . 864a * open the common signalling channel */ static Chan* dkopenline(Dk *dp, int line) { Chan *c; c = 0; if(waserror()){ if(c) close(c); nexterror(); } c = dkattach(dp->name); c->qid = STREAMQID(line, Sdataqid); dkopen(c, ORDWR); poperror(); return c; } /* . 754,758d 749,751d 701d 698a lp->state = Lopened; qunlock(lp); . 685d 681a dp = &dk[c->dev]; . 629,634d 610,620c dp = dkalloc(spec); /* * return the new channel */ . 516,519c sprint(buf, "timer.%s.%d", dp->name, dp->ncsc); kproc(buf, dktimer, dp); . 514c * start a keepalive process . 511d 507c * start a process to listen to csc messages . 502,503c DPRINT("dktimer: restart %s\n", dp->name); dkmesg(dp->csc, T_ALIVE, D_RESTART, 0, 0); . 499a * do this here to get it done before trying to open a channel. . 498a * open csc here so that boot, dktimer, and dkcsckproc aren't * all fighting for it at once. */ dp->csc = dkopenline(dp, dp->ncsc); /* . 493,496c dp->ncsc = ncsc; dp->lines = lines; dp->restart = restart; dp->urpwindow = window; dp->s = RD(q)->ptr; q->ptr = q->other->ptr = dp; dp->opened = 1; dp->wq = WR(q); unlock(dp); . 487,491c dp = dkalloc(name); lock(dp); if(dp->opened){ unlock(dp); error(0, Ebadarg); . 485c * set up . 480,482d 477,478c if(ncsc <= 0 || lines <= ncsc) . 470c ncsc = strtoul(fields[0], 0, 0); . 468c lines = strtoul(fields[1], 0, 0); . 466c restart = 0; . 463c strncpy(name, fields[3], sizeof(name)); . 461c window = strtoul(fields[4], 0, 0); . 457,458d 455d 452a * defaults */ ncsc = 1; restart = 1; lines = 16; window = WS_2K; strcpy(name, "dk"); /* . 449c error(0, Egreg); . 447c if(WR(q)->ptr){ . 445c char name[NAMELEN]; int lines; int ncsc; int restart; int window; . 441c Dk *dp; . 439c dkmuxconfig(Queue *q, Block *bp) . 382a out: . 381a poperror(); close(c); . 378,380d 375c dkmesg(c, T_CHG, D_CLOSE, lp - dp->line, 0); . 370c dkmesg(c, T_CHG, D_CLOSE, lp - dp->line, 0); . 365c dkmesg(c, T_CHG, D_CLOSE, lp - dp->line, 0); . 360c dkmesg(c, T_CHG, D_CLOSE, lp - dp->line, 0); . 358a c = 0; if(waserror()){ lp->state = Lclosed; if(c) close(c); goto out; } c = dkopenline(dp, dp->ncsc); /* * shake hands with dk */ switch(lp->state){ . 357c case Lopened: lp->state = Lclosed; goto out; } . 353a if(lp->rq == 0){ lp->state = Lclosed; return; } /* * decrement ref count on mux'd line */ streamexit(dp->s, 0); /* * these states don't need the datakit */ . 352c * if we never got going, we're done . 346a Chan *c; . 336a lp->rq = q; . 334,335c lock(dp); if(dp->opened==0 || streamenter(dp->s)<0){ unlock(dp); error(0, Ehungup); } unlock(dp); if(lp->state==Lclosed) . 283a /* * not configured yet */ if(q->other->ptr == 0){ freeb(bp); return; } . 275c * work. . 259c dkmuxconfig(q, bp); . 254,256d 240,245c dp = WR(q)->ptr; if(dp == 0) return; /* * disallow new dkstopens() on this line. * the lock syncs with dkstopen(). */ lock(dp); dp->opened = 0; unlock(dp); /* * hang up all datakit connections */ for(i=dp->ncsc; i < dp->lines; i++) dkhangup(&dp->line[i]); /* * wakeup the timer so it can die */ wakeup(&dp->timer); . 238a int i; . 232a * a new dkmux. find a free dk structure and assign it to this queue. * when we get though here dp->s is meaningful and the name is set to "/". */ static void dkmuxopen(Queue *q, Stream *s) { RD(q)->ptr = s; WR(q)->ptr = 0; } /* . 229c if(freep == 0){ unlock(&dklock); error(0, Enoifc); } dp = freep; dp->opened = 0; dp->s = 0; dp->ncsc = 1; strncpy(dp->name, name, sizeof(freep->name)); unlock(&dklock); return dp; . 227a if(dp->name[0] == 0) freep = dp; . 212,226c if(strcmp(name, dp->name) == 0){ unlock(&dklock); return dp; . 210a lock(&dklock); freep = 0; . 209c Dk *freep; . 203,206c * Look for a dk struct with a name. If none exists, create one. */ static Dk * dkalloc(char *name) . 191a static void dkhangup(Line*); . 189c static void dkchgmesg(Chan*, Dk*, Dkmsg*, int); . 181,182c static void dkmuxconfig(Queue*, Block*); static Chan* dkopenline(Dk*, int); static int dkmesg(Chan*, int, int, int, int); . 130a static Lock dklock; . 128a Rendez timer; . 125c Chan *csc; . 122a Stream *s; . 119,120c Lock; int opened; . ## diffname port/devdk.c 1990/1104 ## diff -e /n/bootesdump/1990/1101/sys/src/9/mips/devdk.c /n/bootesdump/1990/1104/sys/src/9/mips/devdk.c 382d 379a lp->rq = q; . ## diffname port/devdk.c 1990/1113 ## diff -e /n/bootesdump/1990/1104/sys/src/9/mips/devdk.c /n/bootesdump/1990/1113/sys/src/9/mips/devdk.c 360c Qinfo dkinfo = { dkiput, dkoput, dkstopen, dkstclose, "dk" }; . 205c Qinfo dkmuxinfo = { dkmuxiput, dkmuxoput, dkmuxopen, dkmuxclose, "dkmux" }; . ## diffname port/devdk.c 1990/11161 ## diff -e /n/bootesdump/1990/1113/sys/src/9/mips/devdk.c /n/bootesdump/1990/11161/sys/src/9/mips/devdk.c 1670a DPRINT("keep alive\n"); . 9c #define DPRINT if(0) print . ## diffname port/devdk.c 1990/11211 ## diff -e /n/bootesdump/1990/11161/sys/src/9/mips/devdk.c /n/bootesdump/1990/11211/sys/src/9/mips/devdk.c 1666c error(Ehungup); . 1447c error(Ehungup); . 1398c lp = &dk[c->dev].line[STREAMID(c->qid.path)]; . 1375c dc->qid.path = STREAMQID(STREAMID(c->qid.path), Sdataqid); . 1335c error(Ebadarg); . 1231c error(Eio); . 1221c error(Eio); . 1205c dc = dkopenline(dp, STREAMID(c->qid.path)); . 1147c error(dkerr[lp->err]); . 1145c error(dkerr[0]); . 1112c error(Ebadarg); . 1045c error(Ebadarg); . 1043c error(Ebadarg); . 1033c error(Ebadarg); . 1025c line = STREAMID(c->qid.path); . 965c c->qid.path = STREAMQID(line, Sdataqid); . 936,949d 933c error(Eperm); . 927c error(Eperm); . 921c error(Eperm); . 914c error(Ebadarg); . 910c error(Ebadarg); . 906c error(Ebadarg); . 902c error(Ebadarg); . 898c error(Ebadarg); . 882c t = STREAMTYPE(c->qid.path); . 871c error(Eperm); . 862,863c lp = &dk[c->dev].line[STREAMID(c->qid.path)]; switch(STREAMTYPE(c->qid.path)){ . 855,856c if(c->qid.path & CHDIR){ if(c->qid.path == CHDIR) . 837c error(Eperm); . 816c error(Ebadarg); . 803c c->qid.path = STREAMQID(line, Sctlqid); . 791c error(Enodev); . 786c c->qid.path = STREAMQID(lp-dp->line, Sctlqid); . 772,773c error(Ebadarg); } else switch(STREAMTYPE(c->qid.path)){ . 767c if(c->qid.path & CHDIR){ . 743c if(c->qid.path == CHDIR) . 734c if(c->qid.path == CHDIR) . 699c dkdir[0].qid.path = Dcloneqid; dkdir[0].qid.vers = 0; . 690c dkdir[i].qid.path = CHDIR|STREAMQID(i, Dlineqid); dkdir[i].qid.vers = 0; . 656,660c "addr", {Daddrqid}, 0, 0600, "listen", {Dlistenqid}, 0, 0600, "other", {Dotherqid}, 0, 0600, "raddr", {Draddrqid}, 0, 0600, "ruser", {Duserqid}, 0, 0600, . 587c error(Ebadarg); . 578c error(Ebadarg); . 574c error(Ebadarg); . 543c error(Egreg); . 502c error(Ebadarg); . 391c error(Ehungup); . 235c error(Enoifc); . ## diffname port/devdk.c 1990/1126 ## diff -e /n/bootesdump/1990/11211/sys/src/9/mips/devdk.c /n/bootesdump/1990/1126/sys/src/9/mips/devdk.c 779c * get an unused device and open its control file . 746a else if(c->qid.path == Dcloneqid) devstat(c, dp, dkdir, 1, devgen); . ## diffname port/devdk.c 1990/1202 ## diff -e /n/bootesdump/1990/1126/sys/src/9/mips/devdk.c /n/bootesdump/1990/1202/sys/src/9/mips/devdk.c 1566a dp->allclosedp = 1; wakeup(&dp->rallclosed); . 624a /* * wait for closeall in response to D_RESTART */ if(dp->restart) tsleep(&dp->rallclosed, allclosed, dp, 10000); . 615,620d 605a * start a process to listen to csc messages */ sprint(buf, "csc.%s.%d", dp->name, dp->ncsc); kproc(buf, dkcsckproc, dp); /* * wait for first possible closeall (may not come) */ tsleep(&dp->rallclosed, allclosed, dp, 2000); /* . 527a static int allclosed(void *arg) { Dk *dp; dp = arg; return dp->allclosedp; } . 130a Rendez rallclosed; int allclosedp; /* true once a closeall has been seen */ . ## diffname port/devdk.c 1990/1210 ## diff -e /n/bootesdump/1990/1210/sys/src/9/mips/devdk.c /n/bootesdump/1990/1210/sys/src/9/port/devdk.c 1588,1589c dp->closeall = 1; wakeup(&dp->closeallr); . 640,645d 632a tsleep(&dp->closeallr, haveca, dp, 5000); /* wait for restart closeall */ . 631a dp->closeall = 0; . 622,626d 619a tsleep(&dp->closeallr, haveca, dp, 5000); /* wait for initial closeall */ . 612a dp->closeall = 0; . 536c return dp->closeall; . 531c haveca(void *arg) . 131,132c int closeall; /* set when we receive a closeall message */ Rendez closeallr; /* wait here for a closeall */ . ## diffname port/devdk.c 1990/1214 ## diff -e /n/bootesdump/1990/1210/sys/src/9/port/devdk.c /n/bootesdump/1990/1214/sys/src/9/port/devdk.c 1667d 1641a dp = (Dk *)a; . 1107d 1105a poperror(); . 1104a if(waserror()){ close(csc); nexterror(); } . 1092,1096d 1086,1089c close(dc); . 1083,1084c dc = dkopenline(dp, line); . 1081c * open the data file . 1077a default: t_val = 0; d_val = 0; panic("bad dial type"); . ## diffname port/devdk.c 1991/0411 ## diff -e /n/bootesdump/1990/1214/sys/src/9/port/devdk.c /n/bootesdump/1991/0411/sys/src/9/port/devdk.c 893c dkwrite(Chan *c, void *a, long n, ulong offset) . 887c return stringread(c, a, n, lp->ruser, offset); . 885c return stringread(c, a, n, lp->raddr, offset); . 883c return stringread(c, a, n, lp->addr, offset); . 866c dkread(Chan *c, void *a, long n, ulong offset) . ## diffname port/devdk.c 1991/0419 ## diff -e /n/bootesdump/1991/0411/sys/src/9/port/devdk.c /n/bootesdump/1991/0419/sys/src/9/port/devdk.c 755a Chan* dkclwalk(Chan *c, char *name) { return devclwalk(c, name); } . ## diffname port/devdk.c 1991/0427 ## diff -e /n/bootesdump/1991/0419/sys/src/9/port/devdk.c /n/bootesdump/1991/0427/sys/src/9/port/devdk.c 756,761d ## diffname port/devdk.c 1991/0706 ## diff -e /n/bootesdump/1991/0427/sys/src/9/port/devdk.c /n/bootesdump/1991/0706/sys/src/9/port/devdk.c 1476c print("unrecognized csc message %o.%o(%o)\n", d.type, d.srv, line); . 770c * its ctl file. . ## diffname port/devdk.c 1991/0723 ## diff -e /n/bootesdump/1991/0706/sys/src/9/port/devdk.c /n/bootesdump/1991/0723/sys/src/9/port/devdk.c 1467c /* print("dksrvmesg(%d)\n", line); /**/ . ## diffname port/devdk.c 1991/0828 ## diff -e /n/bootesdump/1991/0723/sys/src/9/port/devdk.c /n/bootesdump/1991/0828/sys/src/9/port/devdk.c 1472c dp->lines = line+1; . ## diffname port/devdk.c 1991/1105 ## diff -e /n/bootesdump/1991/0828/sys/src/9/port/devdk.c /n/bootesdump/1991/1105/sys/src/9/port/devdk.c 1062c strcat(dialstr, u->p->user); . 1048c if(strlen(addr)+strlen(u->p->user)+2 >= sizeof(dialstr)) . ## diffname port/devdk.c 1991/1107 ## diff -e /n/bootesdump/1991/1105/sys/src/9/port/devdk.c /n/bootesdump/1991/1107/sys/src/9/port/devdk.c 1685c lp = dp->linep[i]; . 1661a freeb(dp->alloc); . 1649c lp = dp->linep[i]; . 1604c lp = dp->linep[line]; . 1555c lp = dp->linep[line]; . 1535c lp = dp->linep[line]; . 1499c lp = dp->linep[line]; . 1401c lp = dk[c->dev].linep[STREAMID(c->qid.path)]; . 1368c lp = dp->linep[line]; . 1341,1343c DPRINT("src(%s)user(%s)dest(%s)w(%d)\n", lp->raddr, lp->ruser, lp->addr, W_TRAF(lp->window)); . 1275c lp = dp->linep[lineno]; . 1031c lp = dp->linep[line]; . 880c lp = dk[c->dev].linep[STREAMID(c->qid.path)]; . 829d 810,811d 808c if(line == dp->lines) . 804c c->qid.path = STREAMQID(line, Sctlqid); lp->state = Lopened; qunlock(lp); . 797,798c for(line = dp->ncsc+1; line < dp->lines; line++){ lp = dp->linep[line]; . 781c Line *lp; . 731c dp = dkalloc(spec, 0, 0); . 683a dk = (Dk*)ialloc(conf.dkif*sizeof(Dk), 0); . 672d 652d 599,600d 593c dp = dkalloc(name, ncsc, lines); . 509c line = lp->lineno; . 467c dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0); . 462c dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0); . 457c dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0); . 452c dkmesg(c, T_CHG, D_CLOSE, lp->lineno, 0); . 388c q->other->ptr = q->ptr = lp = dp->linep[s->id]; . 347c lp = dp->linep[line]; . 284c dkhangup(dp->linep[i]); . 243a /* * allocate memory for line structures */ n = sizeof(Line*)*dp->lines; bp = allocb(n); if(bp->lim - bp->base < n){ unlock(&dklock); errors("too many lines"); } dp->linep = (Line **)bp->base; bp->wptr += n; dp->alloc = bp; for(i = 0; i < n; i++){ if(bp->lim - bp->wptr < sizeof(Line)){ bp = allocb(sizeof(Line)*n); bp->next = dp->alloc; dp->alloc = bp; } dp->linep[i] = (Line*)bp->wptr; dp->linep[i]->lineno = i; bp->wptr += sizeof(Line); } . 242c dp->ncsc = ncsc; dp->lines = lines; . 238a if(lines == 0) errors("unknown dk interface"); /* * init the structures */ . 227c for(dp = dk; dp < &dk[conf.dkif]; dp++){ . 223a Block *bp; int i, n; . 220c dkalloc(char *name, int ncsc, int lines) . 134c static Dk *dk; . 132a Block *alloc; . 127c Line **linep; . 110d 99a int lineno; . 15,19d ## diffname port/devdk.c 1991/1108 ## diff -e /n/bootesdump/1991/1107/sys/src/9/port/devdk.c /n/bootesdump/1991/1108/sys/src/9/port/devdk.c 1480c DPRINT("t(%d)s(%d)l(%d)\n", d.type, d.srv, line); . 1466a DPRINT("dkcsckproc: %d\n", dp->ncsc); . 1002a * return the contents of the info files */ void dkfilladdr(Chan *c, char *buf, int len) { strncpy(buf, dk[c->dev].linep[STREAMID(c->qid.path)]->addr, len); } void dkfillraddr(Chan *c, char *buf, int len) { strncpy(buf, dk[c->dev].linep[STREAMID(c->qid.path)]->raddr, len); } void dkfillruser(Chan *c, char *buf, int len) { strncpy(buf, dk[c->dev].linep[STREAMID(c->qid.path)]->ruser, len); } /* . 980a * return the number of an unused line (reserve it) */ static int dkcloneline(Chan *c) { Line *lp; Dk *dp; int line; dp = &dk[c->dev]; /* * get an unused device and open its control file */ for(line = dp->ncsc+1; line < dp->lines; line++){ lp = dp->linep[line]; if(lp->state == Lclosed && canqlock(lp)){ if(lp->state != Lclosed){ qunlock(lp); continue; } lp->state = Lopened; qunlock(lp); return lp->lineno; } } error(Enodev); } /* . 894,915c return netread(c, a, n, offset, &dk[c->dev].net); . 806,875c return netopen(c, omode, &dk[c->dev].net); . 794,802d 786,791c netstat(c, dp, &dk[c->dev].net); . 777,780c return netwalk(c, name, &dk[c->dev].net); . 721,744d 714,717d 669,706d 273c /* * fill in the network structure */ dp->net.name = dp->name; dp->net.nconv = dp->lines+1; dp->net.devp = &dkinfo; dp->net.protop = &urpinfo; dp->net.listen = dklisten; dp->net.clone = dkcloneline; dp->net.ninfo = 3; dp->net.info[0].name = "addr"; dp->net.info[0].fill = dkfilladdr; dp->net.info[1].name = "raddr"; dp->net.info[1].fill = dkfillraddr; dp->net.info[2].name = "ruser"; dp->net.info[2].fill = dkfillruser; . 271a n -= sizeof(Line); . 265a memset(bp->base, 0, bp->lim-bp->base); . 263c n = sizeof(Line)*(dp->lines); for(i = 1; i <= dp->lines; i++){ . 259a memset(bp->base, 0, bp->lim-bp->base); . 254c n = sizeof(Line*)*(dp->lines+1); . 239a } . 238c if(lines == 0){ unlock(&dklock); . 222a Line *lp; . 197a * for standard network interface (net.c) */ static int dkcloneline(Chan*); static int dklisten(Chan*); static void dkfilladdr(Chan*, char*, int); static void dkfillraddr(Chan*, char*, int); static void dkfillruser(Chan*, char*, int); extern Qinfo dkinfo; /* . 187d 127a Network net; . 13,21d ## diffname port/devdk.c 1991/1114 ## diff -e /n/bootesdump/1991/1108/sys/src/9/port/devdk.c /n/bootesdump/1991/1114/sys/src/9/port/devdk.c 270c for(i = 0; i <= dp->lines; i++){ . ## diffname port/devdk.c 1991/1115 ## diff -e /n/bootesdump/1991/1114/sys/src/9/port/devdk.c /n/bootesdump/1991/1115/sys/src/9/port/devdk.c 1272a /* listener becomes owner */ netown(&dp->net, lp->lineno, dp->prot[from].owner, 0); . 1130a from = STREAMID(c->qid.path); . 1127a int from; . 854a /* current user becomes owner */ netown(&dp->net, lp->lineno, u->p->user, 0); . 830c netwstat(c, dp, &dk[c->dev].net); . 698a for(i = 0; i < conf.dkif; i++) dk[i].prot = (Netprot*)ialloc(conf.nurp*sizeof(Netprot), 0); . 697a int i; . 532a netdisown(&dp->net, lp->lineno); . 291a dp->net.prot = dp->prot; . 287c dp->net.nconv = dp->lines; . 270c for(i = 0; i < dp->lines; i++){ . 259c n = sizeof(Line*)*(dp->lines); . 119a Netprot *prot; . 16a enum { Maxlines = 256, }; . ## diffname port/devdk.c 1991/1116 ## diff -e /n/bootesdump/1991/1115/sys/src/9/port/devdk.c /n/bootesdump/1991/1116/sys/src/9/port/devdk.c 1613,1616c c = dkopencsc(dp); . 1040c csc = dkopencsc(dp); . 898a * open the common signalling channel */ static Chan* dkopencsc(Dk *dp) { qlock(dp); if(dp->csc == 0) dp->csc = dkopenline(dp, dp->ncsc); else incref(dp->csc); qunlock(dp); return dp->csc; } /* . 876,878d 675c dkopencsc(dp); . 540a if(lp->lineno == dp->ncsc) dp->csc = 0; netdisown(&dp->net, lp->lineno); . 539d 507c c = dkopencsc(dp); . 181a static Chan* dkopencsc(Dk*); . 126c Block *alloc; /* blocks containing Line structs */ . 116c int lines; /* number of lines */ . 114d 110a . 108a QLock; Chan *csc; . ## diffname port/devdk.c 1991/1120 ## diff -e /n/bootesdump/1991/1116/sys/src/9/port/devdk.c /n/bootesdump/1991/1120/sys/src/9/port/devdk.c 1628d 547a lock(dp); dp->ref--; if(dp->ref == 0) freeb(dp->alloc); unlock(dp); . 456a dp->ref++; . 336a dp->name[0] = 0; . 243c if(dp->name[0] == 0 && dp->ref == 0) . 112a int ref; . ## diffname port/devdk.c 1991/1122 ## diff -e /n/bootesdump/1991/1120/sys/src/9/port/devdk.c /n/bootesdump/1991/1122/sys/src/9/port/devdk.c 309a dp->net.info[3].name = "stats"; dp->net.info[3].fill = urpfillstats; . 303c dp->net.ninfo = 4; . ## diffname port/devdk.c 1991/1206 ## diff -e /n/bootesdump/1991/1122/sys/src/9/port/devdk.c /n/bootesdump/1991/1206/sys/src/9/port/devdk.c 1121c errors(dkerr[lp->err]); . 1119c errors(dkerr[0]); . 840c for(m = 0; m < DKERRS-1; m++) if(strcmp(field[2], dkerr[m]) == 0) break; dkanswer(c, strtoul(field[1], 0, 0), m); . 173c #define DKERRS sizeof(dkerr)/sizeof(char*) . 163,171c char* dkerr[]={ [DKok]"", [DKbusy]"host overloaded", [DKnetotl]"network not answering", [DKdestotl]"host not answering", [DKbadnet]"unknown address", [DKnetbusy]"network overloaded", [DKinuse]"server in use", [DKreject]"connection refused", . 151c * map datakit error to errno . 85,87d ## diffname port/devdk.c 1991/1214 ## diff -e /n/bootesdump/1991/1206/sys/src/9/port/devdk.c /n/bootesdump/1991/1214/sys/src/9/port/devdk.c 851a USED(c); . 779a USED(c); . ## diffname port/devdk.c 1991/1228 ## diff -e /n/bootesdump/1991/1214/sys/src/9/port/devdk.c /n/bootesdump/1991/1228/sys/src/9/port/devdk.c 166,167c [DKnetbusy]"network busy", [DKinuse]"service in use", . 164c [DKdestotl]"destination not answering", . 162c [DKbusy]"destination busy", . ## diffname port/devdk.c 1992/0111 ## diff -e /n/bootesdump/1991/1228/sys/src/9/port/devdk.c /n/bootesdump/1992/0111/sys/src/9/port/devdk.c 1123c error(dkerr[lp->err]); . 1121c error(dkerr[0]); . 270c error(Ebadarg); . 248,251d 244c if(freep == 0 || lines == 0){ . 7c #include "../port/error.h" . ## diffname port/devdk.c 1992/0130 ## diff -e /n/bootesdump/1992/0111/sys/src/9/port/devdk.c /n/bootesdump/1992/0130/sys/src/9/port/devdk.c 813c if(n > sizeof buf - 1) n = sizeof buf - 1; strncpy(buf, a, n); buf[n] = '\0'; . ## diffname port/devdk.c 1992/0219 ## diff -e /n/bootesdump/1992/0130/sys/src/9/port/devdk.c /n/bootesdump/1992/0219/sys/src/9/port/devdk.c 318a s->opens++; /* Hold this queue in place */ s->inuse++; . ## diffname port/devdk.c 1992/0221 ## diff -e /n/bootesdump/1992/0219/sys/src/9/port/devdk.c /n/bootesdump/1992/0221/sys/src/9/port/devdk.c 1259c if((dts++ % 1000) == 0) print("dklisten: repeat timestamp %d\n", lineno); . 1177a static int dts; . ## diffname port/devdk.c 1992/0223 ## diff -e /n/bootesdump/1992/0221/sys/src/9/port/devdk.c /n/bootesdump/1992/0223/sys/src/9/port/devdk.c 325c * close down a dkmux, this shouldn't happen . 311,312c * a new dkmux. hold the stream in place so it can never be closed down. . ## diffname port/devdk.c 1992/0305 ## diff -e /n/bootesdump/1992/0223/sys/src/9/port/devdk.c /n/bootesdump/1992/0305/sys/src/9/port/devdk.c 591,592c FLOWCTL(dp->wq, bp); . 109d 106a Lock; . ## diffname port/devdk.c 1992/0321 ## diff -e /n/bootesdump/1992/0305/sys/src/9/port/devdk.c /n/bootesdump/1992/0321/sys/src/9/port/devdk.c 2c #include "../port/lib.h" . ## diffname port/devdk.c 1992/0409 ## diff -e /n/bootesdump/1992/0321/sys/src/9/port/devdk.c /n/bootesdump/1992/0409/sys/src/9/port/devdk.c 1368a /* * set window size */ if(code == 0){ if(waserror()){ close(dc); nexterror(); } sprint(reply, "init %d %d", lp->window, Streamhi); dc = dkopenline(dp, line); dc->qid.path = STREAMQID(line, Sctlqid); streamwrite(dc, reply, strlen(reply), 1); close(dc); poperror(); } . 1154a sprint(lp->other, "w=%d", lp->window); . 947a void dkfillother(Chan *c, char *buf, int len) { strncpy(buf, dk[c->dev].linep[STREAMID(c->qid.path)]->other, len); } . 547a lp->window = 0; . 304a dp->net.info[4].name = "other"; dp->net.info[4].fill = dkfillother; . 296c dp->net.ninfo = 5; . 202a static void dkfillother(Chan*, char*, int); . 97a char other[32]; . ## diffname port/devdk.c 1992/0520 ## diff -e /n/bootesdump/1992/0409/sys/src/9/port/devdk.c /n/bootesdump/1992/0520/sys/src/9/port/devdk.c 1344a return -1; /* never reached */ . 898a return -1; /* never reached */ . 852a return -1; /* never reached */ . ## diffname port/devdk.c 1992/0601 ## diff -e /n/bootesdump/1992/0520/sys/src/9/port/devdk.c /n/bootesdump/1992/0601/sys/src/9/port/devdk.c 163,169c [DKbusy]"devdk: destination busy", [DKnetotl]"devdk: network not answering", [DKdestotl]"devdk: destination not answering", [DKbadnet]"devdk: unknown address", [DKnetbusy]"devdk: network busy", [DKinuse]"devdk: service in use", [DKreject]"devdk: connection refused", . ## diffname port/devdk.c 1992/0622 ## diff -e /n/bootesdump/1992/0601/sys/src/9/port/devdk.c /n/bootesdump/1992/0622/sys/src/9/port/devdk.c 725c dk[i].prot = (Netprot*)xalloc(conf.nurp*sizeof(Netprot)); . 723c dk = (Dk*)xalloc(conf.dkif*sizeof(Dk)); . 270,286d 264,268c dp->linep = (Line **)xalloc(sizeof(Line*) * dp->lines); if(dp->linep == 0) error(Enomem); lp = xalloc(dp->lines*sizeof(Line)); if(lp == 0) error(Enomem); for(i = 0; i < dp->lines; i++) { lp->lineno = i; dp->linep[i] = lp++; . 232d 162,169c [DKok] "", [DKbusy] "devdk: destination busy", [DKnetotl] "devdk: network not answering", [DKdestotl] "devdk: destination not answering", [DKbadnet] "devdk: unknown address", [DKnetbusy] "devdk: network busy", [DKinuse] "devdk: service in use", [DKreject] "devdk: connection refused", . ## diffname port/devdk.c 1992/0623 ## diff -e /n/bootesdump/1992/0622/sys/src/9/port/devdk.c /n/bootesdump/1992/0623/sys/src/9/port/devdk.c 1679a if(lp == 0) continue; . 1667a for(;;){ . 1664,1666c while(waserror()); . 1640,1661d 1601d 1598c if(line < 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) . 1552a if(lp == 0) continue; . 1532d 1527c if (line <= 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) { . 1496d 1491c if (line <= 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) { . 1397c lp = linealloc(&dk[c->dev], STREAMID(c->qid.path), 1); . 1348c lp = linealloc(dp, line, 1); . 1345a Dk *dp; . 1343d 1324c netown(lp, dp->linep[from]->owner, 0); . 1250c lp = linealloc(dp, lineno, 1); . 1002c lp = linealloc(dp, line, 1); . 919c qunlock(&dp->csclock); . 914c Line *lp; qlock(&dp->csclock); . 884a qunlock(&dp->netlock); . 881c qunlock(&dp->netlock); . 879c netown(lp, u->p->user, 0); . 871,875c if(lp == 0 || lp->state == Lclosed){ lp = linealloc(dp, line, 0); . 868a qlock(&dp->netlock); . 762c Dk *dp; dp = &dk[c->dev]; linealloc(dp, STREAMID(c->qid.path), 1); return netopen(c, omode, &dp->net); . 709,711c dk = (Dk*)xalloc(Maxdk*sizeof(Dk)); . 560c * low order byte first. Make sure the first block contains * both the 2 channel bytes and the control byte. . 539,544d 537c netdisown(lp); . 479,483d 445,451d 402,403c lp = linealloc(dp, line, 1); if(lp && canqlock(lp)){ . 314,347d 300a * allocate a line if it doesn't exist */ static Line* linealloc(Dk *dp, int lineno, int dolock) { Line *lp; if(dp->opened == 0) error(Enoifc); if(dolock) qlock(&dp->netlock); if(lineno > dp->lines) panic("linealloc"); lp = dp->linep[lineno]; if(lp == 0){ lp = smalloc(sizeof(Line)); lp->lineno = lineno; netadd(&dp->net, lp, lineno); dp->linep[lineno] = lp; } if(dolock) qunlock(&dp->netlock); return lp; } /* . 283d 263,272c dp->linep = smalloc(sizeof(Line*) * dp->lines); . 261c * allocate memory for array of pointers to lines. * line structures are allocated as needed. . 250,252d 242c if(dp->name[0] == 0) . 237c for(dp = dk; dp < &dk[Maxdk]; dp++){ . 227c static Dk* . 220c 0, . 212d 125,128d 111c Lock; . 107,108c QLock netlock; Network net; QLock csclock; . 86a Netprot; /* stat info */ . 18c Maxdk = 4, . ## diffname port/devdk.c 1992/0625 ## diff -e /n/bootesdump/1992/0623/sys/src/9/port/devdk.c /n/bootesdump/1992/0625/sys/src/9/port/devdk.c 1495d 1491,1493c if (line <= 0 || line >= dp->lines || (lp = dp->linep[line]) == 0) . 1362c lp = linealloc(dk[c->dev], STREAMID(c->qid.path), 1); . 1312c dp = dk[c->dev]; . 1142c dp = dk[c->dev]; . 966c dp = dk[c->dev]; . 909c strncpy(buf, dk[c->dev]->linep[STREAMID(c->qid.path)]->other, len); . 904c strncpy(buf, dk[c->dev]->linep[STREAMID(c->qid.path)]->ruser, len); . 899c strncpy(buf, dk[c->dev]->linep[STREAMID(c->qid.path)]->raddr, len); . 894c strncpy(buf, dk[c->dev]->linep[STREAMID(c->qid.path)]->addr, len); . 882,883c incref(dp->csc); . 872c * open the common signalling channel (dp->csc's reference count never goes below 1) . 829c dp = dk[c->dev]; . 816c netwstat(c, dp, &dk[c->dev]->net); . 746c return netread(c, a, n, offset, &dk[c->dev]->net); . 724c dp = dk[c->dev]; . 716c netstat(c, dp, &dk[c->dev]->net); . 710c return netwalk(c, name, &dk[c->dev]->net); . 697c c->dev = dev; . 691c for(dev = 0; dev < Maxdk; dev++){ dp = dk[dev]; if(dp && strcmp(dp->name, spec) == 0) break; } if(dev == Maxdk) error(Enoifc); . 684a int dev; . 669,671d 657a tsleep(&dp->closeallr, haveca, dp, 15000); . 656d 646d 638d 632c q->ptr = q->other->ptr = dp; dk[n] = dp; unlock(&dklock); poperror(); . 628,630d 625a for(n = 0; n < Maxdk; n++){ dp = dk[n]; if(dp == 0) break; if(strcmp(name, dp->name) == 0) error(Einuse); } if(n == Maxdk) error(Enoifc); /* * allocate both a dk structure and an array of pointers to line * structures */ dp = smalloc(sizeof(Dk)); dp->ncsc = ncsc; dp->lines = lines; dp->linep = smalloc(sizeof(Line*) * dp->lines); strcpy(dp->name, name); dp->net.name = dp->name; dp->net.nconv = dp->lines; dp->net.devp = &dkinfo; dp->net.protop = &urpinfo; dp->net.listen = dklisten; dp->net.clone = dkcloneline; dp->net.ninfo = 5; dp->net.info[0].name = "addr"; dp->net.info[0].fill = dkfilladdr; dp->net.info[1].name = "raddr"; dp->net.info[1].fill = dkfillraddr; dp->net.info[2].name = "ruser"; dp->net.info[2].fill = dkfillruser; dp->net.info[3].name = "stats"; dp->net.info[3].fill = urpfillstats; dp->net.info[4].name = "other"; dp->net.info[4].fill = dkfillother; . 620,624c lock(&dklock); if(waserror()){ unlock(&dklock); nexterror(); . 618c * find a free dk slot. it name is already configured * or no slots are left, error. . 600a name[sizeof(name)-1] = 0; . 501,502d 420c dp = dk[s->dev]; . 398,401c static Streamopen dkstopen; static Streamclose dkstclose; static Streamput dkoput, dkiput; . 321,322c naildownstream(s); . 318c RD(q)->ptr = 0; . 294,295d 223,286d 210,212c static Streamopen dkmuxopen; static Streamput dkmuxoput; static Streamput dkmuxiput; . 129,130c Lock dklock; Dk *dk[Maxdk]; . 122d 119d 114,116d 109c Network net; /* stat info */ Line **linep; /* array of line structures */ . 107c struct Dk { . ## diffname port/devdk.c 1992/0711 ## diff -e /n/bootesdump/1992/0625/sys/src/9/port/devdk.c /n/bootesdump/1992/0711/sys/src/9/port/devdk.c 1560c int i; . 1520d 1324d 843,844d 722a USED(offset); . 698a USED(name); USED(omode); USED(perm); . ## diffname port/devdk.c 1992/0717 ## diff -e /n/bootesdump/1992/0711/sys/src/9/port/devdk.c /n/bootesdump/1992/0717/sys/src/9/port/devdk.c 1218a if(cp = strchr(lp->addr, '.')){ *cp = '!'; if(cp = strchr(cp, '.')) *cp = 0; } . 1216c * Special characters are escaped by '\'s. Convert to * a plan 9 address, i.e. system!service. . 1107a char *cp; . 1085d 876c Dk *dp; Line *lp; int line; char lbuf[65]; line = STREAMID(c->qid.path); dp = dk[c->dev]; lp = linealloc(dp, line, 1); sprint(lbuf, "%s/%d %d %s window %d\n", dp->name, line, lp->state != Lclosed ? 1 : 0, dkstate[lp->state], lp->window); strncpy(buf, lbuf, len); . 874c dkfillstatus(Chan *c, char *buf, int len) . 871c if(len < sizeof(dk[0]->linep[0]->ruser)+2) error(Ebadarg); sprint(buf, "%s\n", dk[c->dev]->linep[STREAMID(c->qid.path)]->ruser); . 866c if(len < sizeof(dk[0]->linep[0]->raddr)+2) error(Ebadarg); sprint(buf, "%s\n", dk[c->dev]->linep[STREAMID(c->qid.path)]->raddr); . 861c if(len < sizeof(dk[0]->linep[0]->addr)+2) error(Ebadarg); sprint(buf, "%s\n", dk[c->dev]->linep[STREAMID(c->qid.path)]->addr); . 588,589c dp->net.info[4].name = "status"; dp->net.info[4].fill = dkfillstatus; . 586c dp->net.info[3].name = "urpstats"; . 582c dp->net.info[1].name = "remote"; . 580c dp->net.info[0].name = "local"; . 200c static void dkfillstatus(Chan*, char*, int); . 142a char *dkstate[] = { [Lclosed] "Closed", [Lopened] "Opened", [Lconnected] "Established", [Lrclose] "Rclose", [Llclose] "Lclose", [Ldialing] "Dialing", [Llistening] "Listen", [Lackwait] "Ackwait", [Laccepting] "Accepting", }; . 99d ## diffname port/devdk.c 1992/1030 ## diff -e /n/bootesdump/1992/0717/sys/src/9/port/devdk.c /n/bootesdump/1992/1030/sys/src/9/port/devdk.c 1034c for(win = 0; ; win++) if(W_VALUE(win) >= dp->urpwindow || win == 15) break; dkmesg(csc, t_val, d_val, line, W_WINDOW(win, win, 2)); . 950c int line, win; . ## diffname port/devdk.c 1992/1031 ## diff -e /n/bootesdump/1992/1030/sys/src/9/port/devdk.c /n/bootesdump/1992/1031/sys/src/9/port/devdk.c 536a if(window < 16) window = 1<<(window+4); . 527c window = 2048; . 491c * the urp window size (default==2048) . 83d ## diffname port/devdk.c 1993/0501 ## diff -e /n/bootesdump/1992/1031/sys/src/9/port/devdk.c /n/fornaxdump/1993/0501/sys/src/brazil/port/devdk.c 993c strcat(dialstr, up->user); . 979c if(strlen(addr)+strlen(up->user)+2 >= sizeof(dialstr)) . 823c netown(lp, up->user, 0); . ## diffname port/devdk.c 1993/0804 # deleted ## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/devdk.c /n/fornaxdump/1993/0804/sys/src/brazil/port/devdk.c 1,1636d