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