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