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