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