| plan 9 kernel history: overview | file list | diff list |
1991/01151/port/devnonet.c (diff list | history)
| 1990/1210/sys/src/9/port/devnonet.c:236,242 – 1990/1214/sys/src/9/port/devnonet.c:236,241 (short | long) | ||
| 1990/1210 | nonetopen(Chan *c, int omode) { Stream *s; | |
| 1990/1210/sys/src/9/port/devnonet.c:252,258 – 1990/1214/sys/src/9/port/devnonet.c:251,257 | ||
| 1990/1210 | * get an unused device and open it's control file */ ifc = &noifc[c->dev]; | |
| 1990/1214 | nonetopenclone(c, ifc); | |
| 1990/1210 | break; case Nlistenqid: /* | |
| 1990/1210/sys/src/9/port/devnonet.c:866,874 – 1990/1214/sys/src/9/port/devnonet.c:865,871 | ||
| 1990/1210 | queueack(Noconv *cp, int mid) { int next; | |
| 1990/1210/sys/src/9/port/devnonet.c:959,964 – 1990/1214/sys/src/9/port/devnonet.c:956,962 | ||
| 1990/1210 | msgrem = mp->len; pktrem = msgrem > ifc->maxtu ? ifc->maxtu : msgrem; bp = mp->first; | |
| 1990/1214 | SET(rptr); | |
| 1990/1210 | if(bp) rptr = bp->rptr; last = pkt = mkhdr(cp, msgrem); | |
| 1990/1210/sys/src/9/port/devnonet.c:1189,1195 – 1990/1214/sys/src/9/port/devnonet.c:1187,1192 | ||
| 1990/1210 | int nonetcksum(Block *bp, int offset) { | |
| 1990/1214/sys/src/9/port/devnonet.c:6,21 – 1990/1229/sys/src/9/port/devnonet.c:6,22 (short | long) | ||
| 1990/1210 | #include "io.h" #include "errno.h" | |
| 1990/1229 | #define DPRINT if(pnonet)print | |
| 1990/1210 | #define NOW (MACHP(0)->ticks*MS2HZ) static Noifc *noifc; | |
| 1990/1229 | int pnonet; | |
| 1990/1210 | enum { /* * tuning parameters */ | |
| 1990/1229 | MSrexmit = 500, /* retranmission interval in ms */ | |
| 1990/1210 | MSack = 50, /* ms to sit on an ack */ /* | |
| 1990/1214/sys/src/9/port/devnonet.c:102,108 – 1990/1229/sys/src/9/port/devnonet.c:103,109 | ||
| 1990/1210 | * allocate the interfaces */ noifc = (Noifc *)ialloc(sizeof(Noifc) * conf.nnoifc, 0); | |
| 1990/1229 | for(i = 0; i < conf.nnoifc; i++) | |
| 1990/1210 | noifc[i].conv = (Noconv *)ialloc(sizeof(Noconv) * conf.nnoconv, 0); /* | |
| 1990/1214/sys/src/9/port/devnonet.c:1040,1045 – 1990/1229/sys/src/9/port/devnonet.c:1041,1047 | ||
| 1990/1210 | * if a new call request comes in on a connected channel, hang up the call */ if(h->mid==0 && (f & NO_NEWCALL) && cp->state==Cconnected){ | |
| 1990/1229 | DPRINT("new call on connected channel\n"); | |
| 1990/1210 | freeb(bp); hangup(cp); return; | |
| 1990/1214/sys/src/9/port/devnonet.c:1227,1230 – 1990/1229/sys/src/9/port/devnonet.c:1229,1237 | ||
| 1990/1210 | hp->sum[1] = s>>8; hp->sum[0] = s; return s & 0xffff; | |
| 1990/1229 | } nonettoggle() { pnonet ^= 1; | |
| 1990/1210 | } | |
| 1990/1229/sys/src/9/port/devnonet.c:37,42 – 1990/1231/sys/src/9/port/devnonet.c:37,43 (short | long) | ||
| 1990/1210 | static void sendmsg(Noconv*, Nomsg*); static void startconv(Noconv*, int, char*, int); static void queueack(Noconv*, int); | |
| 1990/1231 | static void sendack(Noconv*, int); | |
| 1990/1210 | static void nonetiput(Queue*, Block*); static void nonetoput(Queue*, Block*); | |
| 1990/1229/sys/src/9/port/devnonet.c:704,710 – 1990/1231/sys/src/9/port/devnonet.c:705,713 | ||
| 1990/1210 | cp->hdr->flag |= NO_SERVICE; sprint(buf, "%s %s", service, u->p->pgrp->user); c->qid.path = STREAMQID(STREAMID(c->qid.path), Sdataqid); | |
| 1990/1231 | print("sending request\n"); | |
| 1990/1210 | streamwrite(c, buf, strlen(buf), 1); | |
| 1990/1231 | print("request sent\n"); | |
| 1990/1210 | c->qid.path = STREAMQID(STREAMID(c->qid.path), Sctlqid); } } | |
| 1990/1229/sys/src/9/port/devnonet.c:781,786 – 1990/1231/sys/src/9/port/devnonet.c:784,790 | ||
| 1990/1210 | * stuff the connect message into it */ f = ((Nohdr *)(call.msg->rptr))->flag; | |
| 1990/1231 | print("call from %d %s\n", call.circuit, call.raddr); | |
| 1990/1210 | startconv(cp, call.circuit, call.raddr, Cconnecting); print("rcving %d byte message\n", call.msg->wptr - call.msg->rptr); nonetrcvmsg(cp, call.msg); | |
| 1990/1229/sys/src/9/port/devnonet.c:1013,1018 – 1990/1231/sys/src/9/port/devnonet.c:1017,1035 | ||
| 1990/1210 | } /* | |
| 1990/1231 | * send an acknowledgement */ static void sendack(Noconv *cp, int ack) { cp->ackmsg.len = 0; cp->ackmsg.first = 0; cp->ackmsg.acked = ack; cp->ackmsg.mid = cp->lastacked; sendmsg(cp, &cp->ctl); } /* | |
| 1990/1210 | * receive a message (called by the multiplexor; noetheriput, nofddiiput, ...) */ void | |
| 1990/1229/sys/src/9/port/devnonet.c:1058,1064 – 1990/1231/sys/src/9/port/devnonet.c:1075,1081 | ||
| 1990/1210 | hangup(cp); } else { if(r>0) | |
| 1990/1231 | sendack(cp, h->mid); | |
| 1990/1210 | cp->bad++; } freeb(bp); | |
| 1990/1231/sys/src/9/port/devnonet.c:37,43 – 1991/0102/sys/src/9/port/devnonet.c:37,42 (short | long) | ||
| 1990/1210 | static void sendmsg(Noconv*, Nomsg*); static void startconv(Noconv*, int, char*, int); static void queueack(Noconv*, int); | |
| 1990/1231 |
| |
| 1990/1210 | static void nonetiput(Queue*, Block*); static void nonetoput(Queue*, Block*); | |
| 1990/1231/sys/src/9/port/devnonet.c:921,927 – 1991/0102/sys/src/9/port/devnonet.c:920,926 | ||
| 1990/1210 | wq = ifc->wq->next; /* | |
| 1991/0102 | * one transmitter at a time for this connection | |
| 1990/1210 | */ qlock(&cp->xlock); | |
| 1990/1231/sys/src/9/port/devnonet.c:1005,1035 – 1991/0102/sys/src/9/port/devnonet.c:1004,1023 | ||
| 1990/1210 | static void sendctlmsg(Noconv *cp, int flag, int new) { | |
| 1991/0102 | Nomsg ctl; ctl.len = 0; ctl.first = 0; ctl.acked = 0; | |
| 1990/1210 | if(new) | |
| 1991/0102 | ctl.mid = Nnomsg^cp->out[cp->next].mid; | |
| 1990/1210 | else | |
| 1991/0102 | ctl.mid = cp->lastacked; | |
| 1990/1210 | cp->hdr->flag |= flag; | |
| 1991/0102 | sendmsg(cp, &ctl); | |
| 1990/1210 | } /* | |
| 1990/1231 |
| |
| 1990/1210 | * receive a message (called by the multiplexor; noetheriput, nofddiiput, ...) */ void | |
| 1990/1231/sys/src/9/port/devnonet.c:1074,1081 – 1991/0102/sys/src/9/port/devnonet.c:1062,1071 | ||
| 1990/1210 | if(f & NO_HANGUP) hangup(cp); } else { | |
| 1990/1231 |
| |
| 1991/0102 | if(r>0){ queueack(cp, h->mid); sendctlmsg(cp, 0, 0); } | |
| 1990/1210 | cp->bad++; } freeb(bp); | |
| 1991/0102/sys/src/9/port/devnonet.c:16,22 – 1991/0108/sys/src/9/port/devnonet.c:16,22 (short | long) | ||
| 1990/1210 | /* * tuning parameters */ | |
| 1990/1229 |
| |
| 1991/0108 | MSrexmit = 250, /* retranmission interval in ms */ | |
| 1990/1210 | MSack = 50, /* ms to sit on an ack */ /* | |
| 1991/0102/sys/src/9/port/devnonet.c:37,43 – 1991/0108/sys/src/9/port/devnonet.c:37,43 | ||
| 1990/1210 | static void sendmsg(Noconv*, Nomsg*); static void startconv(Noconv*, int, char*, int); static void queueack(Noconv*, int); | |
| 1991/0108 | static void nonetkproc(void*); | |
| 1990/1210 | static void nonetiput(Queue*, Block*); static void nonetoput(Queue*, Block*); static void nonetstclose(Queue*); | |
| 1991/0102/sys/src/9/port/devnonet.c:89,94 – 1991/0108/sys/src/9/port/devnonet.c:89,100 | ||
| 1990/1210 | }; /* | |
| 1991/0108 | * nonet kproc */ static int kstarted; static Rendez nonetkr; /* | |
| 1990/1210 | * nonet file system. most of the calls use dev.c to access the nonet * directory and stream.c to access the nonet devices. * create the nonet directory. the files are `clone' and stream | |
| 1991/0102/sys/src/9/port/devnonet.c:164,169 – 1991/0108/sys/src/9/port/devnonet.c:170,176 | ||
| 1990/1210 | error(Enoifc); c = devattach('n', spec); c->dev = ifc - noifc; | |
| 1991/0108 | ||
| 1990/1210 | return c; } | |
| 1991/0102/sys/src/9/port/devnonet.c:240,245 – 1991/0108/sys/src/9/port/devnonet.c:247,257 | ||
| 1990/1210 | Noifc *ifc; int line; | |
| 1991/0108 | if(!kstarted){ kproc("nonetack", nonetkproc, 0); kstarted = 1; } | |
| 1990/1210 | if(c->qid.path & CHDIR){ /* * directories are read only | |
| 1991/0102/sys/src/9/port/devnonet.c:466,473 – 1991/0108/sys/src/9/port/devnonet.c:478,487 | ||
| 1990/1210 | } } | |
| 1991/0108 | qlock(cp); | |
| 1990/1210 | cp->rcvcircuit = -1; cp->state = Cclosed; | |
| 1991/0108 | qunlock(cp); | |
| 1990/1210 | poperror(); } | |
| 1991/0102/sys/src/9/port/devnonet.c:511,516 – 1991/0108/sys/src/9/port/devnonet.c:525,531 | ||
| 1990/1210 | Noconv *cp; int next; Nomsg *mp; | |
| 1991/0108 | int retries; | |
| 1990/1210 | cp = (Noconv *)(q->ptr); | |
| 1991/0102/sys/src/9/port/devnonet.c:573,581 – 1991/0108/sys/src/9/port/devnonet.c:588,599 | ||
| 1990/1210 | /* * wait for acknowledgement */ | |
| 1991/0108 | retries = 0; | |
| 1990/1210 | while(!mp->acked && cp->state!=Chungup){ sendmsg(cp, mp); tsleep(&mp->r, acked, mp, MSrexmit); | |
| 1991/0108 | if(retries++ > 100) errors("to many nonet rexmits"); | |
| 1990/1210 | } /* | |
| 1991/0102/sys/src/9/port/devnonet.c:704,712 – 1991/0108/sys/src/9/port/devnonet.c:722,730 | ||
| 1990/1210 | cp->hdr->flag |= NO_SERVICE; sprint(buf, "%s %s", service, u->p->pgrp->user); c->qid.path = STREAMQID(STREAMID(c->qid.path), Sdataqid); | |
| 1990/1231 |
| |
| 1991/0108 | DPRINT("sending request\n"); | |
| 1990/1210 | streamwrite(c, buf, strlen(buf), 1); | |
| 1990/1231 |
| |
| 1991/0108 | DPRINT("request sent\n"); | |
| 1990/1210 | c->qid.path = STREAMQID(STREAMID(c->qid.path), Sctlqid); } } | |
| 1991/0102/sys/src/9/port/devnonet.c:783,791 – 1991/0108/sys/src/9/port/devnonet.c:801,809 | ||
| 1990/1210 | * stuff the connect message into it */ f = ((Nohdr *)(call.msg->rptr))->flag; | |
| 1990/1231 |
| |
| 1991/0108 | DPRINT("call from %d %s\n", call.circuit, call.raddr); | |
| 1990/1210 | startconv(cp, call.circuit, call.raddr, Cconnecting); | |
| 1991/0108 | DPRINT("rcving %d byte message\n", call.msg->wptr - call.msg->rptr); | |
| 1990/1210 | nonetrcvmsg(cp, call.msg); call.msg = 0; | |
| 1991/0102/sys/src/9/port/devnonet.c:794,808 – 1991/0108/sys/src/9/port/devnonet.c:812,824 | ||
| 1990/1210 | * grab them */ if(f & NO_SERVICE){ | |
| 1991/0108 | DPRINT("reading service\n"); | |
| 1990/1210 | c->qid.path = STREAMQID(cp - ifc->conv, Sdataqid); n = streamread(c, buf, sizeof(buf)); c->qid.path = STREAMQID(cp - ifc->conv, Sctlqid); | |
| 1991/0102/sys/src/9/port/devnonet.c:1056,1062 – 1991/0108/sys/src/9/port/devnonet.c:1072,1078 | ||
| 1990/1210 | * ignore old messages and process the acknowledgement */ if(h->mid != mp->mid){ | |
| 1991/0108 | DPRINT("old msg %d instead of %d r==%d\n", h->mid, mp->mid, r); | |
| 1990/1210 | if(r == 0){ rcvack(cp, h->ack); if(f & NO_HANGUP) | |
| 1991/0102/sys/src/9/port/devnonet.c:1063,1070 – 1991/0108/sys/src/9/port/devnonet.c:1079,1086 | ||
| 1990/1210 | hangup(cp); } else { | |
| 1991/0102 | if(r>0){ | |
| 1991/0108 | rcvack(cp, h->ack); | |
| 1991/0102 | queueack(cp, h->mid); | |
| 1990/1210 | cp->bad++; } | |
| 1991/0102/sys/src/9/port/devnonet.c:1238,1244 – 1991/0108/sys/src/9/port/devnonet.c:1254,1300 | ||
| 1990/1210 | return s & 0xffff; | |
| 1990/1229 | } | |
| 1991/0108 | /* * send acknowledges that need to be sent. this happens at 1/2 * the retransmission interval. */ static void nonetkproc(void *arg) { Noifc *ifc; Noconv *cp, *ep; cp = 0; ifc = 0; if(waserror()){ if(ifc) unlock(ifc); if(cp) qunlock(cp); } loop: for(ifc = noifc; ifc < &noifc[conf.nnoifc]; ifc++){ if(ifc->wq==0 || !canlock(ifc)) continue; ep = ifc->conv + conf.nnoconv; for(cp = ifc->conv; cp < ep; cp++){ if(cp->state==Cclosed || !canqlock(cp)) continue; if(cp->afirst != cp->anext){ DPRINT("sending ack %d\n", cp->ack[cp->afirst]); sendctlmsg(cp, 0, 0); } qunlock(cp); } unlock(ifc); } tsleep(&nonetkr, return0, 0, MSrexmit/2); goto loop; } | |
| 1990/1229 | nonettoggle() { pnonet ^= 1; | |
| 1990/1210 | } | |
| 1991/0108 | ||
| 1991/0108/sys/src/9/port/devnonet.c:554,561 – 1991/0109/sys/src/9/port/devnonet.c:554,562 (short | long) | ||
| 1990/1210 | mp->first = 0; } mp->inuse = 0; | |
| 1991/0109 | } qunlock(&cp->mlock); nexterror(); | |
| 1990/1210 | } /* | |
| 1991/0108/sys/src/9/port/devnonet.c:593,600 – 1991/0109/sys/src/9/port/devnonet.c:594,602 | ||
| 1990/1210 | sendmsg(cp, mp); tsleep(&mp->r, acked, mp, MSrexmit); | |
| 1991/0108 | if(retries++ > 100) | |
| 1991/0109 | errors("too many nonet rexmits"); | |
| 1990/1210 | } | |
| 1991/0109 | poperror(); | |
| 1990/1210 | /* * free buffer | |
| 1991/0108/sys/src/9/port/devnonet.c:603,609 – 1991/0109/sys/src/9/port/devnonet.c:605,610 | ||
| 1990/1210 | mp->first = 0; mp->inuse = 0; wakeup(&cp->r); | |
| 1991/0109/sys/src/9/port/devnonet.c:781,787 – 1991/0112/sys/src/9/port/devnonet.c:781,787 (short | long) | ||
| 1990/1210 | */ ep = &ifc->conv[conf.nnoconv]; for(cp = &ifc->conv[0]; cp < ep; cp++){ | |
| 1991/0112 | if(cp->state>Cannounced && (call.circuit^1)==cp->rcvcircuit | |
| 1990/1210 | && strcmp(call.raddr, cp->raddr)==0) break; } | |
| 1991/0112/sys/src/9/port/devnonet.c:517,523 – 1991/01151/sys/src/9/port/devnonet.c:517,523 (short | long) | ||
| 1990/1210 | Nomsg *mp; mp = (Nomsg *)a; | |
| 1991/01151 | return mp->inuse; | |
| 1990/1210 | } static void nonetoput(Queue *q, Block *bp) | |
| 1991/0112/sys/src/9/port/devnonet.c:549,559 – 1991/01151/sys/src/9/port/devnonet.c:549,564 | ||
| 1990/1210 | mp = 0; if(waserror()){ if(mp){ | |
| 1991/01151 | q->len = 0; q->first = q->last = 0; | |
| 1990/1210 | if(mp->first){ freeb(mp->first); mp->first = 0; } mp->inuse = 0; | |
| 1991/01151 | mp->acked = 0; if(((cp->first+1)%Nnomsg) == cp->next) cp->first = cp->next; | |
| 1991/0109 | } qunlock(&cp->mlock); nexterror(); | |
| 1991/0112/sys/src/9/port/devnonet.c:584,610 – 1991/01151/sys/src/9/port/devnonet.c:589,601 | ||
| 1990/1210 | q->len = 0; q->first = q->last = 0; cp->sent++; | |
| 1991/01151 | * send the message, the kproc will retry | |
| 1990/1210 | */ | |
| 1991/0108 |
| |
| 1990/1210 |
| |
| 1991/0108 |
| |
| 1991/0109 |
| |
| 1990/1210 |
| |
| 1991/01151 | sendmsg(cp, mp); qunlock(&cp->mlock); | |
| 1991/0109 | poperror(); | |
| 1990/1210 |
| |
| 1991/0112/sys/src/9/port/devnonet.c:871,881 – 1991/01151/sys/src/9/port/devnonet.c:862,886 | ||
| 1990/1210 | return; /* | |
| 1991/01151 | * free it | |
| 1990/1210 | */ | |
| 1991/01151 | cp->rexmit = 0; | |
| 1990/1210 | mp->acked = 1; | |
| 1991/01151 | freeb(mp->first); mp->first = 0; mp->inuse = 0; /* * advance first if this is the first */ if((mid&Nmask) == cp->first){ while(cp->first != cp->next){ if(cp->out[cp->first].acked == 0) break; cp->first = (cp->first+1) % Nnomsg; } } | |
| 1990/1210 | } /* | |
| 1991/0112/sys/src/9/port/devnonet.c:1094,1103 – 1991/01151/sys/src/9/port/devnonet.c:1099,1108 | ||
| 1990/1210 | * start of message packet */ if(mp->first){ | |
| 1991/01151 | DPRINT("mp->mid==%d mp->rem==%d r==%d\n", mp->mid, mp->rem, r); freeb(mp->first); mp->first = mp->last = 0; mp->len = 0; | |
| 1990/1210 | } mp->rem = r; } else { | |
| 1991/0112/sys/src/9/port/devnonet.c:1105,1111 – 1991/01151/sys/src/9/port/devnonet.c:1110,1116 | ||
| 1990/1210 | * a continuation */ if(-r != mp->rem) { | |
| 1991/01151 | DPRINT("mp->mid==%d mp->rem==%d r==%d\n", mp->mid, mp->rem, r); | |
| 1990/1210 | cp->bad++; freeb(bp); return; | |
| 1991/0112/sys/src/9/port/devnonet.c:1275,1287 – 1991/01151/sys/src/9/port/devnonet.c:1280,1318 | ||
| 1991/0108 | } loop: | |
| 1991/01151 | /* * loop through all active interfaces */ | |
| 1991/0108 | for(ifc = noifc; ifc < &noifc[conf.nnoifc]; ifc++){ if(ifc->wq==0 || !canlock(ifc)) continue; | |
| 1991/01151 | /* * loop through all active conversations */ | |
| 1991/0108 | ep = ifc->conv + conf.nnoconv; for(cp = ifc->conv; cp < ep; cp++){ if(cp->state==Cclosed || !canqlock(cp)) continue; | |
| 1991/01151 | if(cp->state == Cclosed){ qunlock(cp); continue; } /* * resend the first message */ if(cp->first!=cp->next && cp->out[cp->first].time>=NOW){ if(cp->rexmit++ > 100){ print("hanging up\n"); hangup(cp); } else sendmsg(cp, &(cp->out[cp->first])); } /* * resend an acknowledge */ | |
| 1991/0108 | if(cp->afirst != cp->anext){ DPRINT("sending ack %d\n", cp->ack[cp->afirst]); sendctlmsg(cp, 0, 0); | |
| 1991/0112/sys/src/9/port/devnonet.c:1294,1300 – 1991/01151/sys/src/9/port/devnonet.c:1325,1332 | ||
| 1991/0108 | goto loop; } | |
| 1990/1229 |
| |
| 1991/01151 | void nonettoggle(void) | |
| 1990/1229 | { pnonet ^= 1; | |
| 1990/1210 | } | |
| 1991/01151/sys/src/9/port/devnonet.c:86,91 – 1991/0118/sys/src/9/port/devnonet.c:86,92 (short | long) | ||
| 1990/1210 | Cconnecting, Chungup, Cclosing, | |
| 1991/0118 | Csuperceded, | |
| 1990/1210 | }; /* | |
| 1991/01151/sys/src/9/port/devnonet.c:470,476 – 1991/0118/sys/src/9/port/devnonet.c:471,477 | ||
| 1990/1210 | * send hangup messages to the other side * until it hangs up or we get tired. */ | |
| 1991/0118 | if(cp->state>=Cconnected && cp->state!=Csuperceded){ | |
| 1990/1210 | sendctlmsg(cp, NO_HANGUP, 1); for(i=0; i<10 && !ishungup(cp); i++){ sendctlmsg(cp, NO_HANGUP, 1); | |
| 1991/01151/sys/src/9/port/devnonet.c:961,966 – 1991/0118/sys/src/9/port/devnonet.c:962,971 | ||
| 1990/1210 | } cp->hdr->mid = mp->mid; | |
| 1991/0118 | /* * package n blocks into m packets. make sure * no packet is < mintu or > maxtu in length. */ | |
| 1990/1210 | if(ifc->mintu > mp->len) { /* * short message: | |
| 1991/01151/sys/src/9/port/devnonet.c:971,977 – 1991/0118/sys/src/9/port/devnonet.c:976,985 | ||
| 1990/1210 | memcpy(pkt->wptr, bp->rptr, n = BLEN(bp)); pkt->wptr += n; } | |
| 1991/0118 | /* * round up to mintu */ memset(pkt->wptr, 0, n = ifc->mintu-mp->len); | |
| 1990/1210 | pkt->wptr += n; } else { /* | |
| 1991/01151/sys/src/9/port/devnonet.c:986,991 – 1991/0118/sys/src/9/port/devnonet.c:994,1000 | ||
| 1990/1210 | if(bp) rptr = bp->rptr; last = pkt = mkhdr(cp, msgrem); | |
| 1991/0118 | n = 0; | |
| 1990/1210 | while(bp){ /* * if pkt full, send and create new header block | |
| 1991/01151/sys/src/9/port/devnonet.c:1011,1021 – 1991/0118/sys/src/9/port/devnonet.c:1020,1043 | ||
| 1990/1210 | rptr = bp->rptr; } } | |
| 1991/0118 | /* * round up last packet to mintu */ if(n < ifc->mintu){ n = ifc->mintu - n; last = last->next = allocb(n); memset(last->wptr, 0, n); last->wptr += n; } | |
| 1990/1210 | } nonetcksum(pkt, ifc->hsize); last->flags |= S_DELIM; | |
| 1991/0118 | if(cp->rexmit > 10) mp->time = NOW + 10*MSrexmit; else mp->time = NOW + (cp->rexmit+1)*MSrexmit; DPRINT("xmit %d %lud %lud\n", cp->rexmit, NOW, mp->time); | |
| 1990/1210 | (*wq->put)(wq, pkt); | |
| 1991/01151/sys/src/9/port/devnonet.c:1067,1076 – 1991/0118/sys/src/9/port/devnonet.c:1089,1102 | ||
| 1990/1210 | /* * if a new call request comes in on a connected channel, hang up the call */ | |
| 1991/0118 | if(h->mid==0 && (f & NO_NEWCALL) && (cp->state==Cconnected || cp->state==Csuperceded)){ | |
| 1990/1229 | DPRINT("new call on connected channel\n"); | |
| 1990/1210 | freeb(bp); | |
| 1991/0118 | if(cp->state != Csuperceded){ cp->state = Csuperceded; hangup(cp); } | |
| 1990/1210 | return; } | |
| 1991/01151/sys/src/9/port/devnonet.c:1269,1274 – 1991/0118/sys/src/9/port/devnonet.c:1295,1301 | ||
| 1991/0108 | { Noifc *ifc; Noconv *cp, *ep; | |
| 1991/0118 | Nomsg *mp; | |
| 1991/0108 | cp = 0; ifc = 0; | |
| 1991/01151/sys/src/9/port/devnonet.c:1302,1313 – 1991/0118/sys/src/9/port/devnonet.c:1329,1342 | ||
| 1991/01151 | /* * resend the first message */ | |
| 1991/0118 | if(cp->first!=cp->next && NOW>=cp->out[cp->first].time){ if(cp->rexmit++ > 60){ | |
| 1991/01151 | print("hanging up\n"); hangup(cp); | |
| 1991/0118 | } else { mp = &(cp->out[cp->first]); sendmsg(cp, mp); } | |
| 1991/01151 | } /* | |
| 1991/0118/sys/src/9/port/devnonet.c:27,47 – 1991/0119/sys/src/9/port/devnonet.c:27,48 (short | long) | ||
| 1990/1210 | }; /* predeclared */ | |
| 1991/0108 |
| |
| 1990/1210 |
| |
| 1991/0119 | static void nohangup(Noconv*); static void noreset(Noconv*); static Block* nohdr(Noconv*, int); static void nolisten(Chan*, Noifc*); static void noannounce(Chan*, char*); static void noconnect(Chan*, char*); static void norack(Noconv*, int); static void nosendctl(Noconv*, int, int); static void nosend(Noconv*, Nomsg*); static void nostartconv(Noconv*, int, char*, int); static void noqack(Noconv*, int); static void nokproc(void*); static void noiput(Queue*, Block*); static void nooput(Queue*, Block*); static void noclose(Queue*); static void noopen(Queue*, Stream*); | |
| 1990/1210 | extern Qinfo noetherinfo; extern Qinfo nonetinfo; | |
| 1991/0118/sys/src/9/port/devnonet.c:85,92 – 1991/0119/sys/src/9/port/devnonet.c:86,92 | ||
| 1990/1210 | Cconnected, Cconnecting, Chungup, | |
| 1991/0118 |
| |
| 1991/0119 | Creset, | |
| 1990/1210 | }; /* | |
| 1991/0118/sys/src/9/port/devnonet.c:249,255 – 1991/0119/sys/src/9/port/devnonet.c:249,255 | ||
| 1990/1210 | int line; | |
| 1991/0108 | if(!kstarted){ | |
| 1991/0119 | kproc("nonetack", nokproc, 0); | |
| 1991/0108 | kstarted = 1; } | |
| 1991/0118/sys/src/9/port/devnonet.c:276,282 – 1991/0119/sys/src/9/port/devnonet.c:276,282 | ||
| 1990/1210 | ifc = &noifc[c->dev]; if(ifc->conv[line].state != Cannounced) error(Enoannounce); | |
| 1991/0119 | nolisten(c, ifc); | |
| 1990/1210 | break; case Nraddrqid: /* | |
| 1991/0118/sys/src/9/port/devnonet.c:311,317 – 1991/0119/sys/src/9/port/devnonet.c:311,317 | ||
| 1990/1210 | Noifc *ifc; /* | |
| 1991/0119 | * real closing happens in noclose | |
| 1990/1210 | */ if(c->qid.path != CHDIR) streamclose(c); | |
| 1991/0118/sys/src/9/port/devnonet.c:374,380 – 1991/0119/sys/src/9/port/devnonet.c:374,380 | ||
| 1990/1210 | return streamwrite(c, a, n, 0); /* | |
| 1991/0119 | * easier to do here than in nooput | |
| 1990/1210 | */ if(t == Sctlqid){ strncpy(buf, a, sizeof buf); | |
| 1991/0118/sys/src/9/port/devnonet.c:382,390 – 1991/0119/sys/src/9/port/devnonet.c:382,390 | ||
| 1990/1210 | if(strcmp(field[0], "connect")==0){ if(m < 2) error(Ebadarg); | |
| 1991/0119 | noconnect(c, field[1]); | |
| 1990/1210 | } else if(strcmp(field[0], "announce")==0){ | |
| 1991/0119 | noannounce(c, field[1]); | |
| 1990/1210 | } else if(strcmp(field[0], "accept")==0){ /* ignore */; } else if(strcmp(field[0], "reject")==0){ | |
| 1991/0118/sys/src/9/port/devnonet.c:414,423 – 1991/0119/sys/src/9/port/devnonet.c:414,423 | ||
| 1990/1210 | */ Qinfo nonetinfo = { | |
| 1991/0119 | noiput, nooput, noopen, noclose, | |
| 1990/1210 | "nonet" }; | |
| 1991/0118/sys/src/9/port/devnonet.c:424,432 – 1991/0119/sys/src/9/port/devnonet.c:424,434 | ||
| 1990/1210 | /* * store the device end of the stream so that the multiplexor can * send blocks upstream. | |
| 1991/0119 | * * State Transition: Cclosed -> Copen | |
| 1990/1210 | */ static void | |
| 1991/0119 | noopen(Queue *q, Stream *s) | |
| 1990/1210 | { Noifc *ifc; Noconv *cp; | |
| 1991/0118/sys/src/9/port/devnonet.c:443,448 – 1991/0119/sys/src/9/port/devnonet.c:445,452 | ||
| 1990/1210 | /* * wait until a hangup is received. * then send a hangup message (until one is received). | |
| 1991/0119 | * * State Transitions: * -> Cclosed | |
| 1990/1210 | */ static int ishungup(void *a) | |
| 1991/0118/sys/src/9/port/devnonet.c:450,459 – 1991/0119/sys/src/9/port/devnonet.c:454,469 | ||
| 1990/1210 | Noconv *cp; cp = (Noconv *)a; | |
| 1991/0119 | switch(cp->state){ case Chungup: case Creset: case Cclosed: return 1; } return 0; | |
| 1990/1210 | } static void | |
| 1991/0119 | noclose(Queue *q) | |
| 1990/1210 | { Noconv *cp; Nomsg *mp; | |
| 1991/0118/sys/src/9/port/devnonet.c:471,482 – 1991/0119/sys/src/9/port/devnonet.c:481,503 | ||
| 1990/1210 | * send hangup messages to the other side * until it hangs up or we get tired. */ | |
| 1991/0118 |
| |
| 1990/1210 |
| |
| 1991/0119 | switch(cp->state){ case Cconnected: /* * send close till we get one back */ nosendctl(cp, NO_HANGUP, 1); | |
| 1990/1210 | for(i=0; i<10 && !ishungup(cp); i++){ | |
| 1991/0119 | nosendctl(cp, NO_HANGUP, 1); | |
| 1990/1210 | tsleep(&cp->r, ishungup, cp, MSrexmit); } | |
| 1991/0119 | break; case Chungup: /* * ack any close */ nosendctl(cp, NO_HANGUP, 1); break; | |
| 1990/1210 | } | |
| 1991/0108 | qlock(cp); | |
| 1991/0118/sys/src/9/port/devnonet.c:488,496 – 1991/0119/sys/src/9/port/devnonet.c:509,519 | ||
| 1990/1210 | /* * send all messages up stream. this should only be control messages | |
| 1991/0119 | * * State Transition: (on M_HANGUP) * -> Chungup | |
| 1990/1210 | */ static void | |
| 1991/0119 | noiput(Queue *q, Block *bp) | |
| 1990/1210 | { Noconv *cp; | |
| 1991/0118/sys/src/9/port/devnonet.c:521,527 – 1991/0119/sys/src/9/port/devnonet.c:544,550 | ||
| 1991/01151 | return mp->inuse; | |
| 1990/1210 | } static void | |
| 1991/0119 | nooput(Queue *q, Block *bp) | |
| 1990/1210 | { Noconv *cp; int next; | |
| 1991/0118/sys/src/9/port/devnonet.c:594,600 – 1991/0119/sys/src/9/port/devnonet.c:617,623 | ||
| 1990/1210 | /* | |
| 1991/01151 | * send the message, the kproc will retry | |
| 1990/1210 | */ | |
| 1991/01151 |
| |
| 1991/0119 | nosend(cp, mp); | |
| 1991/01151 | qunlock(&cp->mlock); | |
| 1991/0109 | poperror(); | |
| 1990/1210 | } | |
| 1991/0118/sys/src/9/port/devnonet.c:604,610 – 1991/0119/sys/src/9/port/devnonet.c:627,633 | ||
| 1990/1210 | * none already exists for this circuit. */ void | |
| 1991/0119 | nostartconv(Noconv *cp, int circuit, char *raddr, int state) | |
| 1990/1210 | { int i; char name[32]; | |
| 1991/0118/sys/src/9/port/devnonet.c:647,653 – 1991/0119/sys/src/9/port/devnonet.c:670,677 | ||
| 1990/1210 | cp->out[0].acked = 1; cp->out[0].rem = 0; cp->first = cp->next = 1; | |
| 1991/0119 | cp->rexmit = cp->bad = cp->sent = cp->rcvd = 0; cp->lastacked = Nnomsg|(Nnomsg-1); | |
| 1990/1210 | /* * used for demultiplexing | |
| 1991/0118/sys/src/9/port/devnonet.c:668,676 – 1991/0119/sys/src/9/port/devnonet.c:692,702 | ||
| 1990/1210 | /* * announce willingness to take calls | |
| 1991/0119 | * * State Transition: Copen -> Chungup | |
| 1990/1210 | */ static void | |
| 1991/0119 | noannounce(Chan *c, char *addr) | |
| 1990/1210 | { Noconv *cp; | |
| 1991/0118/sys/src/9/port/devnonet.c:684,692 – 1991/0119/sys/src/9/port/devnonet.c:710,720 | ||
| 1990/1210 | * connect to the destination whose name is pointed to by bp->rptr. * * a service is separated from the destination system by a '!' | |
| 1991/0119 | * * State Transition: Copen -> Cconnecting | |
| 1990/1210 | */ static void | |
| 1991/0119 | noconnect(Chan *c, char *addr) | |
| 1990/1210 | { Noifc *ifc; Noconv *cp; | |
| 1991/0118/sys/src/9/port/devnonet.c:706,712 – 1991/0119/sys/src/9/port/devnonet.c:734,740 | ||
| 1990/1210 | error(Ebadctl); } | |
| 1991/0119 | nostartconv(cp, 2*(cp - ifc->conv), addr, Cconnecting); | |
| 1990/1210 | if(service){ /* | |
| 1991/0118/sys/src/9/port/devnonet.c:715,723 – 1991/0119/sys/src/9/port/devnonet.c:743,749 | ||
| 1990/1210 | cp->hdr->flag |= NO_SERVICE; sprint(buf, "%s %s", service, u->p->pgrp->user); c->qid.path = STREAMQID(STREAMID(c->qid.path), Sdataqid); | |
| 1991/0108 |
| |
| 1990/1210 | streamwrite(c, buf, strlen(buf), 1); | |
| 1991/0108 |
| |
| 1990/1210 | c->qid.path = STREAMQID(STREAMID(c->qid.path), Sctlqid); } } | |
| 1991/0118/sys/src/9/port/devnonet.c:726,731 – 1991/0119/sys/src/9/port/devnonet.c:752,759 | ||
| 1990/1210 | * listen for a call. There can be many listeners, but only one can sleep * on the circular queue at a time. ifc->listenl lets only one at a time into * the sleep. | |
| 1991/0119 | * * State Transition: Cclosed -> Copen -> Cconnecting | |
| 1990/1210 | */ static int iscall(void *a) | |
| 1991/0118/sys/src/9/port/devnonet.c:736,742 – 1991/0119/sys/src/9/port/devnonet.c:764,770 | ||
| 1990/1210 | return ifc->rptr != ifc->wptr; } static void | |
| 1991/0119 | nolisten(Chan *c, Noifc *ifc) | |
| 1990/1210 | { Noconv *cp, *ep; Nocall call; | |
| 1991/0118/sys/src/9/port/devnonet.c:795,801 – 1991/0119/sys/src/9/port/devnonet.c:823,829 | ||
| 1990/1210 | */ f = ((Nohdr *)(call.msg->rptr))->flag; | |
| 1991/0108 | DPRINT("call from %d %s\n", call.circuit, call.raddr); | |
| 1990/1210 |
| |
| 1991/0119 | nostartconv(cp, call.circuit, call.raddr, Cconnecting); | |
| 1991/0108 | DPRINT("rcving %d byte message\n", call.msg->wptr - call.msg->rptr); | |
| 1990/1210 | nonetrcvmsg(cp, call.msg); call.msg = 0; | |
| 1991/0118/sys/src/9/port/devnonet.c:828,854 – 1991/0119/sys/src/9/port/devnonet.c:856,915 | ||
| 1990/1210 | /* * send a hangup signal up the stream to get all line disciplines * to cease and desist | |
| 1991/0119 | * * State Transition: {Cconnected, Cconnecting} -> Chungup | |
| 1990/1210 | */ static void | |
| 1991/0119 | nohangup(Noconv *cp) | |
| 1990/1210 | { Block *bp; Queue *q; | |
| 1991/0119 | switch(cp->state){ case Cconnected: case Cconnecting: cp->state = Chungup; bp = allocb(0); bp->type = M_HANGUP; q = cp->rq; PUTNEXT(q, bp); break; } | |
| 1990/1210 | wakeup(&cp->r); } /* | |
| 1991/0119 | * send a hangup signal up the stream to get all line disciplines * to cease and desist. The Creset state makes any subsequent close not * send hangup messages. * * State Transition: {Cconnected, Cconnecting} -> Creset */ static void noreset(Noconv *cp) { Block *bp; Queue *q; switch(cp->state){ case Cconnected: case Cconnecting: cp->state = Creset; bp = allocb(0); bp->type = M_HANGUP; q = cp->rq; PUTNEXT(q, bp); break; } wakeup(&cp->r); } /* | |
| 1990/1210 | * process a message acknowledgement. if the message * has any xmit buffers queued, free them. */ static void | |
| 1991/0119 | norack(Noconv *cp, int mid) | |
| 1990/1210 | { Nomsg *mp; Block *bp; | |
| 1991/0118/sys/src/9/port/devnonet.c:889,895 – 1991/0119/sys/src/9/port/devnonet.c:950,956 | ||
| 1990/1210 | * acknowledgements queued. */ static void | |
| 1991/0119 | noqack(Noconv *cp, int mid) | |
| 1990/1210 | { int next; | |
| 1991/0118/sys/src/9/port/devnonet.c:904,910 – 1991/0119/sys/src/9/port/devnonet.c:965,971 | ||
| 1990/1210 | * make a packet header */ Block * | |
| 1991/0119 | nohdr(Noconv *cp, int rem) | |
| 1990/1210 | { Block *bp; Nohdr *hp; | |
| 1991/0118/sys/src/9/port/devnonet.c:923,933 – 1991/0119/sys/src/9/port/devnonet.c:984,994 | ||
| 1990/1210 | * transmit a message. this involves breaking a possibly multi-block message into * a train of packets on the media. * | |
| 1991/0119 | * called by nooput(). the qlock(mp) synchronizes these two | |
| 1990/1210 | * processes. */ static void | |
| 1991/0119 | nosend(Noconv *cp, Nomsg *mp) | |
| 1990/1210 | { Noifc *ifc; Queue *wq; | |
| 1991/0118/sys/src/9/port/devnonet.c:971,977 – 1991/0119/sys/src/9/port/devnonet.c:1032,1038 | ||
| 1990/1210 | * short message: * copy the whole message into the header block */ | |
| 1991/0119 | last = pkt = nohdr(cp, mp->len); | |
| 1990/1210 | for(bp = mp->first; bp; bp = bp->next){ memcpy(pkt->wptr, bp->rptr, n = BLEN(bp)); pkt->wptr += n; | |
| 1991/0118/sys/src/9/port/devnonet.c:993,999 – 1991/0119/sys/src/9/port/devnonet.c:1054,1060 | ||
| 1990/1214 | SET(rptr); | |
| 1990/1210 | if(bp) rptr = bp->rptr; | |
| 1991/0119 | last = pkt = nohdr(cp, msgrem); | |
| 1991/0118 | n = 0; | |
| 1990/1210 | while(bp){ /* | |
| 1991/0118/sys/src/9/port/devnonet.c:1003,1009 – 1991/0119/sys/src/9/port/devnonet.c:1064,1070 | ||
| 1990/1210 | nonetcksum(pkt, ifc->hsize); last->flags |= S_DELIM; (*wq->put)(wq, pkt); | |
| 1991/0119 | last = pkt = nohdr(cp, -msgrem); | |
| 1990/1210 | pktrem = msgrem > ifc->maxtu ? ifc->maxtu : msgrem; } n = bp->wptr - rptr; | |
| 1991/0118/sys/src/9/port/devnonet.c:1036,1042 – 1991/0119/sys/src/9/port/devnonet.c:1097,1102 | ||
| 1991/0118 | mp->time = NOW + 10*MSrexmit; else mp->time = NOW + (cp->rexmit+1)*MSrexmit; | |
| 1990/1210 | (*wq->put)(wq, pkt); qunlock(&cp->xlock); poperror(); | |
| 1991/0118/sys/src/9/port/devnonet.c:1046,1052 – 1991/0119/sys/src/9/port/devnonet.c:1106,1112 | ||
| 1990/1210 | * send a control message (hangup or acknowledgement). */ static void | |
| 1991/0119 | nosendctl(Noconv *cp, int flag, int new) | |
| 1990/1210 | { | |
| 1991/0102 | Nomsg ctl; | |
| 1991/0118/sys/src/9/port/devnonet.c:1058,1068 – 1991/0119/sys/src/9/port/devnonet.c:1118,1130 | ||
| 1990/1210 | else | |
| 1991/0102 | ctl.mid = cp->lastacked; | |
| 1990/1210 | cp->hdr->flag |= flag; | |
| 1991/0102 |
| |
| 1991/0119 | nosend(cp, &ctl); | |
| 1990/1210 | } /* * receive a message (called by the multiplexor; noetheriput, nofddiiput, ...) | |
| 1991/0119 | * * State Transition: (no NO_NEWCALL in msg) Cconnecting -> Cconnected | |
| 1990/1210 | */ void nonetrcvmsg(Noconv *cp, Block *bp) | |
| 1991/0118/sys/src/9/port/devnonet.c:1089,1102 – 1991/0119/sys/src/9/port/devnonet.c:1151,1160 | ||
| 1990/1210 | /* * if a new call request comes in on a connected channel, hang up the call */ | |
| 1991/0118 |
| |
| 1991/0119 | if((f&NO_NEWCALL) && cp->state==Cconnected){ | |
| 1990/1229 | DPRINT("new call on connected channel\n"); | |
| 1990/1210 | freeb(bp); | |
| 1991/0118 |
| |
| 1991/0119 | noreset(cp); | |
| 1990/1210 | return; } | |
| 1991/0118/sys/src/9/port/devnonet.c:1106,1118 – 1991/0119/sys/src/9/port/devnonet.c:1164,1178 | ||
| 1990/1210 | if(h->mid != mp->mid){ | |
| 1991/0108 | DPRINT("old msg %d instead of %d r==%d\n", h->mid, mp->mid, r); | |
| 1990/1210 | if(r == 0){ | |
| 1991/0119 | norack(cp, h->ack); if(f & NO_RESET) noreset(cp); else if(f & NO_HANGUP) nohangup(cp); | |
| 1990/1210 | } else { | |
| 1991/0102 | if(r>0){ | |
| 1991/0108 |
| |
| 1991/0102 |
| |
| 1991/0119 | norack(cp, h->ack); noqack(cp, h->mid); | |
| 1991/0102 | } | |
| 1990/1210 | cp->bad++; } | |
| 1991/0118/sys/src/9/port/devnonet.c:1163,1171 – 1991/0119/sys/src/9/port/devnonet.c:1223,1232 | ||
| 1990/1210 | * if not, strip off the delimiter. */ if(mp->rem == 0){ | |
| 1991/0119 | cp->hdr->flag &= ~(NO_NEWCALL|NO_SERVICE); norack(cp, h->ack); | |
| 1990/1210 | if(f & NO_ACKME) | |
| 1991/0119 | noqack(cp, h->mid); | |
| 1990/1210 | mp->last->flags |= S_DELIM; PUTNEXT(q, mp->first); mp->first = mp->last = 0; | |
| 1991/0118/sys/src/9/port/devnonet.c:1178,1192 – 1991/0119/sys/src/9/port/devnonet.c:1239,1265 | ||
| 1990/1210 | mp->mid ^= Nnomsg; /* | |
| 1991/0119 | * any NO_NEWCALL after this is another call | |
| 1990/1210 | */ | |
| 1991/0119 | if(cp->state==Cconnecting && !(f&NO_NEWCALL)) | |
| 1990/1210 | cp->state = Cconnected; | |
| 1991/0119 | /* * hangup (after processing message) */ if(f & NO_RESET){ DPRINT("reset with message\n"); noreset(cp); } else if(f & NO_HANGUP){ DPRINT("hangup with message\n"); nohangup(cp); } | |
| 1990/1210 | } else mp->last->flags &= ~S_DELIM; } | |
| 1991/0119 | ||
| 1990/1210 | /* * noifc */ | |
| 1991/0118/sys/src/9/port/devnonet.c:1291,1297 – 1991/0119/sys/src/9/port/devnonet.c:1364,1370 | ||
| 1991/0108 | * the retransmission interval. */ static void | |
| 1991/0119 | nokproc(void *arg) | |
| 1991/0108 | { Noifc *ifc; Noconv *cp, *ep; | |
| 1991/0118/sys/src/9/port/devnonet.c:1332,1341 – 1991/0119/sys/src/9/port/devnonet.c:1405,1414 | ||
| 1991/0118 | if(cp->first!=cp->next && NOW>=cp->out[cp->first].time){ if(cp->rexmit++ > 60){ | |
| 1991/01151 | print("hanging up\n"); | |
| 1991/0119 | nohangup(cp); | |
| 1991/0118 | } else { mp = &(cp->out[cp->first]); | |
| 1991/0119 | nosend(cp, mp); | |
| 1991/0118 | } | |
| 1991/01151 | } | |
| 1991/0118/sys/src/9/port/devnonet.c:1344,1350 – 1991/0119/sys/src/9/port/devnonet.c:1417,1423 | ||
| 1991/01151 | */ | |
| 1991/0108 | if(cp->afirst != cp->anext){ DPRINT("sending ack %d\n", cp->ack[cp->afirst]); | |
| 1991/0119 | nosendctl(cp, 0, 0); | |
| 1991/0108 | } qunlock(cp); } | |
| 1991/0119/sys/src/9/port/devnonet.c:8,13 – 1991/0206/sys/src/9/port/devnonet.c:8,14 (short | long) | ||
| 1990/1210 | ||
| 1990/1229 | #define DPRINT if(pnonet)print | |
| 1990/1210 | #define NOW (MACHP(0)->ticks*MS2HZ) | |
| 1991/0206 | #define MSUCC(x) (((x)+1)%Nnomsg) | |
| 1990/1210 | static Noifc *noifc; | |
| 1990/1229 | int pnonet; | |
| 1991/0119/sys/src/9/port/devnonet.c:501,509 – 1991/0206/sys/src/9/port/devnonet.c:502,516 | ||
| 1990/1210 | } | |
| 1991/0108 | qlock(cp); | |
| 1991/0206 | /* * we give up, ack any unacked messages */ for(i = cp->first; i != cp->next; i = MSUCC(i)) norack(cp, cp->out[i].mid); | |
| 1990/1210 | cp->rcvcircuit = -1; cp->state = Cclosed; | |
| 1991/0108 | qunlock(cp); | |
| 1991/0206 | ||
| 1990/1210 | poperror(); } | |
| 1991/0119/sys/src/9/port/devnonet.c:533,548 – 1991/0206/sys/src/9/port/devnonet.c:540,547 | ||
| 1990/1210 | Noconv *cp; cp = (Noconv *)a; | |
| 1991/0206 | return MSUCC(cp->next) != cp->first; | |
| 1990/1210 | } | |
| 1991/01151 |
| |
| 1990/1210 |
| |
| 1991/0119 | nooput(Queue *q, Block *bp) | |
| 1990/1210 | { | |
| 1991/0119/sys/src/9/port/devnonet.c:570,604 – 1991/0206/sys/src/9/port/devnonet.c:569,594 | ||
| 1990/1210 | return; } | |
| 1991/0206 | /* * block till we get an output buffer */ | |
| 1990/1210 | if(waserror()){ | |
| 1991/01151 |
| |
| 1990/1210 |
| |
| 1991/01151 |
| |
| 1991/0109 |
| |
| 1991/0206 | /* throw out the message */ while(bp = getb(q)) freeb(bp); | |
| 1991/0109 | qunlock(&cp->mlock); nexterror(); | |
| 1990/1210 | } | |
| 1991/0206 | while(!windowopen(cp)) | |
| 1990/1210 | sleep(&cp->r, windowopen, cp); mp = &cp->out[cp->next]; | |
| 1991/0206 | cp->next = MSUCC(cp->next); qlock(cp); qunlock(&cp->mlock); poperror(); | |
| 1990/1210 | /* | |
| 1991/0206 | * point the output buffer to the message | |
| 1990/1210 | */ mp->time = NOW + MSrexmit; mp->first = q->first; | |
| 1991/0119/sys/src/9/port/devnonet.c:608,616 – 1991/0206/sys/src/9/port/devnonet.c:598,606 | ||
| 1990/1210 | mp->acked = 0; /* | |
| 1991/0206 | * take the message out of the queue | |
| 1990/1210 | */ | |
| 1991/0206 | q->len = q->nb = 0; | |
| 1990/1210 | q->first = q->last = 0; cp->sent++; | |
| 1991/0119/sys/src/9/port/devnonet.c:617,624 – 1991/0206/sys/src/9/port/devnonet.c:607,624 | ||
| 1990/1210 | /* | |
| 1991/01151 | * send the message, the kproc will retry | |
| 1990/1210 | */ | |
| 1991/0206 | if(waserror()){ /* throw out the message */ freeb(mp->first); mp->first = 0; mp->acked = 0; if(MSUCC(cp->first) == cp->next) cp->first = cp->next; qunlock(cp); nexterror(); } | |
| 1991/0119 | nosend(cp, mp); | |
| 1991/01151 |
| |
| 1991/0206 | qunlock(cp); | |
| 1991/0109 | poperror(); | |
| 1990/1210 | } | |
| 1991/0119/sys/src/9/port/devnonet.c:661,667 – 1991/0206/sys/src/9/port/devnonet.c:661,666 | ||
| 1990/1210 | cp->out[i].mid = i | Nnomsg; cp->out[i].acked = 1; cp->out[i].rem = 0; | |
| 1991/0119/sys/src/9/port/devnonet.c:927,937 – 1991/0206/sys/src/9/port/devnonet.c:926,935 | ||
| 1991/01151 | * free it | |
| 1990/1210 | */ | |
| 1991/01151 | cp->rexmit = 0; | |
| 1990/1210 |
| |
| 1991/0206 | mp->acked = 1; | |
| 1991/01151 | freeb(mp->first); mp->first = 0; | |
| 1991/0119/sys/src/9/port/devnonet.c:940,947 – 1991/0206/sys/src/9/port/devnonet.c:938,946 | ||
| 1991/01151 | while(cp->first != cp->next){ if(cp->out[cp->first].acked == 0) break; | |
| 1991/0206 | cp->first = MSUCC(cp->first); | |
| 1991/01151 | } | |
| 1991/0206 | wakeup(&cp->r); | |
| 1991/01151 | } | |
| 1990/1210 | } | |
| 1991/0119/sys/src/9/port/devnonet.c:1403,1421 – 1991/0206/sys/src/9/port/devnonet.c:1402,1419 | ||
| 1991/01151 | * resend the first message */ | |
| 1991/0118 | if(cp->first!=cp->next && NOW>=cp->out[cp->first].time){ | |
| 1991/0206 | mp = &(cp->out[cp->first]); | |
| 1991/0118 | if(cp->rexmit++ > 60){ | |
| 1991/01151 |
| |
| 1991/0206 | norack(cp, mp->mid); | |
| 1991/0119 | nohangup(cp); | |
| 1991/0118 |
| |
| 1991/0206 | } else | |
| 1991/0119 | nosend(cp, mp); | |
| 1991/0118 |
| |
| 1991/01151 | } /* | |
| 1991/0206 | * get the acknowledges out | |
| 1991/01151 | */ | |
| 1991/0108 |
| |
| 1991/0206 | while(cp->afirst != cp->anext){ | |
| 1991/0108 | DPRINT("sending ack %d\n", cp->ack[cp->afirst]); | |
| 1991/0119 | nosendctl(cp, 0, 0); | |
| 1991/0108 | } | |
| 1991/0206/sys/src/9/port/devnonet.c:538,546 – 1991/0207/sys/src/9/port/devnonet.c:538,552 (short | long) | ||
| 1990/1210 | windowopen(void *a) { Noconv *cp; | |
| 1991/0207 | int i; | |
| 1990/1210 | cp = (Noconv *)a; | |
| 1991/0206 |
| |
| 1991/0207 | i = cp->next - cp->first; if(i>=0 && i<32) return 1; if(i<0 && Nnomsg+i<32) return 1; return 0; | |
| 1990/1210 | } static void | |
| 1991/0119 | nooput(Queue *q, Block *bp) | |
| 1991/0206/sys/src/9/port/devnonet.c:1413,1419 – 1991/0207/sys/src/9/port/devnonet.c:1419,1425 | ||
| 1991/01151 | /* | |
| 1991/0206 | * get the acknowledges out | |
| 1991/01151 | */ | |
| 1991/0206 |
| |
| 1991/0207 | while(cp->afirst!=cp->anext && cp->rq->next->len<16*1024){ | |
| 1991/0108 | DPRINT("sending ack %d\n", cp->ack[cp->afirst]); | |
| 1991/0119 | nosendctl(cp, 0, 0); | |
| 1991/0108 | } | |
| 1991/0207/sys/src/9/port/devnonet.c:489,495 – 1991/0209/sys/src/9/port/devnonet.c:489,495 (short | long) | ||
| 1991/0119 | */ nosendctl(cp, NO_HANGUP, 1); | |
| 1990/1210 | for(i=0; i<10 && !ishungup(cp); i++){ | |
| 1991/0119 |
| |
| 1991/0209 | nosendctl(cp, NO_HANGUP, 0); | |
| 1990/1210 | tsleep(&cp->r, ishungup, cp, MSrexmit); } | |
| 1991/0119 | break; | |
| 1991/0207/sys/src/9/port/devnonet.c:1009,1028 – 1991/0209/sys/src/9/port/devnonet.c:1009,1018 | ||
| 1990/1210 | wq = ifc->wq->next; /* | |
| 1991/0102 |
| |
| 1990/1210 |
| |
| 1991/0209 | if(cp->afirst!=cp->anext && cp->rq->next->len<16*1024){ | |
| 1990/1210 | cp->hdr->ack = cp->ack[cp->afirst]; cp->afirst = (cp->afirst+1)&Nmask; } | |
| 1991/0207/sys/src/9/port/devnonet.c:1103,1110 – 1991/0209/sys/src/9/port/devnonet.c:1093,1098 | ||
| 1991/0118 | else mp->time = NOW + (cp->rexmit+1)*MSrexmit; | |
| 1990/1210 | (*wq->put)(wq, pkt); | |
| 1991/0207/sys/src/9/port/devnonet.c:1409,1417 – 1991/0209/sys/src/9/port/devnonet.c:1397,1405 | ||
| 1991/01151 | */ | |
| 1991/0118 | if(cp->first!=cp->next && NOW>=cp->out[cp->first].time){ | |
| 1991/0206 | mp = &(cp->out[cp->first]); | |
| 1991/0118 |
| |
| 1991/0209 | if(cp->rexmit++ > 15){ | |
| 1991/0206 | norack(cp, mp->mid); | |
| 1991/0119 |
| |
| 1991/0209 | noreset(cp); | |
| 1991/0206 | } else | |
| 1991/0119 | nosend(cp, mp); | |
| 1991/01151 | } | |
| 1991/0209/sys/src/9/port/devnonet.c:276,282 – 1991/0316/sys/src/9/port/devnonet.c:276,282 (short | long) | ||
| 1990/1210 | line = STREAMID(c->qid.path); ifc = &noifc[c->dev]; if(ifc->conv[line].state != Cannounced) | |
| 1991/0316 | errors("channel not announced"); | |
| 1991/0119 | nolisten(c, ifc); | |
| 1990/1210 | break; case Nraddrqid: | |
| 1991/0316/sys/src/9/port/devnonet.c:976,987 – 1991/0318/sys/src/9/port/devnonet.c:976,988 (short | long) | ||
| 1990/1210 | Nohdr *hp; bp = allocb(cp->ifc->hsize + NO_HDRSIZE + cp->ifc->mintu); | |
| 1991/0318 | memmove(bp->wptr, cp->media->rptr, cp->ifc->hsize + NO_HDRSIZE); | |
| 1990/1210 | bp->wptr += cp->ifc->hsize + NO_HDRSIZE; hp = (Nohdr *)(bp->rptr + cp->ifc->hsize); hp->remain[1] = rem>>8; hp->remain[0] = rem; hp->sum[0] = hp->sum[1] = 0; | |
| 1991/0318 | ||
| 1990/1210 | return bp; } | |
| 1991/0316/sys/src/9/port/devnonet.c:1029,1035 – 1991/0318/sys/src/9/port/devnonet.c:1030,1036 | ||
| 1990/1210 | */ | |
| 1991/0119 | last = pkt = nohdr(cp, mp->len); | |
| 1990/1210 | for(bp = mp->first; bp; bp = bp->next){ | |
| 1991/0318 | memmove(pkt->wptr, bp->rptr, n = BLEN(bp)); | |
| 1990/1210 | pkt->wptr += n; } | |
| 1991/0118 | /* | |
| 1991/0316/sys/src/9/port/devnonet.c:1092,1097 – 1991/0318/sys/src/9/port/devnonet.c:1093,1099 | ||
| 1991/0118 | mp->time = NOW + 10*MSrexmit; else mp->time = NOW + (cp->rexmit+1)*MSrexmit; | |
| 1991/0318 | ||
| 1990/1210 | (*wq->put)(wq, pkt); } | |
| 1991/0318/sys/src/9/port/devnonet.c:443,454 – 1991/0320/sys/src/9/port/devnonet.c:443,449 (short | long) | ||
| 1990/1210 | RD(q)->ptr = WR(q)->ptr = (void *)cp; } | |
| 1991/0119 |
| |
| 1990/1210 |
| |
| 1991/0320 | ||
| 1990/1210 | static int ishungup(void *a) { | |
| 1991/0318/sys/src/9/port/devnonet.c:463,468 – 1991/0320/sys/src/9/port/devnonet.c:458,469 | ||
| 1991/0119 | } return 0; | |
| 1990/1210 | } | |
| 1991/0320 | /* * wait until a hangup is received. * then send a hangup message (until one is received). * * State Transitions: * -> Cclosed */ | |
| 1990/1210 | static void | |
| 1991/0119 | noclose(Queue *q) | |
| 1990/1210 | { | |
| 1991/0318/sys/src/9/port/devnonet.c:1147,1153 – 1991/0320/sys/src/9/port/devnonet.c:1148,1154 | ||
| 1990/1210 | * if a new call request comes in on a connected channel, hang up the call */ | |
| 1991/0119 | if((f&NO_NEWCALL) && cp->state==Cconnected){ | |
| 1990/1229 |
| |
| 1991/0320 | print("new call on connected channel\n"); | |
| 1990/1210 | freeb(bp); | |
| 1991/0119 | noreset(cp); | |
| 1990/1210 | return; | |
| 1991/0320/sys/src/9/port/devnonet.c:5,10 – 1991/0328/sys/src/9/port/devnonet.c:5,11 (short | long) | ||
| 1990/1210 | #include "fns.h" #include "io.h" #include "errno.h" | |
| 1991/0328 | #include "../port/nonet.h" | |
| 1990/1210 | ||
| 1990/1229 | #define DPRINT if(pnonet)print | |
| 1990/1210 | #define NOW (MACHP(0)->ticks*MS2HZ) | |
| 1991/0320/sys/src/9/port/devnonet.c:510,515 – 1991/0328/sys/src/9/port/devnonet.c:511,520 | ||
| 1991/0206 | norack(cp, cp->out[i].mid); | |
| 1990/1210 | cp->rcvcircuit = -1; cp->state = Cclosed; | |
| 1991/0328 | if(cp->media){ freeb(cp->media); cp->media = 0; } | |
| 1991/0108 | qunlock(cp); | |
| 1991/0206 | ||
| 1990/1210 | poperror(); | |
| 1991/0320/sys/src/9/port/devnonet.c:885,895 – 1991/0328/sys/src/9/port/devnonet.c:890,901 | ||
| 1990/1210 | } /* | |
| 1991/0119 |
| |
| 1991/0328 | * Send a hangup signal up the stream to get all line disciplines * to cease and desist. Disassociate this conversation from a circuit * number. Any subsequent close of the conversation will * not send hangup messages. | |
| 1991/0119 | * | |
| 1991/0328 | * State Transition: {Cconnected, Cconnecting, Chungup} -> Creset | |
| 1991/0119 | */ static void noreset(Noconv *cp) | |
| 1991/0320/sys/src/9/port/devnonet.c:900,907 – 1991/0328/sys/src/9/port/devnonet.c:906,916 | ||
| 1991/0119 | switch(cp->state){ case Cconnected: case Cconnecting: | |
| 1991/0328 | case Chungup: print("resetting connection\n"); | |
| 1991/0119 | cp->state = Creset; | |
| 1991/0328 | cp->rcvcircuit = -1; bp = allocb(0); | |
| 1991/0119 | bp->type = M_HANGUP; q = cp->rq; PUTNEXT(q, bp); | |
| 1991/0320/sys/src/9/port/devnonet.c:1145,1160 – 1991/0328/sys/src/9/port/devnonet.c:1154,1202 | ||
| 1990/1210 | f = h->flag; /* | |
| 1991/0328 | * Obey reset even if the message id is bogus | |
| 1990/1210 | */ | |
| 1991/0119 |
| |
| 1991/0320 |
| |
| 1990/1210 |
| |
| 1991/0328 | if(f & NO_RESET){ print("reset received\n"); | |
| 1991/0119 | noreset(cp); | |
| 1991/0328 | freeb(bp); | |
| 1990/1210 | return; } /* | |
| 1991/0328 | * A new call request (maybe), treat it as a reset if seen on a * connected, hungup, or reset channel. * * On a connecting channel, treat as a reset if this is an * invalid message ID. */ if(f & NO_NEWCALL){ switch(cp->state){ case Cclosed: case Copen: case Cannounced: case Creset: panic("nonetrcvmsg %d %d\n", cp->rcvcircuit, cp - cp->ifc->conv); case Chungup: case Cconnected: print("Nonet call on connected/hanging-up circ %d conv %d\n", cp->rcvcircuit, cp - cp->ifc->conv); freeb(bp); noreset(cp); return; case Cconnecting: if(h->mid != mp->mid){ print("Nonet call on connecting circ %d conv %d\n", cp->rcvcircuit, cp - cp->ifc->conv); freeb(bp); noreset(cp); return; } break; } } /* | |
| 1990/1210 | * ignore old messages and process the acknowledgement */ if(h->mid != mp->mid){ | |
| 1991/0320/sys/src/9/port/devnonet.c:1161,1169 – 1991/0328/sys/src/9/port/devnonet.c:1203,1209 | ||
| 1991/0108 | DPRINT("old msg %d instead of %d r==%d\n", h->mid, mp->mid, r); | |
| 1990/1210 | if(r == 0){ | |
| 1991/0119 | norack(cp, h->ack); | |
| 1991/0328 | if(f & NO_HANGUP) | |
| 1991/0119 | nohangup(cp); | |
| 1990/1210 | } else { | |
| 1991/0102 | if(r>0){ | |
| 1991/0320/sys/src/9/port/devnonet.c:1243,1252 – 1991/0328/sys/src/9/port/devnonet.c:1283,1289 | ||
| 1991/0119 | /* * hangup (after processing message) */ | |
| 1991/0328 | if(f & NO_HANGUP){ | |
| 1991/0119 | DPRINT("hangup with message\n"); nohangup(cp); } | |
| 1991/0328/sys/src/9/port/devnonet.c:325,331 – 1991/0411/sys/src/9/port/devnonet.c:325,331 (short | long) | ||
| 1990/1210 | } long | |
| 1991/0411 | nonetread(Chan *c, void *a, long n, ulong offset) | |
| 1990/1210 | { int t; Noconv *cp; | |
| 1991/0328/sys/src/9/port/devnonet.c:346,366 – 1991/0411/sys/src/9/port/devnonet.c:346,366 | ||
| 1990/1210 | cp = &noifc[c->dev].conv[STREAMID(c->qid.path)]; switch(t){ case Nraddrqid: | |
| 1991/0411 | return stringread(c, a, n, cp->raddr, offset); | |
| 1990/1210 | case Naddrqid: | |
| 1991/0411 | return stringread(c, a, n, cp->addr, offset); | |
| 1990/1210 | case Nruserqid: | |
| 1991/0411 | return stringread(c, a, n, cp->ruser, offset); | |
| 1990/1210 | case Nstatsqid: sprint(stats, "sent: %d\nrcved: %d\nrexmit: %d\nbad: %d\n", cp->sent, cp->rcvd, cp->rexmit, cp->bad); | |
| 1991/0411 | return stringread(c, a, n, stats, offset); | |
| 1990/1210 | } error(Eperm); } long | |
| 1991/0411 | nonetwrite(Chan *c, void *a, long n, ulong offset) | |
| 1990/1210 | { int t; int m; | |
| 1991/0411/sys/src/9/port/devnonet.c:208,214 – 1991/0412/sys/src/9/port/devnonet.c:208,214 (short | long) | ||
| 1990/1210 | if(c->qid.path == CHDIR) devstat(c, dp, nonetdir, conf.nnoconv+1, devgen); else if(c->qid.path == Ncloneqid) | |
| 1991/0412 | devstat(c, dp, &nonetdir[conf.nnoconv], 1, devgen); | |
| 1990/1210 | else devstat(c, dp, nosubdir, Nsubdir, streamgen); } | |
| 1991/0412/sys/src/9/port/devnonet.c:82,94 – 1991/0413/sys/src/9/port/devnonet.c:82,94 (short | long) | ||
| 1990/1210 | * Nonet conversation states (for Noconv.state) */ enum { | |
| 1991/0119 |
| |
| 1991/0413 | Cclosed= 0, Copen= 1, Cannounced= 2, Cconnected= 3, Cconnecting= 4, Chungup= 5, Creset= 6, | |
| 1990/1210 | }; /* | |
| 1991/0412/sys/src/9/port/devnonet.c:680,685 – 1991/0413/sys/src/9/port/devnonet.c:680,686 | ||
| 1990/1210 | cp->out[0].mid = 0; cp->out[0].acked = 1; cp->out[0].rem = 0; | |
| 1991/0413 | cp->afirst = cp->anext = 0; | |
| 1990/1210 | cp->first = cp->next = 1; | |
| 1991/0119 | cp->rexmit = cp->bad = cp->sent = cp->rcvd = 0; cp->lastacked = Nnomsg|(Nnomsg-1); | |
| 1991/0412/sys/src/9/port/devnonet.c:1425,1433 – 1991/0413/sys/src/9/port/devnonet.c:1426,1434 | ||
| 1991/01151 | */ | |
| 1991/0108 | ep = ifc->conv + conf.nnoconv; for(cp = ifc->conv; cp < ep; cp++){ | |
| 1991/0413 | if(cp->state<=Copen || !canqlock(cp)) | |
| 1991/0108 | continue; | |
| 1991/01151 |
| |
| 1991/0413 | if(cp->state <= Copen){ | |
| 1991/01151 | qunlock(cp); continue; } | |
| 1991/0413/sys/src/9/port/devnonet.c:202,207 – 1991/0419/sys/src/9/port/devnonet.c:202,213 (short | long) | ||
| 1990/1210 | return devwalk(c, name, nosubdir, Nsubdir, streamgen); } | |
| 1991/0419 | Chan* nonetclwalk(Chan *c, char *name) { return devclwalk(c, name); } | |
| 1990/1210 | void nonetstat(Chan *c, char *dp) { | |
| 1991/0419/sys/src/9/port/devnonet.c:202,213 – 1991/0427/sys/src/9/port/devnonet.c:202,207 (short | long) | ||
| 1990/1210 | return devwalk(c, name, nosubdir, Nsubdir, streamgen); } | |
| 1991/0419 |
| |
| 1990/1210 | void nonetstat(Chan *c, char *dp) { | |
| 1991/0427/sys/src/9/port/devnonet.c:540,545 – 1991/0502/sys/src/9/port/devnonet.c:540,549 (short | long) | ||
| 1990/1210 | /* * queue a block */ | |
| 1991/0502 | enum { Window= 1, }; | |
| 1990/1210 | static int windowopen(void *a) { | |
| 1991/0427/sys/src/9/port/devnonet.c:548,556 – 1991/0502/sys/src/9/port/devnonet.c:552,560 | ||
| 1990/1210 | cp = (Noconv *)a; | |
| 1991/0207 | i = cp->next - cp->first; | |
| 1991/0502 | if(i>=0 && i<Window) | |
| 1991/0207 | return 1; | |
| 1991/0502 | if(i<0 && Nnomsg+i<Window) | |
| 1991/0207 | return 1; return 0; | |
| 1990/1210 | } | |
| 1991/0427/sys/src/9/port/devnonet.c:1355,1360 – 1991/0502/sys/src/9/port/devnonet.c:1359,1365 | ||
| 1990/1210 | int n; ulong s; Nohdr *hp; | |
| 1991/0502 | Block *first; | |
| 1990/1210 | s = 0; p = bp->rptr + offset; | |
| 1991/0427/sys/src/9/port/devnonet.c:1390,1396 – 1991/0502/sys/src/9/port/devnonet.c:1395,1414 | ||
| 1990/1210 | s = (s&0xffff) + (s>>16); hp->sum[1] = s>>8; hp->sum[0] = s; | |
| 1991/0502 | s &= 0xffff; switch(s){ case 0xac9f: case 0xc1a4: case 0xc41c: case 0xc46d: { int i; print("%lux s,", s); for(bp = first; bp; bp = bp->next) for(i = 0; i < BLEN(bp); i++) print(" %ux", bp->rptr[i]); } } return s; | |
| 1990/1229 | } | |
| 1991/0108 | /* | |
| 1991/0502/sys/src/9/port/devnonet.c:1396,1401 – 1991/0503/sys/src/9/port/devnonet.c:1396,1402 (short | long) | ||
| 1990/1210 | hp->sum[1] = s>>8; hp->sum[0] = s; | |
| 1991/0502 | s &= 0xffff; | |
| 1991/0503 | if(0) | |
| 1991/0502 | switch(s){ case 0xac9f: case 0xc1a4: | |
| 1991/0503/sys/src/9/port/devnonet.c:1457,1466 – 1991/0604/sys/src/9/port/devnonet.c:1457,1466 (short | long) | ||
| 1991/01151 | */ | |
| 1991/0118 | if(cp->first!=cp->next && NOW>=cp->out[cp->first].time){ | |
| 1991/0206 | mp = &(cp->out[cp->first]); | |
| 1991/0209 |
| |
| 1991/0604 | /* if(cp->rexmit++ > 15){ | |
| 1991/0206 | norack(cp, mp->mid); | |
| 1991/0209 | noreset(cp); | |
| 1991/0206 |
| |
| 1991/0604 | } else /**/ | |
| 1991/0119 | nosend(cp, mp); | |
| 1991/01151 | } | |
| Too many diffs (26 > 25). Stopping. | ||