xref: /netbsd/sys/arch/sun68k/sun68k/bus.c (revision c4a72b64)
1 /*	$NetBSD: bus.c,v 1.7 2002/09/27 15:36:59 provos Exp $	*/
2 
3 /*
4  * Copyright (c) 2001 Matthew Fredette.
5  * Copyright (c) 1994, 1995 Gordon W. Ross
6  * Copyright (c) 1993 Adam Glass
7  * Copyright (c) 1988 University of Utah.
8  * Copyright (c) 1982, 1986, 1990, 1993
9  *	The Regents of the University of California.  All rights reserved.
10  *
11  * This code is derived from software contributed to Berkeley by
12  * the Systems Programming Group of the University of Utah Computer
13  * Science Department.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. All advertising materials mentioning features or use of this software
24  *    must display the following acknowledgement:
25  *	This product includes software developed by the University of
26  *	California, Berkeley and its contributors.
27  * 4. Neither the name of the University nor the names of its contributors
28  *    may be used to endorse or promote products derived from this software
29  *    without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
32  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
35  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41  * SUCH DAMAGE.
42  *
43  *	from: Utah Hdr: machdep.c 1.74 92/12/20
44  *	from: @(#)machdep.c	8.10 (Berkeley) 4/20/94
45  */
46 
47 /*-
48  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
49  * All rights reserved.
50  *
51  * This code is derived from software contributed to The NetBSD Foundation
52  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
53  * NASA Ames Research Center.
54  *
55  * Redistribution and use in source and binary forms, with or without
56  * modification, are permitted provided that the following conditions
57  * are met:
58  * 1. Redistributions of source code must retain the above copyright
59  *    notice, this list of conditions and the following disclaimer.
60  * 2. Redistributions in binary form must reproduce the above copyright
61  *    notice, this list of conditions and the following disclaimer in the
62  *    documentation and/or other materials provided with the distribution.
63  * 3. All advertising materials mentioning features or use of this software
64  *    must display the following acknowledgement:
65  *	This product includes software developed by the NetBSD
66  *	Foundation, Inc. and its contributors.
67  * 4. Neither the name of The NetBSD Foundation nor the names of its
68  *    contributors may be used to endorse or promote products derived
69  *    from this software without specific prior written permission.
70  *
71  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
72  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
73  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
74  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
75  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
76  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
77  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
78  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
79  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
80  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
81  * POSSIBILITY OF SUCH DAMAGE.
82  */
83 
84 /*
85  * Copyright (c) 1992, 1993
86  *	The Regents of the University of California.  All rights reserved.
87  *
88  * This software was developed by the Computer Systems Engineering group
89  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
90  * contributed to Berkeley.
91  *
92  * All advertising materials mentioning features or use of this software
93  * must display the following acknowledgement:
94  *	This product includes software developed by the University of
95  *	California, Lawrence Berkeley Laboratory.
96  *
97  * Redistribution and use in source and binary forms, with or without
98  * modification, are permitted provided that the following conditions
99  * are met:
100  * 1. Redistributions of source code must retain the above copyright
101  *    notice, this list of conditions and the following disclaimer.
102  * 2. Redistributions in binary form must reproduce the above copyright
103  *    notice, this list of conditions and the following disclaimer in the
104  *    documentation and/or other materials provided with the distribution.
105  * 3. All advertising materials mentioning features or use of this software
106  *    must display the following acknowledgement:
107  *	This product includes software developed by the University of
108  *	California, Berkeley and its contributors.
109  * 4. Neither the name of the University nor the names of its contributors
110  *    may be used to endorse or promote products derived from this software
111  *    without specific prior written permission.
112  *
113  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
114  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
115  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
116  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
117  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
118  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
119  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
120  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
121  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
122  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
123  * SUCH DAMAGE.
124  *
125  *	@(#)machdep.c	8.6 (Berkeley) 1/14/94
126  */
127 
128 #include <sys/param.h>
129 #include <sys/systm.h>
130 #include <sys/kernel.h>
131 #include <sys/device.h>
132 #include <sys/malloc.h>
133 #include <sys/mbuf.h>
134 
135 #include <uvm/uvm.h> /* XXX: not _extern ... need vm_map_create */
136 
137 #include <machine/pte.h>
138 #define _SUN68K_BUS_DMA_PRIVATE
139 #include <machine/autoconf.h>
140 #include <machine/bus.h>
141 #include <machine/intr.h>
142 #include <machine/pmap.h>
143 
144 #include <sun68k/sun68k/control.h>
145 
146 /*
147  * Common function for DMA map creation.  May be called by bus-specific
148  * DMA map creation functions.
149  */
150 int
151 _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
152 	bus_dma_tag_t t;
153 	bus_size_t size;
154 	int nsegments;
155 	bus_size_t maxsegsz;
156 	bus_size_t boundary;
157 	int flags;
158 	bus_dmamap_t *dmamp;
159 {
160 	struct sun68k_bus_dmamap *map;
161 	void *mapstore;
162 	size_t mapsize;
163 
164 	/*
165 	 * Allocate and initialize the DMA map.  The end of the map
166 	 * is a variable-sized array of segments, so we allocate enough
167 	 * room for them in one shot.
168 	 *
169 	 * Note we don't preserve the WAITOK or NOWAIT flags.  Preservation
170 	 * of ALLOCNOW notifies others that we've reserved these resources,
171 	 * and they are not to be freed.
172 	 *
173 	 * The bus_dmamap_t includes one bus_dma_segment_t, hence
174 	 * the (nsegments - 1).
175 	 */
176 	mapsize = sizeof(struct sun68k_bus_dmamap) +
177 	    (sizeof(bus_dma_segment_t) * (nsegments - 1));
178 	if ((mapstore = malloc(mapsize, M_DMAMAP,
179 	    (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
180 		return (ENOMEM);
181 
182 	bzero(mapstore, mapsize);
183 	map = (struct sun68k_bus_dmamap *)mapstore;
184 	map->_dm_size = size;
185 	map->_dm_segcnt = nsegments;
186 	map->_dm_maxsegsz = maxsegsz;
187 	map->_dm_boundary = boundary;
188 	map->_dm_align = PAGE_SIZE;
189 	map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
190 	map->dm_mapsize = 0;		/* no valid mappings */
191 	map->dm_nsegs = 0;
192 
193 	*dmamp = map;
194 	return (0);
195 }
196 
197 /*
198  * Common function for DMA map destruction.  May be called by bus-specific
199  * DMA map destruction functions.
200  */
201 void
202 _bus_dmamap_destroy(t, map)
203 	bus_dma_tag_t t;
204 	bus_dmamap_t map;
205 {
206 
207 	/*
208 	 * If the handle contains a valid mapping, unload it.
209 	 */
210 	if (map->dm_mapsize != 0)
211 		bus_dmamap_unload(t, map);
212 
213 	free(map, M_DMAMAP);
214 }
215 
216 /*
217  * Common function for DMA-safe memory allocation.  May be called
218  * by bus-specific DMA memory allocation functions.
219  */
220 int
221 _bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
222 	bus_dma_tag_t t;
223 	bus_size_t size, alignment, boundary;
224 	bus_dma_segment_t *segs;
225 	int nsegs;
226 	int *rsegs;
227 	int flags;
228 {
229 	vaddr_t low, high;
230 	struct pglist *mlist;
231 	int error;
232 extern	paddr_t avail_start;
233 extern	paddr_t avail_end;
234 
235 	/* Always round the size. */
236 	size = m68k_round_page(size);
237 	low = avail_start;
238 	high = avail_end;
239 
240 	if ((mlist = malloc(sizeof(*mlist), M_DEVBUF,
241 	    (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
242 		return (ENOMEM);
243 
244 	/*
245 	 * Allocate physical pages from the VM system.
246 	 */
247 	error = uvm_pglistalloc(size, low, high, 0, 0,
248 				mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
249 	if (error)
250 		return (error);
251 
252 	/*
253 	 * Simply keep a pointer around to the linked list, so
254 	 * bus_dmamap_free() can return it.
255 	 *
256 	 * NOBODY SHOULD TOUCH THE pageq FIELDS WHILE THESE PAGES
257 	 * ARE IN OUR CUSTODY.
258 	 */
259 	segs[0]._ds_mlist = mlist;
260 
261 	/*
262 	 * We now have physical pages, but no DVMA addresses yet. These
263 	 * will be allocated in bus_dmamap_load*() routines. Hence we
264 	 * save any alignment and boundary requirements in this dma
265 	 * segment.
266 	 */
267 	segs[0].ds_addr = 0;
268 	segs[0].ds_len = 0;
269 	segs[0]._ds_va = 0;
270 	*rsegs = 1;
271 	return (0);
272 }
273 
274 /*
275  * Common function for freeing DMA-safe memory.  May be called by
276  * bus-specific DMA memory free functions.
277  */
278 void
279 _bus_dmamem_free(t, segs, nsegs)
280 	bus_dma_tag_t t;
281 	bus_dma_segment_t *segs;
282 	int nsegs;
283 {
284 
285 	if (nsegs != 1)
286 		panic("bus_dmamem_free: nsegs = %d", nsegs);
287 
288 	/*
289 	 * Return the list of physical pages back to the VM system.
290 	 */
291 	uvm_pglistfree(segs[0]._ds_mlist);
292 	free(segs[0]._ds_mlist, M_DEVBUF);
293 }
294 
295 /*
296  * Common function for mapping DMA-safe memory.  May be called by
297  * bus-specific DMA memory map functions.
298  */
299 int
300 _bus_dmamem_map(t, segs, nsegs, size, kvap, flags)
301 	bus_dma_tag_t t;
302 	bus_dma_segment_t *segs;
303 	int nsegs;
304 	size_t size;
305 	caddr_t *kvap;
306 	int flags;
307 {
308 	struct vm_page *m;
309 	vaddr_t va;
310 	struct pglist *mlist;
311 
312 	if (nsegs != 1)
313 		panic("_bus_dmamem_map: nsegs = %d", nsegs);
314 
315 	size = m68k_round_page(size);
316 
317 	va = uvm_km_valloc(kernel_map, size);
318 	if (va == 0)
319 		return (ENOMEM);
320 
321 	segs[0]._ds_va = va;
322 	*kvap = (caddr_t)va;
323 
324 	mlist = segs[0]._ds_mlist;
325 	for (m = TAILQ_FIRST(mlist); m != NULL; m = TAILQ_NEXT(m,pageq)) {
326 		paddr_t pa;
327 
328 		if (size == 0)
329 			panic("_bus_dmamem_map: size botch");
330 
331 		pa = VM_PAGE_TO_PHYS(m);
332 		pmap_enter(pmap_kernel(), va, pa | PMAP_NC,
333 			   VM_PROT_READ | VM_PROT_WRITE,
334 			   VM_PROT_READ | VM_PROT_WRITE | PMAP_WIRED);
335 
336 		va += PAGE_SIZE;
337 		size -= PAGE_SIZE;
338 	}
339 	pmap_update(pmap_kernel());
340 
341 	return (0);
342 }
343 
344 /*
345  * Common function for unmapping DMA-safe memory.  May be called by
346  * bus-specific DMA memory unmapping functions.
347  */
348 void
349 _bus_dmamem_unmap(t, kva, size)
350 	bus_dma_tag_t t;
351 	caddr_t kva;
352 	size_t size;
353 {
354 
355 #ifdef DIAGNOSTIC
356 	if ((u_long)kva & PAGE_MASK)
357 		panic("_bus_dmamem_unmap");
358 #endif
359 
360 	size = m68k_round_page(size);
361 	uvm_unmap(kernel_map, (vaddr_t)kva, (vaddr_t)kva + size);
362 }
363 
364 /*
365  * Common functin for mmap(2)'ing DMA-safe memory.  May be called by
366  * bus-specific DMA mmap(2)'ing functions.
367  */
368 paddr_t
369 _bus_dmamem_mmap(t, segs, nsegs, off, prot, flags)
370 	bus_dma_tag_t t;
371 	bus_dma_segment_t *segs;
372 	int nsegs;
373 	off_t off;
374 	int prot, flags;
375 {
376 
377 	panic("_bus_dmamem_mmap: not implemented");
378 }
379 
380 /*
381  * Utility to allocate an aligned kernel virtual address range
382  */
383 vaddr_t
384 _bus_dma_valloc_skewed(size, boundary, align, skew)
385 	size_t size;
386 	u_long boundary;
387 	u_long align;
388 	u_long skew;
389 {
390 	size_t oversize;
391 	vaddr_t va, sva;
392 
393 	/*
394 	 * Find a region of kernel virtual addresses that is aligned
395 	 * to the given address modulo the requested alignment, i.e.
396 	 *
397 	 *	(va - skew) == 0 mod align
398 	 *
399 	 * The following conditions apply to the arguments:
400 	 *
401 	 *	- `size' must be a multiple of the VM page size
402 	 *	- `align' must be a power of two
403 	 *	   and greater than or equal to the VM page size
404 	 *	- `skew' must be smaller than `align'
405 	 *	- `size' must be smaller than `boundary'
406 	 */
407 
408 #ifdef DIAGNOSTIC
409 	if ((size & PAGE_MASK) != 0)
410 		panic("_bus_dma_valloc_skewed: invalid size %lx", (unsigned long) size);
411 	if ((align & PAGE_MASK) != 0)
412 		panic("_bus_dma_valloc_skewed: invalid alignment %lx", align);
413 	if (align < skew)
414 		panic("_bus_dma_valloc_skewed: align %lx < skew %lx",
415 			align, skew);
416 #endif
417 
418 	/* XXX - Implement this! */
419 	if (boundary)
420 		panic("_bus_dma_valloc_skewed: not implemented");
421 
422 	/*
423 	 * First, find a region large enough to contain any aligned chunk
424 	 */
425 	oversize = size + align - PAGE_SIZE;
426 	sva = uvm_km_valloc(kernel_map, oversize);
427 	if (sva == 0)
428 		return (ENOMEM);
429 
430 	/*
431 	 * Compute start of aligned region
432 	 */
433 	va = sva;
434 	va += (skew + align - va) & (align - 1);
435 
436 	/*
437 	 * Return excess virtual addresses
438 	 */
439 	if (va != sva)
440 		(void)uvm_unmap(kernel_map, sva, va);
441 	if (va + size != sva + oversize)
442 		(void)uvm_unmap(kernel_map, va + size, sva + oversize);
443 
444 	return (va);
445 }
446 
447 /*
448  * Like _bus_dmamap_load(), but for mbufs.
449  */
450 int
451 _bus_dmamap_load_mbuf(t, map, m, flags)
452 	bus_dma_tag_t t;
453 	bus_dmamap_t map;
454 	struct mbuf *m;
455 	int flags;
456 {
457 
458 	panic("_bus_dmamap_load_mbuf: not implemented");
459 }
460 
461 /*
462  * Like _bus_dmamap_load(), but for uios.
463  */
464 int
465 _bus_dmamap_load_uio(t, map, uio, flags)
466 	bus_dma_tag_t t;
467 	bus_dmamap_t map;
468 	struct uio *uio;
469 	int flags;
470 {
471 
472 	panic("_bus_dmamap_load_uio: not implemented");
473 }
474 
475 /*
476  * Common function for DMA map synchronization.  May be called
477  * by bus-specific DMA map synchronization functions.
478  */
479 void
480 _bus_dmamap_sync(t, map, offset, len, ops)
481 	bus_dma_tag_t t;
482 	bus_dmamap_t map;
483 	bus_addr_t offset;
484 	bus_size_t len;
485 	int ops;
486 {
487 }
488 
489 struct sun68k_bus_dma_tag mainbus_dma_tag = {
490 	NULL,
491 	_bus_dmamap_create,
492 	_bus_dmamap_destroy,
493 	_bus_dmamap_load,
494 	_bus_dmamap_load_mbuf,
495 	_bus_dmamap_load_uio,
496 	_bus_dmamap_load_raw,
497 	_bus_dmamap_unload,
498 	_bus_dmamap_sync,
499 
500 	_bus_dmamem_alloc,
501 	_bus_dmamem_free,
502 	_bus_dmamem_map,
503 	_bus_dmamem_unmap,
504 	_bus_dmamem_mmap
505 };
506 
507 
508 /*
509  * Base bus space handlers.
510  */
511 int		sun68k_find_prom_map __P(( bus_addr_t, bus_type_t,
512 					   int, bus_space_handle_t *));
513 static int	sun68k_bus_map __P(( bus_space_tag_t, bus_type_t, bus_addr_t,
514 				    bus_size_t, int, vaddr_t,
515 				    bus_space_handle_t *));
516 static int	sun68k_bus_unmap __P((bus_space_tag_t, bus_space_handle_t,
517 				     bus_size_t));
518 static int	sun68k_bus_subregion __P((bus_space_tag_t, bus_space_handle_t,
519 					 bus_size_t, bus_size_t,
520 					 bus_space_handle_t *));
521 static paddr_t	sun68k_bus_mmap __P((bus_space_tag_t, bus_type_t,
522 				    bus_addr_t, off_t, int, int));
523 static void	*sun68k_mainbus_intr_establish __P((bus_space_tag_t, int, int,
524 						   int, int (*) __P((void *)),
525 						   void *));
526 static void     sun68k_bus_barrier __P(( bus_space_tag_t, bus_space_handle_t,
527 					bus_size_t, bus_size_t, int));
528 static int	sun68k_bus_peek __P(( bus_space_tag_t, bus_space_handle_t,
529 				      bus_size_t, size_t, void *));
530 static int	sun68k_bus_poke __P(( bus_space_tag_t, bus_space_handle_t,
531 				      bus_size_t, size_t, u_int32_t));
532 
533 /*
534  * If we can find a mapping that was established by the PROM, use it.
535  */
536 int
537 sun68k_find_prom_map(pa, iospace, len, hp)
538 	bus_addr_t	pa;
539 	bus_type_t	iospace;
540 	int		len;
541 	bus_space_handle_t *hp;
542 {
543 	u_long	pf;
544 	int	pgtype;
545 	u_long	va, eva;
546 	int	sme;
547 	u_long	pte;
548 	int	saved_ctx;
549 
550 	/*
551 	 * The mapping must fit entirely within one page.
552 	 */
553 	if ((((u_long)pa & PGOFSET) + len) > NBPG)
554 		return (EINVAL);
555 
556 	pf = PA_PGNUM(pa);
557 	pgtype = iospace << PG_MOD_SHIFT;
558 	saved_ctx = kernel_context();
559 
560 	/*
561 	 * Walk the PROM address space, looking for a page with the
562 	 * mapping we want.
563 	 */
564 	for (va = SUN_MONSTART; va < SUN_MONEND; ) {
565 
566 		/*
567 		 * Make sure this segment is mapped.
568 		 */
569 		sme = get_segmap(va);
570 		if (sme == SEGINV) {
571 			va += NBSG;
572 			continue;			/* next segment */
573 		}
574 
575 		/*
576 		 * Walk the pages of this segment.
577 		 */
578 		for(eva = va + NBSG; va < eva; va += NBPG) {
579 			pte = get_pte(va);
580 
581 			if ((pte & (PG_VALID | PG_TYPE)) ==
582 				(PG_VALID | pgtype) &&
583 			    PG_PFNUM(pte) == pf)
584 			{
585 				/*
586 				 * Found the PROM mapping.
587 				 * note: preserve page offset
588 				 */
589 				*hp = (bus_space_handle_t)(va | ((u_long)pa & PGOFSET));
590 				restore_context(saved_ctx);
591 				return (0);
592 			}
593 		}
594 	}
595 	restore_context(saved_ctx);
596 	return (ENOENT);
597 }
598 
599 int
600 sun68k_bus_map(t, iospace, addr, size, flags, vaddr, hp)
601 	bus_space_tag_t t;
602 	bus_type_t	iospace;
603 	bus_addr_t	addr;
604 	bus_size_t	size;
605 	vaddr_t		vaddr;
606 	bus_space_handle_t *hp;
607 {
608 	bus_size_t	offset;
609 	vaddr_t v;
610 
611 	/*
612 	 * If we suspect there might be one, try to find
613 	 * and use a PROM mapping.
614 	 */
615 	if ((flags & _SUN68K_BUS_MAP_USE_PROM) != 0 &&
616 	     sun68k_find_prom_map(addr, iospace, size, hp) == 0)
617 		return (0);
618 
619 	/*
620 	 * Adjust the user's request to be page-aligned.
621 	 */
622 	offset = addr & PGOFSET;
623 	addr -= offset;
624 	size += offset;
625 	size = m68k_round_page(size);
626 	if (size == 0) {
627 		printf("sun68k_bus_map: zero size\n");
628 		return (EINVAL);
629 	}
630 
631 	/* Get some kernel virtual address space. */
632 	if (vaddr)
633 		v = vaddr;
634 	else
635 		v = uvm_km_valloc_wait(kernel_map, size);
636 	if (v == 0)
637 		panic("sun68k_bus_map: no memory");
638 
639 	/* note: preserve page offset */
640 	*hp = (bus_space_handle_t)(v | offset);
641 
642 	/*
643 	 * Map the device.
644 	 */
645 	addr |= iospace | PMAP_NC;
646 	pmap_map(v, addr, addr + size, VM_PROT_ALL);
647 
648 	return (0);
649 }
650 
651 int
652 sun68k_bus_unmap(t, bh, size)
653 	bus_space_tag_t t;
654 	bus_size_t	size;
655 	bus_space_handle_t bh;
656 {
657 	bus_size_t	offset;
658 	vaddr_t va = (vaddr_t)bh;
659 
660 	/*
661 	 * Adjust the user's request to be page-aligned.
662 	 */
663 	offset = va & PGOFSET;
664 	va -= offset;
665 	size += offset;
666 	size = m68k_round_page(size);
667 	if (size == 0) {
668 		printf("sun68k_bus_unmap: zero size\n");
669 		return (EINVAL);
670 	}
671 
672 	/*
673 	 * If any part of the request is in the PROM's address space,
674 	 * don't unmap it.
675 	 */
676 #ifdef	DIAGNOSTIC
677 	if ((va >= SUN_MONSTART && va < SUN_MONEND) !=
678 	    ((va + size) >= SUN_MONSTART && (va + size) < SUN_MONEND))
679 		panic("sun_bus_unmap: bad PROM mapping");
680 #endif
681 	if (va >= SUN_MONSTART && va < SUN_MONEND)
682 		return (0);
683 
684 	uvm_km_free_wakeup(kernel_map, va, size);
685 	return (0);
686 }
687 
688 int
689 sun68k_bus_subregion(tag, handle, offset, size, nhandlep)
690 	bus_space_tag_t		tag;
691 	bus_space_handle_t	handle;
692 	bus_size_t		offset;
693 	bus_size_t		size;
694 	bus_space_handle_t	*nhandlep;
695 {
696 	*nhandlep = handle + offset;
697 	return (0);
698 }
699 
700 paddr_t
701 sun68k_bus_mmap(t, iospace, paddr, offset, prot, flags)
702 	bus_space_tag_t t;
703 	bus_type_t	iospace;
704 	bus_addr_t	paddr;
705 	off_t		offset;
706 	int		prot;
707 	int		flags;
708 {
709 	paddr_t npaddr;
710 	npaddr = m68k_trunc_page(paddr + offset);
711 	return (npaddr | (paddr_t)iospace | PMAP_NC);
712 }
713 
714 /*
715  * These assist in device probes.
716  */
717 
718 extern label_t *nofault;
719 
720 int
721 sun68k_bus_peek(tag, handle, offset, size, vp)
722 	bus_space_tag_t 	tag;
723 	bus_space_handle_t	handle;
724 	bus_size_t		offset;
725 	size_t			size;
726 	void 			*vp;
727 {
728 	int result;
729 	label_t	faultbuf;
730 	u_int32_t junk;
731 
732 	if (vp == NULL)
733 		vp = &junk;
734 
735 	nofault = &faultbuf;
736 	if (setjmp(&faultbuf))
737 		result = -1;
738 	else {
739 		switch(size) {
740 		case 1:
741 			*((u_int8_t *) vp) = bus_space_read_1(tag, handle, offset);
742 			break;
743 		case 2:
744 			*((u_int16_t *) vp) = bus_space_read_2(tag, handle, offset);
745 			break;
746 		case 4:
747 			*((u_int32_t *) vp) = bus_space_read_4(tag, handle, offset);
748 			break;
749 		default:
750 			panic("_bus_space_peek: bad size");
751 		}
752 		result = 0;
753 	}
754 
755 	nofault = NULL;
756 	return (result);
757 }
758 
759 int
760 sun68k_bus_poke(tag, handle, offset, size, v)
761 	bus_space_tag_t 	tag;
762 	bus_space_handle_t	handle;
763 	bus_size_t		offset;
764 	size_t			size;
765 	u_int32_t		v;
766 {
767 	int result;
768 	label_t	faultbuf;
769 
770 	nofault = &faultbuf;
771 	if (setjmp(&faultbuf))
772 		result = -1;
773 	else {
774 		switch(size) {
775 		case 1:
776 			bus_space_write_1(tag, handle, offset, (u_int8_t) v);
777 			break;
778 		case 2:
779 			bus_space_write_2(tag, handle, offset, (u_int16_t) v);
780 			break;
781 		case 4:
782 			bus_space_write_4(tag, handle, offset, (u_int32_t) v);
783 			break;
784 		default:
785 			panic("_bus_space_poke: bad size");
786 		}
787 		result = 0;
788 	}
789 
790 	nofault = NULL;
791 	return (result);
792 }
793 
794 void *
795 sun68k_mainbus_intr_establish(t, pil, level, flags, handler, arg)
796 	bus_space_tag_t t;
797 	int	pil;
798 	int	level;
799 	int	flags;
800 	int	(*handler)__P((void *));
801 	void	*arg;
802 {
803 	isr_add_autovect(handler, arg, pil);
804 	return (NULL);
805 }
806 
807 void sun68k_bus_barrier (t, h, offset, size, flags)
808 	bus_space_tag_t	t;
809 	bus_space_handle_t h;
810 	bus_size_t	offset;
811 	bus_size_t	size;
812 	int		flags;
813 {
814 	/* No default barrier action defined */
815 	return;
816 }
817 
818 struct sun68k_bus_space_tag mainbus_space_tag = {
819 	NULL,				/* cookie */
820 	NULL,				/* parent bus tag */
821 	sun68k_bus_map,			/* bus_space_map */
822 	sun68k_bus_unmap,		/* bus_space_unmap */
823 	sun68k_bus_subregion,		/* bus_space_subregion */
824 	sun68k_bus_barrier,		/* bus_space_barrier */
825 	sun68k_bus_mmap,		/* bus_space_mmap */
826 	sun68k_mainbus_intr_establish,	/* bus_intr_establish */
827 	sun68k_bus_peek,		/* bus_space_peek_N */
828 	sun68k_bus_poke			/* bus_space_poke_N */
829 };
830