xref: /netbsd-src/sys/arch/sparc64/dev/sbus.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: sbus.c,v 1.78 2007/03/04 06:00:49 christos Exp $ */
2 
3 /*
4  * Copyright (c) 1999-2002 Eduardo Horvath
5  * 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,
23  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 
32 /*
33  * Sbus stuff.
34  */
35 
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: sbus.c,v 1.78 2007/03/04 06:00:49 christos Exp $");
38 
39 #include "opt_ddb.h"
40 
41 #include <sys/param.h>
42 #include <sys/extent.h>
43 #include <sys/malloc.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
46 #include <sys/reboot.h>
47 
48 #include <machine/bus.h>
49 #include <machine/openfirm.h>
50 
51 #include <sparc64/sparc64/cache.h>
52 #include <sparc64/dev/iommureg.h>
53 #include <sparc64/dev/iommuvar.h>
54 #include <sparc64/dev/sbusreg.h>
55 #include <dev/sbus/sbusvar.h>
56 
57 #include <uvm/uvm_extern.h>
58 
59 #include <machine/autoconf.h>
60 #include <machine/cpu.h>
61 #include <machine/sparc64.h>
62 
63 #ifdef DEBUG
64 #define SDB_DVMA	0x1
65 #define SDB_INTR	0x2
66 int sbus_debug = 0;
67 #define DPRINTF(l, s)   do { if (sbus_debug & l) printf s; } while (0)
68 #else
69 #define DPRINTF(l, s)
70 #endif
71 
72 void sbusreset(int);
73 
74 static bus_dma_tag_t sbus_alloc_dmatag(struct sbus_softc *);
75 static int sbus_get_intr(struct sbus_softc *, int, struct openprom_intr **,
76 	int *, int);
77 static int sbus_overtemp(void *);
78 static int _sbus_bus_map(
79 		bus_space_tag_t,
80 		bus_addr_t,		/*offset*/
81 		bus_size_t,		/*size*/
82 		int,			/*flags*/
83 		vaddr_t,			/* XXX unused -- compat w/sparc */
84 		bus_space_handle_t *);
85 static void *sbus_intr_establish(
86 		bus_space_tag_t,
87 		int,			/*`device class' priority*/
88 		int,			/*Sbus interrupt level*/
89 		int (*)(void *),	/*handler*/
90 		void *,			/*handler arg*/
91 		void (*)(void));	/*optional fast trap*/
92 
93 
94 /* autoconfiguration driver */
95 int	sbus_match(struct device *, struct cfdata *, void *);
96 void	sbus_attach(struct device *, struct device *, void *);
97 
98 
99 CFATTACH_DECL(sbus, sizeof(struct sbus_softc),
100     sbus_match, sbus_attach, NULL, NULL);
101 
102 extern struct cfdriver sbus_cd;
103 
104 /*
105  * DVMA routines
106  */
107 int	sbus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
108 		struct proc *, int);
109 void	sbus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
110 int	sbus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, bus_dma_segment_t *,
111 		int, bus_size_t, int);
112 void	sbus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t,
113 		int);
114 int	sbus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
115 		bus_size_t alignment, bus_size_t boundary,
116 		bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
117 void	sbus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs);
118 int	sbus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs,
119 		size_t size, void **kvap, int flags);
120 void	sbus_dmamem_unmap(bus_dma_tag_t tag, void *kva, size_t size);
121 
122 /*
123  * Child devices receive the Sbus interrupt level in their attach
124  * arguments. We translate these to CPU IPLs using the following
125  * tables. Note: obio bus interrupt levels are identical to the
126  * processor IPL.
127  *
128  * The second set of tables is used when the Sbus interrupt level
129  * cannot be had from the PROM as an `interrupt' property. We then
130  * fall back on the `intr' property which contains the CPU IPL.
131  */
132 
133 /*
134  * This value is or'ed into the attach args' interrupt level cookie
135  * if the interrupt level comes from an `intr' property, i.e. it is
136  * not an Sbus interrupt level.
137  */
138 #define SBUS_INTR_COMPAT	0x80000000
139 
140 
141 /*
142  * Print the location of some sbus-attached device (called just
143  * before attaching that device).  If `sbus' is not NULL, the
144  * device was found but not configured; print the sbus as well.
145  * Return UNCONF (config_find ignores this if the device was configured).
146  */
147 int
148 sbus_print(void *args, const char *busname)
149 {
150 	struct sbus_attach_args *sa = args;
151 	int i;
152 
153 	if (busname)
154 		aprint_normal("%s at %s", sa->sa_name, busname);
155 	aprint_normal(" slot %ld offset 0x%lx", (long)sa->sa_slot,
156 	       (u_long)sa->sa_offset);
157 	for (i = 0; i < sa->sa_nintr; i++) {
158 		struct openprom_intr *sbi = &sa->sa_intr[i];
159 
160 		aprint_normal(" vector %lx ipl %ld",
161 		       (u_long)sbi->oi_vec,
162 		       (long)INTLEV(sbi->oi_pri));
163 	}
164 	return (UNCONF);
165 }
166 
167 int
168 sbus_match(struct device *parent, struct cfdata *cf, void *aux)
169 {
170 	struct mainbus_attach_args *ma = aux;
171 
172 	return (strcmp(cf->cf_name, ma->ma_name) == 0);
173 }
174 
175 /*
176  * Attach an Sbus.
177  */
178 void
179 sbus_attach(struct device *parent, struct device *self, void *aux)
180 {
181 	struct sbus_softc *sc = (struct sbus_softc *)self;
182 	struct mainbus_attach_args *ma = aux;
183 	struct intrhand *ih;
184 	int ipl;
185 	char *name;
186 	int node = ma->ma_node;
187 	int node0, error;
188 	bus_space_tag_t sbt;
189 	struct sbus_attach_args sa;
190 
191 	sc->sc_bustag = ma->ma_bustag;
192 	sc->sc_dmatag = ma->ma_dmatag;
193 	sc->sc_ign = ma->ma_interrupts[0] & INTMAP_IGN;
194 
195 	/* XXXX Use sysio PROM mappings for interrupt vector regs. */
196 	sparc_promaddr_to_handle(sc->sc_bustag,	ma->ma_address[0], &sc->sc_bh);
197 	sc->sc_sysio = (struct sysioreg *)bus_space_vaddr(sc->sc_bustag,
198 		sc->sc_bh);
199 
200 #ifdef _LP64
201 	/*
202 	 * 32-bit kernels use virtual addresses for bus space operations
203 	 * so we may as well use the prom VA.
204 	 *
205 	 * 64-bit kernels use physical addresses for bus space operations
206 	 * so mapping this in again will reduce TLB thrashing.
207 	 */
208 	if (bus_space_map(sc->sc_bustag, ma->ma_reg[0].ur_paddr,
209 		ma->ma_reg[0].ur_len, 0, &sc->sc_bh) != 0) {
210 		printf("%s: cannot map registers\n", self->dv_xname);
211 		return;
212 	}
213 #endif
214 
215 	/*
216 	 * Record clock frequency for synchronous SCSI.
217 	 * IS THIS THE CORRECT DEFAULT??
218 	 */
219 	sc->sc_clockfreq = prom_getpropint(node, "clock-frequency",
220 		25*1000*1000);
221 	printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq));
222 
223 	sbt = bus_space_tag_alloc(sc->sc_bustag, sc);
224 	sbt->type = SBUS_BUS_SPACE;
225 	sbt->sparc_bus_map = _sbus_bus_map;
226 	sbt->sparc_intr_establish = sbus_intr_establish;
227 
228 	sc->sc_dmatag = sbus_alloc_dmatag(sc);
229 
230 	/*
231 	 * Get the SBus burst transfer size if burst transfers are supported
232 	 */
233 	sc->sc_burst = prom_getpropint(node, "burst-sizes", 0);
234 
235 	/*
236 	 * Collect address translations from the OBP.
237 	 */
238 	error = prom_getprop(node, "ranges", sizeof(struct openprom_range),
239 			 &sbt->nranges, &sbt->ranges);
240 	if (error)
241 		panic("%s: error getting ranges property", sc->sc_dev.dv_xname);
242 
243 	/* initialize the IOMMU */
244 
245 	/* punch in our copies */
246 	sc->sc_is.is_bustag = sc->sc_bustag;
247 	bus_space_subregion(sc->sc_bustag, sc->sc_bh,
248 		(vaddr_t)&((struct sysioreg *)NULL)->sys_iommu,
249 		sizeof (struct iommureg), &sc->sc_is.is_iommu);
250 
251 	/* initialize our strbuf_ctl */
252 	sc->sc_is.is_sb[0] = &sc->sc_sb;
253 	sc->sc_sb.sb_is = &sc->sc_is;
254 	bus_space_subregion(sc->sc_bustag, sc->sc_bh,
255 		(vaddr_t)&((struct sysioreg *)NULL)->sys_strbuf,
256 		sizeof (struct iommu_strbuf), &sc->sc_sb.sb_sb);
257 	/* Point sb_flush to our flush buffer. */
258 	sc->sc_sb.sb_flush = &sc->sc_flush;
259 
260 	/* give us a nice name.. */
261 	name = (char *)malloc(32, M_DEVBUF, M_NOWAIT);
262 	if (name == 0)
263 		panic("couldn't malloc iommu name");
264 	snprintf(name, 32, "%s dvma", sc->sc_dev.dv_xname);
265 
266 	iommu_init(name, &sc->sc_is, 0, -1);
267 
268 	/* Enable the over temp intr */
269 	ih = (struct intrhand *)
270 		malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT);
271 	ih->ih_map = &sc->sc_sysio->therm_int_map;
272 	ih->ih_clr = NULL; /* &sc->sc_sysio->therm_clr_int; */
273 	ih->ih_fun = sbus_overtemp;
274 	ipl = 1;
275 	ih->ih_pil = (1<<ipl);
276 	ih->ih_number = INTVEC(*(ih->ih_map));
277 	intr_establish(ipl, ih);
278 	*(ih->ih_map) |= INTMAP_V|(CPU_UPAID << INTMAP_TID_SHIFT);
279 
280 	/*
281 	 * Note: the stupid SBUS IOMMU ignores the high bits of an address, so a
282 	 * NULL DMA pointer will be translated by the first page of the IOTSB.
283 	 * To avoid bugs we'll alloc and ignore the first entry in the IOTSB.
284 	 */
285 	{
286 		u_long dummy;
287 
288 		if (extent_alloc_subregion(sc->sc_is.is_dvmamap,
289 		    sc->sc_is.is_dvmabase, sc->sc_is.is_dvmabase + PAGE_SIZE,
290 		    PAGE_SIZE, PAGE_SIZE, 0, EX_NOWAIT|EX_BOUNDZERO,
291 		    (u_long *)&dummy) != 0)
292 			panic("sbus iommu: can't toss first dvma page");
293 	}
294 
295 	/*
296 	 * Loop through ROM children, fixing any relative addresses
297 	 * and then configuring each device.
298 	 * `specials' is an array of device names that are treated
299 	 * specially:
300 	 */
301 	node0 = OF_child(node);
302 	for (node = node0; node; node = OF_peer(node)) {
303 		char *name1 = prom_getpropstring(node, "name");
304 
305 		if (sbus_setup_attach_args(sc, sbt, sc->sc_dmatag,
306 					   node, &sa) != 0) {
307 			printf("sbus_attach: %s: incomplete\n", name1);
308 			continue;
309 		}
310 		(void) config_found(&sc->sc_dev, (void *)&sa, sbus_print);
311 		sbus_destroy_attach_args(&sa);
312 	}
313 }
314 
315 int
316 sbus_setup_attach_args(struct sbus_softc *sc, bus_space_tag_t bustag,
317 	bus_dma_tag_t dmatag, int node, struct sbus_attach_args	*sa)
318 {
319 	/*struct	openprom_addr sbusreg;*/
320 	/*int	base;*/
321 	int	error;
322 	int n;
323 
324 	memset(sa, 0, sizeof(struct sbus_attach_args));
325 	n = 0;
326 	error = prom_getprop(node, "name", 1, &n, &sa->sa_name);
327 	if (error != 0)
328 		return (error);
329 	sa->sa_name[n] = '\0';
330 
331 	sa->sa_bustag = bustag;
332 	sa->sa_dmatag = dmatag;
333 	sa->sa_node = node;
334 	sa->sa_frequency = sc->sc_clockfreq;
335 
336 	error = prom_getprop(node, "reg", sizeof(struct openprom_addr),
337 			 &sa->sa_nreg, &sa->sa_reg);
338 	if (error != 0) {
339 		char buf[32];
340 		if (error != ENOENT ||
341 		    !node_has_property(node, "device_type") ||
342 		    strcmp(prom_getpropstringA(node, "device_type", buf, sizeof buf),
343 			   "hierarchical") != 0)
344 			return (error);
345 	}
346 	for (n = 0; n < sa->sa_nreg; n++) {
347 		/* Convert to relative addressing, if necessary */
348 		uint32_t base = sa->sa_reg[n].oa_base;
349 		if (SBUS_ABS(base)) {
350 			sa->sa_reg[n].oa_space = SBUS_ABS_TO_SLOT(base);
351 			sa->sa_reg[n].oa_base = SBUS_ABS_TO_OFFSET(base);
352 		}
353 	}
354 
355 	if ((error = sbus_get_intr(sc, node, &sa->sa_intr, &sa->sa_nintr,
356 	    sa->sa_slot)) != 0)
357 		return (error);
358 
359 	error = prom_getprop(node, "address", sizeof(uint32_t),
360 			 &sa->sa_npromvaddrs, &sa->sa_promvaddrs);
361 	if (error != 0 && error != ENOENT)
362 		return (error);
363 
364 	return (0);
365 }
366 
367 void
368 sbus_destroy_attach_args(struct sbus_attach_args *sa)
369 {
370 	if (sa->sa_name != NULL)
371 		free(sa->sa_name, M_DEVBUF);
372 
373 	if (sa->sa_nreg != 0)
374 		free(sa->sa_reg, M_DEVBUF);
375 
376 	if (sa->sa_intr)
377 		free(sa->sa_intr, M_DEVBUF);
378 
379 	if (sa->sa_promvaddrs)
380 		free((void *)sa->sa_promvaddrs, M_DEVBUF);
381 
382 	memset(sa, 0, sizeof(struct sbus_attach_args)); /*DEBUG*/
383 }
384 
385 
386 int
387 _sbus_bus_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, int flags,
388 	vaddr_t v, bus_space_handle_t *hp)
389 {
390 	int error;
391 
392 	if (t->ranges != NULL) {
393 		if ((error = bus_space_translate_address_generic(
394 				t->ranges, t->nranges, &addr)) != 0)
395 			return (error);
396 	}
397 
398 	return (bus_space_map(t->parent, addr, size, flags, hp));
399 }
400 
401 
402 bus_addr_t
403 sbus_bus_addr(bus_space_tag_t t, u_int btype, u_int offset)
404 {
405 	int slot = btype;
406 	struct openprom_range *rp;
407 	int i;
408 
409 	for (i = 0; i < t->nranges; i++) {
410 		rp = &t->ranges[i];
411 		if (rp->or_child_space != slot)
412 			continue;
413 
414 		return BUS_ADDR(rp->or_parent_space,
415 				rp->or_parent_base + offset);
416 	}
417 
418 	return (0);
419 }
420 
421 
422 /*
423  * Each attached device calls sbus_establish after it initializes
424  * its sbusdev portion.
425  */
426 void
427 sbus_establish(register struct sbusdev *sd, register struct device *dev)
428 {
429 	register struct sbus_softc *sc;
430 	register struct device *curdev;
431 
432 	/*
433 	 * We have to look for the sbus by name, since it is not necessarily
434 	 * our immediate parent (i.e. sun4m /iommu/sbus/espdma/esp)
435 	 * We don't just use the device structure of the above-attached
436 	 * sbus, since we might (in the future) support multiple sbus's.
437 	 */
438 	for (curdev = device_parent(dev); ; curdev = device_parent(curdev)) {
439 		if (!curdev || !curdev->dv_xname)
440 			panic("sbus_establish: can't find sbus parent for %s",
441 			      sd->sd_dev->dv_xname
442 					? sd->sd_dev->dv_xname
443 					: "<unknown>" );
444 
445 		if (strncmp(curdev->dv_xname, "sbus", 4) == 0)
446 			break;
447 	}
448 	sc = (struct sbus_softc *) curdev;
449 
450 	sd->sd_dev = dev;
451 	sd->sd_bchain = sc->sc_sbdev;
452 	sc->sc_sbdev = sd;
453 }
454 
455 /*
456  * Reset the given sbus.
457  */
458 void
459 sbusreset(int sbus)
460 {
461 	register struct sbusdev *sd;
462 	struct sbus_softc *sc = sbus_cd.cd_devs[sbus];
463 	struct device *dev;
464 
465 	printf("reset %s:", sc->sc_dev.dv_xname);
466 	for (sd = sc->sc_sbdev; sd != NULL; sd = sd->sd_bchain) {
467 		if (sd->sd_reset) {
468 			dev = sd->sd_dev;
469 			(*sd->sd_reset)(dev);
470 			printf(" %s", dev->dv_xname);
471 		}
472 	}
473 	/* Reload iommu regs */
474 	iommu_reset(&sc->sc_is);
475 }
476 
477 /*
478  * Handle an overtemp situation.
479  *
480  * SPARCs have temperature sensors which generate interrupts
481  * if the machine's temperature exceeds a certain threshold.
482  * This handles the interrupt and powers off the machine.
483  * The same needs to be done to PCI controller drivers.
484  */
485 int
486 sbus_overtemp(void *arg)
487 {
488 	/* Should try a clean shutdown first */
489 	printf("DANGER: OVER TEMPERATURE detected\nShutting down...\n");
490 	delay(20);
491 	cpu_reboot(RB_POWERDOWN|RB_HALT, NULL);
492 }
493 
494 /*
495  * Get interrupt attributes for an Sbus device.
496  */
497 int
498 sbus_get_intr(struct sbus_softc *sc, int node, struct openprom_intr **ipp,
499 	int *np, int slot)
500 {
501 	int *ipl;
502 	int n, i;
503 	char buf[32];
504 
505 	/*
506 	 * The `interrupts' property contains the Sbus interrupt level.
507 	 */
508 	ipl = NULL;
509 	if (prom_getprop(node, "interrupts", sizeof(int), np, &ipl) == 0) {
510 		struct openprom_intr *ip;
511 		int pri;
512 
513 		/* Default to interrupt level 2 -- otherwise unused */
514 		pri = INTLEVENCODE(2);
515 
516 		/* Change format to an `struct sbus_intr' array */
517 		ip = malloc(*np * sizeof(struct openprom_intr), M_DEVBUF,
518 		    M_NOWAIT);
519 		if (ip == NULL)
520 			return (ENOMEM);
521 
522 		/*
523 		 * Now things get ugly.  We need to take this value which is
524 		 * the interrupt vector number and encode the IPL into it
525 		 * somehow. Luckily, the interrupt vector has lots of free
526 		 * space and we can easily stuff the IPL in there for a while.
527 		 */
528 		prom_getpropstringA(node, "device_type", buf, sizeof buf);
529 		if (buf[0] == '\0')
530 			prom_getpropstringA(node, "name", buf, sizeof buf);
531 
532 		for (i = 0; intrmap[i].in_class; i++)
533 			if (strcmp(intrmap[i].in_class, buf) == 0) {
534 				pri = INTLEVENCODE(intrmap[i].in_lev);
535 				break;
536 			}
537 
538 		/*
539 		 * Sbus card devices need the slot number encoded into
540 		 * the vector as this is generally not done.
541 		 */
542 		if ((ipl[0] & INTMAP_OBIO) == 0)
543 			pri |= slot << 3;
544 
545 		for (n = 0; n < *np; n++) {
546 			/*
547 			 * We encode vector and priority into sbi_pri so we
548 			 * can pass them as a unit.  This will go away if
549 			 * sbus_establish ever takes an sbus_intr instead
550 			 * of an integer level.
551 			 * Stuff the real vector in sbi_vec.
552 			 */
553 
554 			ip[n].oi_pri = pri|ipl[n];
555 			ip[n].oi_vec = ipl[n];
556 		}
557 		free(ipl, M_DEVBUF);
558 		*ipp = ip;
559 	}
560 
561 	return (0);
562 }
563 
564 
565 /*
566  * Install an interrupt handler for an Sbus device.
567  */
568 void *
569 sbus_intr_establish(bus_space_tag_t t, int pri, int level,
570 	int (*handler)(void *), void *arg, void (*fastvec)(void))
571 {
572 	struct sbus_softc *sc = t->cookie;
573 	struct intrhand *ih;
574 	int ipl;
575 	long vec = pri;
576 
577 	ih = (struct intrhand *)
578 		malloc(sizeof(struct intrhand), M_DEVBUF, M_NOWAIT);
579 	if (ih == NULL)
580 		return (NULL);
581 
582 	if ((vec & SBUS_INTR_COMPAT) != 0)
583 		ipl = vec & ~SBUS_INTR_COMPAT;
584 	else {
585 		/* Decode and remove IPL */
586 		ipl = INTLEV(vec);
587 		vec = INTVEC(vec);
588 		DPRINTF(SDB_INTR,
589 		    ("\nsbus: intr[%ld]%lx: %lx\nHunting for IRQ...\n",
590 		    (long)ipl, (long)vec, (u_long)intrlev[vec]));
591 		if ((vec & INTMAP_OBIO) == 0) {
592 			/* We're in an SBUS slot */
593 			/* Register the map and clear intr registers */
594 
595 			int slot = INTSLOT(pri);
596 
597 			ih->ih_map = &(&sc->sc_sysio->sbus_slot0_int)[slot];
598 			ih->ih_clr = &sc->sc_sysio->sbus0_clr_int[vec];
599 #ifdef DEBUG
600 			if (sbus_debug & SDB_INTR) {
601 				int64_t imap = *ih->ih_map;
602 
603 				printf("SBUS %lx IRQ as %llx in slot %d\n",
604 				       (long)vec, (long long)imap, slot);
605 				printf("\tmap addr %p clr addr %p\n",
606 				    ih->ih_map, ih->ih_clr);
607 			}
608 #endif
609 			/* Enable the interrupt */
610 			vec |= INTMAP_V | sc->sc_ign |
611 				(CPU_UPAID << INTMAP_TID_SHIFT);
612 			*(ih->ih_map) = vec;
613 		} else {
614 			int64_t *intrptr = &sc->sc_sysio->scsi_int_map;
615 			int64_t imap = 0;
616 			int i;
617 
618 			/* Insert IGN */
619 			vec |= sc->sc_ign;
620 			for (i = 0; &intrptr[i] <=
621 			    (int64_t *)&sc->sc_sysio->reserved_int_map &&
622 			    INTVEC(imap = intrptr[i]) != INTVEC(vec); i++)
623 				;
624 			if (INTVEC(imap) == INTVEC(vec)) {
625 				DPRINTF(SDB_INTR,
626 				    ("OBIO %lx IRQ as %lx in slot %d\n",
627 				    vec, (long)imap, i));
628 				/* Register the map and clear intr registers */
629 				ih->ih_map = &intrptr[i];
630 				intrptr = (int64_t *)&sc->sc_sysio->scsi_clr_int;
631 				ih->ih_clr = &intrptr[i];
632 				/* Enable the interrupt */
633 				imap |= INTMAP_V
634 				    |(CPU_UPAID << INTMAP_TID_SHIFT);
635 				/* XXXX */
636 				*(ih->ih_map) = imap;
637 			} else
638 				panic("IRQ not found!");
639 		}
640 	}
641 #ifdef DEBUG
642 	if (sbus_debug & SDB_INTR) { long i; for (i = 0; i < 400000000; i++); }
643 #endif
644 
645 	ih->ih_fun = handler;
646 	ih->ih_arg = arg;
647 	ih->ih_number = vec;
648 	ih->ih_pil = (1<<ipl);
649 	intr_establish(ipl, ih);
650 	return (ih);
651 }
652 
653 static bus_dma_tag_t
654 sbus_alloc_dmatag(struct sbus_softc *sc)
655 {
656 	bus_dma_tag_t sdt, psdt = sc->sc_dmatag;
657 
658 	sdt = (bus_dma_tag_t)
659 		malloc(sizeof(struct sparc_bus_dma_tag), M_DEVBUF, M_NOWAIT);
660 	if (sdt == NULL)
661 		/* Panic? */
662 		return (psdt);
663 
664 	sdt->_cookie = sc;
665 	sdt->_parent = psdt;
666 #define PCOPY(x)	sdt->x = psdt->x
667 	PCOPY(_dmamap_create);
668 	PCOPY(_dmamap_destroy);
669 	sdt->_dmamap_load = sbus_dmamap_load;
670 	PCOPY(_dmamap_load_mbuf);
671 	PCOPY(_dmamap_load_uio);
672 	sdt->_dmamap_load_raw = sbus_dmamap_load_raw;
673 	sdt->_dmamap_unload = sbus_dmamap_unload;
674 	sdt->_dmamap_sync = sbus_dmamap_sync;
675 	sdt->_dmamem_alloc = sbus_dmamem_alloc;
676 	sdt->_dmamem_free = sbus_dmamem_free;
677 	sdt->_dmamem_map = sbus_dmamem_map;
678 	sdt->_dmamem_unmap = sbus_dmamem_unmap;
679 	PCOPY(_dmamem_mmap);
680 #undef	PCOPY
681 	sc->sc_dmatag = sdt;
682 	return (sdt);
683 }
684 
685 int
686 sbus_dmamap_load(bus_dma_tag_t tag, bus_dmamap_t map, void *buf,
687 	bus_size_t buflen, struct proc *p, int flags)
688 {
689 	struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie;
690 
691 	return (iommu_dvmamap_load(tag, &sc->sc_sb, map, buf, buflen, p, flags));
692 }
693 
694 int
695 sbus_dmamap_load_raw(bus_dma_tag_t tag, bus_dmamap_t map,
696 	bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags)
697 {
698 	struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie;
699 
700 	return (iommu_dvmamap_load_raw(tag, &sc->sc_sb, map, segs, nsegs, flags, size));
701 }
702 
703 void
704 sbus_dmamap_unload(bus_dma_tag_t tag, bus_dmamap_t map)
705 {
706 	struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie;
707 
708 	iommu_dvmamap_unload(tag, &sc->sc_sb, map);
709 }
710 
711 void
712 sbus_dmamap_sync(bus_dma_tag_t tag, bus_dmamap_t map, bus_addr_t offset,
713 	bus_size_t len, int ops)
714 {
715 	struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie;
716 
717 	if (ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) {
718 		/* Flush the CPU then the IOMMU */
719 		bus_dmamap_sync(tag->_parent, map, offset, len, ops);
720 		iommu_dvmamap_sync(tag, &sc->sc_sb, map, offset, len, ops);
721 	}
722 	if (ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) {
723 		/* Flush the IOMMU then the CPU */
724 		iommu_dvmamap_sync(tag, &sc->sc_sb, map, offset, len, ops);
725 		bus_dmamap_sync(tag->_parent, map, offset, len, ops);
726 	}
727 }
728 
729 int
730 sbus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, bus_size_t alignment,
731 	bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
732 	int flags)
733 {
734 	struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie;
735 
736 	return (iommu_dvmamem_alloc(tag, &sc->sc_sb, size, alignment, boundary,
737 	    segs, nsegs, rsegs, flags));
738 }
739 
740 void
741 sbus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs)
742 {
743 	struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie;
744 
745 	iommu_dvmamem_free(tag, &sc->sc_sb, segs, nsegs);
746 }
747 
748 int
749 sbus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs,
750 	size_t size, void **kvap, int flags)
751 {
752 	struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie;
753 
754 	return (iommu_dvmamem_map(tag, &sc->sc_sb, segs, nsegs, size, kvap, flags));
755 }
756 
757 void
758 sbus_dmamem_unmap(bus_dma_tag_t tag, void *kva, size_t size)
759 {
760 	struct sbus_softc *sc = (struct sbus_softc *)tag->_cookie;
761 
762 	iommu_dvmamem_unmap(tag, &sc->sc_sb, kva, size);
763 }
764