xref: /netbsd-src/sys/arch/hp300/dev/fhpib.c (revision ce0bb6e8d2e560ecacbe865a848624f94498063b)
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