|
|
1.1 root 1: /*
2: * simple CURE datakit driver
3: * -- assumes it is the first CURE, and only one allowed for now
4: * (the latter not severe, as 256 channels are permitted)
5: */
6: #include "sys/param.h"
7: #include "sys/stream.h"
8: #include "sys/dkio.h"
9: #include "sys/ubaddr.h"
10: #include "sys/conf.h"
11: #include "sys/kc.h"
12: #include "sys/dkstat.h"
13: #include "sys/dkmod.h"
14: #include "sys/buf.h"
15:
16: /*
17: * hardware stuff
18: */
19: struct device {
20: unsigned short buf;
21: unsigned char csr;
22: char fill1;
23: short fill2;
24: char reset;
25: };
26:
27: /*
28: * status bits
29: */
30: #define SSEQ 01 /* 1-bit command sequence # */
31: #define SRRDY 02 /* receive ready */
32: #define SXRDY 04 /* transmit ready */
33: #define SUBERR 010 /* unibus error */
34: #define SERR 020 /* protocol error */
35: #define STATE 0300 /* booting state mask... */
36: #define SOK 0200 /* ready for real IO */
37: #define SBOOT 0100 /* ready for download (just been reset) */
38: #define SBOOTING 0 /* in middle of download */
39: #define SRESET 0300 /* finished download, must reset UB base, vector */
40:
41: /*
42: * command bits
43: */
44: #define CSEND 02 /* send */
45: #define CSETB 03 /* announce location of control buffers */
46: #define CRCV 04 /* receive */
47: #define CBA 06 /* set bus address */
48: #define CBC 010 /* set buffer count */
49: #define CINTR 012 /* set vector address */
50: #define CRESET 014 /* reset interface */
51: #define CIACK 016 /* ack interrupt or reset */
52:
53: #define CXA 0140 /* high address bits */
54: #define XASHIFT 11 /* shift high address bits this much */
55:
56: typedef short Env; /* datakit envelope in our buffers */
57:
58: /*
59: * bits in transmit buffer
60: */
61: #define XDATA 0400 /* data, not control */
62:
63: /*
64: * bits in receive buffer
65: */
66: #define RMARK 01000 /* channel mark */
67: #define RDATA 0400 /* this is data */
68: #define RSPCL 0100000 /* special (sign bit): mark or control */
69: #define REOT (RSPCL|RMARK) /* end of receive buffer, if short */
70:
71: /*
72: * per-channel stuff
73: */
74: #define NCHAN 256
75: struct kc kc[NCHAN];
76: int kccnt = NCHAN;
77: char kcstate[NCHAN];
78:
79: /*
80: * kc flags
81: */
82: #define DKXCL 01 /* exclusive open */
83: #define DKXWANT 02 /* output pending this channel */
84:
85: /*
86: * per-controller stuff;
87: * always just one for now
88: */
89:
90: extern struct ubaddr cureaddr[];
91: struct kccure kccure[1];
92: #define KBNO 0 /* always this kc for now */
93: int kcxfirst;
94: int kcxnext;
95: int kcrfirst;
96: int kcrnext;
97:
98: /*
99: * kccure flags
100: */
101: #define XBUSY 01 /* transmit busy */
102: #define XWANT 02 /* output needed */
103: #define INIT 04
104:
105: /*
106: * illicit linkage to other datakit code
107: */
108:
109: struct dkstat dkstat;
110:
111: #define KNO 0
112:
113: #define DKISML 16 /* smallest interesting allocation */
114: #define DKITHRES 200
115:
116: long kcopen();
117: int kcclose(), kcput(), kcosrv();
118:
119: static struct qinit kcrinit = { noput, NULL, kcopen, kcclose, 0, 0 };
120: struct qinit kcwinit = { kcput, kcosrv, kcopen, kcclose, 1500, 600 };
121: struct streamtab kcinfo = { &kcrinit, &kcwinit };
122: struct cdevsw curecdev = cstrinit(&kcinfo);
123:
124: static kclastseq;
125:
126: /*
127: * open DK channel
128: */
129: long
130: kcopen(q, dev)
131: register struct queue *q;
132: register dev_t dev;
133: {
134: register struct kc *dkp;
135: register struct kccure *kk;
136: register chan;
137: extern struct dkmodule *dkmodall();
138: int kcclock();
139:
140: chan = minor(dev);
141: if (chan<=0 || chan>=kccnt)
142: return(0);
143: kk = &kccure[KBNO];
144: if ((kk->flags & INIT) == 0) {
145: if ((kk->modp = dkmodall(dev, 0, kccnt)) == NULL)
146: return (0);
147: kk->modp->dkstate = kcstate;
148: if (kcinit(kk, 1) == 0)
149: return (0);
150: kk->flags |= INIT;
151: timeout(kcclock, (caddr_t)minor(dev), 10*HZ);
152: }
153: dkp = &kc[chan];
154: if (kcstate[chan] != DKCLOSED) { /* already open */
155: if (dkp->flag & DKXCL)
156: return(0);
157: if (kcstate[chan] != DKOPEN)
158: return(0); /* closing channels can't reopen */
159: return(1);
160: }
161: dkp->dkrq = q;
162: q->ptr = (caddr_t)dkp;
163: WR(q)->ptr = (caddr_t)dkp;
164: WR(q)->flag |= QNOENB|QBIGB;
165: dkp->flag = DKXCL;
166: kcstate[chan] = DKOPEN;
167: return(1);
168: }
169:
170: /*
171: * make sure cure is alive;
172: * init data structures once
173: * it might be better to deal with BDPs dynamically somehow,
174: * e.g. on the comet where there are very few
175: */
176: kcinit(kk, firsttime)
177: register struct kccure *kk;
178: {
179: register struct device *reg;
180: register int i;
181: register struct kc *dkp;
182: static ubm_t map;
183: uaddr_t uaddr;
184: extern cure0int(), kcreset();
185:
186: kk->kno = KNO;
187: if ((reg = (struct device *)ubaddr(&cureaddr[0])) == NULL
188: || badaddr(reg, 2)) {
189: printf("cure0 absent\n");
190: return (0);
191: }
192: for (i = kccnt - 1, dkp = &kc[i]; i >= 0; --dkp, --i)
193: dkp->chan = i;
194: kk->addr = reg;
195: if ((reg->csr&STATE) != SRESET && (reg->csr&STATE) != SOK)
196: return(0); /* check downloaded OK */
197: kclastseq = (reg->csr^SSEQ) & SSEQ;
198: if (kcwcmd(kk, CINTR, cureaddr[0].vec) == 0)
199: return (0);
200: /* allocate and announce command buffers */
201: if (firsttime)
202: map = ubmalloc(kk->ubno, (2*NCBUF+1)*sizeof(struct cmd), 0);
203: else { /* resetting; free blocks in use */
204: for (i=0; i<NCBUF; i++) {
205: if (kk->ibp[i])
206: freeb(kk->ibp[i]);
207: if (kk->obp[i])
208: freeb(kk->obp[i]);
209: kk->ibp[i] = NULL;
210: kk->obp[i] = NULL;
211: }
212: kcxfirst = kcrfirst = kcxnext = kcrnext = 0;
213: }
214: uaddr = ubmaddr(kk->ubno, kk->xcbuf, (2*NCBUF+1)*sizeof(struct cmd), map);
215: printf("cure reset, uaddr %x map %x\n", uaddr, map);
216: kcwcmd(kk, CBA, uaddr);
217: kcwcmd(kk, CBC, NCBUF);
218: kcwcmd(kk, CSETB|((uaddr>>XASHIFT)&CXA), 0);
219: kcwcmd(kk, CIACK, 0); /* to delay until CSETB processed */
220: if ((reg->csr&STATE)!=SOK) {
221: printf("cure not ready, state %o\n", reg->csr);
222: return(0);
223: }
224: kcistart(kk);
225: return (1);
226: }
227:
228: /*
229: * close DK channel
230: */
231: kcclose(q)
232: register struct queue *q;
233: {
234: register struct kc *dkp;
235: register struct kccure *kk;
236:
237: kk = &kccure[KBNO];
238: dkp = (struct kc *)q->ptr;
239: if (dkp == NULL)
240: panic("kcclose");
241: dkp->dkrq = NULL;
242: dkp->flag = 0;
243: if (kcstate[dkp->chan] == DKRCLOSE || kk->modp->listnrq==NULL)
244: kcstate[dkp->chan] = DKCLOSED;
245: else if (kcstate[dkp->chan] == DKOPEN)
246: kcstate[dkp->chan] = DKLCLOSE;
247: if (kk->modp->listnrq)
248: putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan);
249: }
250:
251: /*
252: * interrupt
253: */
254: cure1int(dev) {}
255: cure0int(dev)
256: {
257: register struct kccure *kk;
258: register struct device *reg;
259: register doneb, i, csr;
260:
261:
262: kk = &kccure[KBNO];
263: if ((reg = kk->addr) == NULL)
264: return;
265: csr = reg->csr;
266: i = csr&STATE;
267: if (i!=SOK && i!=SRESET)
268: return;
269: if (csr & (SERR|SUBERR))
270: printf("cure status %o\n", reg->csr);
271: doneb = reg->buf;
272: i = doneb&0377; /* first rcv buf not done */
273: while (i != kcrfirst) {
274: kcrecv(kk, kcrfirst);
275: kcrfirst = (kcrfirst+1)%NCBUF;
276: }
277: kcistart(kk);
278: i = (doneb>>8)&0377; /* first xmit buf not done */
279: while (i != kcxfirst) {
280: kk->flags &=~ XBUSY;
281: if (kk->obp[kcxfirst]) {
282: freeb(kk->obp[kcxfirst]);
283: ubmfree(kk->ubno, kk->omap[kcxfirst]);
284: }
285: kk->obp[kcxfirst] = NULL;
286: kcxfirst = (kcxfirst+1)%NCBUF;
287: }
288: if (kk->xfirst)
289: kcosrv((struct queue *)NULL);
290: }
291:
292: /*
293: * receive a buffer
294: */
295: kcrecv(kk, i)
296: register struct kccure *kk;
297: {
298: register struct block *bp, *nbp;
299: register struct queue *q;
300: register c;
301: struct cmd rcbuf;
302:
303: rcbuf = kk->rcbuf[i];
304: bp = kk->ibp[i];
305: if (bp==NULL) {
306: printf("null bp in kcrecv\n");
307: return;
308: }
309: kk->ibp[i] = NULL;
310: c = rcbuf.chan;
311: if (c==0 || c>=kccnt || (q = kc[c].dkrq)==NULL) {
312: if (c==0)
313: dkstat.pack0++;
314: else if (c>=kccnt)
315: dkstat.packstrange++;
316: else {
317: if (kk->modp->listnrq)
318: putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, c);
319: dkstat.closepack++;
320: }
321: freeb(bp);
322: return;
323: }
324: if (q->next->flag&QFULL) { /* channel overflow */
325: freeb(bp);
326: return;
327: }
328: if (rcbuf.count==0)
329: freeb(bp);
330: else { /* use small buffer if not much data */
331: if (rcbuf.count<=64 && (nbp=allocb(rcbuf.count))) {
332: bcopy(bp->rptr, nbp->rptr, rcbuf.count);
333: freeb(bp);
334: bp = nbp;
335: }
336: bp->wptr += rcbuf.count;
337: dkstat.input += rcbuf.count;
338: (*q->next->qinfo->putp)(q->next, bp);
339: }
340: for (c=0; c<NCTL; c++) {
341: if (rcbuf.ctl[c]==0)
342: continue;
343: bp = allocb(1);
344: *bp->wptr++ = rcbuf.ctl[c];
345: if ((rcbuf.ctl[c]&RDATA)==0)
346: bp->type = M_CTL;
347: (*q->next->qinfo->putp)(q->next, bp);
348: }
349: }
350:
351: /*
352: * start new input buffers
353: */
354: kcistart(kk)
355: register struct kccure *kk;
356: {
357: register struct device *reg;
358: register struct block *bp;
359: register i;
360:
361: if ((reg = kk->addr) == NULL)
362: return;
363: while((kcrnext+1)%NCBUF != kcrfirst) {
364: i = kcrnext;
365: kk->ibp[i] = bp = allocb(1024);
366: kk->imap[i] = ubmblk(kk->ubno, bp, 0);
367: kk->rcbuf[i].ubaddr = ubadrptr(kk->ubno, bp, kk->imap[i]);
368: kk->rcbuf[i].count = bp->lim - bp->base;
369: kcwcmd(kk, CRCV, i);
370: kcrnext = (i+1)%NCBUF;
371: }
372: }
373:
374: /*
375: * put procedure for output
376: */
377: kcput(q, bp)
378: register struct queue *q;
379: register struct block *bp;
380: {
381: register struct kc *dkp;
382: register struct kccure *kk;
383: register int n;
384:
385: dkp = (struct kc *)q->ptr;
386: kk = &kccure[KBNO];
387: switch (bp->type) {
388:
389: case M_IOCTL:
390: switch (stiocom(bp)) {
391: case DIOCNXCL:
392: dkp->flag &=~ DKXCL;
393: bp->wptr = bp->rptr;
394: bp->type = M_IOCACK;
395: break;
396:
397: case KIOCINIT:
398: /* eventually, reset things here */
399:
400: default:
401: bp->type = M_IOCNAK;
402: break;
403: }
404: qreply(q, bp);
405: return;
406:
407: case M_CTL:
408: case M_DATA:
409: dkstat.output += bp->wptr - bp->rptr;
410: putq(q, bp);
411: n = spl5();
412: if ((dkp->flag & DKXWANT) == 0) {
413: if (kk->xfirst == NULL)
414: kk->xfirst = dkp;
415: else
416: kk->xlast->link = dkp;
417: dkp->link = NULL;
418: kk->xlast = dkp;
419: dkp->flag |= DKXWANT;
420: }
421: if ((kk->flags & XBUSY) == 0)
422: qenable(q);
423: splx(n);
424: return;
425:
426: case M_PRICTL:
427: switch (*bp->rptr) {
428: case DKMCLOSE:
429: n = bp->rptr[1];
430: if (n < kccnt) {
431: if (kcstate[n] == DKOPEN) {
432: kcstate[n] = DKRCLOSE;
433: putctl(kc[n].dkrq->next, M_HANGUP);
434: } else if (kcstate[n] == DKLCLOSE)
435: kcstate[n] = DKCLOSED;
436: }
437: freeb(bp);
438: return;
439:
440: case DKMXINIT:
441: n = bp->rptr[1];
442: if (n < kccnt && kcstate[n] == DKOPEN)
443: (*kc[n].dkrq->next->qinfo->putp)(kc[n].dkrq->next, bp);
444: else
445: freeb(bp);
446: return;
447:
448: default:
449: freeb(bp);
450: return;
451: }
452:
453: default:
454: freeb(bp);
455: return;
456: }
457: }
458:
459: kcosrv(junk)
460: struct queue *junk;
461: {
462: register struct kccure *kk = &kccure[KBNO];
463: register s;
464:
465: s = spl5();
466: while (kk->xfirst) {
467: if ((kcxnext+1)%NCBUF == kcxfirst) {
468: kk->flags |= XBUSY;
469: return;
470: }
471: if (kcosrvbuf(kcxnext))
472: kcxnext = (kcxnext+1)%NCBUF;
473: }
474: splx(s);
475: }
476:
477: /*
478: * fill up one buffer and send it
479: */
480:
481: kcosrvbuf(i)
482: register i;
483: {
484:
485: register struct kccure *kk;
486: register struct block *bp;
487: register struct queue *q;
488: register struct device *reg;
489: register struct kc *dkp;
490: int c;
491:
492: kk = &kccure[KBNO];
493: reg = kk->addr;
494: dkp = kk->xfirst;
495: more:
496: if (dkp==NULL) {
497: printf("null dkp in kcosrvbuf\n");
498: return 0;
499: }
500: if (dkp->dkrq==NULL) {
501: dkp->flag &=~ DKXWANT;
502: dkp = dkp->link;
503: if ((kk->xfirst = dkp) == NULL) {
504: kk->xlast = NULL;
505: return 0;
506: }
507: goto more;
508: }
509: q = WR(dkp->dkrq);
510: kk->xcbuf[i].chan = dkp->chan;
511: c = 0;
512: kk->xcbuf[i].count = 0;
513: while ((bp = getq(q)) != NULL) {
514: if (bp->type == M_CTL || bp->rptr+NCTL >= bp->wptr) {
515: while (bp->rptr < bp->wptr && c < NCTL) {
516: kk->xcbuf[i].ctl[c++] = *bp->rptr++ |
517: (bp->type==M_CTL?0:XDATA);
518: bp->type = M_DATA;
519: }
520: if (bp->rptr >= bp->wptr) {
521: freeb(bp);
522: continue;
523: }
524: } else if (c==0 && kk->xcbuf[i].count==0) {
525: kk->omap[i] = ubmblk(kk->ubno, bp, 0);
526: kk->xcbuf[i].ubaddr = ubadrptr(kk->ubno, bp, kk->omap[i]);
527: kk->xcbuf[i].count = bp->wptr - bp->rptr;
528: kk->obp[i] = bp;
529: continue;
530: }
531: putbq(q, bp);
532: break;
533: }
534: if (bp==NULL) {
535: dkp->flag &=~ DKXWANT;
536: dkp = dkp->link;
537: if ((kk->xfirst = dkp) == NULL)
538: kk->xlast = NULL;
539: }
540: while (c<NCTL)
541: kk->xcbuf[i].ctl[c++] = 0;
542: kcwcmd(kk, CSEND, i);
543: return 1;
544: }
545:
546: kcwcmd(kk, cmd, buf)
547: register struct kccure *kk;
548: {
549: register ocsr;
550: register count = 0;
551: register state;
552:
553: ocsr = kk->addr->csr;
554: state = ocsr&STATE;
555: if (state != SOK) {
556: if (state!=SRESET)
557: return(0);
558: switch(cmd&037) {
559: case CSETB:
560: case CBA:
561: case CBC:
562: case CINTR:
563: case CIACK:
564: break;
565: default:
566: if (kcinit(kk, 0)==0)
567: return(0);
568: break;
569: }
570: }
571: /* wait for last command to be accepted */
572: while ((kk->addr->csr&SSEQ) == kclastseq) {
573: if (++count > 100000) {
574: printf("cure not responding: csr %o\n", kk->addr->csr);
575: return(0);
576: }
577: }
578: if (kk->addr->csr & (SERR|SUBERR))
579: printf("cure csr %o\n", kk->addr->csr);
580: kclastseq = kk->addr->csr&SSEQ;
581: kk->addr->buf = buf;
582: kk->addr->csr = cmd;
583: return(1);
584: }
585:
586: kcclock(dev)
587: caddr_t dev;
588: {
589: cure0int(minor((int)dev));
590: timeout(kcclock, dev, 10*HZ);
591: }
592:
593: /*
594: * raw cure device for downloading
595: */
596: long rcureopen();
597: int rcureclose(), rcureoput();
598:
599: static struct qinit rcurerinit = {
600: noput, NULL, rcureopen, nulldev, 0, 0
601: };
602: static struct qinit rcurewinit = {
603: rcureoput, NULL, rcureopen, nulldev, 200, 100
604: };
605: struct streamtab rcureinfo = {
606: &rcurerinit, &rcurewinit
607: };
608:
609: /*
610: * config glue
611: */
612: extern struct ubaddr rcureaddr[]; /* one per device */
613: extern int rcurecnt; /* one per device or what? */
614: struct cdevsw rcurecdev = cstrinit(&rcureinfo);
615:
616: long
617: rcureopen(q, d)
618: register struct queue *q;
619: {
620: register dev;
621: register struct device *mp;
622:
623: if((dev = minor(d)) >= rcurecnt)
624: return 0;
625: if((mp = (struct device *)ubaddr(&rcureaddr[dev])) == 0
626: || badaddr(mp, sizeof(u_char))) {
627: printf("cure %d absent\n", d);
628: return 0;
629: }
630: WR(q)->ptr = q->ptr = (caddr_t) dev;
631: return 1;
632: }
633:
634: rcureoput(q, bp)
635: register struct queue *q;
636: register struct block *bp;
637: {
638: #define DV 017 /* actual device number */
639: #define BOOTOK 020 /* initialization flag */
640:
641: register struct device *mp =
642: (struct device *)ubaddr(&rcureaddr[(int)q->ptr & DV]);
643: register int csr, n;
644:
645: switch(bp->type) {
646:
647: case M_IOCTL:
648: bp->type = M_IOCNAK;
649: bp->wptr = bp->rptr;
650: switch(stiocom(bp)) {
651: case KIOCINIT: /* reboot cure */
652: mp->reset = 1;
653: delay(10);
654: mp->reset = 0;
655: bp->type = M_IOCACK;
656: break;
657: }
658: qreply(q, bp);
659: return;
660:
661: case M_DATA:
662: if (((int)q->ptr&BOOTOK) == 0) { /* first write */
663: if ((mp->csr&STATE) != SBOOT) {
664: printf("cure not ready to load, %o\n", mp->csr);
665: goto err;
666: }
667: mp->buf = 070707; /* magic number starts bootload */
668: delay(10);
669: if ((mp->csr&STATE) != SBOOTING) {
670: printf("cure load err0 %o\n", mp->csr);
671: goto err;
672: }
673: q->ptr = (caddr_t)((int)q->ptr | BOOTOK);
674: }
675: while (bp->rptr < bp->wptr) {
676: if ((mp->csr&STATE) != SBOOTING) {
677: printf("cure load err1\n");
678: goto err;
679: }
680: csr = mp->csr;
681: mp->buf = *bp->rptr++;
682: for (n=0; ((csr ^ mp->csr)&SSEQ)==0 && n<100000; ++n) {
683: if (mp->csr&SERR || (mp->csr&STATE)!=SBOOTING) {
684: printf("cure load err2 %o\n", mp->csr);
685: goto err;
686: }
687: }
688: if (n==100000) {
689: printf("cure load err3\n");
690: goto err;
691: }
692: }
693: break;
694: }
695: freeb(bp);
696: return;
697: err:
698: bp->type = M_HANGUP;
699: qreply(q, bp);
700: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.