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
fhpibtype(hc)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
fhpibreset(unit)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
fhpibifc(hd)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
fhpibsend(unit,slave,sec,addr,origcnt)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
fhpibrecv(unit,slave,sec,addr,origcnt)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
fhpibgo(unit,slave,sec,addr,count,rw)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
fhpibdone(unit)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
fhpibintr(unit)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
fhpibppoll(unit)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
fhpibwait(hd,x)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
fhpibppwatch(arg)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