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