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