xref: /netbsd-src/sys/arch/sparc/dev/vme_machdep.c (revision 89c5a767f8fc7a4633b2d409966e2becbb98ff92)
1 /*	$NetBSD: vme_machdep.c,v 1.22 2000/01/11 12:59:47 pk Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Paul Kranenburg.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/extent.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
43 #include <sys/malloc.h>
44 #include <sys/errno.h>
45 
46 #include <sys/proc.h>
47 #include <sys/user.h>
48 #include <sys/syslog.h>
49 
50 #include <vm/vm.h>
51 
52 #define _SPARC_BUS_DMA_PRIVATE
53 #include <machine/bus.h>
54 #include <sparc/sparc/iommuvar.h>
55 #include <machine/autoconf.h>
56 #include <machine/pmap.h>
57 #include <machine/oldmon.h>
58 #include <machine/cpu.h>
59 #include <machine/ctlreg.h>
60 
61 #include <dev/vme/vmereg.h>
62 #include <dev/vme/vmevar.h>
63 
64 #include <sparc/sparc/asm.h>
65 #include <sparc/sparc/vaddrs.h>
66 #include <sparc/sparc/cpuvar.h>
67 #include <sparc/dev/vmereg.h>
68 
69 struct sparcvme_softc {
70 	struct device	 sc_dev;	/* base device */
71 	bus_space_tag_t	 sc_bustag;
72 	bus_dma_tag_t	 sc_dmatag;
73 	struct vmebusreg *sc_reg; 	/* VME control registers */
74 	struct vmebusvec *sc_vec;	/* VME interrupt vector */
75 	struct rom_range *sc_range;	/* ROM range property */
76 	int		 sc_nrange;
77 	volatile u_int32_t *sc_ioctags;	/* VME IO-cache tag registers */
78 	volatile u_int32_t *sc_iocflush;/* VME IO-cache flush registers */
79 	int 		 (*sc_vmeintr) __P((void *));
80 };
81 struct  sparcvme_softc *sparcvme_sc;/*XXX*/
82 
83 /* autoconfiguration driver */
84 static int	vmematch_iommu  __P((struct device *, struct cfdata *, void *));
85 static void	vmeattach_iommu __P((struct device *, struct device *, void *));
86 static int	vmematch_mainbus  __P((struct device *, struct cfdata *, void *));
87 static void	vmeattach_mainbus __P((struct device *, struct device *, void *));
88 #if defined(SUN4)
89 int 		vmeintr4  __P((void *));
90 #endif
91 #if defined(SUN4M)
92 int 		vmeintr4m __P((void *));
93 static int	sparc_vme_error __P((void));
94 #endif
95 
96 
97 static int	sparc_vme_probe __P((void *, vme_addr_t, vme_size_t,
98 	vme_am_t, vme_datasize_t,
99 	int (*) __P((void *, bus_space_tag_t, bus_space_handle_t)), void *));
100 static int	sparc_vme_map __P((void *, vme_addr_t, vme_size_t, vme_am_t,
101 				   vme_datasize_t, vme_swap_t,
102 				   bus_space_tag_t *, bus_space_handle_t *,
103 				   vme_mapresc_t *));
104 static void	sparc_vme_unmap __P((void *, vme_mapresc_t));
105 static int	sparc_vme_intr_map __P((void *, int, int, vme_intr_handle_t *));
106 static void *	sparc_vme_intr_establish __P((void *, vme_intr_handle_t, int,
107 					      int (*) __P((void *)), void *));
108 static void	sparc_vme_intr_disestablish __P((void *, void *));
109 
110 static int	vmebus_translate __P((struct sparcvme_softc *, vme_am_t,
111 				      vme_addr_t, bus_type_t *, bus_addr_t *));
112 #if defined(SUN4M)
113 static void	sparc_vme4m_barrier __P(( bus_space_tag_t, bus_space_handle_t,
114 					  bus_size_t, bus_size_t, int));
115 
116 #endif
117 
118 /*
119  * DMA functions.
120  */
121 #if defined(SUN4)
122 static int	sparc_vme4_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
123 		    bus_size_t, struct proc *, int));
124 static void	sparc_vme4_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
125 static void	sparc_vme4_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t,
126 		    bus_addr_t, bus_size_t, int));
127 
128 static int	sparc_vme4_dmamem_alloc __P((bus_dma_tag_t, bus_size_t,
129 		    bus_size_t, bus_size_t, bus_dma_segment_t *,
130 		    int, int *, int));
131 static void	sparc_vme4_dmamem_free __P((bus_dma_tag_t,
132 		    bus_dma_segment_t *, int));
133 #endif
134 
135 #if defined(SUN4M)
136 static int	sparc_vme4m_dmamap_create __P((bus_dma_tag_t, bus_size_t, int,
137 		    bus_size_t, bus_size_t, int, bus_dmamap_t *));
138 
139 static int	sparc_vme4m_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *,
140 		    bus_size_t, struct proc *, int));
141 static void	sparc_vme4m_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
142 static void	sparc_vme4m_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t,
143 		    bus_addr_t, bus_size_t, int));
144 
145 static int	sparc_vme4m_dmamem_alloc __P((bus_dma_tag_t, bus_size_t,
146 		    bus_size_t, bus_size_t, bus_dma_segment_t *,
147 		    int, int *, int));
148 static void	sparc_vme4m_dmamem_free __P((bus_dma_tag_t,
149 		    bus_dma_segment_t *, int));
150 #endif
151 
152 static int	sparc_vme_dmamem_map __P((bus_dma_tag_t, bus_dma_segment_t *,
153 		    int, size_t, caddr_t *, int));
154 #if 0
155 static void	sparc_vme_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
156 static void	sparc_vme_dmamem_unmap __P((bus_dma_tag_t, caddr_t, size_t));
157 static int	sparc_vme_dmamem_mmap __P((bus_dma_tag_t,
158 		    bus_dma_segment_t *, int, int, int, int));
159 #endif
160 
161 int sparc_vme_mmap_cookie __P((vme_addr_t, vme_am_t, bus_space_handle_t *));
162 
163 struct cfattach vme_mainbus_ca = {
164 	sizeof(struct sparcvme_softc), vmematch_mainbus, vmeattach_mainbus
165 };
166 
167 struct cfattach vme_iommu_ca = {
168 	sizeof(struct sparcvme_softc), vmematch_iommu, vmeattach_iommu
169 };
170 
171 int	(*vmeerr_handler) __P((void));
172 
173 #define VMEMOD_D32 0x40 /* ??? */
174 
175 /* If the PROM does not provide the `ranges' property, we make up our own */
176 struct rom_range vmebus_translations[] = {
177 #define _DS (VME_AM_MBO | VME_AM_SUPER | VME_AM_DATA)
178 	{ VME_AM_A16|_DS, 0, PMAP_VME16, 0xffff0000, 0 },
179 	{ VME_AM_A24|_DS, 0, PMAP_VME16, 0xff000000, 0 },
180 	{ VME_AM_A32|_DS, 0, PMAP_VME16, 0x00000000, 0 },
181 	{ VME_AM_A16|VMEMOD_D32|_DS, 0, PMAP_VME32, 0xffff0000, 0 },
182 	{ VME_AM_A24|VMEMOD_D32|_DS, 0, PMAP_VME32, 0xff000000, 0 },
183 	{ VME_AM_A32|VMEMOD_D32|_DS, 0, PMAP_VME32, 0x00000000, 0 }
184 #undef _DS
185 };
186 
187 /*
188  * DMA on sun4 VME devices use the last MB of virtual space, which
189  * is mapped by hardware onto the first MB of VME space.
190  */
191 struct extent *vme_dvmamap;
192 
193 struct sparc_bus_space_tag sparc_vme_bus_tag = {
194 	NULL, /* cookie */
195 	NULL, /* parent bus tag */
196 	NULL, /* bus_map */
197 	NULL, /* bus_unmap */
198 	NULL, /* bus_subregion */
199 	NULL  /* barrier */
200 };
201 
202 struct vme_chipset_tag sparc_vme_chipset_tag = {
203 	NULL,
204 	sparc_vme_map,
205 	sparc_vme_unmap,
206 	sparc_vme_probe,
207 	sparc_vme_intr_map,
208 	sparc_vme_intr_establish,
209 	sparc_vme_intr_disestablish,
210 	0, 0, 0 /* bus specific DMA stuff */
211 };
212 
213 
214 #if defined(SUN4)
215 struct sparc_bus_dma_tag sparc_vme4_dma_tag = {
216 	NULL,	/* cookie */
217 	_bus_dmamap_create,
218 	_bus_dmamap_destroy,
219 	sparc_vme4_dmamap_load,
220 	_bus_dmamap_load_mbuf,
221 	_bus_dmamap_load_uio,
222 	_bus_dmamap_load_raw,
223 	sparc_vme4_dmamap_unload,
224 	sparc_vme4_dmamap_sync,
225 
226 	sparc_vme4_dmamem_alloc,
227 	sparc_vme4_dmamem_free,
228 	sparc_vme_dmamem_map,
229 	_bus_dmamem_unmap,
230 	_bus_dmamem_mmap
231 };
232 #endif
233 
234 #if defined(SUN4M)
235 struct sparc_bus_dma_tag sparc_vme4m_dma_tag = {
236 	NULL,	/* cookie */
237 	sparc_vme4m_dmamap_create,
238 	_bus_dmamap_destroy,
239 	sparc_vme4m_dmamap_load,
240 	_bus_dmamap_load_mbuf,
241 	_bus_dmamap_load_uio,
242 	_bus_dmamap_load_raw,
243 	sparc_vme4m_dmamap_unload,
244 	sparc_vme4m_dmamap_sync,
245 
246 	sparc_vme4m_dmamem_alloc,
247 	sparc_vme4m_dmamem_free,
248 	sparc_vme_dmamem_map,
249 	_bus_dmamem_unmap,
250 	_bus_dmamem_mmap
251 };
252 #endif
253 
254 
255 int
256 vmematch_mainbus(parent, cf, aux)
257 	struct device *parent;
258 	struct cfdata *cf;
259 	void *aux;
260 {
261 	struct mainbus_attach_args *ma = aux;
262 
263 	if (!CPU_ISSUN4)
264 		return (0);
265 
266 	return (strcmp("vme", ma->ma_name) == 0);
267 }
268 
269 int
270 vmematch_iommu(parent, cf, aux)
271 	struct device *parent;
272 	struct cfdata *cf;
273 	void *aux;
274 {
275 	struct iommu_attach_args *ia = aux;
276 
277 	return (strcmp("vme", ia->iom_name) == 0);
278 }
279 
280 
281 void
282 vmeattach_mainbus(parent, self, aux)
283 	struct device *parent, *self;
284 	void *aux;
285 {
286 #if defined(SUN4)
287 	struct mainbus_attach_args *ma = aux;
288 	struct sparcvme_softc *sc = (struct sparcvme_softc *)self;
289 	struct vmebus_attach_args vba;
290 
291 	if (self->dv_unit > 0) {
292 		printf(" unsupported\n");
293 		return;
294 	}
295 
296 	sc->sc_bustag = ma->ma_bustag;
297 	sc->sc_dmatag = ma->ma_dmatag;
298 
299 	/* VME interrupt entry point */
300 	sc->sc_vmeintr = vmeintr4;
301 
302 /*XXX*/	sparc_vme_chipset_tag.cookie = self;
303 /*XXX*/	sparc_vme4_dma_tag._cookie = self;
304 
305 #if 0
306 	sparc_vme_bus_tag.parent = ma->ma_bustag;
307 	vba.vba_bustag = &sparc_vme_bus_tag;
308 #endif
309 	vba.va_vct = &sparc_vme_chipset_tag;
310 	vba.va_bdt = &sparc_vme4_dma_tag;
311 	vba.va_slaveconfig = 0;
312 
313 	/* Fall back to our own `range' construction */
314 	sc->sc_range = vmebus_translations;
315 	sc->sc_nrange =
316 		sizeof(vmebus_translations)/sizeof(vmebus_translations[0]);
317 
318 	vme_dvmamap = extent_create("vmedvma", VME4_DVMA_BASE, VME4_DVMA_END,
319 				    M_DEVBUF, 0, 0, EX_NOWAIT);
320 	if (vme_dvmamap == NULL)
321 		panic("vme: unable to allocate DVMA map");
322 
323 	printf("\n");
324 	(void)config_found(self, &vba, 0);
325 
326 #endif
327 	return;
328 }
329 
330 /* sun4m vmebus */
331 void
332 vmeattach_iommu(parent, self, aux)
333 	struct device *parent, *self;
334 	void *aux;
335 {
336 #if defined(SUN4M)
337 	struct sparcvme_softc *sc = (struct sparcvme_softc *)self;
338 	struct iommu_attach_args *ia = aux;
339 	struct vmebus_attach_args vba;
340 	bus_space_handle_t bh;
341 	int node;
342 	int cline;
343 
344 	if (self->dv_unit > 0) {
345 		printf(" unsupported\n");
346 		return;
347 	}
348 
349 	sc->sc_bustag = ia->iom_bustag;
350 	sc->sc_dmatag = ia->iom_dmatag;
351 
352 	/* VME interrupt entry point */
353 	sc->sc_vmeintr = vmeintr4m;
354 
355 /*XXX*/	sparc_vme_chipset_tag.cookie = self;
356 /*XXX*/	sparc_vme4m_dma_tag._cookie = self;
357 	sparc_vme_bus_tag.sparc_bus_barrier = sparc_vme4m_barrier;
358 
359 #if 0
360 	vba.vba_bustag = &sparc_vme_bus_tag;
361 #endif
362 	vba.va_vct = &sparc_vme_chipset_tag;
363 	vba.va_bdt = &sparc_vme4m_dma_tag;
364 	vba.va_slaveconfig = 0;
365 
366 	node = ia->iom_node;
367 
368 	/*
369 	 * Map VME control space
370 	 */
371 	if (ia->iom_nreg < 2) {
372 		printf("%s: only %d register sets\n", self->dv_xname,
373 			ia->iom_nreg);
374 		return;
375 	}
376 
377 	if (bus_space_map2(ia->iom_bustag,
378 			  (bus_type_t)ia->iom_reg[0].ior_iospace,
379 			  (bus_addr_t)ia->iom_reg[0].ior_pa,
380 			  (bus_size_t)ia->iom_reg[0].ior_size,
381 			  BUS_SPACE_MAP_LINEAR,
382 			  0, &bh) != 0) {
383 		panic("%s: can't map vmebusreg", self->dv_xname);
384 	}
385 	sc->sc_reg = (struct vmebusreg *)bh;
386 
387 	if (bus_space_map2(ia->iom_bustag,
388 			  (bus_type_t)ia->iom_reg[1].ior_iospace,
389 			  (bus_addr_t)ia->iom_reg[1].ior_pa,
390 			  (bus_size_t)ia->iom_reg[1].ior_size,
391 			  BUS_SPACE_MAP_LINEAR,
392 			  0, &bh) != 0) {
393 		panic("%s: can't map vmebusvec", self->dv_xname);
394 	}
395 	sc->sc_vec = (struct vmebusvec *)bh;
396 
397 	/*
398 	 * Map VME IO cache tags and flush control.
399 	 */
400 	if (bus_space_map2(ia->iom_bustag,
401 			  (bus_type_t)ia->iom_reg[1].ior_iospace,
402 			  (bus_addr_t)ia->iom_reg[1].ior_pa + VME_IOC_TAGOFFSET,
403 			  VME_IOC_SIZE,
404 			  BUS_SPACE_MAP_LINEAR,
405 			  0, &bh) != 0) {
406 		panic("%s: can't map IOC tags", self->dv_xname);
407 	}
408 	sc->sc_ioctags = (u_int32_t *)bh;
409 
410 	if (bus_space_map2(ia->iom_bustag,
411 			  (bus_type_t)ia->iom_reg[1].ior_iospace,
412 			  (bus_addr_t)ia->iom_reg[1].ior_pa+VME_IOC_FLUSHOFFSET,
413 			  VME_IOC_SIZE,
414 			  BUS_SPACE_MAP_LINEAR,
415 			  0, &bh) != 0) {
416 		panic("%s: can't map IOC flush registers", self->dv_xname);
417 	}
418 	sc->sc_iocflush = (u_int32_t *)bh;
419 
420 /*XXX*/	sparc_vme_bus_tag.cookie = sc->sc_reg;
421 
422 	/*
423 	 * Get "range" property.
424 	 */
425 	if (getprop(node, "ranges", sizeof(struct rom_range),
426 		    &sc->sc_nrange, (void **)&sc->sc_range) != 0) {
427 		panic("%s: can't get ranges property", self->dv_xname);
428 	}
429 
430 	sparcvme_sc = sc;
431 	vmeerr_handler = sparc_vme_error;
432 
433 	/*
434 	 * Invalidate all IO-cache entries.
435 	 */
436 	for (cline = VME_IOC_SIZE/VME_IOC_LINESZ; cline > 0;) {
437 		sc->sc_ioctags[--cline] = 0;
438 	}
439 
440 	/* Enable IO-cache */
441 	sc->sc_reg->vmebus_cr |= VMEBUS_CR_C;
442 
443 	printf(": version 0x%x\n",
444 	       sc->sc_reg->vmebus_cr & VMEBUS_CR_IMPL);
445 
446 	(void)config_found(self, &vba, 0);
447 #endif
448 }
449 
450 #if defined(SUN4M)
451 static int
452 sparc_vme_error()
453 {
454 	struct sparcvme_softc *sc = sparcvme_sc;
455 	u_int32_t afsr, afpa;
456 	char bits[64];
457 
458 	afsr = sc->sc_reg->vmebus_afsr;
459 	afpa = sc->sc_reg->vmebus_afar;
460 	printf("VME error:\n\tAFSR %s\n",
461 		bitmask_snprintf(afsr, VMEBUS_AFSR_BITS, bits, sizeof(bits)));
462 	printf("\taddress: 0x%x%x\n", afsr, afpa);
463 	return (0);
464 }
465 #endif
466 
467 int
468 vmebus_translate(sc, mod, addr, btp, bap)
469 	struct sparcvme_softc *sc;
470 	vme_am_t	mod;
471 	vme_addr_t	addr;
472 	bus_type_t	*btp;
473 	bus_addr_t	*bap;
474 {
475 	int i;
476 
477 	for (i = 0; i < sc->sc_nrange; i++) {
478 
479 		if (sc->sc_range[i].cspace != mod)
480 			continue;
481 
482 		/* We've found the connection to the parent bus */
483 		*bap = sc->sc_range[i].poffset + addr;
484 		*btp = sc->sc_range[i].pspace;
485 		return (0);
486 	}
487 	return (ENOENT);
488 }
489 
490 struct vmeprobe_myarg {
491 	int (*cb) __P((void *, bus_space_tag_t, bus_space_handle_t));
492 	void *cbarg;
493 	bus_space_tag_t tag;
494 	int res; /* backwards */
495 };
496 
497 static int vmeprobe_mycb __P((void *, void *));
498 static int
499 vmeprobe_mycb(bh, arg)
500 	void *bh, *arg;
501 {
502 	struct vmeprobe_myarg *a = arg;
503 
504 	a->res = (*a->cb)(a->cbarg, a->tag, (bus_space_handle_t)bh);
505 	return (!a->res);
506 }
507 
508 int
509 sparc_vme_probe(cookie, addr, len, mod, datasize, callback, arg)
510 	void *cookie;
511 	vme_addr_t addr;
512 	vme_size_t len;
513 	vme_am_t mod;
514 	vme_datasize_t datasize;
515 	int (*callback) __P((void *, bus_space_tag_t, bus_space_handle_t));
516 	void *arg;
517 {
518 	struct sparcvme_softc *sc = (struct sparcvme_softc *)cookie;
519 	bus_type_t iospace;
520 	bus_addr_t paddr;
521 	bus_size_t size;
522 	struct vmeprobe_myarg myarg;
523 	int res, i;
524 
525 	if (vmebus_translate(sc, mod, addr, &iospace, &paddr) != 0)
526 		return (EINVAL);
527 
528 	size = (datasize == VME_D8 ? 1 : (datasize == VME_D16 ? 2 : 4));
529 
530 	if (callback) {
531 		myarg.cb = callback;
532 		myarg.cbarg = arg;
533 		myarg.tag = sc->sc_bustag;
534 		myarg.res = 0;
535 		res = bus_space_probe(sc->sc_bustag, iospace, paddr, size, 0,
536 				      0, vmeprobe_mycb, &myarg);
537 		return (res ? 0 : (myarg.res ? myarg.res : EIO));
538 	}
539 
540 	for (i = 0; i < len / size; i++) {
541 		myarg.res = 0;
542 		res = bus_space_probe(sc->sc_bustag, iospace, paddr, size, 0,
543 				      0, 0, 0);
544 		if (res == 0)
545 			return (EIO);
546 		paddr += size;
547 	}
548 	return (0);
549 }
550 
551 int
552 sparc_vme_map(cookie, addr, size, mod, datasize, swap, tp, hp, rp)
553 	void *cookie;
554 	vme_addr_t addr;
555 	vme_size_t size;
556 	vme_am_t mod;
557 	vme_datasize_t datasize;
558 	bus_space_tag_t *tp;
559 	bus_space_handle_t *hp;
560 	vme_mapresc_t *rp;
561 {
562 	struct sparcvme_softc *sc = (struct sparcvme_softc *)cookie;
563 	bus_type_t iospace;
564 	bus_addr_t paddr;
565 	int error;
566 
567 	error = vmebus_translate(sc, mod, addr, &iospace, &paddr);
568 	if (error != 0)
569 		return (error);
570 
571 	*tp = sc->sc_bustag;
572 	return (bus_space_map2(sc->sc_bustag, iospace, paddr, size, 0, 0, hp));
573 }
574 
575 int
576 sparc_vme_mmap_cookie(addr, mod, hp)
577 	vme_addr_t addr;
578 	vme_am_t mod;
579 	bus_space_handle_t *hp;
580 {
581 	struct sparcvme_softc *sc = sparcvme_sc;
582 	bus_type_t iospace;
583 	bus_addr_t paddr;
584 	int error;
585 
586 	error = vmebus_translate(sc, mod, addr, &iospace, &paddr);
587 	if (error != 0)
588 		return (error);
589 
590 	return (bus_space_mmap(sc->sc_bustag, iospace, paddr, 0, hp));
591 }
592 
593 #if defined(SUN4M)
594 void
595 sparc_vme4m_barrier(t, h, offset, size, flags)
596 	bus_space_tag_t t;
597 	bus_space_handle_t h;
598 	bus_size_t offset;
599 	bus_size_t size;
600 	int flags;
601 {
602 	struct vmebusreg *vbp = (struct vmebusreg *)t->cookie;
603 
604 	/* Read async fault status to flush write-buffers */
605 	(*(volatile int *)&vbp->vmebus_afsr);
606 }
607 #endif
608 
609 
610 
611 /*
612  * VME Interrupt Priority Level to sparc Processor Interrupt Level.
613  */
614 static int vme_ipl_to_pil[] = {
615 	0,
616 	2,
617 	3,
618 	5,
619 	7,
620 	9,
621 	11,
622 	13
623 };
624 
625 
626 /*
627  * All VME device interrupts go through vmeintr(). This function reads
628  * the VME vector from the bus, then dispatches the device interrupt
629  * handler.  All handlers for devices that map to the same Processor
630  * Interrupt Level (according to the table above) are on a linked list
631  * of `sparc_vme_intr_handle' structures. The head of which is passed
632  * down as the argument to `vmeintr(void *arg)'.
633  */
634 struct sparc_vme_intr_handle {
635 	struct intrhand ih;
636 	struct sparc_vme_intr_handle *next;
637 	int	vec;		/* VME interrupt vector */
638 	int	pri;		/* VME interrupt priority */
639 	struct sparcvme_softc *sc;/*XXX*/
640 };
641 
642 #if defined(SUN4)
643 int
644 vmeintr4(arg)
645 	void *arg;
646 {
647 	struct sparc_vme_intr_handle *ihp = (vme_intr_handle_t)arg;
648 	int level, vec;
649 	int i = 0;
650 
651 	level = (ihp->pri << 1) | 1;
652 
653 	vec = ldcontrolb((caddr_t)(AC_VMEINTVEC | level));
654 
655 	if (vec == -1) {
656 		printf("vme: spurious interrupt\n");
657 		return 1; /* XXX - pretend we handled it, for now */
658 	}
659 
660 	for (; ihp; ihp = ihp->next)
661 		if (ihp->vec == vec && ihp->ih.ih_fun)
662 			i += (ihp->ih.ih_fun)(ihp->ih.ih_arg);
663 	return (i);
664 }
665 #endif
666 
667 #if defined(SUN4M)
668 int
669 vmeintr4m(arg)
670 	void *arg;
671 {
672 	struct sparc_vme_intr_handle *ihp = (vme_intr_handle_t)arg;
673 	int level, vec;
674 	int i = 0;
675 
676 	level = (ihp->pri << 1) | 1;
677 
678 #if 0
679 	int pending;
680 
681 	/* Flush VME <=> Sbus write buffers */
682 	(*(volatile int *)&ihp->sc->sc_reg->vmebus_afsr);
683 
684 	pending = *((int*)ICR_SI_PEND);
685 	if ((pending & SINTR_VME(ihp->pri)) == 0) {
686 		printf("vmeintr: non pending at pri %x(p 0x%x)\n",
687 			ihp->pri, pending);
688 		return (0);
689 	}
690 #endif
691 #if 0
692 	/* Why gives this a bus timeout sometimes? */
693 	vec = ihp->sc->sc_vec->vmebusvec[level];
694 #else
695 	/* so, arrange to catch the fault... */
696 	{
697 	extern struct user *proc0paddr;
698 	extern int fkbyte __P((caddr_t, struct pcb *));
699 	caddr_t addr = (caddr_t)&ihp->sc->sc_vec->vmebusvec[level];
700 	struct pcb *xpcb;
701 	u_long saveonfault;
702 	int s;
703 
704 	s = splhigh();
705 	if (curproc == NULL)
706 		xpcb = (struct pcb *)proc0paddr;
707 	else
708 		xpcb = &curproc->p_addr->u_pcb;
709 
710 	saveonfault = (u_long)xpcb->pcb_onfault;
711 	vec = fkbyte(addr, xpcb);
712 	xpcb->pcb_onfault = (caddr_t)saveonfault;
713 
714 	splx(s);
715 	}
716 #endif
717 
718 	if (vec == -1) {
719 		printf("vme: spurious interrupt: ");
720 		printf("SI: 0x%x, VME AFSR: 0x%x, VME AFAR 0x%x\n",
721 			*((int*)ICR_SI_PEND),
722 			ihp->sc->sc_reg->vmebus_afsr,
723 			ihp->sc->sc_reg->vmebus_afar);
724 		return (1); /* XXX - pretend we handled it, for now */
725 	}
726 
727 	for (; ihp; ihp = ihp->next)
728 		if (ihp->vec == vec && ihp->ih.ih_fun)
729 			i += (ihp->ih.ih_fun)(ihp->ih.ih_arg);
730 	return (i);
731 }
732 #endif
733 
734 int
735 sparc_vme_intr_map(cookie, level, vec, ihp)
736 	void *cookie;
737 	int level;
738 	int vec;
739 	vme_intr_handle_t *ihp;
740 {
741 	struct sparc_vme_intr_handle *ih;
742 
743 	ih = (vme_intr_handle_t)
744 	    malloc(sizeof(struct sparc_vme_intr_handle), M_DEVBUF, M_NOWAIT);
745 	ih->pri = level;
746 	ih->vec = vec;
747 	ih->sc = cookie;/*XXX*/
748 	*ihp = ih;
749 	return (0);
750 }
751 
752 void *
753 sparc_vme_intr_establish(cookie, vih, pri, func, arg)
754 	void *cookie;
755 	vme_intr_handle_t vih;
756 	int pri;
757 	int (*func) __P((void *));
758 	void *arg;
759 {
760 	struct sparcvme_softc *sc = (struct sparcvme_softc *)cookie;
761 	struct sparc_vme_intr_handle *svih =
762 			(struct sparc_vme_intr_handle *)vih;
763 	struct intrhand *ih;
764 	int level;
765 
766 	/* XXX pri == svih->pri ??? */
767 
768 	/* Translate VME priority to processor IPL */
769 	level = vme_ipl_to_pil[svih->pri];
770 
771 	svih->ih.ih_fun = func;
772 	svih->ih.ih_arg = arg;
773 	svih->next = NULL;
774 
775 	/* ensure the interrupt subsystem will call us at this level */
776 	for (ih = intrhand[level]; ih != NULL; ih = ih->ih_next)
777 		if (ih->ih_fun == sc->sc_vmeintr)
778 			break;
779 
780 	if (ih == NULL) {
781 		ih = (struct intrhand *)
782 			malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT);
783 		if (ih == NULL)
784 			panic("vme_addirq");
785 		bzero(ih, sizeof *ih);
786 		ih->ih_fun = sc->sc_vmeintr;
787 		ih->ih_arg = vih;
788 		intr_establish(level, ih);
789 	} else {
790 		svih->next = (vme_intr_handle_t)ih->ih_arg;
791 		ih->ih_arg = vih;
792 	}
793 	return (NULL);
794 }
795 
796 void
797 sparc_vme_unmap(cookie, resc)
798 	void * cookie;
799 	vme_mapresc_t resc;
800 {
801 	/* Not implemented */
802 	panic("sparc_vme_unmap");
803 }
804 
805 void
806 sparc_vme_intr_disestablish(cookie, a)
807 	void *cookie;
808 	void *a;
809 {
810 	/* Not implemented */
811 	panic("sparc_vme_intr_disestablish");
812 }
813 
814 
815 
816 /*
817  * VME DMA functions.
818  */
819 
820 #if defined(SUN4)
821 int
822 sparc_vme4_dmamap_load(t, map, buf, buflen, p, flags)
823 	bus_dma_tag_t t;
824 	bus_dmamap_t map;
825 	void *buf;
826 	bus_size_t buflen;
827 	struct proc *p;
828 	int flags;
829 {
830 	bus_addr_t dvmaddr;
831 	bus_size_t sgsize;
832 	vaddr_t vaddr;
833 	pmap_t pmap;
834 	int pagesz = PAGE_SIZE;
835 	int error;
836 
837 	error = extent_alloc(vme_dvmamap, round_page(buflen), NBPG,
838 			     map->_dm_boundary,
839 			     (flags & BUS_DMA_NOWAIT) == 0
840 					? EX_WAITOK
841 					: EX_NOWAIT,
842 			     (u_long *)&dvmaddr);
843 	if (error != 0)
844 		return (error);
845 
846 	vaddr = (vaddr_t)buf;
847 	map->dm_mapsize = buflen;
848 	map->dm_nsegs = 1;
849 	map->dm_segs[0].ds_addr = dvmaddr + (vaddr & PGOFSET);
850 	map->dm_segs[0].ds_len = buflen;
851 
852 	pmap = (p == NULL) ? pmap_kernel() : p->p_vmspace->vm_map.pmap;
853 
854 	for (; buflen > 0; ) {
855 		paddr_t pa;
856 		/*
857 		 * Get the physical address for this page.
858 		 */
859 		(void) pmap_extract(pmap, vaddr, &pa);
860 
861 		/*
862 		 * Compute the segment size, and adjust counts.
863 		 */
864 		sgsize = pagesz - ((u_long)vaddr & (pagesz - 1));
865 		if (buflen < sgsize)
866 			sgsize = buflen;
867 
868 #ifdef notyet
869 		if (have_iocache)
870 			curaddr |= PG_IOC;
871 #endif
872 		pmap_enter(pmap_kernel(), dvmaddr,
873 		    (pa & ~(pagesz-1)) | PMAP_NC,
874 		    VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED);
875 
876 		dvmaddr += pagesz;
877 		vaddr += sgsize;
878 		buflen -= sgsize;
879 	}
880 
881 	/* Adjust DVMA address to VME view */
882 	map->dm_segs[0].ds_addr -= VME4_DVMA_BASE;
883 	return (0);
884 }
885 
886 void
887 sparc_vme4_dmamap_unload(t, map)
888 	bus_dma_tag_t t;
889 	bus_dmamap_t map;
890 {
891 	bus_addr_t addr;
892 	bus_size_t len;
893 
894 	/* Go from VME to CPU view */
895 	map->dm_segs[0].ds_addr += VME4_DVMA_BASE;
896 
897 	addr = map->dm_segs[0].ds_addr & ~PGOFSET;
898 	len = round_page(map->dm_segs[0].ds_len);
899 
900 	/* Remove double-mapping in DVMA space */
901 	pmap_remove(pmap_kernel(), addr, addr + len);
902 
903 	/* Release DVMA space */
904 	if (extent_free(vme_dvmamap, addr, len, EX_NOWAIT) != 0)
905 		printf("warning: %ld of DVMA space lost\n", len);
906 
907 	/* Mark the mappings as invalid. */
908 	map->dm_mapsize = 0;
909 	map->dm_nsegs = 0;
910 }
911 
912 int
913 sparc_vme4_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
914 	bus_dma_tag_t t;
915 	bus_size_t size, alignment, boundary;
916 	bus_dma_segment_t *segs;
917 	int nsegs;
918 	int *rsegs;
919 	int flags;
920 {
921 	bus_addr_t dvmaddr;
922 	struct pglist *mlist;
923 	vm_page_t m;
924 	paddr_t pa;
925 	int error;
926 
927 	size = round_page(size);
928 	error = _bus_dmamem_alloc_common(t, size, alignment, boundary,
929 					 segs, nsegs, rsegs, flags);
930 	if (error != 0)
931 		return (error);
932 
933 	if (extent_alloc(vme_dvmamap, size, alignment, boundary,
934 			 (flags & BUS_DMA_NOWAIT) == 0 ? EX_WAITOK : EX_NOWAIT,
935 			 (u_long *)&dvmaddr) != 0)
936 		return (ENOMEM);
937 
938 	/*
939 	 * Compute the location, size, and number of segments actually
940 	 * returned by the VM code.
941 	 */
942 	segs[0].ds_addr = dvmaddr - VME4_DVMA_BASE;
943 	segs[0].ds_len = size;
944 	*rsegs = 1;
945 
946 	/* Map memory into DVMA space */
947 	mlist = segs[0]._ds_mlist;
948 	for (m = TAILQ_FIRST(mlist); m != NULL; m = TAILQ_NEXT(m,pageq)) {
949 		pa = VM_PAGE_TO_PHYS(m);
950 
951 #ifdef notyet
952 		if (have_iocache)
953 			pa |= PG_IOC;
954 #endif
955 		pmap_enter(pmap_kernel(), dvmaddr, pa | PMAP_NC,
956 		    VM_PROT_READ|VM_PROT_WRITE, PMAP_WIRED);
957 		dvmaddr += PAGE_SIZE;
958 	}
959 
960 	return (0);
961 }
962 
963 void
964 sparc_vme4_dmamem_free(t, segs, nsegs)
965 	bus_dma_tag_t t;
966 	bus_dma_segment_t *segs;
967 	int nsegs;
968 {
969 	bus_addr_t addr;
970 	bus_size_t len;
971 
972 	addr = segs[0].ds_addr + VME4_DVMA_BASE;
973 	len = round_page(segs[0].ds_len);
974 
975 	/* Remove DVMA kernel map */
976 	pmap_remove(pmap_kernel(), addr, addr + len);
977 
978 	/* Release DVMA address range */
979 	if (extent_free(vme_dvmamap, addr, len, EX_NOWAIT) != 0)
980 		printf("warning: %ld of DVMA space lost\n", len);
981 
982 	/*
983 	 * Return the list of pages back to the VM system.
984 	 */
985 	_bus_dmamem_free_common(t, segs, nsegs);
986 }
987 
988 void
989 sparc_vme4_dmamap_sync(t, map, offset, len, ops)
990 	bus_dma_tag_t t;
991 	bus_dmamap_t map;
992 	bus_addr_t offset;
993 	bus_size_t len;
994 	int ops;
995 {
996 
997 	/*
998 	 * XXX Should perform cache flushes as necessary (e.g. 4/200 W/B).
999 	 *     Currently the cache is flushed in bus_dma_load()...
1000 	 */
1001 }
1002 #endif /* SUN4 */
1003 
1004 #if defined(SUN4M)
1005 static int
1006 sparc_vme4m_dmamap_create (t, size, nsegments, maxsegsz, boundary, flags, dmamp)
1007 	bus_dma_tag_t t;
1008 	bus_size_t size;
1009 	int nsegments;
1010 	bus_size_t maxsegsz;
1011 	bus_size_t boundary;
1012 	int flags;
1013 	bus_dmamap_t *dmamp;
1014 {
1015 	struct sparcvme_softc *sc = (struct sparcvme_softc *)t->_cookie;
1016 	int error;
1017 
1018 	/* XXX - todo: allocate DVMA addresses from assigned ranges:
1019 		 upper 8MB for A32 space; upper 1MB for A24 space */
1020 	error = bus_dmamap_create(sc->sc_dmatag, size, nsegments, maxsegsz,
1021 				  boundary, flags, dmamp);
1022 	if (error != 0)
1023 		return (error);
1024 
1025 #if 0
1026 	/* VME DVMA addresses must always be 8K aligned */
1027 	(*dmamp)->_dm_align = 8192;
1028 #endif
1029 
1030 	return (0);
1031 }
1032 
1033 int
1034 sparc_vme4m_dmamap_load(t, map, buf, buflen, p, flags)
1035 	bus_dma_tag_t t;
1036 	bus_dmamap_t map;
1037 	void *buf;
1038 	bus_size_t buflen;
1039 	struct proc *p;
1040 	int flags;
1041 {
1042 	struct sparcvme_softc	*sc = (struct sparcvme_softc *)t->_cookie;
1043 	volatile u_int32_t	*ioctags;
1044 	int			error;
1045 
1046 	buflen = (buflen + VME_IOC_PAGESZ - 1) & ~(VME_IOC_PAGESZ - 1);
1047 	error = bus_dmamap_load(sc->sc_dmatag, map, buf, buflen, p, flags);
1048 	if (error != 0)
1049 		return (error);
1050 
1051 	/* allocate IO cache entries for this range */
1052 	ioctags = sc->sc_ioctags + VME_IOC_LINE(map->dm_segs[0].ds_addr);
1053 	for (;buflen > 0;) {
1054 		*ioctags = VME_IOC_IC | VME_IOC_W;
1055 		ioctags += VME_IOC_LINESZ/sizeof(*ioctags);
1056 		buflen -= VME_IOC_PAGESZ;
1057 	}
1058 	return (0);
1059 }
1060 
1061 
1062 void
1063 sparc_vme4m_dmamap_unload(t, map)
1064 	bus_dma_tag_t t;
1065 	bus_dmamap_t map;
1066 {
1067 	struct sparcvme_softc	*sc = (struct sparcvme_softc *)t->_cookie;
1068 	volatile u_int32_t	*flushregs;
1069 	int			len;
1070 
1071 	/* Flush VME IO cache */
1072 	len = map->dm_segs[0].ds_len;
1073 	flushregs = sc->sc_iocflush + VME_IOC_LINE(map->dm_segs[0].ds_addr);
1074 	for (;len > 0;) {
1075 		*flushregs = 0;
1076 		flushregs += VME_IOC_LINESZ/sizeof(*flushregs);
1077 		len -= VME_IOC_PAGESZ;
1078 	}
1079 	/* Read a tag to synchronize the IOC flushes */
1080 	(*sc->sc_ioctags);
1081 
1082 	bus_dmamap_unload(sc->sc_dmatag, map);
1083 }
1084 
1085 int
1086 sparc_vme4m_dmamem_alloc(t, size, alignmnt, boundary, segs, nsegs, rsegs, flags)
1087 	bus_dma_tag_t t;
1088 	bus_size_t size, alignmnt, boundary;
1089 	bus_dma_segment_t *segs;
1090 	int nsegs;
1091 	int *rsegs;
1092 	int flags;
1093 {
1094 	struct sparcvme_softc	*sc = (struct sparcvme_softc *)t->_cookie;
1095 	int error;
1096 
1097 	error = bus_dmamem_alloc(sc->sc_dmatag, size, alignmnt, boundary,
1098 				  segs, nsegs, rsegs, flags);
1099 	if (error != 0)
1100 		return (error);
1101 
1102 	return (0);
1103 }
1104 
1105 void
1106 sparc_vme4m_dmamem_free(t, segs, nsegs)
1107 	bus_dma_tag_t t;
1108 	bus_dma_segment_t *segs;
1109 	int nsegs;
1110 {
1111 	struct sparcvme_softc	*sc = (struct sparcvme_softc *)t->_cookie;
1112 
1113 	bus_dmamem_free(sc->sc_dmatag, segs, nsegs);
1114 }
1115 
1116 void
1117 sparc_vme4m_dmamap_sync(t, map, offset, len, ops)
1118 	bus_dma_tag_t t;
1119 	bus_dmamap_t map;
1120 	bus_addr_t offset;
1121 	bus_size_t len;
1122 	int ops;
1123 {
1124 
1125 	/*
1126 	 * XXX Should perform cache flushes as necessary.
1127 	 */
1128 }
1129 #endif /* SUN4M */
1130 
1131 int
1132 sparc_vme_dmamem_map(t, segs, nsegs, size, kvap, flags)
1133 	bus_dma_tag_t t;
1134 	bus_dma_segment_t *segs;
1135 	int nsegs;
1136 	size_t size;
1137 	caddr_t *kvap;
1138 	int flags;
1139 {
1140 	struct sparcvme_softc	*sc = (struct sparcvme_softc *)t->_cookie;
1141 
1142 	return (bus_dmamem_map(sc->sc_dmatag, segs, nsegs, size, kvap, flags));
1143 }
1144