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