FreeBSD/Linux Kernel Cross Reference
sys/dev/vme/vme.c
1 /* $NetBSD: vme.c,v 1.10 2003/01/01 00:10:27 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1999
5 * Matthias Drochner. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: vme.c,v 1.10 2003/01/01 00:10:27 thorpej Exp $");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 #include <sys/malloc.h>
38 #include <sys/extent.h>
39 #include <machine/bus.h>
40
41 #include <dev/vme/vmereg.h>
42 #include <dev/vme/vmevar.h>
43
44 static void vme_extractlocators __P((int*, struct vme_attach_args*));
45 static int vmeprint __P((struct vme_attach_args*, char*));
46 static int vmesubmatch1 __P((struct device*, struct cfdata*, void*));
47 static int vmesubmatch __P((struct device*, struct cfdata*, void*));
48 int vmematch __P((struct device *, struct cfdata *, void *));
49 void vmeattach __P((struct device*, struct device*,void*));
50 static struct extent *vme_select_map __P((struct vmebus_softc*, vme_am_t));
51
52 #ifdef notyet
53 int vmedetach __P((struct device*));
54 #endif
55
56 #define VME_SLAVE_DUMMYDRV "vme_slv"
57
58 #define VME_NUMCFRANGES 3 /* cf. "files.vme" */
59
60 CFATTACH_DECL(vme, sizeof(struct vmebus_softc),
61 vmematch, vmeattach, NULL, NULL);
62
63 const struct cfattach vme_slv_ca = {
64 0 /* never used */
65 };
66
67 static void
68 vme_extractlocators(loc, aa)
69 int *loc;
70 struct vme_attach_args *aa;
71 {
72 int i = 0;
73
74 /* XXX can't use constants in locators.h this way */
75
76 while (i < VME_NUMCFRANGES && i < VME_MAXCFRANGES &&
77 loc[i] != -1) {
78 aa->r[i].offset = (vme_addr_t)loc[i];
79 aa->r[i].size = (vme_size_t)loc[3 + i];
80 aa->r[i].am = (vme_am_t)loc[6 + i];
81 i++;
82 }
83 aa->numcfranges = i;
84 aa->ilevel = loc[9];
85 aa->ivector = loc[10];
86 }
87
88 static int
89 vmeprint(v, dummy)
90 struct vme_attach_args *v;
91 char *dummy;
92 {
93 int i;
94
95 for (i = 0; i < v->numcfranges; i++) {
96 aprint_normal(" addr %x", v->r[i].offset);
97 if (v->r[i].size != -1)
98 aprint_normal("-%x", v->r[i].offset + v->r[i].size - 1);
99 if (v->r[i].am != -1)
100 aprint_normal(" am %02x", v->r[i].am);
101 }
102 if (v->ilevel != -1) {
103 aprint_normal(" irq %d", v->ilevel);
104 if (v->ivector != -1)
105 aprint_normal(" vector %x", v->ivector);
106 }
107 return (UNCONF);
108 }
109
110 /*
111 * This looks for a (dummy) vme device "VME_SLAVE_DUMMYDRV".
112 * A callback provided by the bus's parent is called for every such
113 * entry in the config database.
114 * This is a special hack allowing to communicate the address settings
115 * of the VME master's slave side to its driver via the normal
116 * configuration mechanism.
117 * Needed in following cases:
118 * -DMA windows are hardware settable but not readable by software
119 * (driver gets offsets for DMA address calculations this way)
120 * -DMA windows are software settable, but not persistent
121 * (hardware is set up from config file entry)
122 * -other adapter VME slave ranges which should be kept track of
123 * for address space accounting
124 * In any case, the adapter driver must get the data before VME
125 * devices are attached.
126 */
127 static int
128 vmesubmatch1(bus, dev, aux)
129 struct device *bus;
130 struct cfdata *dev;
131 void *aux;
132 {
133 struct vmebus_softc *sc = (struct vmebus_softc*)bus;
134 struct vme_attach_args v;
135
136 if (strcmp(dev->cf_name, VME_SLAVE_DUMMYDRV))
137 return (0);
138
139 vme_extractlocators(dev->cf_loc, &v);
140
141 v.va_vct = sc->sc_vct; /* for space allocation */
142
143 (*sc->slaveconfig)(bus->dv_parent, &v);
144 return (0);
145 }
146
147 static int
148 vmesubmatch(bus, dev, aux)
149 struct device *bus;
150 struct cfdata *dev;
151 void *aux;
152 {
153 struct vmebus_softc *sc = (struct vmebus_softc*)bus;
154 struct vme_attach_args v;
155
156 if (!strcmp(dev->cf_name, VME_SLAVE_DUMMYDRV))
157 return (0);
158
159 vme_extractlocators(dev->cf_loc, &v);
160
161 v.va_vct = sc->sc_vct;
162 v.va_bdt = sc->sc_bdt;
163
164 if (config_match(bus, dev, &v)) {
165 config_attach(bus, dev, &v, (cfprint_t)vmeprint);
166 return (1);
167 }
168 return (0);
169 }
170
171 int
172 vmematch(parent, match, aux)
173 struct device *parent;
174 struct cfdata *match;
175 void *aux;
176 {
177 return (1);
178 }
179
180 void
181 vmeattach(parent, self, aux)
182 struct device *parent, *self;
183 void *aux;
184 {
185 struct vmebus_softc *sc = (struct vmebus_softc *)self;
186
187 struct vmebus_attach_args *aa =
188 (struct vmebus_attach_args*)aux;
189
190 sc->sc_vct = aa->va_vct;
191 sc->sc_bdt = aa->va_bdt;
192
193 /* the "bus" are we ourselves */
194 sc->sc_vct->bus = sc;
195
196 sc->slaveconfig = aa->va_slaveconfig;
197
198 printf("\n");
199
200 /*
201 * set up address space accounting - assume incomplete decoding
202 */
203 sc->vme32ext = extent_create("vme32", 0, 0xffffffff,
204 M_DEVBUF, 0, 0, 0);
205 if (!sc->vme32ext) {
206 printf("error creating A32 map\n");
207 return;
208 }
209
210 sc->vme24ext = extent_create("vme24", 0, 0x00ffffff,
211 M_DEVBUF, 0, 0, 0);
212 if (!sc->vme24ext) {
213 printf("error creating A24 map\n");
214 return;
215 }
216
217 sc->vme16ext = extent_create("vme16", 0, 0x0000ffff,
218 M_DEVBUF, 0, 0, 0);
219 if (!sc->vme16ext) {
220 printf("error creating A16 map\n");
221 return;
222 }
223
224 if (sc->slaveconfig) {
225 /* first get info about the bus master's slave side,
226 if present */
227 config_search((cfmatch_t)vmesubmatch1, self, 0);
228 }
229 config_search((cfmatch_t)vmesubmatch, self, 0);
230
231 #ifdef VMEDEBUG
232 if (sc->vme32ext)
233 extent_print(sc->vme32ext);
234 if (sc->vme24ext)
235 extent_print(sc->vme24ext);
236 if (sc->vme16ext)
237 extent_print(sc->vme16ext);
238 #endif
239 }
240
241 #ifdef notyet
242 int
243 vmedetach(dev)
244 struct device *dev;
245 {
246 struct vmebus_softc *sc = (struct vmebus_softc*)dev;
247
248 if (sc->slaveconfig) {
249 /* allow bus master to free its bus ressources */
250 (*sc->slaveconfig)(dev->dv_parent, 0);
251 }
252
253 /* extent maps should be empty now */
254
255 if (sc->vme32ext) {
256 #ifdef VMEDEBUG
257 extent_print(sc->vme32ext);
258 #endif
259 extent_destroy(sc->vme32ext);
260 }
261 if (sc->vme24ext) {
262 #ifdef VMEDEBUG
263 extent_print(sc->vme24ext);
264 #endif
265 extent_destroy(sc->vme24ext);
266 }
267 if (sc->vme16ext) {
268 #ifdef VMEDEBUG
269 extent_print(sc->vme16ext);
270 #endif
271 extent_destroy(sc->vme16ext);
272 }
273
274 return (0);
275 }
276 #endif
277
278 static struct extent *
279 vme_select_map(sc, ams)
280 struct vmebus_softc *sc;
281 vme_am_t ams;
282 {
283 if ((ams & VME_AM_ADRSIZEMASK) == VME_AM_A32)
284 return (sc->vme32ext);
285 else if ((ams & VME_AM_ADRSIZEMASK) == VME_AM_A24)
286 return (sc->vme24ext);
287 else if ((ams & VME_AM_ADRSIZEMASK) == VME_AM_A16)
288 return (sc->vme16ext);
289 else
290 return (0);
291 }
292
293 int
294 _vme_space_alloc(sc, addr, len, ams)
295 struct vmebus_softc *sc;
296 vme_addr_t addr;
297 vme_size_t len;
298 vme_am_t ams;
299 {
300 struct extent *ex;
301
302 ex = vme_select_map(sc, ams);
303 if (!ex)
304 return (EINVAL);
305
306 return (extent_alloc_region(ex, addr, len, EX_NOWAIT));
307 }
308
309 void
310 _vme_space_free(sc, addr, len, ams)
311 struct vmebus_softc *sc;
312 vme_addr_t addr;
313 vme_size_t len;
314 vme_am_t ams;
315 {
316 struct extent *ex;
317
318 ex = vme_select_map(sc, ams);
319 if (!ex) {
320 panic("vme_space_free: invalid am %x", ams);
321 return;
322 }
323
324 extent_free(ex, addr, len, EX_NOWAIT);
325 }
326
327 int
328 _vme_space_get(sc, len, ams, align, addr)
329 struct vmebus_softc *sc;
330 vme_size_t len;
331 vme_am_t ams;
332 u_long align;
333 vme_addr_t *addr;
334 {
335 struct extent *ex;
336
337 ex = vme_select_map(sc, ams);
338 if (!ex)
339 return (EINVAL);
340
341 return (extent_alloc(ex, len, align, EX_NOBOUNDARY, EX_NOWAIT,
342 (u_long *)addr));
343 }
Cache object: 86407a8d036ccec3aad5860683ca0519
|