date and time created 94/01/05 12:54:31 by pendry
[unix-history] / usr / src / sys / hp300 / dev / fhpib.c
CommitLineData
60f56dfc 1/*
030a8056
KB
2 * Copyright (c) 1982, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
60f56dfc
KM
4 *
5 * %sccs.include.redist.c%
6 *
030a8056 7 * @(#)fhpib.c 8.1 (Berkeley) %G%
60f56dfc
KM
8 */
9
10/*
11 * 98625A/B HPIB driver
12 */
13#include "hpib.h"
14#if NHPIB > 0
15
38a01dbe
KB
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>
60f56dfc
KM
25
26/*
27 * Inline version of fhpibwait to be used in places where
28 * we don't worry about getting hung.
29 */
da1e0abb 30#define FHPIBWAIT(hd, m) while (((hd)->hpib_intr & (m)) == 0) DELAY(1)
60f56dfc
KM
31
32#ifdef DEBUG
33int fhpibdebugunit = -1;
34int fhpibdebug = 0;
35#define FDB_FAIL 0x01
36#define FDB_DMA 0x02
37#define FDB_WAIT 0x04
38#define FDB_PPOLL 0x08
39
40int dopriodma = 0; /* use high priority DMA */
41int doworddma = 1; /* non-zero if we should attempt word dma */
60f56dfc 42int doppollint = 1; /* use ppoll interrupts instead of watchdog */
9acfa6cd 43int fhpibppolldelay = 50;
60f56dfc
KM
44
45long fhpibbadint[2] = { 0 };
46long fhpibtransfer[NHPIB] = { 0 };
47long fhpibnondma[NHPIB] = { 0 };
48long fhpibworddma[NHPIB] = { 0 };
9acfa6cd 49long fhpibppollfail[NHPIB] = { 0 };
60f56dfc
KM
50#endif
51
52int fhpibcmd[NHPIB];
60f56dfc
KM
53
54fhpibtype(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
68fhpibreset(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
98fhpibifc(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
da1e0abb 109fhpibsend(unit, slave, sec, addr, origcnt)
60f56dfc 110 register char *addr;
60f56dfc
KM
111{
112 register struct hpib_softc *hs = &hpib_softc[unit];
113 register struct fhpibdevice *hd;
da1e0abb 114 register int cnt = origcnt;
60f56dfc 115 register int timo;
60f56dfc
KM
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)
da1e0abb 121 goto senderr;
60f56dfc
KM
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)
da1e0abb
KM
129 goto senderr;
130 if (cnt) {
131 hd->hpib_stat = ST_WRITE;
60f56dfc
KM
132 while (--cnt) {
133 hd->hpib_data = *addr++;
134 timo = hpibtimeout;
da1e0abb
KM
135 while ((hd->hpib_intr & IM_ROOM) == 0) {
136 if (--timo <= 0)
137 goto senderr;
138 DELAY(1);
139 }
60f56dfc
KM
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;
da1e0abb 149 (void) fhpibwait(hd, IM_IDLE);
60f56dfc 150 }
da1e0abb
KM
151 hd->hpib_imask = 0;
152 return (origcnt);
153senderr:
154 hd->hpib_imask = 0;
155 fhpibifc(hd);
60f56dfc 156#ifdef DEBUG
da1e0abb
KM
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);
60f56dfc 161 }
da1e0abb
KM
162#endif
163 return(origcnt - cnt - 1);
60f56dfc
KM
164}
165
da1e0abb 166fhpibrecv(unit, slave, sec, addr, origcnt)
60f56dfc 167 register char *addr;
60f56dfc
KM
168{
169 register struct hpib_softc *hs = &hpib_softc[unit];
170 register struct fhpibdevice *hd;
da1e0abb 171 register int cnt = origcnt;
60f56dfc 172 register int timo;
60f56dfc
KM
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)
da1e0abb 178 goto recverror;
60f56dfc
KM
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)
da1e0abb 186 goto recverror;
60f56dfc
KM
187 hd->hpib_stat = ST_READ0;
188 hd->hpib_data = 0;
da1e0abb
KM
189 if (cnt) {
190 while (--cnt >= 0) {
60f56dfc 191 timo = hpibtimeout;
da1e0abb
KM
192 while ((hd->hpib_intr & IM_BYTE) == 0) {
193 if (--timo == 0)
194 goto recvbyteserror;
195 DELAY(1);
196 }
60f56dfc 197 *addr++ = hd->hpib_data;
da1e0abb 198 }
60f56dfc
KM
199 FHPIBWAIT(hd, IM_ROOM);
200 hd->hpib_stat = ST_ATN;
201 hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
da1e0abb 202 (void) fhpibwait(hd, IM_IDLE);
60f56dfc 203 }
da1e0abb
KM
204 hd->hpib_imask = 0;
205 return (origcnt);
206
207recverror:
208 fhpibifc(hd);
209recvbyteserror:
210 hd->hpib_imask = 0;
60f56dfc 211#ifdef DEBUG
da1e0abb
KM
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);
60f56dfc 216 }
da1e0abb
KM
217#endif
218 return(origcnt - cnt - 1);
60f56dfc
KM
219}
220
221fhpibgo(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;
da1e0abb 281 if (count < hpibdmathresh) {
60f56dfc
KM
282#ifdef DEBUG
283 fhpibnondma[unit]++;
da1e0abb
KM
284 if (flags & DMAGO_WORD)
285 fhpibworddma[unit]--;
60f56dfc
KM
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
307fhpibdone(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;
60f56dfc 330 FHPIBWAIT(hd, IM_IDLE);
60f56dfc
KM
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
346fhpibintr(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) {
9acfa6cd
MH
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);
60f56dfc
KM
412 }
413#endif
414 hs->sc_flags &= ~HPIBF_PPOLL;
415 (dq->dq_driver->d_intr)(dq->dq_unit);
416 }
417 return(1);
418}
419
420fhpibppoll(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
441fhpibwait(hd, x)
442 register struct fhpibdevice *hd;
443{
444 register int timo = hpibtimeout;
445
446 while ((hd->hpib_intr & x) == 0 && --timo)
da1e0abb 447 DELAY(1);
60f56dfc
KM
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/*
88a0c57a 459 * XXX: this will have to change if we ever allow more than one
60f56dfc
KM
460 * pending operation per HP-IB.
461 */
88a0c57a
CT
462void
463fhpibppwatch(arg)
464 void *arg;
60f56dfc 465{
88a0c57a
CT
466 register int unit;
467 register struct hpib_softc *hs;
60f56dfc
KM
468 register struct fhpibdevice *hd;
469 register int slave;
470
88a0c57a
CT
471 unit = (int)arg;
472 hs = &hpib_softc[unit];
60f56dfc
KM
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
88a0c57a 483 timeout(fhpibppwatch, (void *)unit, 1);
60f56dfc
KM
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