fhpib.c revision 1.6 1 /* $NetBSD: fhpib.c,v 1.6 1995/01/07 10:30:10 mycroft Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)fhpib.c 8.2 (Berkeley) 1/12/94
36 */
37
38 /*
39 * 98625A/B HPIB driver
40 */
41 #include "hpib.h"
42 #if NHPIB > 0
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/kernel.h>
47 #include <sys/buf.h>
48
49 #include <hp300/dev/device.h>
50 #include <hp300/dev/fhpibreg.h>
51 #include <hp300/dev/hpibvar.h>
52 #include <hp300/dev/dmavar.h>
53
54 /*
55 * Inline version of fhpibwait to be used in places where
56 * we don't worry about getting hung.
57 */
58 #define FHPIBWAIT(hd, m) while (((hd)->hpib_intr & (m)) == 0) DELAY(1)
59
60 #ifdef DEBUG
61 int fhpibdebugunit = -1;
62 int fhpibdebug = 0;
63 #define FDB_FAIL 0x01
64 #define FDB_DMA 0x02
65 #define FDB_WAIT 0x04
66 #define FDB_PPOLL 0x08
67
68 int dopriodma = 0; /* use high priority DMA */
69 int doworddma = 1; /* non-zero if we should attempt word dma */
70 int doppollint = 1; /* use ppoll interrupts instead of watchdog */
71 int fhpibppolldelay = 50;
72
73 long fhpibbadint[2] = { 0 };
74 long fhpibtransfer[NHPIB] = { 0 };
75 long fhpibnondma[NHPIB] = { 0 };
76 long fhpibworddma[NHPIB] = { 0 };
77 long fhpibppollfail[NHPIB] = { 0 };
78 #endif
79
80 int fhpibcmd[NHPIB];
81
82 fhpibtype(hc)
83 register struct hp_ctlr *hc;
84 {
85 register struct hpib_softc *hs = &hpib_softc[hc->hp_unit];
86 register struct fhpibdevice *hd = (struct fhpibdevice *)hc->hp_addr;
87
88 if (hd->hpib_cid != HPIBC)
89 return(0);
90 hs->sc_type = HPIBC;
91 hs->sc_ba = HPIBC_BA;
92 hc->hp_ipl = HPIB_IPL(hd->hpib_ids);
93 return(1);
94 }
95
96 fhpibreset(unit)
97 int unit;
98 {
99 register struct hpib_softc *hs = &hpib_softc[unit];
100 register struct fhpibdevice *hd;
101
102 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
103 hd->hpib_cid = 0xFF;
104 DELAY(100);
105 hd->hpib_cmd = CT_8BIT;
106 hd->hpib_ar = AR_ARONC;
107 fhpibifc(hd);
108 hd->hpib_ie = IDS_IE;
109 hd->hpib_data = C_DCL;
110 DELAY(100000);
111 /*
112 * See if we can do word dma.
113 * If so, we should be able to write and read back the appropos bit.
114 */
115 hd->hpib_ie |= IDS_WDMA;
116 if (hd->hpib_ie & IDS_WDMA) {
117 hd->hpib_ie &= ~IDS_WDMA;
118 hs->sc_flags |= HPIBF_DMA16;
119 #ifdef DEBUG
120 if (fhpibdebug & FDB_DMA)
121 printf("fhpibtype: unit %d has word dma\n", unit);
122
123 #endif
124 }
125 }
126
127 fhpibifc(hd)
128 register struct fhpibdevice *hd;
129 {
130 hd->hpib_cmd |= CT_IFC;
131 hd->hpib_cmd |= CT_INITFIFO;
132 DELAY(100);
133 hd->hpib_cmd &= ~CT_IFC;
134 hd->hpib_cmd |= CT_REN;
135 hd->hpib_stat = ST_ATN;
136 }
137
138 fhpibsend(unit, slave, sec, addr, origcnt)
139 int unit, slave, sec, origcnt;
140 register char *addr;
141 {
142 register struct hpib_softc *hs = &hpib_softc[unit];
143 register struct fhpibdevice *hd;
144 register int cnt = origcnt;
145 register int timo;
146
147 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
148 hd->hpib_stat = 0;
149 hd->hpib_imask = IM_IDLE | IM_ROOM;
150 if (fhpibwait(hd, IM_IDLE) < 0)
151 goto senderr;
152 hd->hpib_stat = ST_ATN;
153 hd->hpib_data = C_UNL;
154 hd->hpib_data = C_TAG + hs->sc_ba;
155 hd->hpib_data = C_LAG + slave;
156 if (sec < 0) {
157 if (sec == -2) /* selected device clear KLUDGE */
158 hd->hpib_data = C_SDC;
159 } else
160 hd->hpib_data = C_SCG + sec;
161 if (fhpibwait(hd, IM_IDLE) < 0)
162 goto senderr;
163 if (cnt) {
164 hd->hpib_stat = ST_WRITE;
165 while (--cnt) {
166 hd->hpib_data = *addr++;
167 timo = hpibtimeout;
168 while ((hd->hpib_intr & IM_ROOM) == 0) {
169 if (--timo <= 0)
170 goto senderr;
171 DELAY(1);
172 }
173 }
174 hd->hpib_stat = ST_EOI;
175 hd->hpib_data = *addr;
176 FHPIBWAIT(hd, IM_ROOM);
177 hd->hpib_stat = ST_ATN;
178 /* XXX: HP-UX claims bug with CS80 transparent messages */
179 if (sec == 0x12)
180 DELAY(150);
181 hd->hpib_data = C_UNL;
182 (void) fhpibwait(hd, IM_IDLE);
183 }
184 hd->hpib_imask = 0;
185 return (origcnt);
186
187 senderr:
188 hd->hpib_imask = 0;
189 fhpibifc(hd);
190 #ifdef DEBUG
191 if (fhpibdebug & FDB_FAIL) {
192 printf("hpib%d: fhpibsend failed: slave %d, sec %x, ",
193 unit, slave, sec);
194 printf("sent %d of %d bytes\n", origcnt-cnt-1, origcnt);
195 }
196 #endif
197 return (origcnt - cnt - 1);
198 }
199
200 fhpibrecv(unit, slave, sec, addr, origcnt)
201 int unit, slave, sec, origcnt;
202 register char *addr;
203 {
204 register struct hpib_softc *hs = &hpib_softc[unit];
205 register struct fhpibdevice *hd;
206 register int cnt = origcnt;
207 register int timo;
208
209 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
210 /*
211 * Slave < 0 implies continuation of a previous receive
212 * that probably timed out.
213 */
214 if (slave >= 0) {
215 hd->hpib_stat = 0;
216 hd->hpib_imask = IM_IDLE | IM_ROOM | IM_BYTE;
217 if (fhpibwait(hd, IM_IDLE) < 0)
218 goto recverror;
219 hd->hpib_stat = ST_ATN;
220 hd->hpib_data = C_UNL;
221 hd->hpib_data = C_LAG + hs->sc_ba;
222 hd->hpib_data = C_TAG + slave;
223 if (sec != -1)
224 hd->hpib_data = C_SCG + sec;
225 if (fhpibwait(hd, IM_IDLE) < 0)
226 goto recverror;
227 hd->hpib_stat = ST_READ0;
228 hd->hpib_data = 0;
229 }
230 if (cnt) {
231 while (--cnt >= 0) {
232 timo = hpibtimeout;
233 while ((hd->hpib_intr & IM_BYTE) == 0) {
234 if (--timo == 0)
235 goto recvbyteserror;
236 DELAY(1);
237 }
238 *addr++ = hd->hpib_data;
239 }
240 FHPIBWAIT(hd, IM_ROOM);
241 hd->hpib_stat = ST_ATN;
242 hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
243 (void) fhpibwait(hd, IM_IDLE);
244 }
245 hd->hpib_imask = 0;
246 return (origcnt);
247
248 recverror:
249 fhpibifc(hd);
250 recvbyteserror:
251 hd->hpib_imask = 0;
252 #ifdef DEBUG
253 if (fhpibdebug & FDB_FAIL) {
254 printf("hpib%d: fhpibrecv failed: slave %d, sec %x, ",
255 unit, slave, sec);
256 printf("got %d of %d bytes\n", origcnt-cnt-1, origcnt);
257 }
258 #endif
259 return (origcnt - cnt - 1);
260 }
261
262 fhpibgo(unit, slave, sec, addr, count, rw, timo)
263 register int unit;
264 int slave, sec, count, rw;
265 char *addr;
266 {
267 register struct hpib_softc *hs = &hpib_softc[unit];
268 register struct fhpibdevice *hd;
269 register int i;
270 int flags = 0;
271
272 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
273 hs->sc_flags |= HPIBF_IO;
274 if (timo)
275 hs->sc_flags |= HPIBF_TIMO;
276 if (rw == B_READ)
277 hs->sc_flags |= HPIBF_READ;
278 #ifdef DEBUG
279 else if (hs->sc_flags & HPIBF_READ) {
280 printf("fhpibgo: HPIBF_READ still set\n");
281 hs->sc_flags &= ~HPIBF_READ;
282 }
283 #endif
284 hs->sc_count = count;
285 hs->sc_addr = addr;
286 #ifdef DEBUG
287 fhpibtransfer[unit]++;
288 #endif
289 if ((hs->sc_flags & HPIBF_DMA16) &&
290 ((int)addr & 1) == 0 && count && (count & 1) == 0
291 #ifdef DEBUG
292 && doworddma
293 #endif
294 ) {
295 #ifdef DEBUG
296 fhpibworddma[unit]++;
297 #endif
298 flags |= DMAGO_WORD;
299 hd->hpib_latch = 0;
300 }
301 #ifdef DEBUG
302 if (dopriodma)
303 flags |= DMAGO_PRI;
304 #endif
305 if (hs->sc_flags & HPIBF_READ) {
306 fhpibcmd[unit] = CT_REN | CT_8BIT;
307 hs->sc_curcnt = count;
308 dmago(hs->sc_dq.dq_ctlr, addr, count, flags|DMAGO_READ);
309 if (fhpibrecv(unit, slave, sec, 0, 0) < 0) {
310 #ifdef DEBUG
311 printf("fhpibgo: recv failed, retrying...\n");
312 #endif
313 (void) fhpibrecv(unit, slave, sec, 0, 0);
314 }
315 i = hd->hpib_cmd;
316 hd->hpib_cmd = fhpibcmd[unit];
317 hd->hpib_ie = IDS_DMA(hs->sc_dq.dq_ctlr) |
318 ((flags & DMAGO_WORD) ? IDS_WDMA : 0);
319 return;
320 }
321 fhpibcmd[unit] = CT_REN | CT_8BIT | CT_FIFOSEL;
322 if (count < hpibdmathresh) {
323 #ifdef DEBUG
324 fhpibnondma[unit]++;
325 if (flags & DMAGO_WORD)
326 fhpibworddma[unit]--;
327 #endif
328 hs->sc_curcnt = count;
329 (void) fhpibsend(unit, slave, sec, addr, count);
330 fhpibdone(unit);
331 return;
332 }
333 count -= (flags & DMAGO_WORD) ? 2 : 1;
334 hs->sc_curcnt = count;
335 dmago(hs->sc_dq.dq_ctlr, addr, count, flags);
336 if (fhpibsend(unit, slave, sec, 0, 0) < 0) {
337 #ifdef DEBUG
338 printf("fhpibgo: send failed, retrying...\n");
339 #endif
340 (void) fhpibsend(unit, slave, sec, 0, 0);
341 }
342 i = hd->hpib_cmd;
343 hd->hpib_cmd = fhpibcmd[unit];
344 hd->hpib_ie = IDS_DMA(hs->sc_dq.dq_ctlr) | IDS_WRITE |
345 ((flags & DMAGO_WORD) ? IDS_WDMA : 0);
346 }
347
348 /*
349 * A DMA read can finish but the device can still be waiting (MAG-tape
350 * with more data than we're waiting for). This timeout routine
351 * takes care of that. Somehow, the thing gets hosed. For now, since
352 * this should be a very rare occurence, we RESET it.
353 */
354 void
355 fhpibdmadone(arg)
356 void *arg;
357 {
358 register int unit;
359 register struct hpib_softc *hs;
360 int s = splbio();
361
362 unit = (int)arg;
363 hs = &hpib_softc[unit];
364 if (hs->sc_flags & HPIBF_IO) {
365 register struct fhpibdevice *hd;
366 register struct devqueue *dq;
367
368 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
369 hd->hpib_imask = 0;
370 hd->hpib_cid = 0xFF;
371 DELAY(100);
372 hd->hpib_cmd = CT_8BIT;
373 hd->hpib_ar = AR_ARONC;
374 fhpibifc(hd);
375 hd->hpib_ie = IDS_IE;
376 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
377 dmafree(&hs->sc_dq);
378 dq = hs->sc_sq.dq_forw;
379 (dq->dq_driver->d_intr)(dq->dq_unit);
380 }
381 (void) splx(s);
382 }
383
384 fhpibdone(unit)
385 int unit;
386 {
387 register struct hpib_softc *hs = &hpib_softc[unit];
388 register struct fhpibdevice *hd;
389 register char *addr;
390 register int cnt;
391
392 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
393 cnt = hs->sc_curcnt;
394 hs->sc_addr += cnt;
395 hs->sc_count -= cnt;
396 #ifdef DEBUG
397 if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit)
398 printf("fhpibdone: addr %x cnt %d\n",
399 hs->sc_addr, hs->sc_count);
400 #endif
401 if (hs->sc_flags & HPIBF_READ) {
402 hd->hpib_imask = IM_IDLE | IM_BYTE;
403 if (hs->sc_flags & HPIBF_TIMO)
404 timeout(fhpibdmadone, (void *)unit, hz >> 2);
405 } else {
406 cnt = hs->sc_count;
407 if (cnt) {
408 addr = hs->sc_addr;
409 hd->hpib_imask = IM_IDLE | IM_ROOM;
410 FHPIBWAIT(hd, IM_IDLE);
411 hd->hpib_stat = ST_WRITE;
412 while (--cnt) {
413 hd->hpib_data = *addr++;
414 FHPIBWAIT(hd, IM_ROOM);
415 }
416 hd->hpib_stat = ST_EOI;
417 hd->hpib_data = *addr;
418 }
419 hd->hpib_imask = IM_IDLE;
420 }
421 hs->sc_flags |= HPIBF_DONE;
422 hd->hpib_stat = ST_IENAB;
423 hd->hpib_ie = IDS_IE;
424 }
425
426 fhpibintr(unit)
427 register int unit;
428 {
429 register struct hpib_softc *hs = &hpib_softc[unit];
430 register struct fhpibdevice *hd;
431 register struct devqueue *dq;
432 register int stat0;
433
434 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
435 stat0 = hd->hpib_ids;
436 if ((stat0 & (IDS_IE|IDS_IR)) != (IDS_IE|IDS_IR)) {
437 #ifdef DEBUG
438 if ((fhpibdebug & FDB_FAIL) && (stat0 & IDS_IR) &&
439 (hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) != HPIBF_IO)
440 printf("hpib%d: fhpibintr: bad status %x\n",
441 unit, stat0);
442 fhpibbadint[0]++;
443 #endif
444 return(0);
445 }
446 if ((hs->sc_flags & (HPIBF_IO|HPIBF_DONE)) == HPIBF_IO) {
447 #ifdef DEBUG
448 fhpibbadint[1]++;
449 #endif
450 return(0);
451 }
452 #ifdef DEBUG
453 if ((fhpibdebug & FDB_DMA) && fhpibdebugunit == unit)
454 printf("fhpibintr: flags %x\n", hs->sc_flags);
455 #endif
456 dq = hs->sc_sq.dq_forw;
457 if (hs->sc_flags & HPIBF_IO) {
458 if (hs->sc_flags & HPIBF_TIMO)
459 untimeout(fhpibdmadone, (void *)unit);
460 stat0 = hd->hpib_cmd;
461 hd->hpib_cmd = fhpibcmd[unit] & ~CT_8BIT;
462 hd->hpib_stat = 0;
463 hd->hpib_cmd = CT_REN | CT_8BIT;
464 stat0 = hd->hpib_intr;
465 hd->hpib_imask = 0;
466 hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
467 dmafree(&hs->sc_dq);
468 (dq->dq_driver->d_intr)(dq->dq_unit);
469 } else if (hs->sc_flags & HPIBF_PPOLL) {
470 stat0 = hd->hpib_intr;
471 #ifdef DEBUG
472 if ((fhpibdebug & FDB_FAIL) &&
473 doppollint && (stat0 & IM_PPRESP) == 0)
474 printf("hpib%d: fhpibintr: bad intr reg %x\n",
475 unit, stat0);
476 #endif
477 hd->hpib_stat = 0;
478 hd->hpib_imask = 0;
479 #ifdef DEBUG
480 stat0 = fhpibppoll(unit);
481 if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit)
482 printf("fhpibintr: got PPOLL status %x\n", stat0);
483 if ((stat0 & (0x80 >> dq->dq_slave)) == 0) {
484 /*
485 * XXX give it another shot (68040)
486 */
487 fhpibppollfail[unit]++;
488 DELAY(fhpibppolldelay);
489 stat0 = fhpibppoll(unit);
490 if ((stat0 & (0x80 >> dq->dq_slave)) == 0 &&
491 (fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit)
492 printf("fhpibintr: PPOLL: unit %d slave %d stat %x\n",
493 unit, dq->dq_slave, stat0);
494 }
495 #endif
496 hs->sc_flags &= ~HPIBF_PPOLL;
497 (dq->dq_driver->d_intr)(dq->dq_unit);
498 }
499 return(1);
500 }
501
502 fhpibppoll(unit)
503 int unit;
504 {
505 register struct fhpibdevice *hd;
506 register int ppoll;
507
508 hd = (struct fhpibdevice *)hpib_softc[unit].sc_hc->hp_addr;
509 hd->hpib_stat = 0;
510 hd->hpib_psense = 0;
511 hd->hpib_pmask = 0xFF;
512 hd->hpib_imask = IM_PPRESP | IM_PABORT;
513 DELAY(25);
514 hd->hpib_intr = IM_PABORT;
515 ppoll = hd->hpib_data;
516 if (hd->hpib_intr & IM_PABORT)
517 ppoll = 0;
518 hd->hpib_imask = 0;
519 hd->hpib_pmask = 0;
520 hd->hpib_stat = ST_IENAB;
521 return(ppoll);
522 }
523
524 fhpibwait(hd, x)
525 register struct fhpibdevice *hd;
526 int x;
527 {
528 register int timo = hpibtimeout;
529
530 while ((hd->hpib_intr & x) == 0 && --timo)
531 DELAY(1);
532 if (timo == 0) {
533 #ifdef DEBUG
534 if (fhpibdebug & FDB_FAIL)
535 printf("fhpibwait(%x, %x) timeout\n", hd, x);
536 #endif
537 return(-1);
538 }
539 return(0);
540 }
541
542 /*
543 * XXX: this will have to change if we ever allow more than one
544 * pending operation per HP-IB.
545 */
546 void
547 fhpibppwatch(arg)
548 void *arg;
549 {
550 register int unit;
551 register struct hpib_softc *hs;
552 register struct fhpibdevice *hd;
553 register int slave;
554
555 unit = (int)arg;
556 hs = &hpib_softc[unit];
557 if ((hs->sc_flags & HPIBF_PPOLL) == 0)
558 return;
559 hd = (struct fhpibdevice *)hs->sc_hc->hp_addr;
560 slave = (0x80 >> hs->sc_sq.dq_forw->dq_slave);
561 #ifdef DEBUG
562 if (!doppollint) {
563 if (fhpibppoll(unit) & slave) {
564 hd->hpib_stat = ST_IENAB;
565 hd->hpib_imask = IM_IDLE | IM_ROOM;
566 } else
567 timeout(fhpibppwatch, (void *)unit, 1);
568 return;
569 }
570 if ((fhpibdebug & FDB_PPOLL) && unit == fhpibdebugunit)
571 printf("fhpibppwatch: sense request on %d\n", unit);
572 #endif
573 hd->hpib_psense = ~slave;
574 hd->hpib_pmask = slave;
575 hd->hpib_stat = ST_IENAB;
576 hd->hpib_imask = IM_PPRESP | IM_PABORT;
577 hd->hpib_ie = IDS_IE;
578 }
579 #endif
580