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