bus_machdep.c revision 91783
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 91783 2002-03-07 06:01:40Z 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/smp.h> 117#include <sys/systm.h> 118 119#include <vm/vm.h> 120#include <vm/vm_extern.h> 121#include <vm/vm_kern.h> 122#include <vm/vm_page.h> 123#include <vm/vm_param.h> 124 125#include <machine/asi.h> 126#include <machine/bus.h> 127#include <machine/cache.h> 128#include <machine/pmap.h> 129#include <machine/smp.h> 130#include <machine/tlb.h> 131 132/* ASI's for bus access. */ 133int bus_type_asi[] = { 134 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* UPA */ 135 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* SBUS */ 136 ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI configuration space */ 137 ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI memory space */ 138 ASI_PHYS_BYPASS_EC_WITH_EBIT_L, /* PCI I/O space */ 139 0 140}; 141 142int bus_stream_asi[] = { 143 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* UPA */ 144 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* SBUS */ 145 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI configuration space */ 146 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI memory space */ 147 ASI_PHYS_BYPASS_EC_WITH_EBIT, /* PCI I/O space */ 148 0 149}; 150 151/* 152 * busdma support code. 153 * Note: there is no support for bounce buffers yet. 154 */ 155 156static int nexus_dmamap_create(bus_dma_tag_t, int, bus_dmamap_t *); 157static int nexus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); 158static int nexus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, 159 bus_dmamap_callback_t *, void *, int); 160static void nexus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); 161static void nexus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t); 162static int nexus_dmamem_alloc(bus_dma_tag_t, void **, int, bus_dmamap_t *); 163static void nexus_dmamem_free(bus_dma_tag_t, void *, bus_dmamap_t); 164 165 166bus_dma_tag_t sparc64_root_dma_tag; 167 168/* 169 * Allocate a device specific dma_tag. 170 */ 171int 172bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, 173 bus_size_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, 174 bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, 175 int nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat) 176{ 177 178 bus_dma_tag_t newtag, eparent; 179 180 /* Return a NULL tag on failure */ 181 *dmat = NULL; 182 183 newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT); 184 if (newtag == NULL) 185 return (ENOMEM); 186 187 /* Ugh... */ 188 eparent = parent != NULL ? parent : sparc64_root_dma_tag; 189 memcpy(newtag, eparent, sizeof(*newtag)); 190 if (parent != NULL) 191 newtag->parent = parent; 192 newtag->alignment = alignment; 193 newtag->boundary = boundary; 194 newtag->lowaddr = trunc_page((vm_offset_t)lowaddr) + (PAGE_SIZE - 1); 195 newtag->highaddr = trunc_page((vm_offset_t)highaddr) + (PAGE_SIZE - 1); 196 newtag->filter = filter; 197 newtag->filterarg = filterarg; 198 newtag->maxsize = maxsize; 199 newtag->nsegments = nsegments; 200 newtag->maxsegsz = maxsegsz; 201 newtag->flags = flags; 202 newtag->ref_count = 1; /* Count ourself */ 203 newtag->map_count = 0; 204 205 /* Take into account any restrictions imposed by our parent tag */ 206 if (parent != NULL) { 207 newtag->lowaddr = ulmin(parent->lowaddr, newtag->lowaddr); 208 newtag->highaddr = ulmax(parent->highaddr, newtag->highaddr); 209 /* 210 * XXX Not really correct??? Probably need to honor boundary 211 * all the way up the inheritence chain. 212 */ 213 newtag->boundary = ulmax(parent->boundary, newtag->boundary); 214 if (parent != NULL) 215 parent->ref_count++; 216 } 217 218 *dmat = newtag; 219 return (0); 220} 221 222int 223bus_dma_tag_destroy(bus_dma_tag_t dmat) 224{ 225 226 if (dmat != NULL) { 227 if (dmat->map_count != 0) 228 return (EBUSY); 229 230 while (dmat != NULL) { 231 bus_dma_tag_t parent; 232 233 parent = dmat->parent; 234 dmat->ref_count--; 235 if (dmat->ref_count == 0) { 236 free(dmat, M_DEVBUF); 237 /* 238 * Last reference count, so 239 * release our reference 240 * count on our parent. 241 */ 242 dmat = parent; 243 } else 244 dmat = NULL; 245 } 246 } 247 return (0); 248} 249 250/* 251 * Common function for DMA map creation. May be called by bus-specific 252 * DMA map creation functions. 253 */ 254static int 255nexus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp) 256{ 257 258 /* Not much to do...? */ 259 *mapp = malloc(sizeof(**mapp), M_DEVBUF, M_WAITOK | M_ZERO); 260 dmat->map_count++; 261 return (0); 262} 263 264/* 265 * Common function for DMA map destruction. May be called by bus-specific 266 * DMA map destruction functions. 267 */ 268static int 269nexus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map) 270{ 271 272 free(map, M_DEVBUF); 273 dmat->map_count--; 274 return (0); 275} 276 277#define BUS_DMAMAP_NSEGS ((BUS_SPACE_MAXSIZE / PAGE_SIZE) + 1) 278 279/* 280 * Common function for loading a DMA map with a linear buffer. May 281 * be called by bus-specific DMA map load functions. 282 * 283 * Most SPARCs have IOMMUs in the bus controllers. In those cases 284 * they only need one segment and will use virtual addresses for DVMA. 285 * Those bus controllers should intercept these vectors and should 286 * *NEVER* call nexus_dmamap_load() which is used only by devices that 287 * bypass DVMA. 288 */ 289static int 290nexus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 291 bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, 292 int flags) 293{ 294 vm_offset_t vaddr; 295 vm_offset_t paddr; 296#ifdef __GNUC__ 297 bus_dma_segment_t dm_segments[dmat->nsegments]; 298#else 299 bus_dma_segment_t dm_segments[BUS_DMAMAP_NSEGS]; 300#endif 301 bus_dma_segment_t *sg; 302 int seg; 303 int error; 304 vm_offset_t nextpaddr; 305 bus_size_t size; 306 307 error = 0; 308 309 vaddr = (vm_offset_t)buf; 310 sg = &dm_segments[0]; 311 seg = 1; 312 sg->ds_len = 0; 313 314 map->buf = buf; 315 map->buflen = buflen; 316 map->start = (bus_addr_t)buf; 317 318 nextpaddr = 0; 319 do { 320 paddr = pmap_kextract(vaddr); 321 size = PAGE_SIZE - (paddr & PAGE_MASK); 322 if (size > buflen) 323 size = buflen; 324 325 if (sg->ds_len == 0) { 326 sg->ds_addr = paddr; 327 sg->ds_len = size; 328 } else if (paddr == nextpaddr) { 329 sg->ds_len += size; 330 } else { 331 /* Go to the next segment */ 332 sg++; 333 seg++; 334 if (seg > dmat->nsegments) 335 break; 336 sg->ds_addr = paddr; 337 sg->ds_len = size; 338 } 339 vaddr += size; 340 nextpaddr = paddr + size; 341 buflen -= size; 342 } while (buflen > 0); 343 344 if (buflen != 0) { 345 printf("bus_dmamap_load: Too many segs! buf_len = 0x%lx\n", 346 (u_long)buflen); 347 error = EFBIG; 348 } 349 350 (*callback)(callback_arg, dm_segments, seg, error); 351 352 return (0); 353} 354 355/* 356 * Common function for unloading a DMA map. May be called by 357 * bus-specific DMA map unload functions. 358 */ 359static void 360nexus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map) 361{ 362 363 /* Nothing to do...? */ 364} 365 366/* 367 * Common function for DMA map synchronization. May be called 368 * by bus-specific DMA map synchronization functions. 369 */ 370static void 371nexus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op) 372{ 373 374 /* 375 * We sync out our caches, but the bus must do the same. 376 * 377 * Actually a #Sync is expensive. We should optimize. 378 */ 379 if ((op == BUS_DMASYNC_PREREAD) || (op == BUS_DMASYNC_PREWRITE)) { 380 /* 381 * Don't really need to do anything, but flush any pending 382 * writes anyway. 383 */ 384 membar(Sync); 385 } 386 if (op == BUS_DMASYNC_POSTREAD) { 387 /* 388 * Invalidate the caches (it is unclear whether that is really 389 * needed. The manual only mentions that PCI transactions are 390 * cache coherent). 391 */ 392 ecache_flush((vm_offset_t)map->buf, 393 (vm_offset_t)map->buf + map->buflen - 1); 394 } 395 if (op == BUS_DMASYNC_POSTWRITE) { 396 /* Nothing to do. Handled by the bus controller. */ 397 } 398} 399 400/* 401 * Helper functions for buses that use their private dmamem_alloc/dmamem_free 402 * versions. 403 * These differ from the dmamap_alloc() functions in that they create a tag 404 * that is specifically for use with dmamem_alloc'ed memory. 405 * These are primitive now, but I expect that some fields of the map will need 406 * to be filled soon. 407 */ 408int 409sparc64_dmamem_alloc_map(bus_dma_tag_t dmat, bus_dmamap_t *mapp) 410{ 411 412 *mapp = malloc(sizeof(**mapp), M_DEVBUF, M_WAITOK | M_ZERO); 413 if (*mapp == NULL) 414 return (ENOMEM); 415 416 dmat->map_count++; 417 return (0); 418} 419 420void 421sparc64_dmamem_free_map(bus_dma_tag_t dmat, bus_dmamap_t map) 422{ 423 424 free(map, M_DEVBUF); 425 dmat->map_count--; 426} 427 428/* 429 * Common function for DMA-safe memory allocation. May be called 430 * by bus-specific DMA memory allocation functions. 431 */ 432static int 433nexus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags, 434 bus_dmamap_t *mapp) 435{ 436 437 if ((dmat->maxsize <= PAGE_SIZE)) { 438 *vaddr = malloc(dmat->maxsize, M_DEVBUF, 439 (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK); 440 } else { 441 /* 442 * XXX: Use contigmalloc until it is merged into this facility 443 * and handles multi-seg allocations. Nobody is doing multi-seg 444 * allocations yet though. 445 */ 446 *vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, 447 (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK, 448 0ul, dmat->lowaddr, dmat->alignment ? dmat->alignment : 1UL, 449 dmat->boundary); 450 } 451 if (*vaddr == NULL) { 452 free(*mapp, M_DEVBUF); 453 return (ENOMEM); 454 } 455 return (0); 456} 457 458/* 459 * Common function for freeing DMA-safe memory. May be called by 460 * bus-specific DMA memory free functions. 461 */ 462static void 463nexus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map) 464{ 465 466 sparc64_dmamem_free_map(dmat, map); 467 if ((dmat->maxsize <= PAGE_SIZE)) 468 free(vaddr, M_DEVBUF); 469 else 470 contigfree(vaddr, dmat->maxsize, M_DEVBUF); 471} 472 473struct bus_dma_tag nexus_dmatag = { 474 NULL, 475 NULL, 476 8, 477 0, 478 0, 479 0x3ffffffff, 480 NULL, /* XXX */ 481 NULL, 482 0x3ffffffff, /* XXX */ 483 0xff, /* XXX */ 484 0xffffffff, /* XXX */ 485 0, 486 0, 487 0, 488 nexus_dmamap_create, 489 nexus_dmamap_destroy, 490 nexus_dmamap_load, 491 nexus_dmamap_unload, 492 nexus_dmamap_sync, 493 494 nexus_dmamem_alloc, 495 nexus_dmamem_free, 496}; 497 498/* 499 * Helpers to map/unmap bus memory 500 */ 501int 502sparc64_bus_mem_map(bus_space_tag_t tag, bus_space_handle_t handle, 503 bus_size_t size, int flags, vm_offset_t vaddr, void **hp) 504{ 505 vm_offset_t addr; 506 vm_offset_t sva; 507 vm_offset_t va; 508 vm_offset_t pa; 509 vm_size_t vsz; 510 u_long pm_flags; 511 512 addr = (vm_offset_t)handle; 513 size = round_page(size); 514 if (size == 0) { 515 printf("sparc64_bus_map: zero size\n"); 516 return (EINVAL); 517 } 518 switch (tag->type) { 519 case PCI_CONFIG_BUS_SPACE: 520 case PCI_IO_BUS_SPACE: 521 case PCI_MEMORY_BUS_SPACE: 522 pm_flags = TD_IE; 523 break; 524 default: 525 pm_flags = 0; 526 break; 527 } 528 529 if (!(flags & BUS_SPACE_MAP_CACHEABLE)) 530 pm_flags |= TD_E; 531 532 if (vaddr != NULL) 533 sva = trunc_page(vaddr); 534 else { 535 if ((sva = kmem_alloc_nofault(kernel_map, size)) == NULL) 536 panic("sparc64_bus_map: cannot allocate virtual " 537 "memory"); 538 } 539 540 /* note: preserve page offset */ 541 *hp = (void *)(sva | ((u_long)addr & PAGE_MASK)); 542 543 pa = trunc_page(addr); 544 if ((flags & BUS_SPACE_MAP_READONLY) == 0) 545 pm_flags |= TD_W; 546 547 va = sva; 548 vsz = size; 549 do { 550 pmap_kenter_flags(va, pa, pm_flags); 551 va += PAGE_SIZE; 552 pa += PAGE_SIZE; 553 } while ((vsz -= PAGE_SIZE) > 0); 554 tlb_range_demap(kernel_pmap, sva, sva + size - 1); 555 return (0); 556} 557 558int 559sparc64_bus_mem_unmap(void *bh, bus_size_t size) 560{ 561 vm_offset_t sva; 562 vm_offset_t va; 563 vm_offset_t endva; 564 565 sva = trunc_page((vm_offset_t)bh); 566 endva = sva + round_page(size); 567 for (va = sva; va < endva; va += PAGE_SIZE) 568 pmap_kremove(va); 569 tlb_range_demap(kernel_pmap, sva, sva + size - 1); 570 kmem_free(kernel_map, va, size); 571 return (0); 572} 573 574/* 575 * Fake up a bus tag, for use by console drivers in early boot when the regular 576 * means to allocate resources are not yet available. 577 * Note that these tags are not eligible for bus_space_barrier operations. 578 * Addr is the physical address of the desired start of the handle. 579 */ 580bus_space_handle_t 581sparc64_fake_bustag(int space, bus_addr_t addr, struct bus_space_tag *ptag) 582{ 583 584 ptag->cookie = NULL; 585 ptag->parent = NULL; 586 ptag->type = space; 587 ptag->bus_barrier = NULL; 588 return (addr); 589} 590 591/* 592 * Base bus space handlers. 593 */ 594static void nexus_bus_barrier(bus_space_tag_t, bus_space_handle_t, 595 bus_size_t, bus_size_t, int); 596 597static void 598nexus_bus_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, 599 bus_size_t size, int flags) 600{ 601 602 /* 603 * We have lots of alternatives depending on whether we're 604 * synchronizing loads with loads, loads with stores, stores 605 * with loads, or stores with stores. The only ones that seem 606 * generic are #Sync and #MemIssue. I'll use #Sync for safety. 607 */ 608 switch(flags) { 609 case BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE: 610 case BUS_SPACE_BARRIER_READ: 611 case BUS_SPACE_BARRIER_WRITE: 612 membar(Sync); 613 break; 614 default: 615 panic("sparc64_bus_barrier: unknown flags"); 616 } 617 return; 618} 619 620struct bus_space_tag nexus_bustag = { 621 NULL, /* cookie */ 622 NULL, /* parent bus tag */ 623 UPA_BUS_SPACE, /* type */ 624 nexus_bus_barrier, /* bus_space_barrier */ 625}; 626