Annotation of sys/arch/hp300/dev/nhpib.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: nhpib.c,v 1.16 2005/11/13 18:52:15 miod Exp $ */
2: /* $NetBSD: nhpib.c,v 1.17 1997/05/05 21:06:41 thorpej Exp $ */
3:
4: /*
5: * Copyright (c) 1996, 1997 Jason R. Thorpe. All rights reserved.
6: * Copyright (c) 1982, 1990, 1993
7: * The Regents of the University of California. All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. 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: * @(#)nhpib.c 8.2 (Berkeley) 1/12/94
34: */
35:
36: /*
37: * Internal/98624 HPIB driver
38: */
39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/kernel.h>
43: #include <sys/buf.h>
44: #include <sys/device.h>
45: #include <sys/timeout.h>
46:
47: #include <machine/autoconf.h>
48: #include <machine/intr.h>
49:
50: #include <hp300/dev/dioreg.h>
51: #include <hp300/dev/diovar.h>
52: #include <hp300/dev/diodevs.h>
53:
54: #include <hp300/dev/dmavar.h>
55:
56: #include <hp300/dev/nhpibreg.h>
57: #include <hp300/dev/hpibvar.h>
58:
59: /*
60: * ODD parity table for listen and talk addresses and secondary commands.
61: * The TI9914A doesn't produce the parity bit.
62: */
63: static const u_char listnr_par[] = {
64: 0040,0241,0242,0043,0244,0045,0046,0247,
65: 0250,0051,0052,0253,0054,0255,0256,0057,
66: 0260,0061,0062,0263,0064,0265,0266,0067,
67: 0070,0271,0272,0073,0274,0075,0076,0277,
68: };
69: static const u_char talker_par[] = {
70: 0100,0301,0302,0103,0304,0105,0106,0307,
71: 0310,0111,0112,0313,0114,0315,0316,0117,
72: 0320,0121,0122,0323,0124,0325,0326,0127,
73: 0130,0331,0332,0133,0334,0135,0136,0337,
74: };
75: static const u_char sec_par[] = {
76: 0340,0141,0142,0343,0144,0345,0346,0147,
77: 0150,0351,0352,0153,0354,0155,0156,0357,
78: 0160,0361,0362,0163,0364,0165,0166,0367,
79: 0370,0171,0172,0373,0174,0375,0376,0177
80: };
81:
82: void nhpibifc(struct nhpibdevice *);
83: void nhpibreadtimo(void *);
84: int nhpibwait(struct nhpibdevice *, int);
85:
86: void nhpibreset(struct hpibbus_softc *);
87: int nhpibsend(struct hpibbus_softc *, int, int, void *, int);
88: int nhpibrecv(struct hpibbus_softc *, int, int, void *, int);
89: int nhpibppoll(struct hpibbus_softc *);
90: void nhpibppwatch(void *);
91: void nhpibgo(struct hpibbus_softc *, int, int, void *, int, int, int);
92: void nhpibdone(struct hpibbus_softc *);
93: int nhpibintr(void *);
94:
95: /*
96: * Our controller ops structure.
97: */
98: struct hpib_controller nhpib_controller = {
99: nhpibreset,
100: nhpibsend,
101: nhpibrecv,
102: nhpibppoll,
103: nhpibppwatch,
104: nhpibgo,
105: nhpibdone,
106: nhpibintr
107: };
108:
109: struct nhpib_softc {
110: struct device sc_dev; /* generic device glue */
111: struct isr sc_isr;
112: struct nhpibdevice *sc_regs; /* device registers */
113: struct hpibbus_softc *sc_hpibbus; /* XXX */
114: struct timeout sc_read_to; /* nhpibreadtimo timeout */
115: struct timeout sc_watch_to; /* nhpibppwatch timeout */
116: };
117:
118: int nhpibmatch(struct device *, void *, void *);
119: void nhpibattach(struct device *, struct device *, void *);
120:
121: struct cfattach nhpib_ca = {
122: sizeof(struct nhpib_softc), nhpibmatch, nhpibattach
123: };
124:
125: struct cfdriver nhpib_cd = {
126: NULL, "nhpib", DV_DULL
127: };
128:
129: int
130: nhpibmatch(parent, match, aux)
131: struct device *parent;
132: void *match, *aux;
133: {
134: struct dio_attach_args *da = aux;
135:
136: /*
137: * Internal HP-IB doesn't always return a device ID,
138: * so we rely on the sysflags.
139: */
140: if (da->da_scode == 7 && internalhpib)
141: return (1);
142:
143: if (da->da_id == DIO_DEVICE_ID_NHPIB)
144: return (1);
145:
146: return (0);
147: }
148:
149: void
150: nhpibattach(parent, self, aux)
151: struct device *parent, *self;
152: void *aux;
153: {
154: struct nhpib_softc *sc = (struct nhpib_softc *)self;
155: struct dio_attach_args *da = aux;
156: struct hpibdev_attach_args ha;
157: const char *desc;
158: int ipl, type = HPIBA;
159:
160: sc->sc_regs = (struct nhpibdevice *)iomap(dio_scodetopa(da->da_scode),
161: da->da_size);
162: if (sc->sc_regs == NULL) {
163: printf("\n%s: can't map registers\n", self->dv_xname);
164: return;
165: }
166:
167: ipl = DIO_IPL(sc->sc_regs);
168:
169: if (da->da_scode == 7 && internalhpib)
170: desc = DIO_DEVICE_DESC_IHPIB;
171: else if (da->da_id == DIO_DEVICE_ID_NHPIB) {
172: type = HPIBB;
173: desc = DIO_DEVICE_DESC_NHPIB;
174: } else
175: desc = "unknown HP-IB!";
176:
177: printf(" ipl %d: %s\n", ipl, desc);
178:
179: /* Establish the interrupt handler. */
180: sc->sc_isr.isr_func = nhpibintr;
181: sc->sc_isr.isr_arg = sc;
182: sc->sc_isr.isr_ipl = ipl;
183: sc->sc_isr.isr_priority = IPL_BIO;
184: dio_intr_establish(&sc->sc_isr, self->dv_xname);
185:
186: /* Initialize timeout structures */
187: timeout_set(&sc->sc_read_to, nhpibreadtimo, sc);
188:
189: ha.ha_ops = &nhpib_controller;
190: ha.ha_type = type; /* XXX */
191: ha.ha_ba = (type == HPIBA) ? HPIBA_BA :
192: (sc->sc_regs->hpib_csa & CSA_BA);
193: ha.ha_softcpp = &sc->sc_hpibbus; /* XXX */
194: (void)config_found(self, &ha, hpibdevprint);
195: }
196:
197: void
198: nhpibreset(hs)
199: struct hpibbus_softc *hs;
200: {
201: struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
202: struct nhpibdevice *hd = sc->sc_regs;
203:
204: hd->hpib_acr = AUX_SSWRST;
205: hd->hpib_ar = hs->sc_ba;
206: hd->hpib_lim = LIS_ERR;
207: hd->hpib_mim = 0;
208: hd->hpib_acr = AUX_CDAI;
209: hd->hpib_acr = AUX_CSHDW;
210: hd->hpib_acr = AUX_SSTD1;
211: hd->hpib_acr = AUX_SVSTD1;
212: hd->hpib_acr = AUX_CPP;
213: hd->hpib_acr = AUX_CHDFA;
214: hd->hpib_acr = AUX_CHDFE;
215: hd->hpib_acr = AUX_RHDF;
216: hd->hpib_acr = AUX_CSWRST;
217: nhpibifc(hd);
218: hd->hpib_ie = IDS_IE;
219: hd->hpib_data = C_DCL_P;
220: DELAY(100000);
221: }
222:
223: void
224: nhpibifc(hd)
225: struct nhpibdevice *hd;
226: {
227: hd->hpib_acr = AUX_TCA;
228: hd->hpib_acr = AUX_CSRE;
229: hd->hpib_acr = AUX_SSIC;
230: DELAY(100);
231: hd->hpib_acr = AUX_CSIC;
232: hd->hpib_acr = AUX_SSRE;
233: }
234:
235: int
236: nhpibsend(hs, slave, sec, ptr, origcnt)
237: struct hpibbus_softc *hs;
238: int slave, sec, origcnt;
239: void *ptr;
240: {
241: struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
242: struct nhpibdevice *hd = sc->sc_regs;
243: int cnt = origcnt;
244: char *addr = ptr;
245:
246: hd->hpib_acr = AUX_TCA;
247: hd->hpib_data = C_UNL_P;
248: if (nhpibwait(hd, MIS_BO))
249: goto senderror;
250: hd->hpib_data = talker_par[hs->sc_ba];
251: hd->hpib_acr = AUX_STON;
252: if (nhpibwait(hd, MIS_BO))
253: goto senderror;
254: hd->hpib_data = listnr_par[slave];
255: if (nhpibwait(hd, MIS_BO))
256: goto senderror;
257: if (sec >= 0 || sec == -2) {
258: if (sec == -2) /* selected device clear KLUDGE */
259: hd->hpib_data = C_SDC_P;
260: else
261: hd->hpib_data = sec_par[sec];
262: if (nhpibwait(hd, MIS_BO))
263: goto senderror;
264: }
265: hd->hpib_acr = AUX_GTS;
266: if (cnt) {
267: while (--cnt > 0) {
268: hd->hpib_data = *addr++;
269: if (nhpibwait(hd, MIS_BO))
270: goto senderror;
271: }
272: hd->hpib_acr = AUX_EOI;
273: hd->hpib_data = *addr;
274: if (nhpibwait(hd, MIS_BO))
275: goto senderror;
276: hd->hpib_acr = AUX_TCA;
277: #if 0
278: /*
279: * May be causing 345 disks to hang due to interference
280: * with PPOLL mechanism.
281: */
282: hd->hpib_data = C_UNL_P;
283: (void) nhpibwait(hd, MIS_BO);
284: #endif
285: }
286: return(origcnt);
287:
288: senderror:
289: nhpibifc(hd);
290: return(origcnt - cnt - 1);
291: }
292:
293: int
294: nhpibrecv(hs, slave, sec, ptr, origcnt)
295: struct hpibbus_softc *hs;
296: int slave, sec, origcnt;
297: void *ptr;
298: {
299: struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
300: struct nhpibdevice *hd = sc->sc_regs;
301: int cnt = origcnt;
302: char *addr = ptr;
303:
304: /*
305: * Slave < 0 implies continuation of a previous receive
306: * that probably timed out.
307: */
308: if (slave >= 0) {
309: hd->hpib_acr = AUX_TCA;
310: hd->hpib_data = C_UNL_P;
311: if (nhpibwait(hd, MIS_BO))
312: goto recverror;
313: hd->hpib_data = listnr_par[hs->sc_ba];
314: hd->hpib_acr = AUX_SLON;
315: if (nhpibwait(hd, MIS_BO))
316: goto recverror;
317: hd->hpib_data = talker_par[slave];
318: if (nhpibwait(hd, MIS_BO))
319: goto recverror;
320: if (sec >= 0) {
321: hd->hpib_data = sec_par[sec];
322: if (nhpibwait(hd, MIS_BO))
323: goto recverror;
324: }
325: hd->hpib_acr = AUX_RHDF;
326: hd->hpib_acr = AUX_GTS;
327: }
328: if (cnt) {
329: while (--cnt >= 0) {
330: if (nhpibwait(hd, MIS_BI))
331: goto recvbyteserror;
332: *addr++ = hd->hpib_data;
333: }
334: hd->hpib_acr = AUX_TCA;
335: hd->hpib_data = (slave == 31) ? C_UNA_P : C_UNT_P;
336: (void) nhpibwait(hd, MIS_BO);
337: }
338: return(origcnt);
339:
340: recverror:
341: nhpibifc(hd);
342: recvbyteserror:
343: return(origcnt - cnt - 1);
344: }
345:
346: void
347: nhpibgo(hs, slave, sec, ptr, count, rw, timo)
348: struct hpibbus_softc *hs;
349: int slave, sec, count, rw, timo;
350: void *ptr;
351: {
352: struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
353: struct nhpibdevice *hd = sc->sc_regs;
354: char *addr = ptr;
355:
356: hs->sc_flags |= HPIBF_IO;
357: if (timo)
358: hs->sc_flags |= HPIBF_TIMO;
359: if (rw == B_READ)
360: hs->sc_flags |= HPIBF_READ;
361: #ifdef DEBUG
362: else if (hs->sc_flags & HPIBF_READ) {
363: printf("nhpibgo: HPIBF_READ still set\n");
364: hs->sc_flags &= ~HPIBF_READ;
365: }
366: #endif
367: hs->sc_count = count;
368: hs->sc_addr = addr;
369: if (hs->sc_flags & HPIBF_READ) {
370: hs->sc_curcnt = count;
371: dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE|DMAGO_READ);
372: nhpibrecv(hs, slave, sec, 0, 0);
373: hd->hpib_mim = MIS_END;
374: } else {
375: hd->hpib_mim = 0;
376: if (count < hpibdmathresh) {
377: hs->sc_curcnt = count;
378: nhpibsend(hs, slave, sec, addr, count);
379: nhpibdone(hs);
380: return;
381: }
382: hs->sc_curcnt = --count;
383: dmago(hs->sc_dq->dq_chan, addr, count, DMAGO_BYTE);
384: nhpibsend(hs, slave, sec, 0, 0);
385: }
386: hd->hpib_ie = IDS_IE | IDS_DMA(hs->sc_dq->dq_chan);
387: }
388:
389: /*
390: * This timeout can only happen if a DMA read finishes DMAing with the read
391: * still pending (more data in read transaction than the driver was prepared
392: * to accept). At the moment, variable-record tape drives are the only things
393: * capabale of doing this. We repeat the necessary code from nhpibintr() -
394: * easier and quicker than calling nhpibintr() for this special case.
395: */
396: void
397: nhpibreadtimo(arg)
398: void *arg;
399: {
400: struct nhpib_softc *sc = arg;
401: struct hpibbus_softc *hs = sc->sc_hpibbus;
402: int s;
403:
404: s = splbio();
405: if (hs->sc_flags & HPIBF_IO) {
406: struct nhpibdevice *hd = sc->sc_regs;
407: struct hpibqueue *hq;
408:
409: hd->hpib_mim = 0;
410: hd->hpib_acr = AUX_TCA;
411: hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
412: dmafree(hs->sc_dq);
413:
414: hq = TAILQ_FIRST(&hs->sc_queue);
415: (hq->hq_intr)(hq->hq_softc);
416: }
417: splx(s);
418: }
419:
420: void
421: nhpibdone(hs)
422: struct hpibbus_softc *hs;
423: {
424: struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
425: struct nhpibdevice *hd = sc->sc_regs;
426: int cnt;
427:
428: cnt = hs->sc_curcnt;
429: hs->sc_addr += cnt;
430: hs->sc_count -= cnt;
431: hs->sc_flags |= HPIBF_DONE;
432: hd->hpib_ie = IDS_IE;
433: if (hs->sc_flags & HPIBF_READ) {
434: if ((hs->sc_flags & HPIBF_TIMO) &&
435: (hd->hpib_ids & IDS_IR) == 0)
436: timeout_add(&sc->sc_read_to, hz >> 2);
437: } else {
438: if (hs->sc_count == 1) {
439: (void) nhpibwait(hd, MIS_BO);
440: hd->hpib_acr = AUX_EOI;
441: hd->hpib_data = *hs->sc_addr;
442: hd->hpib_mim = MIS_BO;
443: }
444: #ifdef DEBUG
445: else if (hs->sc_count)
446: panic("nhpibdone");
447: #endif
448: }
449: }
450:
451: int
452: nhpibintr(arg)
453: void *arg;
454: {
455: struct nhpib_softc *sc = arg;
456: struct hpibbus_softc *hs = sc->sc_hpibbus;
457: struct nhpibdevice *hd = sc->sc_regs;
458: struct hpibqueue *hq;
459: int stat0;
460: int stat1;
461:
462: #ifdef lint
463: if (stat1 = unit) return(1);
464: #endif
465: if ((hd->hpib_ids & IDS_IR) == 0)
466: return(0);
467: stat0 = hd->hpib_mis;
468: stat1 = hd->hpib_lis;
469:
470: hq = TAILQ_FIRST(&hs->sc_queue);
471:
472: if (hs->sc_flags & HPIBF_IO) {
473: hd->hpib_mim = 0;
474: if ((hs->sc_flags & HPIBF_DONE) == 0) {
475: hs->sc_flags &= ~HPIBF_TIMO;
476: dmastop(hs->sc_dq->dq_chan);
477: } else if (hs->sc_flags & HPIBF_TIMO)
478: timeout_del(&sc->sc_read_to);
479: hd->hpib_acr = AUX_TCA;
480: hs->sc_flags &= ~(HPIBF_DONE|HPIBF_IO|HPIBF_READ|HPIBF_TIMO);
481:
482: dmafree(hs->sc_dq);
483: (hq->hq_intr)(hq->hq_softc);
484: } else if (hs->sc_flags & HPIBF_PPOLL) {
485: hd->hpib_mim = 0;
486: stat0 = nhpibppoll(hs);
487: if (stat0 & (0x80 >> hq->hq_slave)) {
488: hs->sc_flags &= ~HPIBF_PPOLL;
489: (hq->hq_intr)(hq->hq_softc);
490: }
491: #ifdef DEBUG
492: else
493: printf("%s: PPOLL intr bad status %x\n",
494: hs->sc_dev.dv_xname, stat0);
495: #endif
496: }
497: return(1);
498: }
499:
500: int
501: nhpibppoll(hs)
502: struct hpibbus_softc *hs;
503: {
504: struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
505: struct nhpibdevice *hd = sc->sc_regs;
506: int ppoll;
507:
508: hd->hpib_acr = AUX_SPP;
509: DELAY(25);
510: ppoll = hd->hpib_cpt;
511: hd->hpib_acr = AUX_CPP;
512: return(ppoll);
513: }
514:
515: #ifdef DEBUG
516: int nhpibreporttimo = 0;
517: #endif
518:
519: int
520: nhpibwait(hd, x)
521: struct nhpibdevice *hd;
522: int x;
523: {
524: int timo = hpibtimeout;
525:
526: while ((hd->hpib_mis & x) == 0 && --timo)
527: DELAY(1);
528: if (timo == 0) {
529: #ifdef DEBUG
530: if (nhpibreporttimo)
531: printf("hpib0: %s timo\n", x==MIS_BO?"OUT":"IN");
532: #endif
533: return(-1);
534: }
535: return(0);
536: }
537:
538: void
539: nhpibppwatch(arg)
540: void *arg;
541: {
542: struct hpibbus_softc *hs = arg;
543: struct nhpib_softc *sc = (struct nhpib_softc *)hs->sc_dev.dv_parent;
544:
545: if ((hs->sc_flags & HPIBF_PPOLL) == 0)
546: return;
547:
548: again:
549: if (nhpibppoll(hs) & (0x80 >> TAILQ_FIRST(&hs->sc_queue)->hq_slave))
550: sc->sc_regs->hpib_mim = MIS_BO;
551: else if (cold)
552: /* timeouts not working yet */
553: goto again;
554: else {
555: timeout_set(&sc->sc_watch_to, nhpibppwatch, hs);
556: timeout_add(&sc->sc_watch_to, 1);
557: }
558: }
CVSweb