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