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