|
|
1.1 root 1: /*
2: * Copyright (c) 1988 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Computer Consoles Inc.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
36: * @(#)dr.c 7.9 (Berkeley) 12/16/90
37: */
38:
39: #include "dr.h"
40: #if NDR > 0
41: /*
42: * DRV11-W DMA interface driver.
43: *
44: * UNTESTED WITH 4.3
45: */
46: #include "../include/mtpr.h"
47: #include "../include/pte.h"
48:
49: #include "sys/param.h"
50: #include "sys/conf.h"
51: #include "sys/user.h"
52: #include "sys/proc.h"
53: #include "sys/map.h"
54: #include "sys/ioctl.h"
55: #include "sys/buf.h"
56: #include "sys/vm.h"
57: #include "sys/kernel.h"
58:
59: #include "../vba/vbavar.h"
60: #include "../vba/drreg.h"
61:
62: #define YES 1
63: #define NO 0
64:
65: struct vba_device *drinfo[NDR];
66: struct dr_aux dr_aux[NDR];
67:
68: unsigned drminphys();
69: int drprobe(), drintr(), drattach(), drtimo(), drrwtimo();
70: int drstrategy();
71: extern struct vba_device *drinfo[];
72: static long drstd[] = { 0 };
73: struct vba_driver drdriver =
74: { drprobe, 0, drattach, 0, drstd, "rs", drinfo };
75:
76: #define RSUNIT(dev) (minor(dev) & 7)
77: #define SPL_UP spl5
78:
79: /* -------- Per-unit data -------- */
80:
81: extern struct dr_aux dr_aux[];
82:
83: #ifdef DR_DEBUG
84: long DR11 = 0;
85: #endif
86:
87: drprobe(reg, vi)
88: caddr_t reg;
89: struct vba_device *vi;
90: {
91: register int br, cvec; /* must be r12, r11 */
92: struct rsdevice *dr;
93:
94: #ifdef lint
95: br = 0; cvec = br; br = cvec;
96: drintr(0);
97: #endif
98: if (badaddr(reg, 2))
99: return (0);
100: dr = (struct rsdevice *)reg;
101: dr->dr_intvect = --vi->ui_hd->vh_lastiv;
102: #ifdef DR_DEBUG
103: printf("dprobe: Set interrupt vector %lx and init\n",dr->dr_intvec);
104: #endif
105: /* generate interrupt here for autoconfig */
106: dr->dr_cstat = MCLR; /* init board and device */
107: #ifdef DR_DEBUG
108: printf("drprobe: Initial status %lx\n", dr->dr_cstat);
109: #endif
110: br = 0x18, cvec = dr->dr_intvect; /* XXX */
111: return (sizeof (struct rsdevice)); /* DR11 exist */
112: }
113:
114: /* ARGSUSED */
115: drattach(ui)
116: struct vba_device *ui;
117: {
118: register struct dr_aux *rsd;
119:
120: rsd = &dr_aux[ui->ui_unit];
121: rsd->dr_flags = DR_PRES; /* This dr11 is present */
122: rsd->dr_addr = (struct rsdevice *)ui->ui_addr; /* Save addr of this dr11 */
123: rsd->dr_istat = 0;
124: rsd->dr_bycnt = 0;
125: rsd->dr_cmd = 0;
126: rsd->currenttimo = 0;
127: }
128:
129: /*ARGSUSED*/
130: dropen(dev, flag)
131: dev_t dev;
132: int flag;
133: {
134: register int unit = RSUNIT(dev);
135: register struct rsdevice *dr;
136: register struct dr_aux *rsd;
137:
138: if (drinfo[unit] == 0 || !drinfo[unit]->ui_alive)
139: return (ENXIO);
140: dr = RSADDR(unit);
141: rsd = &dr_aux[unit];
142: if (rsd->dr_flags & DR_OPEN) {
143: #ifdef DR_DEBUG
144: printf("\ndropen: dr11 unit %ld already open",unit);
145: #endif
146: return (ENXIO); /* DR11 already open */
147: }
148: rsd->dr_flags |= DR_OPEN; /* Mark it OPEN */
149: rsd->dr_istat = 0; /* Clear status of previous interrupt */
150: rsd->rtimoticks = hz; /* Set read no stall timout to 1 sec */
151: rsd->wtimoticks = hz*60; /* Set write no stall timout to 1 min */
152: dr->dr_cstat = DR_ZERO; /* Clear function & latches */
153: dr->dr_pulse = (RDMA | RATN); /* clear leftover attn & e-o-r flags */
154: drtimo(dev); /* start the self kicker */
155: return (0);
156: }
157:
158: drclose (dev)
159: dev_t dev;
160: {
161: register int unit = RSUNIT(dev);
162: register struct dr_aux *dra;
163: register struct rsdevice *rs;
164: register short s;
165:
166: dra = &dr_aux[unit];
167: if ((dra->dr_flags & DR_OPEN) == 0) {
168: #ifdef DR_DEBUG
169: printf("\ndrclose: DR11 device %ld not open",unit);
170: #endif
171: return;
172: }
173: dra->dr_flags &= ~(DR_OPEN|DR_ACTV);
174: rs = dra->dr_addr;
175: s = SPL_UP();
176: rs->dr_cstat = DR_ZERO;
177: if (dra->dr_buf.b_flags & B_BUSY) {
178: dra->dr_buf.b_flags &= ~B_BUSY;
179: wakeup((caddr_t)&dra->dr_buf.b_flags);
180: }
181: splx(s);
182: return (0);
183: }
184:
185:
186: /* drread() works exactly like drwrite() except that the
187: B_READ flag is used when physio() is called
188: */
189: drread (dev, uio)
190: dev_t dev;
191: struct uio *uio;
192: { register struct dr_aux *dra;
193: register struct buf *bp;
194: register int spl, err;
195: register int unit = RSUNIT(dev);
196:
197: if (uio->uio_iov->iov_len <= 0 || /* Negative count */
198: uio->uio_iov->iov_len & 1 || /* odd count */
199: (int)uio->uio_iov->iov_base & 1) /* odd destination address */
200: return (EINVAL);
201: #ifdef DR_DEBUG
202: if (DR11 & 8)
203: printf("\ndrread: (len:%ld)(base:%lx)",
204: uio->uio_iov->iov_len,(int)uio->uio_iov->iov_base);
205: #endif
206: dra = &dr_aux[RSUNIT(dev)];
207: dra->dr_op = DR_READ;
208: bp = &dra->dr_buf;
209: bp->b_resid = 0;
210: if (dra->dr_flags & DR_NORSTALL) {
211: /*
212: * We are in no stall mode, start the timer,
213: * raise IPL so nothing can stop us once the
214: * timer's running
215: */
216: spl = SPL_UP();
217: timeout(drrwtimo, (caddr_t)((dra->currenttimo<<8) | unit),
218: (int)dra->rtimoticks);
219: err = physio(drstrategy, bp, dev,B_READ, drminphys, uio);
220: splx(spl);
221: if (err)
222: return (err);
223: dra->currenttimo++; /* Update current timeout number */
224: /* Did we timeout */
225: if (dra->dr_flags & DR_TMDM)
226: dra->dr_flags &= ~DR_TMDM; /* Clear timeout flag */
227: return (err);
228: }
229: return (physio(drstrategy, bp, dev,B_READ, drminphys, uio));
230: }
231:
232: drwrite(dev, uio)
233: dev_t dev;
234: struct uio *uio;
235: { register struct dr_aux *dra;
236: register struct buf *bp;
237: register int unit = RSUNIT(dev);
238: int spl, err;
239:
240: if (uio->uio_iov->iov_len <= 0 || uio->uio_iov->iov_len & 1 ||
241: (int)uio->uio_iov->iov_base & 1)
242: return (EINVAL);
243: #ifdef DR_DEBUG
244: if (DR11 & 4)
245: printf("\ndrwrite: (len:%ld)(base:%lx)",
246: uio->uio_iov->iov_len,(int)uio->uio_iov->iov_base);
247: #endif
248: dra = &dr_aux[RSUNIT(dev)];
249: dra->dr_op = DR_WRITE;
250: bp = &dra->dr_buf;
251: bp->b_resid = 0;
252: if (dra->dr_flags & DR_NOWSTALL) {
253: /*
254: * We are in no stall mode, start the timer,
255: * raise IPL so nothing can stop us once the
256: * timer's running
257: */
258: spl = SPL_UP();
259: timeout(drrwtimo,(caddr_t)((dra->currenttimo<<8) | unit),
260: (int)dra->wtimoticks);
261: err = physio (drstrategy, bp, dev,B_WRITE, drminphys, uio);
262: splx(spl);
263: if (err)
264: return (err);
265: dra->currenttimo++; /* Update current timeout number */
266: /* Did we timeout */
267: if (dra->dr_flags & DR_TMDM)
268: dra->dr_flags &= ~DR_TMDM; /* Clear timeout flag */
269: return (err);
270: }
271: return (physio(drstrategy, bp, dev,B_WRITE, drminphys, uio));
272: }
273:
274: /*
275: * Routine used by calling program to issue commands to dr11 driver and
276: * through it to the device.
277: * It is also used to read status from the device and driver and to wait
278: * for attention interrupts.
279: * Status is returned in an 8 elements unsigned short integer array, the
280: * first two elements of the array are also used to pass arguments to
281: * drioctl() if required.
282: * The function bits to be written to the dr11 are included in the cmd
283: * argument. Even if they are not being written to the dr11 in a particular
284: * drioctl() call, they will update the copy of cmd that is stored in the
285: * driver. When drstrategy() is called, this updated copy is used if a
286: * deferred function bit write has been specified. The "side effect" of
287: * calls to the drioctl() requires that the last call prior to a read or
288: * write has an appropriate copy of the function bits in cmd if they are
289: * to be used in drstrategy().
290: * When used as command value, the contents of data[0] is the command
291: * parameter.
292: */
293: drioctl(dev, cmd, data)
294: dev_t dev;
295: int cmd;
296: long *data;
297: {
298: register int unit = RSUNIT(dev);
299: register struct dr_aux *dra;
300: register struct rsdevice *rsaddr = RSADDR(unit);
301: int s, error = 0;
302: u_short status;
303: long temp;
304:
305: #ifdef DR_DEBUG
306: if (DR11 & 0x10)
307: printf("\ndrioctl: (dev:%lx)(cmd:%lx)(data:%lx)(data[0]:%lx)",
308: dev,cmd,data,data[0]);
309: #endif
310: dra = &dr_aux[unit];
311: dra->dr_cmd = 0; /* Fresh copy; clear all previous flags */
312: switch (cmd) {
313:
314: case DRWAIT: /* Wait for attention interrupt */
315: #ifdef DR_DEBUG
316: printf("\ndrioctl: wait for attention interrupt");
317: #endif
318: s = SPL_UP();
319: /*
320: * If the attention flag in dr_flags is set, it probably
321: * means that an attention has arrived by the time a
322: * previous DMA end-of-range interrupt was serviced. If
323: * ATRX is set, we will return with out sleeping, since
324: * we have received an attention since the last call to
325: * wait on attention. This may not be appropriate for
326: * some applications.
327: */
328: if ((dra->dr_flags & DR_ATRX) == 0) {
329: dra->dr_flags |= DR_ATWT; /* Set waiting flag */
330: /*
331: * Enable interrupt; use pulse reg.
332: * so function bits are not changed
333: */
334: rsaddr->dr_pulse = IENB;
335: error = tsleep((caddr_t)&dra->dr_cmd, DRPRI | PCATCH,
336: devio, 0);
337: }
338: splx(s);
339: break;
340:
341: case DRPIOW: /* Write to p-i/o register */
342: rsaddr->dr_data = data[0];
343: break;
344:
345: case DRPACL: /* Send pulse to device */
346: rsaddr->dr_pulse = FCN2;
347: break;
348:
349: case DRDACL: /* Defer alco pulse until go */
350: dra->dr_cmd |= DR_DACL;
351: break;
352:
353: case DRPCYL: /* Set cycle with next go */
354: dra->dr_cmd |= DR_PCYL;
355: break;
356:
357: case DRDFCN: /* Update function with next go */
358: dra->dr_cmd |= DR_DFCN;
359: break;
360:
361: case DRRATN: /* Reset attention flag */
362: rsaddr->dr_pulse = RATN;
363: break;
364:
365: case DRRDMA: /* Reset DMA e-o-r flag */
366: rsaddr->dr_pulse = RDMA;
367: break;
368:
369: case DRSFCN: /* Set function bits */
370: temp = data[0] & DR_FMSK;
371: /*
372: * This has a very important side effect -- It clears
373: * the interrupt enable flag. That is fine for this driver,
374: * but if it is desired to leave interrupt enable at all
375: * times, it will be necessary to read the status register
376: * first to get IENB, or carry a software flag that indicates
377: * whether interrupts are set, and or this into the control
378: * register value being written.
379: */
380: rsaddr->dr_cstat = temp;
381: break;
382:
383: case DRRPER: /* Clear parity flag */
384: rsaddr->dr_pulse = RPER;
385: break;
386:
387: case DRSETRSTALL: /* Set read stall mode. */
388: dra->dr_flags &= (~DR_NORSTALL);
389: break;
390:
391: case DRSETNORSTALL: /* Set no stall read mode. */
392: dra->dr_flags |= DR_NORSTALL;
393: break;
394:
395: case DRGETRSTALL: /* Returns true if in read stall mode */
396: data[0] = (dra->dr_flags & DR_NORSTALL)? 0 : 1;
397: break;
398:
399: case DRSETRTIMEOUT: /* Set read stall timeout (1/10 secs) */
400: if (data[0] < 1)
401: error = EINVAL;
402: dra->rtimoticks = (data[0] * hz )/10;
403: break;
404:
405: case DRGETRTIMEOUT: /* Return read stall timeout */
406: data[0] = ((dra->rtimoticks)*10)/hz;
407: break;
408:
409: case DRSETWSTALL: /* Set write stall mode. */
410: dra->dr_flags &= (~DR_NOWSTALL);
411: break;
412:
413: case DRSETNOWSTALL: /* Set write stall mode. */
414: dra->dr_flags |= DR_NOWSTALL;
415: break;
416:
417: case DRGETWSTALL: /* Return true if in write stall mode */
418: data[0] = (dra->dr_flags & DR_NOWSTALL)? 0 : 1;
419: break;
420:
421: case DRSETWTIMEOUT: /* Set write stall timeout (1/10's) */
422: if (data[0] < 1)
423: error = EINVAL;
424: dra->wtimoticks = (data[0] * hz )/10;
425: break;
426:
427: case DRGETWTIMEOUT: /* Return write stall timeout */
428: data[0] = ((dra->wtimoticks)*10)/hz;
429: break;
430:
431: case DRWRITEREADY: /* Return true if can write data */
432: data[0] = (rsaddr->dr_cstat & STTA)? 1 : 0;
433: break;
434:
435: case DRREADREADY: /* Return true if data to be read */
436: data[0] = (rsaddr->dr_cstat & STTB)? 1 : 0;
437: break;
438:
439: case DRBUSY: /* Return true if device busy */
440: /*
441: * Internally this is the DR11-W
442: * STAT C bit, but there is a bug in the Omega 500/FIFO
443: * interface board that it cannot drive this signal low
444: * for certain DR11-W ctlr such as the Ikon. We use the
445: * REDY signal of the CSR on the Ikon DR11-W instead.
446: */
447: #ifdef notdef
448: data[0] = (rsaddr->dr_cstat & STTC)? 1 : 0;
449: #else
450: data[0] = ((rsaddr->dr_cstat & REDY)? 0 : 1);
451: #endif
452: break;
453:
454: case DRRESET: /* Reset device */
455: /* Reset DMA ATN RPER flag */
456: rsaddr->dr_pulse = (MCLR|RDMA|RATN|RPER);
457: DELAY(0x1f000);
458: while ((rsaddr->dr_cstat & REDY) == 0 && error == 0)
459: /* Wakeup by drtimo() */
460: error = tsleep((caddr_t)dra, DRPRI | PCATCH, devio, 0);
461: dra->dr_istat = 0;
462: dra->dr_cmd = 0;
463: dra->currenttimo = 0;
464: break;
465:
466: case DR11STAT: { /* Copy back dr11 status to user */
467: register struct dr11io *dr = (struct dr11io *)data;
468: dr->arg[0] = dra->dr_flags;
469: dr->arg[1] = rsaddr->dr_cstat;
470: dr->arg[2] = dra->dr_istat; /* Status at last interrupt */
471: dr->arg[3] = rsaddr->dr_data; /* P-i/o input data */
472: status = (u_short)((rsaddr->dr_addmod << 8) & 0xff00);
473: dr->arg[4] = status | (u_short)(rsaddr->dr_intvect & 0xff);
474: dr->arg[5] = rsaddr->dr_range;
475: dr->arg[6] = rsaddr->dr_rahi;
476: dr->arg[7] = rsaddr->dr_ralo;
477: break;
478: }
479: case DR11LOOP: /* Perform loopback test */
480: /*
481: * NB: MUST HAVE LOOPBACK CABLE ATTACHED --
482: * Test results are printed on system console
483: */
484: if (error = suser(u.u_cred, &u.u_acflag))
485: break;
486: dr11loop(rsaddr, dra, unit);
487: break;
488:
489: default:
490: return (EINVAL);
491: }
492: #ifdef DR_DEBUG
493: if (DR11 & 0x10)
494: printf("**** (data[0]:%lx)",data[0]);
495: #endif
496: return (error);
497: }
498:
499: #define NPAT 2
500: #define DMATBL 20
501: u_short tstpat[DMATBL] = { 0xAAAA, 0x5555};
502: long DMAin = 0;
503:
504: /*
505: * Perform loopback test -- MUST HAVE LOOPBACK CABLE ATTACHED
506: * Test results are printed on system console
507: */
508: dr11loop(dr, dra, unit)
509: struct rsdevice *dr;
510: struct dr_aux *dra;
511: int unit;
512: {
513: register long result, ix;
514: long addr, wait;
515:
516: dr->dr_cstat = MCLR; /* Clear board & device, disable intr */
517: printf("\n\t ----- DR11 unit %ld loopback test -----", unit);
518: printf("\n\t Program I/O ...");
519: for (ix=0;ix<NPAT;ix++) {
520: dr->dr_data = tstpat[ix]; /* Write to Data out register */
521: result = dr->dr_data & 0xFFFF; /* Read it back */
522: if (result != tstpat[ix]) {
523: printf("Failed, expected : %lx --- actual : %lx",
524: tstpat[ix], result);
525: return;
526: }
527: }
528: printf("OK\n\t Functions & Status Bits ...");
529: dr->dr_cstat = (FCN1 | FCN3);
530: result = dr->dr_cstat & 0xffff; /* Read them back */
531: if ((result & (STTC | STTA)) != (STTC |STTA)) {
532: printf("Failed, expected : %lx --- actual : %lx, ISR:%lx",
533: (STTA|STTC), (result & (STTA|STTC)), result);
534: return;
535: }
536: dr->dr_cstat = FCN2;
537: result = dr->dr_cstat & 0xffff; /* Read them back */
538: if ((result & STTB) != STTB) {
539: printf("Failed, expected : %lx --- actual : %lx, ISR:%lx",
540: STTB, (result & STTB), result);
541: return;
542: }
543: printf("OK\n\t DMA output ...");
544: if (DMAin)
545: goto dmain;
546: /* Initialize DMA data buffer */
547: for (ix=0; ix<DMATBL; ix++)
548: tstpat[ix] = 0xCCCC + ix;
549: tstpat[DMATBL-1] = 0xCCCC; /* Last word output */
550: /* Setup normal DMA */
551: addr = (long)vtoph((struct proc *)0, (unsigned)tstpat);
552: dr->dr_walo = (addr >> 1) & 0xffff;
553: dr->dr_wahi = (addr >> 17) & 0x7fff;
554: /* Set DMA range count: (number of words - 1) */
555: dr->dr_range = DMATBL - 1;
556: /* Set address modifier code to be used for DMA access to memory */
557: dr->dr_addmod = DRADDMOD;
558:
559: /*
560: * Clear dmaf and attf to assure a clean dma start, also disable
561: * attention interrupt
562: */
563: dr->dr_pulse = RDMA|RATN|RMSK; /* Use pulse register */
564: dr->dr_cstat = GO|CYCL; /* GO...... */
565:
566: /* Wait for DMA complete; REDY and DMAF are true in ISR */
567: wait = 0;
568: while ((result=(dr->dr_cstat & (REDY|DMAF))) != (REDY|DMAF)) {
569: printf("\n\tWait for DMA complete...ISR : %lx", result);
570: if (++wait > 5) {
571: printf("\n\t DMA output fails...timeout!!, ISR:%lx",
572: result);
573: return;
574: }
575: }
576: result = dr->dr_data & 0xffff; /* Read last word output */
577: if (result != 0xCCCC) {
578: printf("\n\t Fails, expected : %lx --- actual : %lx",
579: 0xCCCC, result);
580: return;
581: }
582: printf("OK\n\t DMA input ...");
583: dmain:
584: dr->dr_data = 0x1111; /* DMA input data */
585: /* Setup normal DMA */
586: addr = (long)vtoph((struct proc *)0, (unsigned)tstpat);
587: dr->dr_walo = (addr >> 1) & 0xffff;
588: dr->dr_wahi = (addr >> 17) & 0x7fff;
589: dr->dr_range = DMATBL - 1;
590: dr->dr_addmod = (char)DRADDMOD;
591: dr->dr_cstat = FCN1; /* Set FCN1 in ICR to DMA in*/
592: if ((dra->dr_flags & DR_LOOPTST) == 0) {
593: /* Use pulse reg */
594: dr->dr_pulse = RDMA|RATN|RMSK|CYCL|GO;
595: /* Wait for DMA complete; REDY and DMAF are true in ISR */
596: wait = 0;
597: while ((result=(dr->dr_cstat & (REDY|DMAF))) != (REDY|DMAF)) {
598: printf("\n\tWait for DMA to complete...ISR:%lx",result);
599: if (++wait > 5) {
600: printf("\n\t DMA input timeout!!, ISR:%lx",
601: result);
602: return;
603: }
604: }
605: } else {
606: /* Enable DMA e-o-r interrupt */
607: dr->dr_pulse = IENB|RDMA|RATN|CYCL|GO;
608: /* Wait for DMA complete; DR_LOOPTST is false in dra->dr_flags*/
609: wait = 0;
610: while (dra->dr_flags & DR_LOOPTST) {
611: result = dr->dr_cstat & 0xffff;
612: printf("\n\tWait for DMA e-o-r intr...ISR:%lx", result);
613: if (++wait > 7) {
614: printf("\n\t DMA e-o-r timeout!!, ISR:%lx",
615: result);
616: dra->dr_flags &= ~DR_LOOPTST;
617: return;
618: }
619: }
620: dra->dr_flags |= DR_LOOPTST;
621: }
622: mtpr(P1DC, tstpat); /* Purge cache */
623: mtpr(P1DC, 0x3ff+tstpat);
624: for (ix=0; ix<DMATBL; ix++) {
625: if (tstpat[ix] != 0x1111) {
626: printf("\n\t Fails, ix:%d, expected:%x --- actual:%x",
627: ix, 0x1111, tstpat[ix]);
628: return;
629: }
630: }
631: if ((dra->dr_flags & DR_LOOPTST) == 0) {
632: dra->dr_flags |= DR_LOOPTST;
633: printf(" OK..\n\tDMA end of range interrupt...");
634: goto dmain;
635: }
636: printf(" OK..\n\tAttention interrupt....");
637: dr->dr_pulse = IENB|RDMA;
638: dr->dr_pulse = FCN2;
639: /* Wait for ATTN interrupt; DR_LOOPTST is false in dra->dr_flags*/
640: wait = 0;
641: while (dra->dr_flags & DR_LOOPTST) {
642: result = dr->dr_cstat & 0xffff;
643: printf("\n\tWait for Attention intr...ISR:%lx",result);
644: if (++wait > 7) {
645: printf("\n\t Attention interrupt timeout!!, ISR:%lx",
646: result);
647: dra->dr_flags &= ~DR_LOOPTST;
648: return;
649: }
650: }
651: dra->dr_flags &= ~DR_LOOPTST;
652: printf(" OK..\n\tDone...");
653: }
654:
655: /* Reset state on Unibus reset */
656: /*ARGSUSED*/
657: drreset(uban)
658: int uban;
659: {
660:
661: }
662:
663: /*
664: * An interrupt is caused either by an error,
665: * base address overflow, or transfer complete
666: */
667: drintr(dr11)
668: int dr11;
669: {
670: register struct dr_aux *dra = &dr_aux[dr11];
671: register struct rsdevice *rsaddr = RSADDR(dr11);
672: register struct buf *bp;
673: register short status;
674:
675: status = rsaddr->dr_cstat & 0xffff; /* get board status register */
676: dra->dr_istat = status;
677: #ifdef DR_DEBUG
678: if (DR11 & 2)
679: printf("\ndrintr: dr11 status : %lx",status & 0xffff);
680: #endif
681: if (dra->dr_flags & DR_LOOPTST) { /* doing loopback test */
682: dra->dr_flags &= ~DR_LOOPTST;
683: return;
684: }
685: /*
686: * Make sure this is not a stray interrupt; at least one of dmaf or attf
687: * must be set. Note that if the dr11 interrupt enable latch is reset
688: * during a hardware interrupt ack sequence, and by the we get to this
689: * point in the interrupt code it will be 0. This is done to give the
690: * programmer some control over how the two more-or-less independent
691: * interrupt sources on the board are handled.
692: * If the attention flag is set when drstrategy() is called to start a
693: * dma read or write an interrupt will be generated as soon as the
694: * strategy routine enables interrupts for dma end-of-range. This will
695: * cause execution of the interrupt routine (not necessarily bad) and
696: * will cause the interrupt enable mask to be reset (very bad since the
697: * dma end-of-range condition will not be able to generate an interrupt
698: * when it occurs) causing the dma operation to time-out (even though
699: * the dma transfer will be done successfully) or hang the process if a
700: * software time-out capability is not implemented. One way to avoid
701: * this situation is to check for a pending attention interrupt (attf
702: * set) by calling drioctl() before doing a read or a write. For the
703: * time being this driver will solve the problem by clearing the attf
704: * flag in the status register before enabling interrupts in
705: * drstrategy().
706: *
707: * **** The IKON 10084 for which this driver is written will set both
708: * attf and dmaf if dma is terminated by an attention pulse. This will
709: * cause a wakeup(&dr_aux), which will be ignored since it is not being
710: * waited on, and an iodone(bp) which is the desired action. Some other
711: * dr11 emulators, in particular the IKON 10077 for the Multibus, donot
712: * dmaf in this case. This may require some addtional code in the inter-
713: * rupt routine to ensure that en iodone(bp) is issued when dma is term-
714: * inated by attention.
715: */
716: bp = dra->dr_actf;
717: if ((status & (ATTF | DMAF)) == 0) {
718: printf("dr%d: stray interrupt, status=%x", dr11, status);
719: return;
720: }
721: if (status & DMAF) { /* End-of-range interrupt */
722: dra->dr_flags |= DR_DMAX;
723:
724: #ifdef DR_DEBUG
725: if (DR11 & 2)
726: printf("\ndrintr: e-o-r interrupt,cstat:%lx,dr_flags:%lx",
727: status&0xffff, dra->dr_flags & DR_ACTV);
728: #endif
729: if ((dra->dr_flags & DR_ACTV) == 0) {
730: /* We are not doing DMA !! */
731: bp->b_flags |= B_ERROR;
732: } else {
733: if (dra->dr_op == DR_READ)
734: mtpr(P1DC, bp->b_un.b_addr);
735: dra->dr_bycnt -= bp->b_bcount;
736: if (dra->dr_bycnt >0) {
737: bp->b_un.b_addr += bp->b_bcount;
738: bp->b_bcount = (dra->dr_bycnt > NBPG) ? NBPG:
739: dra->dr_bycnt;
740: drstart(rsaddr, dra, bp);
741: return;
742: }
743: }
744: dra->dr_flags &= ~DR_ACTV;
745: wakeup((caddr_t)dra); /* Wakeup waiting in drwait() */
746: rsaddr->dr_pulse = (RPER|RDMA|RATN); /* reset dma e-o-r flag */
747: }
748: /*
749: * Now test for attention interrupt -- It may be set in addition to
750: * the dma e-o-r interrupt. If we get one we will issue a wakeup to
751: * the drioctl() routine which is presumable waiting for one.
752: * The program may have to monitor the attention interrupt received
753: * flag in addition to doing waits for the interrupt. Futhermore,
754: * interrupts are not enabled unless dma is in progress or drioctl()
755: * has been called to wait for attention -- this may produce some
756: * strange results if attf is set on the dr11 when a read or a write
757: * is initiated, since that will enables interrupts.
758: * **** The appropriate code for this interrupt routine will probably
759: * be rather application dependent.
760: */
761: if (status & ATTF) {
762: dra->dr_flags |= DR_ATRX;
763: dra->dr_flags &= ~DR_ATWT;
764: rsaddr->dr_cstat = RATN; /* reset attention flag */
765: /*
766: * Some applications which use attention to terminate
767: * dma may also want to issue an iodone() here to
768: * wakeup physio().
769: */
770: wakeup((caddr_t)&dra->dr_cmd);
771: }
772: }
773:
774: unsigned
775: drminphys(bp)
776: struct buf *bp;
777: {
778:
779: if (bp->b_bcount > 65536)
780: bp->b_bcount = 65536;
781: }
782:
783: /*
784: * This routine performs the device unique operations on the DR11W
785: * it is passed as an argument to and invoked by physio
786: */
787: drstrategy (bp)
788: register struct buf *bp;
789: {
790: register int s;
791: int unit = RSUNIT(bp->b_dev);
792: register struct rsdevice *rsaddr = RSADDR(unit);
793: register struct dr_aux *dra = &dr_aux[unit];
794: register int ok;
795: #ifdef DR_DEBUG
796: register char *caddr;
797: long drva();
798: #endif
799:
800: if ((dra->dr_flags & DR_OPEN) == 0) { /* Device not open */
801: bp->b_error = ENXIO;
802: bp->b_flags |= B_ERROR;
803: iodone (bp);
804: return;
805: }
806: while (dra->dr_flags & DR_ACTV)
807: /* Device is active; should never be in here... */
808: (void) tsleep((caddr_t)&dra->dr_flags, DRPRI, devio, 0);
809: dra->dr_actf = bp;
810: #ifdef DR_DEBUG
811: drva(dra, bp->b_proc, bp->b_un.b_addr, bp->b_bcount);
812: #endif
813: dra->dr_oba = bp->b_un.b_addr; /* Save original addr, count */
814: dra->dr_obc = bp->b_bcount;
815: dra->dr_bycnt = bp->b_bcount; /* Save xfer count used by drintr() */
816: if ((((long)bp->b_un.b_addr & 0x3fffffff) >> PGSHIFT) !=
817: ((((long)bp->b_un.b_addr & 0x3fffffff) + bp->b_bcount) >> PGSHIFT))
818: bp->b_bcount = NBPG - (((long)bp->b_un.b_addr) & PGOFSET);
819: dra->dr_flags |= DR_ACTV; /* Mark active (use in intr handler) */
820: s = SPL_UP();
821: drstart(rsaddr,dra,bp);
822: splx(s);
823: ok = drwait(rsaddr,dra);
824: #ifdef DR_DEBUG
825: if (DR11 & 0x40) {
826: caddr = (char *)dra->dr_oba;
827: if (dra->dr_op == DR_READ)
828: printf("\nAfter read: (%lx)(%lx)",
829: caddr[0]&0xff, caddr[1]&0xff);
830: }
831: #endif
832: dra->dr_flags &= ~DR_ACTV; /* Clear active flag */
833: bp->b_un.b_addr = dra->dr_oba; /* Restore original addr, count */
834: bp->b_bcount = dra->dr_obc;
835: if (!ok)
836: bp->b_flags |= B_ERROR;
837: /* Mark buffer B_DONE,so physstrat() in ml/machdep.c won't sleep */
838: iodone(bp);
839: wakeup((caddr_t)&dra->dr_flags);
840: /*
841: * Return to the calling program (physio()). Physio() will sleep
842: * until awaken by a call to iodone() in the interupt handler --
843: * which will be called by the dispatcher when it receives dma
844: * end-of-range interrupt.
845: */
846: }
847:
848: drwait(rs, dr)
849: register struct rsdevice *rs;
850: register struct dr_aux *dr;
851: {
852: int s;
853:
854: s = SPL_UP();
855: while (dr->dr_flags & DR_ACTV)
856: (void) tsleep((caddr_t)dr, DRPRI, devio, 0);
857: splx(s);
858: if (dr->dr_flags & DR_TMDM) { /* DMA timed out */
859: dr->dr_flags &= ~DR_TMDM;
860: return (0);
861: }
862: if (rs->dr_cstat & (PERR|BERR|TERR)) {
863: dr->dr_actf->b_flags |= B_ERROR;
864: return (0);
865: }
866: dr->dr_flags &= ~DR_DMAX;
867: return (1);
868: }
869:
870: /*
871: *
872: * The lower 8-bit of tinfo is the minor device number, the
873: * remaining higher 8-bit is the current timout number
874: */
875: drrwtimo(tinfo)
876: register u_long tinfo;
877: {
878: register long unit = tinfo & 0xff;
879: register struct dr_aux *dr = &dr_aux[unit];
880: register struct rsdevice *rs = dr->dr_addr;
881:
882: /*
883: * If this is not the timeout that drwrite/drread is waiting
884: * for then we should just go away
885: */
886: if ((tinfo &~ 0xff) != (dr->currenttimo << 8))
887: return;
888: /* Mark the device timed out */
889: dr->dr_flags |= DR_TMDM;
890: dr->dr_flags &= ~DR_ACTV;
891: rs->dr_pulse = RMSK; /* Inihibit interrupt */
892: rs->dr_pulse = (RPER|RDMA|RATN|IENB); /* Clear DMA logic */
893: /*
894: * Some applications will not issue a master after dma timeout,
895: * since doing so sends an INIT H pulse to the external device,
896: * which may produce undesirable side-effects.
897: */
898: /* Wake up process waiting in drwait() and flag the error */
899: dr->dr_actf->b_flags |= B_ERROR;
900: wakeup((caddr_t)dr->dr_cmd);
901: }
902:
903: /*
904: * Kick the driver every second
905: */
906: drtimo(dev)
907: dev_t dev;
908: {
909: register int unit = RSUNIT(dev);
910: register struct dr_aux *dr;
911:
912: dr = &dr_aux[unit];
913: if (dr->dr_flags & DR_OPEN)
914: timeout(drtimo, (caddr_t)dev, hz);
915: wakeup((caddr_t)dr); /* Wakeup any process waiting for interrupt */
916: }
917:
918: #ifdef DR_DEBUG
919: drva(dra, p, va, bcnt)
920: struct dr_aux *dra;
921: struct proc *p;
922: char *va;
923: long bcnt;
924: {
925: register long first, last , np;
926:
927: if (DR11 & 0x20) {
928: first = ((long)(vtoph(p, (unsigned)va))) >> 10;
929: last = ((long)(vtoph(p, (unsigned)va+bcnt))) >> 10;
930: np = bcnt / 0x3ff;
931: printf("\ndrva: (op:%ld)(first:%ld)(last:%ld)(np:%ld)(cnt:%ld)",
932: dra->dr_op,first,last,np,bcnt);
933: }
934: }
935: #endif
936:
937: drstart(rsaddr, dra, bp)
938: register struct rsdevice *rsaddr;
939: register struct dr_aux *dra;
940: register struct buf *bp;
941: {
942: register long addr;
943: u_short go;
944:
945: #ifdef DR_DEBUG
946: if (dra->dr_op == DR_READ && (DR11 & 8)) {
947: char *caddr = (char *)bp->b_un.b_addr;
948: printf("\ndrstart: READ, bcnt:%ld",bp->b_bcount);
949: printf(",(%lx)(%lx)",caddr[0]&0xff,caddr[1]&0xff);
950: }
951: #endif
952: /* we are doing raw IO, bp->b_un.b_addr is user's address */
953: addr = (long)vtoph(bp->b_proc, (unsigned)bp->b_un.b_addr);
954: /*
955: * Set DMA address into DR11 interace registers: DR11 requires that
956: * the address be right shifted 1 bit position before it is written
957: * to the board (The board will left shift it one bit position before
958: * it places the address on the bus
959: */
960: rsaddr->dr_walo = (addr >> 1) & 0xffff;
961: rsaddr->dr_wahi = (addr >> 17) & 0x7fff;
962: /* Set DMA range count: (number of words - 1) */
963: rsaddr->dr_range = (bp->b_bcount >> 1) - 1;
964: /* Set address modifier code to be used for DMA access to memory */
965: rsaddr->dr_addmod = DRADDMOD;
966: /*
967: * Now determine whether this is a read or a write. ***** This is
968: * probably only usefull for link mode operation, since dr11 doesnot
969: * controll the direction of data transfer. The C1 control input
970: * controls whether the hardware is doing a read or a write. In link
971: * mode this is controlled by function 1 latch (looped back by the
972: * cable) and could be set the program. In the general case, the dr11
973: * doesnot know in advance what the direction of transfer is - although
974: * the program and protocol logic probably is
975: */
976: #ifdef DR_DEBUG
977: if (DR11 & 1)
978: printf(
979: "\ndrstrat: about to GO..,dr_cmd:%lx,drstat:%lx,drcnt:%ld,cdata:%lx,OP:%ld",
980: dra->dr_cmd, rsaddr->dr_cstat, rsaddr->dr_range,
981: rsaddr->dr_data, dra->dr_op);
982: #endif
983: /*
984: * Update function latches may have been done already by drioctl() if
985: * request from drioctl()
986: */
987: if (dra->dr_cmd & DR_DFCN) { /* deferred function write */
988: dra->dr_cmd &= ~DR_DFCN; /* Clear request */
989: go = dra->dr_cmd & DR_FMSK; /* mask out fcn bits */
990: rsaddr->dr_cstat = go; /* Write it to the board */
991: }
992: /* Clear dmaf and attf to assure a clean dma start */
993: rsaddr->dr_pulse = RATN|RDMA|RPER;
994: rsaddr->dr_cstat = IENB|GO|CYCL|dra->dr_op; /* GO...... */
995: /*
996: * Now check for software cycle request -- usually
997: * by transmitter in link mode.
998: */
999: if (dra->dr_cmd & DR_PCYL) {
1000: dra->dr_cmd &= ~DR_PCYL; /* Clear request */
1001: rsaddr->dr_pulse = CYCL; /* Use pulse register again */
1002: }
1003: /*
1004: * Now check for deferred ACLO FCNT2 pulse request -- usually to tell
1005: * the transmitter (via its attention) that we have enabled dma.
1006: */
1007: if (dra->dr_cmd & DR_DACL) {
1008: dra->dr_cmd &= ~DR_DACL; /* Clear request */
1009: rsaddr->dr_pulse = FCN2; /* Use pulse register again */
1010: }
1011: }
1012: #endif NDR
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.