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