Annotation of sys/arch/hp300/dev/dio.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: dio.c,v 1.12 2005/01/15 23:37:45 miod Exp $ */
2: /* $NetBSD: dio.c,v 1.7 1997/05/05 21:00:32 thorpej Exp $ */
3:
4: /*-
5: * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Jason R. Thorpe.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
31: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: /*
41: * Autoconfiguration and mapping support for the DIO bus.
42: */
43:
44: #include <sys/param.h>
45: #include <sys/systm.h>
46: #include <sys/device.h>
47: #include <sys/kernel.h>
48: #include <sys/device.h>
49:
50: #include <machine/autoconf.h>
51: #include <machine/cpu.h>
52: #include <machine/hp300spu.h>
53:
54: #include <hp300/dev/dmavar.h>
55:
56: #include <hp300/dev/dioreg.h>
57: #include <hp300/dev/diovar.h>
58:
59: #include <hp300/dev/diodevs.h>
60: #include <hp300/dev/diodevs_data.h>
61:
62: extern caddr_t internalhpib;
63:
64: int dio_scodesize(struct dio_attach_args *);
65: char *dio_devinfo(struct dio_attach_args *, char *, size_t);
66:
67: int diomatch(struct device *, void *, void *);
68: void dioattach(struct device *, struct device *, void *);
69: int dioprint(void *, const char *);
70: int diosubmatch(struct device *, void *, void *);
71:
72: struct cfattach dio_ca = {
73: sizeof(struct device), diomatch, dioattach
74: };
75:
76: struct cfdriver dio_cd = {
77: NULL, "dio", DV_DULL
78: };
79:
80: int
81: diomatch(parent, match, aux)
82: struct device *parent;
83: void *match, *aux;
84: {
85: static int dio_matched = 0;
86:
87: /* Allow only one instance. */
88: if (dio_matched)
89: return (0);
90:
91: dio_matched = 1;
92: return (1);
93: }
94:
95: void
96: dioattach(parent, self, aux)
97: struct device *parent, *self;
98: void *aux;
99: {
100: struct dio_attach_args da;
101: caddr_t pa, va;
102: int scode, scmax, didmap, scodesize;
103:
104: scmax = DIO_SCMAX(machineid);
105: printf(": ");
106: dmainit();
107:
108: for (scode = 0; scode < scmax; ) {
109: if (DIO_INHOLE(scode)) {
110: scode++;
111: continue;
112: }
113:
114: didmap = 0;
115:
116: /*
117: * Temporarily map the space corresponding to
118: * the current select code unless:
119: * - this is the internal hpib select code,
120: * - this is the console select code.
121: */
122: pa = dio_scodetopa(scode);
123: if (scode == conscode)
124: va = conaddr;
125: else if ((scode == 7) && internalhpib)
126: va = internalhpib = (caddr_t)IIOV(pa);
127: else {
128: va = iomap(pa, NBPG);
129: if (va == NULL) {
130: printf("%s: can't map scode %d\n",
131: self->dv_xname, scode);
132: scode++;
133: continue;
134: }
135: didmap = 1;
136: }
137:
138: /* Check for hardware. */
139: if (badaddr(va)) {
140: if (didmap)
141: iounmap(va, NBPG);
142: scode++;
143: continue;
144: }
145:
146: /* Fill out attach args. */
147: bzero(&da, sizeof(da));
148: da.da_scode = scode;
149: if (scode == 7 && internalhpib)
150: da.da_id = DIO_DEVICE_ID_IHPIB;
151: else {
152: da.da_id = DIO_ID(va);
153: /*
154: * If we probe an unknown device, we do not necessarily
155: * know how many scodes it will span.
156: * Extra scodes will usually report an id of zero,
157: * which would match ihpib!
158: * Check for this, warn the user, and skip that scode.
159: */
160: if (da.da_id == 0) {
161: if (didmap)
162: iounmap(va, NBPG);
163: printf("%s: warning: select code %d is likely "
164: "a span of a previous unsupported device\n",
165: self->dv_xname, scode);
166: scode++;
167: continue;
168: }
169: }
170:
171: if (DIO_ISFRAMEBUFFER(da.da_id))
172: da.da_secid = DIO_SECID(va);
173:
174: da.da_size = DIO_SIZE(scode, va);
175: scodesize = dio_scodesize(&da);
176: if (DIO_ISDIO(scode))
177: da.da_size *= scodesize;
178:
179: /* No longer need the device to be mapped. */
180: if (didmap)
181: iounmap(va, NBPG);
182:
183: /* Attach matching device. */
184: config_found_sm(self, &da, dioprint, diosubmatch);
185: scode += scodesize;
186: }
187: }
188:
189: int
190: diosubmatch(parent, match, aux)
191: struct device *parent;
192: void *match, *aux;
193: {
194: struct cfdata *cf = match;
195: struct dio_attach_args *da = aux;
196:
197: if (cf->diocf_scode != DIO_UNKNOWN_SCODE &&
198: cf->diocf_scode != da->da_scode)
199: return (0);
200:
201: return ((*cf->cf_attach->ca_match)(parent, cf, aux));
202: }
203:
204: int
205: dioprint(aux, pnp)
206: void *aux;
207: const char *pnp;
208: {
209: struct dio_attach_args *da = aux;
210: char buf[128];
211:
212: if (pnp)
213: printf("%s at %s", dio_devinfo(da, buf, sizeof(buf)), pnp);
214: printf(" scode %d", da->da_scode);
215: return (UNCONF);
216: }
217:
218: /*
219: * Convert a select code to a system physical address.
220: */
221: void *
222: dio_scodetopa(scode)
223: int scode;
224: {
225: u_long rval;
226:
227: if (scode == 7 && internalhpib)
228: rval = DIO_IHPIBADDR;
229: else if (DIO_ISDIO(scode))
230: rval = DIO_BASE + (scode * DIO_DEVSIZE);
231: else if (DIO_ISDIOII(scode))
232: rval = DIOII_BASE + ((scode - DIOII_SCBASE) * DIOII_DEVSIZE);
233: else
234: rval = 0;
235:
236: return ((void *)rval);
237: }
238:
239: /*
240: * Return the select code size for this device, defaulting to 1
241: * if we don't know what kind of device we have.
242: */
243: int
244: dio_scodesize(da)
245: struct dio_attach_args *da;
246: {
247: int i;
248:
249: /*
250: * Deal with lame internal HP-IB controllers which don't have
251: * consistent/reliable device ids.
252: */
253: if (da->da_scode == 7 && internalhpib)
254: return (1);
255:
256: /*
257: * Find the dio_devdata matching the primary id.
258: * If we're a framebuffer, we also check the secondary id.
259: */
260: for (i = 0; i < DIO_NDEVICES; i++) {
261: if (da->da_id == dio_devdatas[i].dd_id) {
262: if (DIO_ISFRAMEBUFFER(da->da_id)) {
263: if (da->da_secid == dio_devdatas[i].dd_secid) {
264: goto foundit;
265: }
266: } else {
267: foundit:
268: return (dio_devdatas[i].dd_nscode);
269: }
270: }
271: }
272:
273: /*
274: * Device is unknown. Print a warning and assume a default.
275: */
276: printf("WARNING: select code size unknown for id = 0x%x secid = 0x%x\n",
277: da->da_id, da->da_secid);
278: return (1);
279: }
280:
281: /*
282: * Return a reasonable description of a DIO device.
283: */
284: char *
285: dio_devinfo(da, buf, buflen)
286: struct dio_attach_args *da;
287: char *buf;
288: size_t buflen;
289: {
290: #ifdef DIOVERBOSE
291: int i;
292: #endif
293:
294: bzero(buf, buflen);
295:
296: /*
297: * Deal with lame internal HP-IB controllers which don't have
298: * consistent/reliable device ids.
299: */
300: if (da->da_scode == 7 && internalhpib) {
301: snprintf(buf, buflen, DIO_DEVICE_DESC_IHPIB);
302: return (buf);
303: }
304:
305: #ifdef DIOVERBOSE
306: /*
307: * Find the description matching our primary id.
308: * If we're a framebuffer, we also check the secondary id.
309: */
310: for (i = 0; i < DIO_NDEVICES; i++) {
311: if (da->da_id == dio_devdescs[i].dd_id) {
312: if (DIO_ISFRAMEBUFFER(da->da_id)) {
313: if (da->da_secid == dio_devdescs[i].dd_secid) {
314: goto foundit;
315: }
316: } else {
317: foundit:
318: snprintf(buf, buflen, "%s",
319: dio_devdescs[i].dd_desc);
320: return (buf);
321: }
322: }
323: }
324: #endif /* DIOVERBOSE */
325:
326: /*
327: * Device is unknown. Construct something reasonable.
328: */
329: snprintf(buf, buflen, "device id = 0x%x secid = 0x%x",
330: da->da_id, da->da_secid);
331: return (buf);
332: }
333:
334: /*
335: * Establish an interrupt handler for a DIO device.
336: */
337: void
338: dio_intr_establish(struct isr *isr, const char *name)
339: {
340: intr_establish(isr, name);
341:
342: if (isr->isr_priority == IPL_BIO)
343: dmacomputeipl();
344: }
345:
346: /*
347: * Remove an interrupt handler for a DIO device.
348: */
349: void
350: dio_intr_disestablish(struct isr *isr)
351: {
352: intr_disestablish(isr);
353:
354: if (isr->isr_priority == IPL_BIO)
355: dmacomputeipl();
356: }
CVSweb