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