Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / sys / hp300 / dev / fhpib.c
CommitLineData
60f56dfc
KM
1/*
2 * Copyright (c) 1982, 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
af359dea
C
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.
60f56dfc 20 *
af359dea
C
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
60f56dfc
KM
34 */
35
36/*
37 * 98625A/B HPIB driver
38 */
39#include "hpib.h"
40#if NHPIB > 0
41
b28b3a13
KB
42#include "sys/param.h"
43#include "sys/systm.h"
44#include "sys/buf.h"
60f56dfc
KM
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 */
da1e0abb 54#define FHPIBWAIT(hd, m) while (((hd)->hpib_intr & (m)) == 0) DELAY(1)
60f56dfc
KM
55
56#ifdef DEBUG
57int fhpibdebugunit = -1;
58int fhpibdebug = 0;
59#define FDB_FAIL 0x01
60#define FDB_DMA 0x02
61#define FDB_WAIT 0x04
62#define FDB_PPOLL 0x08
63
64int dopriodma = 0; /* use high priority DMA */
65int doworddma = 1; /* non-zero if we should attempt word dma */
60f56dfc
KM
66int doppollint = 1; /* use ppoll interrupts instead of watchdog */
67
68long fhpibbadint[2] = { 0 };
69long fhpibtransfer[NHPIB] = { 0 };
70long fhpibnondma[NHPIB] = { 0 };
71long fhpibworddma[NHPIB] = { 0 };
60f56dfc
KM
72#endif
73
74int fhpibcmd[NHPIB];
60f56dfc
KM
75
76fhpibtype(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
90fhpibreset(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
120fhpibifc(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
da1e0abb 131fhpibsend(unit, slave, sec, addr, origcnt)
60f56dfc 132 register char *addr;
60f56dfc
KM
133{
134 register struct hpib_softc *hs = &hpib_softc[unit];
135 register struct fhpibdevice *hd;
da1e0abb 136 register int cnt = origcnt;
60f56dfc 137 register int timo;
60f56dfc
KM
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)
da1e0abb 143 goto senderr;
60f56dfc
KM
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)
da1e0abb
KM
151 goto senderr;
152 if (cnt) {
153 hd->hpib_stat = ST_WRITE;
60f56dfc
KM
154 while (--cnt) {
155 hd->hpib_data = *addr++;
156 timo = hpibtimeout;
da1e0abb
KM
157 while ((hd->hpib_intr & IM_ROOM) == 0) {
158 if (--timo <= 0)
159 goto senderr;
160 DELAY(1);
161 }
60f56dfc
KM
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;
da1e0abb 171 (void) fhpibwait(hd, IM_IDLE);
60f56dfc 172 }
da1e0abb
KM
173 hd->hpib_imask = 0;
174 return (origcnt);
175senderr:
176 hd->hpib_imask = 0;
177 fhpibifc(hd);
60f56dfc 178#ifdef DEBUG
da1e0abb
KM
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);
60f56dfc 183 }
da1e0abb
KM
184#endif
185 return(origcnt - cnt - 1);
60f56dfc
KM
186}
187
da1e0abb 188fhpibrecv(unit, slave, sec, addr, origcnt)
60f56dfc 189 register char *addr;
60f56dfc
KM
190{
191 register struct hpib_softc *hs = &hpib_softc[unit];
192 register struct fhpibdevice *hd;
da1e0abb 193 register int cnt = origcnt;
60f56dfc 194 register int timo;
60f56dfc
KM
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)
da1e0abb 200 goto recverror;
60f56dfc
KM
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)
da1e0abb 208 goto recverror;
60f56dfc
KM
209 hd->hpib_stat = ST_READ0;
210 hd->hpib_data = 0;
da1e0abb
KM
211 if (cnt) {
212 while (--cnt >= 0) {
60f56dfc 213 timo = hpibtimeout;
da1e0abb
KM
214 while ((hd->hpib_intr & IM_BYTE) == 0) {
215 if (--timo == 0)
216 goto recvbyteserror;
217 DELAY(1);
218 }
60f56dfc 219 *addr++ = hd->hpib_data;
da1e0abb 220 }
60f56dfc
KM
221 FHPIBWAIT(hd, IM_ROOM);
222 hd->hpib_stat = ST_ATN;
223 hd->hpib_data = (slave == 31) ? C_UNA : C_UNT;
da1e0abb 224 (void) fhpibwait(hd, IM_IDLE);
60f56dfc 225 }
da1e0abb
KM
226 hd->hpib_imask = 0;
227 return (origcnt);
228
229recverror:
230 fhpibifc(hd);
231recvbyteserror:
232 hd->hpib_imask = 0;
60f56dfc 233#ifdef DEBUG
da1e0abb
KM
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);
60f56dfc 238 }
da1e0abb
KM
239#endif
240 return(origcnt - cnt - 1);
60f56dfc
KM
241}
242
243fhpibgo(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;
da1e0abb 303 if (count < hpibdmathresh) {
60f56dfc
KM
304#ifdef DEBUG
305 fhpibnondma[unit]++;
da1e0abb
KM
306 if (flags & DMAGO_WORD)
307 fhpibworddma[unit]--;
60f56dfc
KM
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
329fhpibdone(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;
60f56dfc 352 FHPIBWAIT(hd, IM_IDLE);
60f56dfc
KM
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
368fhpibintr(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
435fhpibppoll(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
456fhpibwait(hd, x)
457 register struct fhpibdevice *hd;
458{
459 register int timo = hpibtimeout;
460
461 while ((hd->hpib_intr & x) == 0 && --timo)
da1e0abb 462 DELAY(1);
60f56dfc
KM
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 */
477fhpibppwatch(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