|
|
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: dkstat.closepack++;
318: freeb(bp);
319: return;
320: }
321: if (q->next->flag&QFULL) { /* channel overflow */
322: freeb(bp);
323: return;
324: }
325: if (rcbuf.count==0)
326: freeb(bp);
327: else { /* use small buffer if not much data */
328: if (rcbuf.count<=64 && (nbp=allocb(rcbuf.count))) {
329: bcopy(bp->rptr, nbp->rptr, rcbuf.count);
330: freeb(bp);
331: bp = nbp;
332: }
333: bp->wptr += rcbuf.count;
334: dkstat.input += rcbuf.count;
335: (*q->next->qinfo->putp)(q->next, bp);
336: }
337: for (c=0; c<NCTL; c++) {
338: if (rcbuf.ctl[c]==0)
339: continue;
340: bp = allocb(1);
341: *bp->wptr++ = rcbuf.ctl[c];
342: if ((rcbuf.ctl[c]&RDATA)==0)
343: bp->type = M_CTL;
344: (*q->next->qinfo->putp)(q->next, bp);
345: }
346: }
347:
348: /*
349: * start new input buffers
350: */
351: kcistart(kk)
352: register struct kccure *kk;
353: {
354: register struct device *reg;
355: register struct block *bp;
356: register i;
357:
358: if ((reg = kk->addr) == NULL)
359: return;
360: while((kcrnext+1)%NCBUF != kcrfirst) {
361: i = kcrnext;
362: kk->ibp[i] = bp = allocb(1024);
363: kk->imap[i] = ubmblk(kk->ubno, bp, 0);
364: kk->rcbuf[i].ubaddr = ubadrptr(kk->ubno, bp, kk->imap[i]);
365: kk->rcbuf[i].count = bp->lim - bp->base;
366: kcwcmd(kk, CRCV, i);
367: kcrnext = (i+1)%NCBUF;
368: }
369: }
370:
371: /*
372: * put procedure for output
373: */
374: kcput(q, bp)
375: register struct queue *q;
376: register struct block *bp;
377: {
378: register struct kc *dkp;
379: register struct kccure *kk;
380: register int n;
381:
382: dkp = (struct kc *)q->ptr;
383: kk = &kccure[KBNO];
384: switch (bp->type) {
385:
386: case M_IOCTL:
387: switch (stiocom(bp)) {
388: case DIOCNXCL:
389: dkp->flag &=~ DKXCL;
390: bp->wptr = bp->rptr;
391: bp->type = M_IOCACK;
392: break;
393:
394: case KIOCINIT:
395: /* eventually, reset things here */
396:
397: default:
398: bp->type = M_IOCNAK;
399: break;
400: }
401: qreply(q, bp);
402: return;
403:
404: case M_CTL:
405: case M_DATA:
406: dkstat.output += bp->wptr - bp->rptr;
407: putq(q, bp);
408: n = spl5();
409: if ((dkp->flag & DKXWANT) == 0) {
410: if (kk->xfirst == NULL)
411: kk->xfirst = dkp;
412: else
413: kk->xlast->link = dkp;
414: dkp->link = NULL;
415: kk->xlast = dkp;
416: dkp->flag |= DKXWANT;
417: }
418: if ((kk->flags & XBUSY) == 0)
419: qenable(q);
420: splx(n);
421: return;
422:
423: case M_PRICTL:
424: switch (*bp->rptr) {
425: case DKMCLOSE:
426: n = bp->rptr[1];
427: if (n < kccnt) {
428: if (kcstate[n] == DKOPEN) {
429: kcstate[n] = DKRCLOSE;
430: putctl(kc[n].dkrq->next, M_HANGUP);
431: } else if (kcstate[n] == DKLCLOSE)
432: kcstate[n] = DKCLOSED;
433: }
434: freeb(bp);
435: return;
436:
437: case DKMXINIT:
438: n = bp->rptr[1];
439: if (n < kccnt && kcstate[n] == DKOPEN)
440: (*kc[n].dkrq->next->qinfo->putp)(kc[n].dkrq->next, bp);
441: else
442: freeb(bp);
443: return;
444:
445: default:
446: freeb(bp);
447: return;
448: }
449:
450: default:
451: freeb(bp);
452: return;
453: }
454: }
455:
456: kcosrv(junk)
457: struct queue *junk;
458: {
459: register struct kccure *kk = &kccure[KBNO];
460: register s;
461:
462: s = spl5();
463: while (kk->xfirst) {
464: if ((kcxnext+1)%NCBUF == kcxfirst) {
465: kk->flags |= XBUSY;
466: return;
467: }
468: if (kcosrvbuf(kcxnext))
469: kcxnext = (kcxnext+1)%NCBUF;
470: }
471: splx(s);
472: }
473:
474: /*
475: * fill up one buffer and send it
476: */
477:
478: kcosrvbuf(i)
479: register i;
480: {
481:
482: register struct kccure *kk;
483: register struct block *bp;
484: register struct queue *q;
485: register struct device *reg;
486: register struct kc *dkp;
487: int c;
488:
489: kk = &kccure[KBNO];
490: reg = kk->addr;
491: dkp = kk->xfirst;
492: more:
493: if (dkp==NULL) {
494: printf("null dkp in kcosrvbuf\n");
495: return 0;
496: }
497: if (dkp->dkrq==NULL) {
498: dkp->flag &=~ DKXWANT;
499: dkp = dkp->link;
500: if ((kk->xfirst = dkp) == NULL) {
501: kk->xlast = NULL;
502: return 0;
503: }
504: goto more;
505: }
506: q = WR(dkp->dkrq);
507: kk->xcbuf[i].chan = dkp->chan;
508: c = 0;
509: kk->xcbuf[i].count = 0;
510: while ((bp = getq(q)) != NULL) {
511: if (bp->type == M_CTL || bp->rptr+NCTL >= bp->wptr) {
512: while (bp->rptr < bp->wptr && c < NCTL) {
513: kk->xcbuf[i].ctl[c++] = *bp->rptr++ |
514: (bp->type==M_CTL?0:XDATA);
515: bp->type = M_DATA;
516: }
517: if (bp->rptr >= bp->wptr) {
518: freeb(bp);
519: continue;
520: }
521: } else if (c==0 && kk->xcbuf[i].count==0) {
522: kk->omap[i] = ubmblk(kk->ubno, bp, 0);
523: kk->xcbuf[i].ubaddr = ubadrptr(kk->ubno, bp, kk->omap[i]);
524: kk->xcbuf[i].count = bp->wptr - bp->rptr;
525: kk->obp[i] = bp;
526: continue;
527: }
528: putbq(q, bp);
529: break;
530: }
531: if (bp==NULL) {
532: dkp->flag &=~ DKXWANT;
533: dkp = dkp->link;
534: if ((kk->xfirst = dkp) == NULL)
535: kk->xlast = NULL;
536: }
537: while (c<NCTL)
538: kk->xcbuf[i].ctl[c++] = 0;
539: kcwcmd(kk, CSEND, i);
540: return 1;
541: }
542:
543: kcwcmd(kk, cmd, buf)
544: register struct kccure *kk;
545: {
546: register ocsr;
547: register count = 0;
548: register state;
549:
550: ocsr = kk->addr->csr;
551: state = ocsr&STATE;
552: if (state != SOK) {
553: if (state!=SRESET)
554: return(0);
555: switch(cmd&037) {
556: case CSETB:
557: case CBA:
558: case CBC:
559: case CINTR:
560: case CIACK:
561: break;
562: default:
563: if (kcinit(kk, 0)==0)
564: return(0);
565: break;
566: }
567: }
568: /* wait for last command to be accepted */
569: while ((kk->addr->csr&SSEQ) == kclastseq) {
570: if (++count > 100000) {
571: printf("cure not responding: csr %o\n", kk->addr->csr);
572: return(0);
573: }
574: }
575: if (kk->addr->csr & (SERR|SUBERR))
576: printf("cure csr %o\n", kk->addr->csr);
577: kclastseq = kk->addr->csr&SSEQ;
578: kk->addr->buf = buf;
579: kk->addr->csr = cmd;
580: return(1);
581: }
582:
583: kcclock(dev)
584: caddr_t dev;
585: {
586: cure0int(minor((int)dev));
587: timeout(kcclock, dev, 10*HZ);
588: }
589:
590: /*
591: * raw cure device for downloading
592: */
593: long rcureopen();
594: int rcureclose(), rcureoput();
595:
596: static struct qinit rcurerinit = {
597: noput, NULL, rcureopen, nulldev, 0, 0
598: };
599: static struct qinit rcurewinit = {
600: rcureoput, NULL, rcureopen, nulldev, 200, 100
601: };
602: struct streamtab rcureinfo = {
603: &rcurerinit, &rcurewinit
604: };
605:
606: /*
607: * config glue
608: */
609: extern struct ubaddr rcureaddr[]; /* one per device */
610: extern int rcurecnt; /* one per device or what? */
611: struct cdevsw rcurecdev = cstrinit(&rcureinfo);
612:
613: long
614: rcureopen(q, d)
615: register struct queue *q;
616: {
617: register dev;
618: register struct device *mp;
619:
620: if((dev = minor(d)) >= rcurecnt)
621: return 0;
622: if((mp = (struct device *)ubaddr(&rcureaddr[dev])) == 0
623: || badaddr(mp, sizeof(u_char))) {
624: printf("cure %d absent\n", d);
625: return 0;
626: }
627: WR(q)->ptr = q->ptr = (caddr_t) dev;
628: return 1;
629: }
630:
631: rcureoput(q, bp)
632: register struct queue *q;
633: register struct block *bp;
634: {
635: #define DV 017 /* actual device number */
636: #define BOOTOK 020 /* initialization flag */
637:
638: register struct device *mp =
639: (struct device *)ubaddr(&rcureaddr[(int)q->ptr & DV]);
640: register int csr, n;
641:
642: switch(bp->type) {
643:
644: case M_IOCTL:
645: bp->type = M_IOCNAK;
646: bp->wptr = bp->rptr;
647: switch(stiocom(bp)) {
648: case KIOCINIT: /* reboot cure */
649: mp->reset = 1;
650: delay(10);
651: mp->reset = 0;
652: bp->type = M_IOCACK;
653: break;
654: }
655: qreply(q, bp);
656: return;
657:
658: case M_DATA:
659: if (((int)q->ptr&BOOTOK) == 0) { /* first write */
660: if ((mp->csr&STATE) != SBOOT) {
661: printf("cure not ready to load, %o\n", mp->csr);
662: goto err;
663: }
664: mp->buf = 070707; /* magic number starts bootload */
665: delay(10);
666: if ((mp->csr&STATE) != SBOOTING) {
667: printf("cure load err0 %o\n", mp->csr);
668: goto err;
669: }
670: q->ptr = (caddr_t)((int)q->ptr | BOOTOK);
671: }
672: while (bp->rptr < bp->wptr) {
673: if ((mp->csr&STATE) != SBOOTING) {
674: printf("cure load err1\n");
675: goto err;
676: }
677: csr = mp->csr;
678: mp->buf = *bp->rptr++;
679: for (n=0; ((csr ^ mp->csr)&SSEQ)==0 && n<100000; ++n) {
680: if (mp->csr&SERR || (mp->csr&STATE)!=SBOOTING) {
681: printf("cure load err2 %o\n", mp->csr);
682: goto err;
683: }
684: }
685: if (n==100000) {
686: printf("cure load err3\n");
687: goto err;
688: }
689: }
690: break;
691: }
692: freeb(bp);
693: return;
694: err:
695: bp->type = M_HANGUP;
696: qreply(q, bp);
697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.