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