|
|
1.1 root 1: /*
2: * Copyright (c) 1986 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)ik.c 7.6 (Berkeley) 6/28/90
21: */
22:
23: #include "ik.h"
24: #if NIK > 0
25: /*
26: * PS300/IKON DR-11W Device Driver.
27: */
28: #include "param.h"
29: #include "buf.h"
30: #include "cmap.h"
31: #include "conf.h"
32: #include "dkstat.h"
33: #include "map.h"
34: #include "systm.h"
35: #include "user.h"
36: #include "vmmac.h"
37: #include "proc.h"
38: #include "kernel.h"
39: #include "syslog.h"
40:
41: #include "../tahoe/mtpr.h"
42: #include "../tahoe/pte.h"
43:
44: #include "../tahoevba/vbavar.h"
45: #include "../tahoevba/ikreg.h"
46: #include "../tahoevba/psreg.h"
47: #include "../tahoevba/psproto.h"
48:
49: int ikprobe(), ikattach(), iktimer();
50: struct vba_device *ikinfo[NIK];
51: long ikstd[] = { 0 };
52: struct vba_driver ikdriver = { ikprobe, 0, ikattach, 0, ikstd, "ik", ikinfo };
53:
54: #define splik() spl4()
55: /*
56: * Devices are organized in pairs with the odd valued
57: * device being used for ``diagnostic'' purposes. That
58: * is diagnostic devices don't get auto-attach'd and
59: * detach'd on open-close.
60: */
61: #define IKUNIT(dev) (minor(dev) >> 1)
62: #define IKDIAG(dev) (minor(dev) & 01) /* is a diagnostic unit */
63:
64: struct ik_softc {
65: uid_t is_uid; /* uid of open processes */
66: u_short is_timeout; /* current timeout (seconds) */
67: u_short is_error; /* internal error codes */
68: u_short is_flags;
69: #define IKF_ATTACHED 0x1 /* unit is attached (not used yet) */
70: union {
71: u_short w[2];
72: u_long l;
73: } is_nameaddr; /* address of last symbol lookup */
74: caddr_t is_buf[PS_MAXDMA];/* i/o buffer XXX */
75: } ik_softc[NIK];
76:
77: struct buf iktab[NIK]; /* unit command queue headers */
78: struct buf rikbuf[NIK]; /* buffers for read/write operations */
79: struct buf cikbuf[NIK]; /* buffers for control operations */
80:
81: /* buf overlay definitions */
82: #define b_command b_resid
83:
84: int ikdiotimo = PS_DIOTIMO; /* dio polling timeout */
85: int iktimeout = PS_TIMEOUT; /* attention/dma timeout (in hz) */
86:
87: ikprobe(reg, vi)
88: caddr_t reg;
89: struct vba_device *vi;
90: {
91: register int br, cvec; /* r12, r11 */
92: register struct ikdevice *ik;
93:
94: #ifdef lint
95: br = 0; cvec = br; br = cvec;
96: ikintr(0);
97: #endif
98: if (badaddr(reg, 2))
99: return (0);
100: ik = (struct ikdevice *)reg;
101: ik->ik_vec = --vi->ui_hd->vh_lastiv;
102: /*
103: * Use extended non-privileged address modifier
104: * to avoid address overlap with 24-bit devices.
105: */
106: ik->ik_mod = 0xf1; /* address modifier */
107: /*
108: * Try and reset the PS300. Since this
109: * won't work if it's powered off, we
110: * can't use sucess/failure to decide
111: * if the device is present.
112: */
113: br = 0;
114: (void) psreset(ik, IKCSR_IENA);
115: if (br == 0) /* XXX */
116: br = 0x18, cvec = ik->ik_vec; /* XXX */
117: return (sizeof (struct ikdevice));
118: }
119:
120: /*
121: * Perform a ``hard'' reset.
122: */
123: psreset(ik, iena)
124: register struct ikdevice *ik;
125: {
126:
127: ik->ik_csr = IKCSR_MCLR|iena;
128: DELAY(10000);
129: ik->ik_csr = IKCSR_FNC3|iena;
130: if (!iena)
131: return (dioread(ik) == PS_RESET);
132: return (1);
133: }
134:
135: ikattach(vi)
136: struct vba_device *vi;
137: {
138:
139: ik_softc[vi->ui_unit].is_uid = -1;
140: }
141:
142: /*
143: * Open a PS300 and attach. We allow multiple
144: * processes with the same uid to share a unit.
145: */
146: /*ARGSUSED*/
147: ikopen(dev, flag)
148: dev_t dev;
149: int flag;
150: {
151: register int unit = IKUNIT(dev);
152: register struct ik_softc *sc;
153: struct vba_device *vi;
154: struct ikdevice *ik;
155: int reset;
156:
157: if (unit >= NIK || (vi = ikinfo[unit]) == 0 || vi->ui_alive == 0)
158: return (ENXIO);
159: sc = &ik_softc[unit];
160: if (sc->is_uid != (uid_t)-1 && sc->is_uid != u.u_uid)
161: return (EBUSY);
162: if (sc->is_uid == (uid_t)-1) {
163: sc->is_timeout = 0;
164: timeout(iktimer, (caddr_t)unit, hz);
165: /*
166: * Perform PS300 attach for first process.
167: */
168: if (!IKDIAG(dev)) {
169: reset = 0;
170: again:
171: if (ikcommand(dev, PS_ATTACH, 1)) {
172: /*
173: * If attach fails, perform a hard
174: * reset once, then retry the command.
175: */
176: ik = (struct ikdevice *)ikinfo[unit]->ui_addr;
177: if (!reset++ && psreset(ik, 0))
178: goto again;
179: untimeout(iktimer, (caddr_t)unit);
180: return (EIO);
181: }
182: }
183: sc->is_uid = u.u_uid;
184: }
185: return (0);
186: }
187:
188: /*ARGSUSED*/
189: ikclose(dev, flag)
190: dev_t dev;
191: int flag;
192: {
193: int unit = IKUNIT(dev);
194: register struct ik_softc *sc = &ik_softc[unit];
195:
196: if (!IKDIAG(dev))
197: (void) ikcommand(dev, PS_DETACH, 1); /* auto detach */
198: sc->is_uid = -1;
199: untimeout(iktimer, (caddr_t)unit);
200: return (0);
201: }
202:
203: ikread(dev, uio)
204: dev_t dev;
205: struct uio *uio;
206: {
207:
208: return (ikrw(dev, uio, B_READ));
209: }
210:
211: ikwrite(dev, uio)
212: dev_t dev;
213: struct uio *uio;
214: {
215:
216: return (ikrw(dev, uio, B_WRITE));
217: }
218:
219: /*
220: * Take read/write request and perform physical i/o
221: * transaction with PS300. This involves constructing
222: * a physical i/o request vector based on the uio
223: * vector, performing the dma, and, finally, moving
224: * the data to it's final destination (because of CCI
225: * VERSAbus bogosities).
226: */
227: ikrw(dev, uio, rw)
228: dev_t dev;
229: register struct uio *uio;
230: int rw;
231: {
232: int error, unit = IKUNIT(dev), s, wrcmd;
233: register struct buf *bp;
234: register struct iovec *iov;
235: register struct psalist *ap;
236: struct ik_softc *sc = &ik_softc[unit];
237:
238: if (unit >= NIK)
239: return (ENXIO);
240: bp = &rikbuf[unit];
241: error = 0, iov = uio->uio_iov, wrcmd = PS_WRPHY;
242: for (; !error && uio->uio_iovcnt; iov++, uio->uio_iovcnt--) {
243: /*
244: * Hack way to set PS300 address w/o doing an lseek
245: * and specify write physical w/ refresh synchronization.
246: */
247: if (iov->iov_len == 0) {
248: if ((int)iov->iov_base&PSIO_SYNC)
249: wrcmd = PS_WRPHY_SYNC;
250: uio->uio_offset = (int)iov->iov_base & ~PSIO_SYNC;
251: continue;
252: }
253: if (iov->iov_len > PS_MAXDMA) {
254: sc->is_error = PSERROR_INVALBC, error = EINVAL;
255: continue;
256: }
257: if ((int)uio->uio_offset&01) {
258: sc->is_error = PSERROR_BADADDR, error = EINVAL;
259: continue;
260: }
261: s = splbio();
262: while (bp->b_flags&B_BUSY) {
263: bp->b_flags |= B_WANTED;
264: sleep((caddr_t)bp, PRIBIO+1);
265: }
266: splx(s);
267: bp->b_flags = B_BUSY | rw;
268: /*
269: * Construct address descriptor in buffer.
270: */
271: ap = (struct psalist *)sc->is_buf;
272: ap->nblocks = 1;
273: /* work-around dr300 word swapping */
274: ap->addr[0] = uio->uio_offset & 0xffff;
275: ap->addr[1] = uio->uio_offset >> 16;
276: ap->wc = (iov->iov_len + 1) >> 1;
277: if (rw == B_WRITE) {
278: error = copyin(iov->iov_base, (caddr_t)&ap[1],
279: (unsigned)iov->iov_len);
280: if (!error)
281: error = ikcommand(dev, wrcmd,
282: iov->iov_len + sizeof (*ap));
283: } else {
284: caddr_t cp;
285: int len;
286:
287: error = ikcommand(dev, PS_RDPHY, sizeof (*ap));
288: cp = (caddr_t)&ap[1], len = iov->iov_len;
289: for (; len > 0; len -= NBPG, cp += NBPG)
290: mtpr(P1DC, cp);
291: if (!error)
292: error = copyout((caddr_t)&ap[1], iov->iov_base,
293: (unsigned)iov->iov_len);
294: }
295: (void) splbio();
296: if (bp->b_flags&B_WANTED)
297: wakeup((caddr_t)bp);
298: splx(s);
299: uio->uio_resid -= iov->iov_len;
300: uio->uio_offset += iov->iov_len;
301: bp->b_flags &= ~(B_BUSY|B_WANTED);
302: }
303: return (error);
304: }
305:
306: /*
307: * Perform a PS300 command.
308: */
309: ikcommand(dev, com, count)
310: dev_t dev;
311: int com, count;
312: {
313: register struct buf *bp;
314: register int s;
315: int error;
316:
317: bp = &cikbuf[IKUNIT(dev)];
318: s = splik();
319: while (bp->b_flags&B_BUSY) {
320: if (bp->b_flags&B_DONE)
321: break;
322: bp->b_flags |= B_WANTED;
323: sleep((caddr_t)bp, PRIBIO);
324: }
325: bp->b_flags = B_BUSY|B_READ;
326: splx(s);
327: bp->b_dev = dev;
328: bp->b_command = com;
329: bp->b_bcount = count;
330: ikstrategy(bp);
331: error = biowait(bp);
332: if (bp->b_flags&B_WANTED)
333: wakeup((caddr_t)bp);
334: bp->b_flags &= B_ERROR;
335: return (error);
336: }
337:
338: /*
339: * Physio strategy routine
340: */
341: ikstrategy(bp)
342: register struct buf *bp;
343: {
344: register struct buf *dp;
345:
346: /*
347: * Put request at end of controller queue.
348: */
349: dp = &iktab[IKUNIT(bp->b_dev)];
350: bp->av_forw = NULL;
351: (void) splik();
352: if (dp->b_actf != NULL) {
353: dp->b_actl->av_forw = bp;
354: dp->b_actl = bp;
355: } else
356: dp->b_actf = dp->b_actl = bp;
357: if (!dp->b_active)
358: ikstart(dp);
359: (void) spl0();
360: }
361:
362: /*
363: * Start the next command on the controller's queue.
364: */
365: ikstart(dp)
366: register struct buf *dp;
367: {
368: register struct buf *bp;
369: register struct ikdevice *ik;
370: register struct ik_softc *sc;
371: u_short bc, csr;
372: u_int addr;
373: int unit;
374:
375: loop:
376: /*
377: * Pull a request off the controller queue
378: */
379: if ((bp = dp->b_actf) == NULL) {
380: dp->b_active = 0;
381: return;
382: }
383: /*
384: * Mark controller busy and process this request.
385: */
386: dp->b_active = 1;
387: unit = IKUNIT(bp->b_dev);
388: sc = &ik_softc[unit];
389: ik = (struct ikdevice *)ikinfo[unit]->ui_addr;
390: switch ((int)bp->b_command) {
391:
392: case PS_ATTACH: /* logical unit attach */
393: case PS_DETACH: /* logical unit detach */
394: case PS_LOOKUP: /* name lookup */
395: case PS_RDPHY: /* physical i/o read */
396: case PS_WRPHY: /* physical i/o write */
397: case PS_WRPHY_SYNC: /* physical i/o write w/ sync */
398: /*
399: * Handshake command and, optionally,
400: * byte count and byte swap flag.
401: */
402: if (sc->is_error = diowrite(ik, (u_short)bp->b_command))
403: goto bad;
404: if (bp->b_command < PS_DETACH) {
405: if (sc->is_error = diowrite(ik, (u_short)bp->b_bcount))
406: goto bad;
407: if (sc->is_error = diowrite(ik, (u_short)0 /* !swab */))
408: goto bad;
409: }
410: /*
411: * Set timeout and wait for an attention interrupt.
412: */
413: sc->is_timeout = iktimeout;
414: return;
415:
416: case PS_DMAOUT: /* dma data host->PS300 */
417: bc = bp->b_bcount;
418: csr = IKCSR_CYCLE;
419: break;
420:
421: case PS_DMAIN: /* dma data PS300->host */
422: bc = bp->b_bcount;
423: csr = IKCSR_CYCLE|IKCSR_FNC1;
424: break;
425:
426: default:
427: log(LOG_ERR, "ik%d: bad cmd %x\n", unit, bp->b_command);
428: sc->is_error = PSERROR_BADCMD;
429: goto bad;
430: }
431: /* initiate dma transfer */
432: addr = vtoph((struct proc *)0, (unsigned)sc->is_buf);
433: ik->ik_bahi = addr >> 17;
434: ik->ik_balo = (addr >> 1) & 0xffff;
435: ik->ik_wc = ((bc + 1) >> 1) - 1; /* round & convert */
436: ik->ik_pulse = IKPULSE_RATTF|IKPULSE_RDMAF;
437: sc->is_timeout = iktimeout;
438: ik->ik_csr = IKCSR_IENA|IKCSR_GO|csr;
439: return;
440: bad:
441: bp->b_flags |= B_ERROR;
442: dp->b_actf = bp->av_forw; /* remove from queue */
443: biodone(bp);
444: goto loop;
445: }
446:
447: #define FETCHWORD(i) { \
448: v = dioread(ik); \
449: if (v == -1) { \
450: sc->is_error = PSERROR_NAMETIMO; \
451: goto bad; \
452: } \
453: sc->is_nameaddr.w[i] = v; \
454: }
455:
456: /*
457: * Process a device interrupt.
458: */
459: ikintr(ikon)
460: int ikon;
461: {
462: register struct ikdevice *ik;
463: register struct buf *bp, *dp;
464: struct ik_softc *sc;
465: register u_short data;
466: int v;
467:
468: /* should go by controller, but for now... */
469: if (ikinfo[ikon] == 0)
470: return;
471: ik = (struct ikdevice *)ikinfo[ikon]->ui_addr;
472: /*
473: * Discard all non-attention interrupts. The
474: * interrupts we're throwing away should all be
475: * associated with DMA completion.
476: */
477: data = ik->ik_data;
478: if ((ik->ik_csr&(IKCSR_ATTF|IKCSR_STATC)) != IKCSR_ATTF) {
479: ik->ik_pulse = IKPULSE_RATTF|IKPULSE_RDMAF|IKPULSE_SIENA;
480: return;
481: }
482: /*
483: * Fetch attention code immediately.
484: */
485: ik->ik_csr = IKCSR_RATTF|IKCSR_RDMAF|IKCSR_FNC1;
486: ik->ik_pulse = IKPULSE_FNC2;
487: /*
488: * Get device and block structures, and a pointer
489: * to the vba_device for the device. We receive an
490: * unsolicited interrupt whenever the PS300 is power
491: * cycled (so ignore it in that case).
492: */
493: dp = &iktab[ikon];
494: if ((bp = dp->b_actf) == NULL) {
495: if (PS_CODE(data) != PS_RESET) /* power failure */
496: log(LOG_WARNING, "ik%d: spurious interrupt, code %x\n",
497: ikon, data);
498: goto enable;
499: }
500: sc = &ik_softc[IKUNIT(bp->b_dev)];
501: sc->is_timeout = 0; /* disable timer */
502: switch (PS_CODE(data)) {
503:
504: case PS_LOOKUP: /* name lookup */
505: if (data == PS_LOOKUP) { /* dma name */
506: bp->b_command = PS_DMAOUT;
507: goto opcont;
508: }
509: if (data == PS_DMAOK(PS_LOOKUP)) {
510: /* reenable interrupt and wait for address */
511: sc->is_timeout = iktimeout;
512: goto enable;
513: }
514: /*
515: * Address should be present, extract it one
516: * word at a time from the PS300 (yech).
517: */
518: if (data != PS_ADROK(PS_LOOKUP))
519: goto bad;
520: FETCHWORD(0);
521: FETCHWORD(1);
522: goto opdone;
523:
524: case PS_WRPHY_SYNC: /* physical i/o write w/ sync */
525: if (data == PS_WRPHY_SYNC) { /* start dma transfer */
526: bp->b_command = PS_DMAOUT;
527: goto opcont;
528: }
529: if (data != PS_DMAOK(PS_WRPHY_SYNC))
530: goto bad;
531: goto opdone;
532:
533: case PS_WRPHY: /* physical i/o write */
534: if (data == PS_WRPHY) { /* start dma transfer */
535: bp->b_command = PS_DMAOUT;
536: goto opcont;
537: }
538: if (data != PS_DMAOK(PS_WRPHY))
539: goto bad;
540: goto opdone;
541:
542: case PS_ATTACH: /* attach unit */
543: case PS_DETACH: /* detach unit */
544: case PS_ABORT: /* abort code from ps300 */
545: if (data != bp->b_command)
546: goto bad;
547: goto opdone;
548:
549: case PS_RDPHY: /* physical i/o read */
550: if (data == PS_RDPHY) { /* dma address list */
551: bp->b_command = PS_DMAOUT;
552: goto opcont;
553: }
554: if (data == PS_ADROK(PS_RDPHY)) {
555: /* collect read byte count and start dma */
556: bp->b_bcount = dioread(ik);
557: if (bp->b_bcount == -1)
558: goto bad;
559: bp->b_command = PS_DMAIN;
560: goto opcont;
561: }
562: if (data == PS_DMAOK(PS_RDPHY))
563: goto opdone;
564: goto bad;
565: }
566: bad:
567: sc->is_error = data;
568: bp->b_flags |= B_ERROR;
569: opdone:
570: dp->b_actf = bp->av_forw; /* remove from queue */
571: biodone(bp);
572: opcont:
573: ikstart(dp);
574: enable:
575: ik->ik_pulse = IKPULSE_SIENA; /* explicitly reenable */
576: }
577:
578: /*
579: * Watchdog timer.
580: */
581: iktimer(unit)
582: int unit;
583: {
584: register struct ik_softc *sc = &ik_softc[unit];
585:
586: if (sc->is_timeout && --sc->is_timeout == 0) {
587: register struct buf *dp, *bp;
588: int s;
589:
590: log(LOG_ERR, "ik%d: timeout\n", unit);
591: s = splik();
592: /* should abort current command */
593: dp = &iktab[unit];
594: if (bp = dp->b_actf) {
595: sc->is_error = PSERROR_CMDTIMO;
596: bp->b_flags |= B_ERROR;
597: dp->b_actf = bp->av_forw; /* remove from queue */
598: biodone(bp);
599: ikstart(dp);
600: }
601: splx(s);
602: }
603: timeout(iktimer, (caddr_t)unit, hz);
604: }
605:
606: /*
607: * Handshake read from DR300.
608: */
609: dioread(ik)
610: register struct ikdevice *ik;
611: {
612: register int t;
613: u_short data;
614:
615: for (t = ikdiotimo; t > 0; t--)
616: if ((ik->ik_csr&(IKCSR_ATTF|IKCSR_STATC)) == IKCSR_ATTF) {
617: data = ik->ik_data;
618: ik->ik_csr = IKCSR_RATTF|IKCSR_RDMAF|IKCSR_FNC1;
619: ik->ik_pulse = IKPULSE_FNC2;
620: return (data);
621: }
622: return (-1);
623: }
624:
625: /*
626: * Handshake write to DR300.
627: *
628: * Interrupts are enabled before completing the work
629: * so the caller should either be at splik or be
630: * prepared to take the interrupt immediately.
631: */
632: diowrite(ik, v)
633: register struct ikdevice *ik;
634: u_short v;
635: {
636: register int t;
637: register u_short csr;
638:
639: top:
640: /*
641: * Deposit data and generate dr300 attention
642: */
643: ik->ik_data = v;
644: ik->ik_csr = IKCSR_RDMAF|IKCSR_RATTF;
645: ik->ik_pulse = IKPULSE_FNC2;
646: for (t = ikdiotimo; t > 0; t--) {
647: csr = ik->ik_csr;
648: #define IKCSR_DONE (IKCSR_STATA|IKCSR_STATC)
649: if ((csr&IKCSR_DONE) == IKCSR_DONE) {
650: /*
651: * Done, complete handshake by notifying dr300.
652: */
653: ik->ik_csr = IKCSR_IENA; /* ~IKCSR_FNC1 */
654: ik->ik_pulse = IKPULSE_FNC2;
655: return (0);
656: }
657: /* beware of potential deadlock with dioread */
658: if ((csr&(IKCSR_ATTF|IKCSR_STATC)) == IKCSR_ATTF)
659: goto top;
660: }
661: ik->ik_csr = IKCSR_IENA;
662: return (PSERROR_DIOTIMO);
663: }
664:
665: /*ARGSUSED*/
666: ikioctl(dev, cmd, data, flag)
667: dev_t dev;
668: int cmd;
669: caddr_t data;
670: int flag;
671: {
672: int error = 0, unit = IKUNIT(dev), s;
673: register struct ik_softc *sc = &ik_softc[unit];
674:
675: switch (cmd) {
676:
677: case PSIOGETERROR: /* get error code for last operation */
678: *(int *)data = sc->is_error;
679: break;
680:
681: case PSIOLOOKUP: { /* PS300 name lookup */
682: register struct pslookup *lp = (struct pslookup *)data;
683: register struct buf *bp;
684:
685: if (lp->pl_len > PS_MAXNAMELEN)
686: return (EINVAL);
687: bp = &rikbuf[unit];
688: s = splbio();
689: while (bp->b_flags&B_BUSY) {
690: bp->b_flags |= B_WANTED;
691: sleep((caddr_t)bp, PRIBIO+1);
692: }
693: splx(s);
694: bp->b_flags = B_BUSY | B_WRITE;
695: error = copyin(lp->pl_name, (caddr_t)sc->is_buf,
696: (unsigned)lp->pl_len);
697: if (error == 0) {
698: if (lp->pl_len&1)
699: sc->is_buf[lp->pl_len] = '\0';
700: error = ikcommand(dev, PS_LOOKUP, lp->pl_len);
701: }
702: s = splbio();
703: if (bp->b_flags&B_WANTED)
704: wakeup((caddr_t)bp);
705: splx(s);
706: bp->b_flags &= ~(B_BUSY|B_WANTED);
707: lp->pl_addr = sc->is_nameaddr.l;
708: break;
709: }
710: default:
711: return (ENOTTY);
712: }
713: return (error);
714: }
715: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.