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