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