bus_machdep.c revision 91782
1/*- 2 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 7 * NASA Ames Research Center. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37/* 38 * Copyright (c) 1992, 1993 39 * The Regents of the University of California. All rights reserved. 40 * 41 * This software was developed by the Computer Systems Engineering group 42 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 43 * contributed to Berkeley. 44 * 45 * All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the University of 48 * California, Lawrence Berkeley Laboratory. 49 * 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 1. Redistributions of source code must retain the above copyright 54 * notice, this list of conditions and the following disclaimer. 55 * 2. Redistributions in binary form must reproduce the above copyright 56 * notice, this list of conditions and the following disclaimer in the 57 * documentation and/or other materials provided with the distribution. 58 * 3. All advertising materials mentioning features or use of this software 59 * must display the following acknowledgement: 60 * This product includes software developed by the University of 61 * California, Berkeley and its contributors. 62 * 4. Neither the name of the University nor the names of its contributors 63 * may be used to endorse or promote products derived from this software 64 * without specific prior written permission. 65 * 66 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 67 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 68 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 69 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 70 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 71 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 72 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 73 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 74 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 75 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 76 * SUCH DAMAGE. 77 */ 78/* 79 * Copyright (c) 1997, 1998 Justin T. Gibbs. 80 * All rights reserved. 81 * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved. 82 * 83 * Redistribution and use in source and binary forms, with or without 84 * modification, are permitted provided that the following conditions 85 * are met: 86 * 1. Redistributions of source code must retain the above copyright 87 * notice, this list of conditions, and the following disclaimer, 88 * without modification, immediately at the beginning of the file. 89 * 2. The name of the author may not be used to endorse or promote products 90 * derived from this software without specific prior written permission. 91 * 92 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 93 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 95 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 96 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 97 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 98 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 100 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 101 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 102 * SUCH DAMAGE. 103 * 104 * from: @(#)machdep.c 8.6 (Berkeley) 1/14/94 105 * from: NetBSD: machdep.c,v 1.111 2001/09/15 07:13:40 eeh Exp 106 * and 107 * from: FreeBSD: src/sys/i386/i386/busdma_machdep.c,v 1.24 2001/08/15 108 * 109 * $FreeBSD: head/sys/sparc64/sparc64/bus_machdep.c 91782 2002-03-07 05:25:15Z jake $ 110 */ 111 112#include <sys/param.h> 113#include <sys/bus.h> 114#include <sys/malloc.h> 115#include <sys/proc.h> 116#include <sys/systm.h> 117 118#include <vm/vm.h> 119#include <vm/vm_extern.h> 120#include <vm/vm_kern.h> 121#include <vm/vm_page.h> 122#include <vm/vm_param.h> 123 124#include <machine/asi.h> 125#include <machine/bus.h> 126#include <machine/cache.h> 127#include <machine/pmap.h> 128#include <machine/tlb.h> 129 130/* ASI's for bus access. */ 131int bus_type_asi[] = { 132 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* UPA */ 133 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* SBUS */ 134 ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI configuration space */ 135 ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI memory space */ 136 ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI I/O space */ 137 0 138}; 139 140int bus_stream_asi[] = { 141 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* UPA */ 142 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* SBUS */ 143 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI configuration space */ 144 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI memory space */ 145 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI I/O space */ 146 0 147}; 148 149/* 150 * busdma support code. 151 * Note: there is no support for bounce buffers yet. 152 */ 153 154static int nexus_dmamap_create(bus_dma_tag_t, int, bus_dmamap_t *); 155static int nexus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); 156static int nexus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, 157 bus_dmamap_callback_t *, void *, int); 158static void nexus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); 159static void nexus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); 160static int nexus_dmamem_alloc(bus_dma_tag_t, void **, int, bus_dmamap_t *); 161static void nexus_dmamem_free(bus_dma_tag_t, void *, bus_dmamap_t); 162 163 164bus_dma_tag_t sparc64_root_dma_tag; 165 166/* 167 * Allocate a device specific dma_tag. 168 */ 169int 170bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, 171 bus_size_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, 172 bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, 173 int nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat) 174{ 175 176 bus_dma_tag_t newtag, eparent; 177 178 /* Return a NULL tag on failure */ 179 *dmat = NULL; 180 181 newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT); 182 if (newtag == NULL) 183 return (ENOMEM); 184 185 /* Ugh... */ 186 eparent = parent != NULL ? parent : sparc64_root_dma_tag; 187 memcpy(newtag, eparent, sizeof(*newtag)); 188 if (parent != NULL) 189 newtag->parent = parent; 190 newtag->alignment = alignment; 191 newtag->boundary = boundary; 192 newtag->lowaddr = trunc_page((vm_offset_t)lowaddr) + (PAGE_SIZE - 1); 193 newtag->highaddr = trunc_page((vm_offset_t)highaddr) + (PAGE_SIZE - 1); 194 newtag->filter = filter; 195 newtag->filterarg = filterarg; 196 newtag->maxsize = maxsize; 197 newtag->nsegments = nsegments; 198 newtag->maxsegsz = maxsegsz; 199 newtag->flags = flags; 200 newtag->ref_count = 1; /* Count ourself */ 201 newtag->map_count = 0; 202 203 /* Take into account any restrictions imposed by our parent tag */ 204 if (parent != NULL) { 205 newtag->lowaddr = ulmin(parent->lowaddr, newtag->lowaddr); 206 newtag->highaddr = ulmax(parent->highaddr, newtag->highaddr); 207 /* 208 * XXX Not really correct??? Probably need to honor boundary 209 * all the way up the inheritence chain. 210 */ 211 newtag->boundary = ulmax(parent->boundary, newtag->boundary); 212 if (parent != NULL) 213 parent->ref_count++; 214 } 215 216 *dmat = newtag; 217 return (0); 218} 219 220int 221bus_dma_tag_destroy(bus_dma_tag_t dmat) 222{ 223 224 if (dmat != NULL) { 225 if (dmat->map_count != 0) 226 return (EBUSY); 227 228 while (dmat != NULL) { 229 bus_dma_tag_t parent; 230 231 parent = dmat->parent; 232 dmat->ref_count--; 233 if (dmat->ref_count == 0) { 234 free(dmat, M_DEVBUF); 235 /* 236 * Last reference count, so 237 * release our reference 238 * count on our parent. 239 */ 240 dmat = parent; 241 } else 242 dmat = NULL; 243 } 244 } 245 return (0); 246} 247 248/* 249 * Common function for DMA map creation. May be called by bus-specific 250 * DMA map creation functions. 251 */ 252static int 253nexus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) 254{ 255 256 /* Not much to do...? */ 257 *mapp = malloc(sizeof(**mapp), M_DEVBUF, M_WAITOK | M_ZERO); 258 dmat->map_count++; 259 return (0); 260} 261 262/* 263 * Common function for DMA map destruction. May be called by bus-specific 264 * DMA map destruction functions. 265 */ 266static int 267nexus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 268{ 269 270 free(map, M_DEVBUF); 271 dmat->map_count--; 272 return (0); 273} 274 275#define BUS_DMAMAP_NSEGS ((BUS_SPACE_MAXSIZE / PAGE_SIZE) + 1) 276 277/* 278 * Common function for loading a DMA map with a linear buffer. May 279 * be called by bus-specific DMA map load functions. 280 * 281 * Most SPARCs have IOMMUs in the bus controllers. In those cases 282 * they only need one segment and will use virtual addresses for DVMA. 283 * Those bus controllers should intercept these vectors and should 284 * *NEVER* call nexus_dmamap_load() which is used only by devices that 285 * bypass DVMA. 286 */ 287static int 288nexus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 289 bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, 290 int flags) 291{ 292 vm_offset_t vaddr; 293 vm_offset_t paddr; 294#ifdef __GNUC__ 295 bus_dma_segment_t dm_segments[dmat->nsegments]; 296#else 297 bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; 298#endif 299 bus_dma_segment_t *sg; 300 int seg; 301 int error; 302 vm_offset_t nextpaddr; 303 bus_size_t size; 304 305 error = 0; 306 307 vaddr = (vm_offset_t)buf; 308 sg = &dm_segments[0]; 309 seg = 1; 310 sg->ds_len = 0; 311 312 map->buf = buf; 313 map->buflen = buflen; 314 map->start = (bus_addr_t)buf; 315 316 nextpaddr = 0; 317 do { 318 paddr = pmap_kextract(vaddr); 319 size = PAGE_SIZE - (paddr & PAGE_MASK); 320 if (size > buflen) 321 size = buflen; 322 323 if (sg->ds_len == 0) { 324 sg->ds_addr = paddr; 325 sg->ds_len = size; 326 } else if (paddr == nextpaddr) { 327 sg->ds_len += size; 328 } else { 329 /* Go to the next segment */ 330 sg++; 331 seg++; 332 if (seg > dmat->nsegments) 333 break; 334 sg->ds_addr = paddr; 335 sg->ds_len = size; 336 } 337 vaddr += size; 338 nextpaddr = paddr + size; 339 buflen -= size; 340 } while (buflen > 0); 341 342 if (buflen != 0) { 343 printf("bus_dmamap_load: Too many segs! buf_len = 0x%lx\n", 344 (u_long)buflen); 345 error = EFBIG; 346 } 347 348 (*callback)(callback_arg, dm_segments, seg, error); 349 350 return (0); 351} 352 353/* 354 * Common function for unloading a DMA map. May be called by 355 * bus-specific DMA map unload functions. 356 */ 357static void 358nexus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) 359{ 360 361 /* Nothing to do...? */ 362} 363 364/* 365 * Common function for DMA map synchronization. May be called 366 * by bus-specific DMA map synchronization functions. 367 */ 368static void 369nexus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) 370{ 371 372 /* 373 * We sync out our caches, but the bus must do the same. 374 * 375 * Actually a #Sync is expensive. We should optimize. 376 */ 377 if ((op == BUS_DMASYNC_PREREAD) || (op == BUS_DMASYNC_PREWRITE)) { 378 /* 379 * Don't really need to do anything, but flush any pending 380 * writes anyway. 381 */ 382 membar(Sync); 383 } 384 if (op == BUS_DMASYNC_POSTREAD) { 385 /* 386 * Invalidate the caches (it is unclear whether that is really 387 * needed. The manual only mentions that PCI transactions are 388 * cache coherent). 389 */ 390 ecache_flush((vm_offset_t)map->buf, 391 (vm_offset_t)map->buf + map->buflen - 1); 392 } 393 if (op == BUS_DMASYNC_POSTWRITE) { 394 /* Nothing to do. Handled by the bus controller. */ 395 } 396} 397 398/* 399 * Helper functions for buses that use their private dmamem_alloc/dmamem_free 400 * versions. 401 * These differ from the dmamap_alloc() functions in that they create a tag 402 * that is specifically for use with dmamem_alloc'ed memory. 403 * These are primitive now, but I expect that some fields of the map will need 404 * to be filled soon. 405 */ 406int 407sparc64_dmamem_alloc_map(bus_dma_tag_t dmat, bus_dmamap_t *mapp) 408{ 409 410 *mapp = malloc(sizeof(**mapp), M_DEVBUF, M_WAITOK | M_ZERO); 411 if (*mapp == NULL) 412 return (ENOMEM); 413 414 dmat->map_count++; 415 return (0); 416} 417 418void 419sparc64_dmamem_free_map(bus_dma_tag_t dmat, bus_dmamap_t map) 420{ 421 422 free(map, M_DEVBUF); 423 dmat->map_count--; 424} 425 426/* 427 * Common function for DMA-safe memory allocation. May be called 428 * by bus-specific DMA memory allocation functions. 429 */ 430static int 431nexus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags, 432 bus_dmamap_t *mapp) 433{ 434 435 if ((dmat->maxsize <= PAGE_SIZE)) { 436 *vaddr = malloc(dmat->maxsize, M_DEVBUF, 437 (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK); 438 } else { 439 /* 440 * XXX: Use contigmalloc until it is merged into this facility 441 * and handles multi-seg allocations. Nobody is doing multi-seg 442 * allocations yet though. 443 */ 444 *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, 445 (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK, 446 0ul, dmat->lowaddr, dmat->alignment ? dmat->alignment : 1UL, 447 dmat->boundary); 448 } 449 if (*vaddr == NULL) { 450 free(*mapp, M_DEVBUF); 451 return (ENOMEM); 452 } 453 return (0); 454} 455 456/* 457 * Common function for freeing DMA-safe memory. May be called by 458 * bus-specific DMA memory free functions. 459 */ 460static void 461nexus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) 462{ 463 464 sparc64_dmamem_free_map(dmat, map); 465 if ((dmat->maxsize <= PAGE_SIZE)) 466 free(vaddr, M_DEVBUF); 467 else 468 contigfree(vaddr, dmat->maxsize, M_DEVBUF); 469} 470 471struct bus_dma_tag nexus_dmatag = { 472 NULL, 473 NULL, 474 8, 475 0, 476 0, 477 0x3ffffffff, 478 NULL, /* XXX */ 479 NULL, 480 0x3ffffffff, /* XXX */ 481 0xff, /* XXX */ 482 0xffffffff, /* XXX */ 483 0, 484 0, 485 0, 486 nexus_dmamap_create, 487 nexus_dmamap_destroy, 488 nexus_dmamap_load, 489 nexus_dmamap_unload, 490 nexus_dmamap_sync, 491 492 nexus_dmamem_alloc, 493 nexus_dmamem_free, 494}; 495 496/* 497 * Helpers to map/unmap bus memory 498 */ 499int 500sparc64_bus_mem_map(bus_space_tag_t tag, bus_space_handle_t handle, 501 bus_size_t size, int flags, vm_offset_t vaddr, void **hp) 502{ 503 vm_offset_t addr; 504 vm_offset_t sva; 505 vm_offset_t va; 506 vm_offset_t pa; 507 vm_size_t vsz; 508 u_long pm_flags; 509 510 addr = (vm_offset_t)handle; 511 size = round_page(size); 512 if (size == 0) { 513 printf("sparc64_bus_map: zero size\n"); 514 return (EINVAL); 515 } 516 switch (tag->type) { 517 case PCI_CONFIG_BUS_SPACE: 518 case PCI_IO_BUS_SPACE: 519 case PCI_MEMORY_BUS_SPACE: 520 pm_flags = TD_IE; 521 break; 522 default: 523 pm_flags = 0; 524 break; 525 } 526 527 if (!(flags & BUS_SPACE_MAP_CACHEABLE)) 528 pm_flags |= TD_E; 529 530 if (vaddr != NULL) 531 sva = trunc_page(vaddr); 532 else { 533 if ((sva = kmem_alloc_nofault(kernel_map, size)) == NULL) 534 panic("sparc64_bus_map: cannot allocate virtual " 535 "memory"); 536 } 537 538 /* note: preserve page offset */ 539 *hp = (void *)(sva | ((u_long)addr & PAGE_MASK)); 540 541 pa = trunc_page(addr); 542 if ((flags & BUS_SPACE_MAP_READONLY) == 0) 543 pm_flags |= TD_W; 544 545 va = sva; 546 vsz = size; 547 do { 548 pmap_kenter_flags(va, pa, pm_flags); 549 va += PAGE_SIZE; 550 pa += PAGE_SIZE; 551 } while ((vsz -= PAGE_SIZE) > 0); 552 tlb_range_demap(kernel_pmap, sva, sva + size - 1); 553 return (0); 554} 555 556int 557sparc64_bus_mem_unmap(void *bh, bus_size_t size) 558{ 559 vm_offset_t sva; 560 vm_offset_t va; 561 vm_offset_t endva; 562 563 sva = trunc_page((vm_offset_t)bh); 564 endva = sva + round_page(size); 565 for (va = sva; va < endva; va += PAGE_SIZE) 566 pmap_kremove(va); 567 tlb_range_demap(kernel_pmap, sva, sva + size - 1); 568 kmem_free(kernel_map, va, size); 569 return (0); 570} 571 572/* 573 * Fake up a bus tag, for use by console drivers in early boot when the regular 574 * means to allocate resources are not yet available. 575 * Note that these tags are not eligible for bus_space_barrier operations. 576 * Addr is the physical address of the desired start of the handle. 577 */ 578bus_space_handle_t 579sparc64_fake_bustag(int space, bus_addr_t addr, struct bus_space_tag *ptag) 580{ 581 582 ptag->cookie = NULL; 583 ptag->parent = NULL; 584 ptag->type = space; 585 ptag->bus_barrier = NULL; 586 return (addr); 587} 588 589/* 590 * Base bus space handlers. 591 */ 592static void nexus_bus_barrier(bus_space_tag_t, bus_space_handle_t, 593 bus_size_t, bus_size_t, int); 594 595static void 596nexus_bus_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, 597 bus_size_t size, int flags) 598{ 599 600 /* 601 * We have lots of alternatives depending on whether we're 602 * synchronizing loads with loads, loads with stores, stores 603 * with loads, or stores with stores. The only ones that seem 604 * generic are #Sync and #MemIssue. I'll use #Sync for safety. 605 */ 606 switch(flags) { 607 case BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE: 608 case BUS_SPACE_BARRIER_READ: 609 case BUS_SPACE_BARRIER_WRITE: 610 membar(Sync); 611 break; 612 default: 613 panic("sparc64_bus_barrier: unknown flags"); 614 } 615 return; 616} 617 618struct bus_space_tag nexus_bustag = { 619 NULL, /* cookie */ 620 NULL, /* parent bus tag */ 621 UPA_BUS_SPACE, /* type */ 622 nexus_bus_barrier, /* bus_space_barrier */ 623}; 624