bus.h revision 131223
1/*- 2 * Copyright (c) 1996, 1997, 1998, 2001 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) 1997-1999 Eduardo E. Horvath. All rights reserved. 39 * Copyright (c) 1996 Charles M. Hannum. All rights reserved. 40 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by Christopher G. Demetriou 53 * for the NetBSD Project. 54 * 4. The name of the author may not be used to endorse or promote products 55 * derived from this software without specific prior written permission 56 * 57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 60 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 61 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 62 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 63 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 64 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 65 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 66 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 67 * 68 * from: NetBSD: bus.h,v 1.28 2001/07/19 15:32:19 thorpej Exp 69 * and 70 * from: FreeBSD: src/sys/alpha/include/bus.h,v 1.9 2001/01/09 71 * 72 * $FreeBSD: head/sys/sparc64/include/bus.h 131223 2004-06-28 03:49:13Z scottl $ 73 */ 74 75#ifndef _MACHINE_BUS_H_ 76#define _MACHINE_BUS_H_ 77 78#ifdef BUS_SPACE_DEBUG 79#include <sys/ktr.h> 80#endif 81 82#include <machine/cpufunc.h> 83#include <machine/upa.h> 84 85/* 86 * UPA and SBUS spaces are non-cached and big endian 87 * (except for RAM and PROM) 88 * 89 * PCI spaces are non-cached and little endian 90 */ 91#define UPA_BUS_SPACE 0 92#define SBUS_BUS_SPACE 1 93#define PCI_CONFIG_BUS_SPACE 2 94#define PCI_IO_BUS_SPACE 3 95#define PCI_MEMORY_BUS_SPACE 4 96#define LAST_BUS_SPACE 5 97 98extern int bus_type_asi[]; 99extern int bus_stream_asi[]; 100 101#define __BUS_SPACE_HAS_STREAM_METHODS 1 102 103/* 104 * Bus address and size types 105 */ 106typedef u_long bus_space_handle_t; 107typedef int bus_type_t; 108typedef u_long bus_addr_t; 109typedef u_long bus_size_t; 110 111#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF 112#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF 113#define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFF 114#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF 115#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF 116#define BUS_SPACE_MAXADDR 0xFFFFFFFF 117 118#define BUS_SPACE_UNRESTRICTED (~0UL) 119 120/* 121 * Access methods for bus resources and address space. 122 */ 123typedef struct bus_space_tag *bus_space_tag_t; 124 125struct bus_space_tag { 126 void *bst_cookie; 127 bus_space_tag_t bst_parent; 128 int bst_type; 129 130 void (*bst_bus_barrier)(bus_space_tag_t, bus_space_handle_t, 131 bus_size_t, bus_size_t, int); 132}; 133 134/* 135 * Bus space function prototypes. 136 */ 137static void bus_space_barrier(bus_space_tag_t, bus_space_handle_t, bus_size_t, 138 bus_size_t, int); 139static int bus_space_subregion(bus_space_tag_t, bus_space_handle_t, 140 bus_size_t, bus_size_t, bus_space_handle_t *); 141 142/* 143 * Map a region of device bus space into CPU virtual address space. 144 */ 145 146static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr, 147 bus_size_t size, int flags, 148 bus_space_handle_t *bshp); 149 150static __inline int 151bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr, 152 bus_size_t size __unused, int flags __unused, 153 bus_space_handle_t *bshp) 154{ 155 156 *bshp = addr; 157 return (0); 158} 159 160/* 161 * Unmap a region of device bus space. 162 */ 163static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, 164 bus_size_t size); 165 166static __inline void 167bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused, 168 bus_size_t size __unused) 169{ 170} 171 172/* This macro finds the first "upstream" implementation of method `f' */ 173#define _BS_CALL(t,f) \ 174 while (t->f == NULL) \ 175 t = t->bst_parent; \ 176 return (*(t)->f) 177 178static __inline void 179bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 180 bus_size_t s, int f) 181{ 182 _BS_CALL(t, bst_bus_barrier)(t, h, o, s, f); 183} 184 185static __inline int 186bus_space_subregion(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 187 bus_size_t s, bus_space_handle_t *hp) 188{ 189 *hp = h + o; 190 return (0); 191} 192 193/* flags for bus space map functions */ 194#define BUS_SPACE_MAP_CACHEABLE 0x0001 195#define BUS_SPACE_MAP_LINEAR 0x0002 196#define BUS_SPACE_MAP_READONLY 0x0004 197#define BUS_SPACE_MAP_PREFETCHABLE 0x0008 198/* placeholders for bus functions... */ 199#define BUS_SPACE_MAP_BUS1 0x0100 200#define BUS_SPACE_MAP_BUS2 0x0200 201#define BUS_SPACE_MAP_BUS3 0x0400 202#define BUS_SPACE_MAP_BUS4 0x0800 203 204/* flags for bus_space_barrier() */ 205#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 206#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 207 208#ifdef BUS_SPACE_DEBUG 209#define KTR_BUS KTR_CT2 210#define BUS_HANDLE_MIN UPA_MEMSTART 211#define __BUS_DEBUG_ACCESS(h, o, desc, sz) do { \ 212 CTR4(KTR_BUS, "bus space: %s %d: handle %#lx, offset %#lx", \ 213 (desc), (sz), (h), (o)); \ 214 if ((h) + (o) < BUS_HANDLE_MIN) \ 215 panic("bus space access at %#lx out of range", \ 216 (h) + (o)); \ 217} while (0) 218#else 219#define __BUS_DEBUG_ACCESS(h, o, desc, sz) 220#endif 221 222static __inline uint8_t 223bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 224{ 225 226 __BUS_DEBUG_ACCESS(h, o, "read", 1); 227 return (lduba_nc((caddr_t)(h + o), bus_type_asi[t->bst_type])); 228} 229 230static __inline uint16_t 231bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 232{ 233 234 __BUS_DEBUG_ACCESS(h, o, "read", 2); 235 return (lduha_nc((caddr_t)(h + o), bus_type_asi[t->bst_type])); 236} 237 238static __inline uint32_t 239bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 240{ 241 242 __BUS_DEBUG_ACCESS(h, o, "read", 4); 243 return (lduwa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type])); 244} 245 246static __inline uint64_t 247bus_space_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 248{ 249 250 __BUS_DEBUG_ACCESS(h, o, "read", 8); 251 return (ldxa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type])); 252} 253 254static __inline void 255bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 256 uint8_t *a, size_t c) 257{ 258 259 while (c-- > 0) 260 *a++ = bus_space_read_1(t, h, o); 261} 262 263static __inline void 264bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 265 uint16_t *a, size_t c) 266{ 267 268 while (c-- > 0) 269 *a++ = bus_space_read_2(t, h, o); 270} 271 272static __inline void 273bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 274 uint32_t *a, size_t c) 275{ 276 277 while (c-- > 0) 278 *a++ = bus_space_read_4(t, h, o); 279} 280 281static __inline void 282bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 283 uint64_t *a, size_t c) 284{ 285 286 while (c-- > 0) 287 *a++ = bus_space_read_8(t, h, o); 288} 289 290static __inline void 291bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 292 uint8_t v) 293{ 294 295 __BUS_DEBUG_ACCESS(h, o, "write", 1); 296 stba_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v); 297} 298 299static __inline void 300bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 301 uint16_t v) 302{ 303 304 __BUS_DEBUG_ACCESS(h, o, "write", 2); 305 stha_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v); 306} 307 308static __inline void 309bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 310 uint32_t v) 311{ 312 313 __BUS_DEBUG_ACCESS(h, o, "write", 4); 314 stwa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v); 315} 316 317static __inline void 318bus_space_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 319 uint64_t v) 320{ 321 322 __BUS_DEBUG_ACCESS(h, o, "write", 8); 323 stxa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v); 324} 325 326static __inline void 327bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 328 uint8_t *a, size_t c) 329{ 330 331 while (c-- > 0) 332 bus_space_write_1(t, h, o, *a++); 333} 334 335static __inline void 336bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 337 uint16_t *a, size_t c) 338{ 339 340 while (c-- > 0) 341 bus_space_write_2(t, h, o, *a++); 342} 343 344static __inline void 345bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 346 uint32_t *a, size_t c) 347{ 348 349 while (c-- > 0) 350 bus_space_write_4(t, h, o, *a++); 351} 352 353static __inline void 354bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 355 uint64_t *a, size_t c) 356{ 357 358 while (c-- > 0) 359 bus_space_write_8(t, h, o, *a++); 360} 361 362static __inline void 363bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 364 uint8_t v, size_t c) 365{ 366 367 while (c-- > 0) 368 bus_space_write_1(t, h, o, v); 369} 370 371static __inline void 372bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 373 uint16_t v, size_t c) 374{ 375 376 while (c-- > 0) 377 bus_space_write_2(t, h, o, v); 378} 379 380static __inline void 381bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 382 uint32_t v, size_t c) 383{ 384 385 while (c-- > 0) 386 bus_space_write_4(t, h, o, v); 387} 388 389static __inline void 390bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 391 uint64_t v, size_t c) 392{ 393 394 while (c-- > 0) 395 bus_space_write_8(t, h, o, v); 396} 397 398static __inline void 399bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 400 u_int8_t *a, bus_size_t c) 401{ 402 for (; c; a++, c--, o++) 403 *a = bus_space_read_1(t, h, o); 404} 405 406static __inline void 407bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 408 u_int16_t *a, bus_size_t c) 409{ 410 for (; c; a++, c--, o+=2) 411 *a = bus_space_read_2(t, h, o); 412} 413 414static __inline void 415bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 416 u_int32_t *a, bus_size_t c) 417{ 418 for (; c; a++, c--, o+=4) 419 *a = bus_space_read_4(t, h, o); 420} 421 422static __inline void 423bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 424 u_int64_t *a, bus_size_t c) 425{ 426 for (; c; a++, c--, o+=8) 427 *a = bus_space_read_8(t, h, o); 428} 429 430static __inline void 431bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 432 const u_int8_t *a, bus_size_t c) 433{ 434 for (; c; a++, c--, o++) 435 bus_space_write_1(t, h, o, *a); 436} 437 438static __inline void 439bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 440 const u_int16_t *a, bus_size_t c) 441{ 442 for (; c; a++, c--, o+=2) 443 bus_space_write_2(t, h, o, *a); 444} 445 446static __inline void 447bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 448 const u_int32_t *a, bus_size_t c) 449{ 450 for (; c; a++, c--, o+=4) 451 bus_space_write_4(t, h, o, *a); 452} 453 454static __inline void 455bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 456 const u_int64_t *a, bus_size_t c) 457{ 458 for (; c; a++, c--, o+=8) 459 bus_space_write_8(t, h, o, *a); 460} 461 462static __inline void 463bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 464 const u_int8_t v, bus_size_t c) 465{ 466 for (; c; c--, o++) 467 bus_space_write_1(t, h, o, v); 468} 469 470static __inline void 471bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 472 const u_int16_t v, bus_size_t c) 473{ 474 for (; c; c--, o+=2) 475 bus_space_write_2(t, h, o, v); 476} 477 478static __inline void 479bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 480 const u_int32_t v, bus_size_t c) 481{ 482 for (; c; c--, o+=4) 483 bus_space_write_4(t, h, o, v); 484} 485 486static __inline void 487bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 488 const u_int64_t v, bus_size_t c) 489{ 490 for (; c; c--, o+=8) 491 bus_space_write_8(t, h, o, v); 492} 493 494static __inline void 495bus_space_copy_region_1(bus_space_tag_t t, bus_space_handle_t h1, 496 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 497{ 498 for (; c; c--, o1++, o2++) 499 bus_space_write_1(t, h1, o1, bus_space_read_1(t, h2, o2)); 500} 501 502static __inline void 503bus_space_copy_region_2(bus_space_tag_t t, bus_space_handle_t h1, 504 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 505{ 506 for (; c; c--, o1+=2, o2+=2) 507 bus_space_write_2(t, h1, o1, bus_space_read_2(t, h2, o2)); 508} 509 510static __inline void 511bus_space_copy_region_4(bus_space_tag_t t, bus_space_handle_t h1, 512 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 513{ 514 for (; c; c--, o1+=4, o2+=4) 515 bus_space_write_4(t, h1, o1, bus_space_read_4(t, h2, o2)); 516} 517 518static __inline void 519bus_space_copy_region_8(bus_space_tag_t t, bus_space_handle_t h1, 520 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 521{ 522 for (; c; c--, o1+=8, o2+=8) 523 bus_space_write_8(t, h1, o1, bus_space_read_8(t, h2, o2)); 524} 525 526static __inline uint8_t 527bus_space_read_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 528{ 529 530 __BUS_DEBUG_ACCESS(h, o, "read stream", 1); 531 return (lduba_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type])); 532} 533 534static __inline uint16_t 535bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 536{ 537 538 __BUS_DEBUG_ACCESS(h, o, "read stream", 2); 539 return (lduha_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type])); 540} 541 542static __inline uint32_t 543bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 544{ 545 546 __BUS_DEBUG_ACCESS(h, o, "read stream", 4); 547 return (lduwa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type])); 548} 549 550static __inline uint64_t 551bus_space_read_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 552{ 553 554 __BUS_DEBUG_ACCESS(h, o, "read stream", 8); 555 return (ldxa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type])); 556} 557 558static __inline void 559bus_space_read_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, 560 bus_size_t o, uint8_t *a, size_t c) 561{ 562 563 while (c-- > 0) 564 *a++ = bus_space_read_stream_1(t, h, o); 565} 566 567static __inline void 568bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, 569 bus_size_t o, uint16_t *a, size_t c) 570{ 571 572 while (c-- > 0) 573 *a++ = bus_space_read_stream_2(t, h, o); 574} 575 576static __inline void 577bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, 578 bus_size_t o, uint32_t *a, size_t c) 579{ 580 581 while (c-- > 0) 582 *a++ = bus_space_read_stream_4(t, h, o); 583} 584 585static __inline void 586bus_space_read_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, 587 bus_size_t o, uint64_t *a, size_t c) 588{ 589 590 while (c-- > 0) 591 *a++ = bus_space_read_stream_8(t, h, o); 592} 593 594static __inline void 595bus_space_write_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 596 uint8_t v) 597{ 598 599 __BUS_DEBUG_ACCESS(h, o, "write stream", 1); 600 stba_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v); 601} 602 603static __inline void 604bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 605 uint16_t v) 606{ 607 608 __BUS_DEBUG_ACCESS(h, o, "write stream", 2); 609 stha_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v); 610} 611 612static __inline void 613bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 614 uint32_t v) 615{ 616 617 __BUS_DEBUG_ACCESS(h, o, "write stream", 4); 618 stwa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v); 619} 620 621static __inline void 622bus_space_write_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 623 uint64_t v) 624{ 625 626 __BUS_DEBUG_ACCESS(h, o, "write stream", 8); 627 stxa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v); 628} 629 630static __inline void 631bus_space_write_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, 632 bus_size_t o, const uint8_t *a, size_t c) 633{ 634 635 while (c-- > 0) 636 bus_space_write_stream_1(t, h, o, *a++); 637} 638 639static __inline void 640bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, 641 bus_size_t o, const uint16_t *a, size_t c) 642{ 643 644 while (c-- > 0) 645 bus_space_write_stream_2(t, h, o, *a++); 646} 647 648static __inline void 649bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, 650 bus_size_t o, const uint32_t *a, size_t c) 651{ 652 653 while (c-- > 0) 654 bus_space_write_stream_4(t, h, o, *a++); 655} 656 657static __inline void 658bus_space_write_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, 659 bus_size_t o, const uint64_t *a, size_t c) 660{ 661 662 while (c-- > 0) 663 bus_space_write_stream_8(t, h, o, *a++); 664} 665 666static __inline void 667bus_space_set_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, 668 bus_size_t o, uint8_t v, size_t c) 669{ 670 671 while (c-- > 0) 672 bus_space_write_stream_1(t, h, o, v); 673} 674 675static __inline void 676bus_space_set_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, 677 bus_size_t o, uint16_t v, size_t c) 678{ 679 680 while (c-- > 0) 681 bus_space_write_stream_2(t, h, o, v); 682} 683 684static __inline void 685bus_space_set_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, 686 bus_size_t o, uint32_t v, size_t c) 687{ 688 689 while (c-- > 0) 690 bus_space_write_stream_4(t, h, o, v); 691} 692 693static __inline void 694bus_space_set_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, 695 bus_size_t o, uint64_t v, size_t c) 696{ 697 698 while (c-- > 0) 699 bus_space_write_stream_8(t, h, o, v); 700} 701 702static __inline void 703bus_space_read_region_stream_1(bus_space_tag_t t, bus_space_handle_t h, 704 bus_size_t o, u_int8_t *a, bus_size_t c) 705{ 706 for (; c; a++, c--, o++) 707 *a = bus_space_read_stream_1(t, h, o); 708} 709 710static __inline void 711bus_space_read_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, 712 bus_size_t o, u_int16_t *a, bus_size_t c) 713{ 714 for (; c; a++, c--, o+=2) 715 *a = bus_space_read_stream_2(t, h, o); 716} 717 718static __inline void 719bus_space_read_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, 720 bus_size_t o, u_int32_t *a, bus_size_t c) 721{ 722 for (; c; a++, c--, o+=4) 723 *a = bus_space_read_stream_4(t, h, o); 724} 725 726static __inline void 727bus_space_read_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, 728 bus_size_t o, u_int64_t *a, bus_size_t c) 729{ 730 for (; c; a++, c--, o+=8) 731 *a = bus_space_read_stream_8(t, h, o); 732} 733 734static __inline void 735bus_space_write_region_stream_1(bus_space_tag_t t, bus_space_handle_t h, 736 bus_size_t o, const u_int8_t *a, bus_size_t c) 737{ 738 for (; c; a++, c--, o++) 739 bus_space_write_stream_1(t, h, o, *a); 740} 741 742static __inline void 743bus_space_write_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, 744 bus_size_t o, const u_int16_t *a, bus_size_t c) 745{ 746 for (; c; a++, c--, o+=2) 747 bus_space_write_stream_2(t, h, o, *a); 748} 749 750static __inline void 751bus_space_write_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, 752 bus_size_t o, const u_int32_t *a, bus_size_t c) 753{ 754 for (; c; a++, c--, o+=4) 755 bus_space_write_stream_4(t, h, o, *a); 756} 757 758static __inline void 759bus_space_write_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, 760 bus_size_t o, const u_int64_t *a, bus_size_t c) 761{ 762 for (; c; a++, c--, o+=8) 763 bus_space_write_stream_8(t, h, o, *a); 764} 765 766static __inline void 767bus_space_set_region_stream_1(bus_space_tag_t t, bus_space_handle_t h, 768 bus_size_t o, const u_int8_t v, bus_size_t c) 769{ 770 for (; c; c--, o++) 771 bus_space_write_stream_1(t, h, o, v); 772} 773 774static __inline void 775bus_space_set_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, 776 bus_size_t o, const u_int16_t v, bus_size_t c) 777{ 778 for (; c; c--, o+=2) 779 bus_space_write_stream_2(t, h, o, v); 780} 781 782static __inline void 783bus_space_set_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, 784 bus_size_t o, const u_int32_t v, bus_size_t c) 785{ 786 for (; c; c--, o+=4) 787 bus_space_write_stream_4(t, h, o, v); 788} 789 790static __inline void 791bus_space_set_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, 792 bus_size_t o, const u_int64_t v, bus_size_t c) 793{ 794 for (; c; c--, o+=8) 795 bus_space_write_stream_8(t, h, o, v); 796} 797 798static __inline void 799bus_space_copy_region_stream_1(bus_space_tag_t t, bus_space_handle_t h1, 800 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 801{ 802 for (; c; c--, o1++, o2++) 803 bus_space_write_stream_1(t, h1, o1, bus_space_read_stream_1(t, h2, 804 o2)); 805} 806 807static __inline void 808bus_space_copy_region_stream_2(bus_space_tag_t t, bus_space_handle_t h1, 809 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 810{ 811 for (; c; c--, o1+=2, o2+=2) 812 bus_space_write_stream_2(t, h1, o1, bus_space_read_stream_2(t, h2, 813 o2)); 814} 815 816static __inline void 817bus_space_copy_region_stream_4(bus_space_tag_t t, bus_space_handle_t h1, 818 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 819{ 820 for (; c; c--, o1+=4, o2+=4) 821 bus_space_write_stream_4(t, h1, o1, bus_space_read_stream_4(t, h2, 822 o2)); 823} 824 825static __inline void 826bus_space_copy_region_stream_8(bus_space_tag_t t, bus_space_handle_t h1, 827 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 828{ 829 for (; c; c--, o1+=8, o2+=8) 830 bus_space_write_stream_8(t, h1, o1, bus_space_read_8(t, h2, o2)); 831} 832 833static __inline int 834bus_space_peek_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 835 u_int8_t *a) 836{ 837 838 __BUS_DEBUG_ACCESS(h, o, "peek", 1); 839 return (fasword8(bus_type_asi[t->bst_type], (caddr_t)(h + o), a)); 840} 841 842static __inline int 843bus_space_peek_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 844 u_int16_t *a) 845{ 846 847 __BUS_DEBUG_ACCESS(h, o, "peek", 2); 848 return (fasword16(bus_type_asi[t->bst_type], (caddr_t)(h + o), a)); 849} 850 851static __inline int 852bus_space_peek_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 853 u_int32_t *a) 854{ 855 856 __BUS_DEBUG_ACCESS(h, o, "peek", 4); 857 return (fasword32(bus_type_asi[t->bst_type], (caddr_t)(h + o), a)); 858} 859 860/* Back-compat functions for old ISA drivers */ 861extern bus_space_tag_t isa_io_bt; 862extern bus_space_handle_t isa_io_hdl; 863extern bus_space_tag_t isa_mem_bt; 864extern bus_space_handle_t isa_mem_hdl; 865 866#define inb(o) bus_space_read_1(isa_io_bt, isa_io_hdl, o) 867#define inw(o) bus_space_read_2(isa_io_bt, isa_io_hdl, o) 868#define inl(o) bus_space_read_4(isa_io_bt, isa_io_hdl, o) 869#define outb(o, v) bus_space_write_1(isa_io_bt, isa_io_hdl, o, v) 870#define outw(o, v) bus_space_write_2(isa_io_bt, isa_io_hdl, o, v) 871#define outl(o, v) bus_space_write_4(isa_io_bt, isa_io_hdl, o, v) 872 873#define readb(o) bus_space_read_1(isa_mem_bt, isa_mem_hdl, o) 874#define readw(o) bus_space_read_2(isa_mem_bt, isa_mem_hdl, o) 875#define readl(o) bus_space_read_4(isa_mem_bt, isa_mem_hdl, o) 876#define writeb(o, v) bus_space_write_1(isa_mem_bt, isa_mem_hdl, o, v) 877#define writew(o, v) bus_space_write_2(isa_mem_bt, isa_mem_hdl, o, v) 878#define writel(o, v) bus_space_write_4(isa_mem_bt, isa_mem_hdl, o, v) 879 880#define insb(o, a, c) \ 881 bus_space_read_multi_1(isa_io_bt, isa_io_hdl, o, (void*)a, c) 882#define insw(o, a, c) \ 883 bus_space_read_multi_2(isa_io_bt, isa_io_hdl, o, (void*)a, c) 884#define insl(o, a, c) \ 885 bus_space_read_multi_4(isa_io_bt, isa_io_hdl, o, (void*)a, c) 886#define outsb(o, a, c) \ 887 bus_space_write_multi_1(isa_io_bt, isa_io_hdl, o, (void*)a, c) 888#define outsw(o, a, c) \ 889 bus_space_write_multi_2(isa_io_bt, isa_io_hdl, o, (void*)a, c) 890#define outsl(o, a, c) \ 891 bus_space_write_multi_4(isa_io_bt, isa_io_hdl, o, (void*)a, c) 892 893#define memcpy_fromio(d, s, c) \ 894 bus_space_read_region_1(isa_mem_bt, isa_mem_hdl, s, d, c) 895#define memcpy_toio(d, s, c) \ 896 bus_space_write_region_1(isa_mem_bt, isa_mem_hdl, d, s, c) 897#define memcpy_io(d, s, c) \ 898 bus_space_copy_region_1(isa_mem_bt, isa_mem_hdl, s, isa_mem_hdl, d, c) 899#define memset_io(d, v, c) \ 900 bus_space_set_region_1(isa_mem_bt, isa_mem_hdl, d, v, c) 901#define memsetw_io(d, v, c) \ 902 bus_space_set_region_2(isa_mem_bt, isa_mem_hdl, d, v, c) 903 904static __inline void 905memsetw(void *d, int val, size_t size) 906{ 907 u_int16_t *sp = d; 908 909 while (size--) 910 *sp++ = val; 911} 912 913/* DMA support */ 914 915/* 916 * Flags used in various bus DMA methods. 917 */ 918#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ 919#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ 920#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ 921#define BUS_DMA_COHERENT 0x004 /* hint: map memory in a coherent way */ 922#define BUS_DMA_ZERO 0x008 /* allocate zero'ed memory */ 923#define BUS_DMA_BUS1 0x010 924#define BUS_DMA_BUS2 0x020 925#define BUS_DMA_BUS3 0x040 926#define BUS_DMA_BUS4 0x080 927 928/* The following two flags are non-standard. */ 929#define BUS_DMA_NOWRITE 0x100 930#define BUS_DMA_NOCACHE 0x200 931 932/* Forwards needed by prototypes below. */ 933struct mbuf; 934struct uio; 935 936typedef int bus_dmasync_op_t; 937#define BUS_DMASYNC_PREREAD 1 938#define BUS_DMASYNC_POSTREAD 2 939#define BUS_DMASYNC_PREWRITE 4 940#define BUS_DMASYNC_POSTWRITE 8 941 942/* 943 * A function that returns 1 if the address cannot be accessed by 944 * a device and 0 if it can be. 945 */ 946typedef int bus_dma_filter_t(void *, bus_addr_t); 947 948typedef struct bus_dma_tag *bus_dma_tag_t; 949typedef struct bus_dmamap *bus_dmamap_t; 950 951struct bus_dma_segment { 952 bus_addr_t ds_addr; /* DVMA address */ 953 bus_size_t ds_len; /* length of transfer */ 954}; 955typedef struct bus_dma_segment bus_dma_segment_t; 956 957/* 958 * A function that processes a successfully loaded dma map or an error 959 * from a delayed load map. 960 */ 961typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); 962 963/* 964 * Like bus_dmamap_callback but includes map size in bytes. This is 965 * defined as a separate interface to maintain compatiiblity for users 966 * of bus_dmamap_callback_t--at some point these interfaces should be merged. 967 */ 968typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, bus_size_t, int); 969 970/* 971 * A function that performs driver-specific syncronization on behalf of 972 * busdma. 973 */ 974typedef enum { 975 BUS_DMA_LOCK = 0x01, 976 BUS_DMA_UNLOCK = 0x02, 977} bus_dma_lock_op_t; 978 979typedef void bus_dma_lock_t(void *, bus_dma_lock_op_t); 980 981/* 982 * Method table for a bus_dma_tag. 983 */ 984struct bus_dma_methods { 985 int (*dm_dmamap_create)(bus_dma_tag_t, int, bus_dmamap_t *); 986 int (*dm_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); 987 int (*dm_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, 988 bus_size_t, bus_dmamap_callback_t *, void *, int); 989 int (*dm_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, 990 struct mbuf *, bus_dmamap_callback2_t *, void *, int); 991 int (*dm_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, struct uio *, 992 bus_dmamap_callback2_t *, void *, int); 993 void (*dm_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); 994 void (*dm_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, 995 bus_dmasync_op_t); 996 int (*dm_dmamem_alloc)(bus_dma_tag_t, void **, int, bus_dmamap_t *); 997 void (*dm_dmamem_free)(bus_dma_tag_t, void *, bus_dmamap_t); 998}; 999 1000/* 1001 * bus_dma_tag_t 1002 * 1003 * A machine-dependent opaque type describing the implementation of 1004 * DMA for a given bus. 1005 */ 1006struct bus_dma_tag { 1007 void *dt_cookie; /* cookie used in the guts */ 1008 bus_dma_tag_t dt_parent; 1009 bus_size_t dt_alignment; 1010 bus_size_t dt_boundary; 1011 bus_addr_t dt_lowaddr; 1012 bus_addr_t dt_highaddr; 1013 bus_dma_filter_t *dt_filter; 1014 void *dt_filterarg; 1015 bus_size_t dt_maxsize; 1016 int dt_nsegments; 1017 bus_size_t dt_maxsegsz; 1018 int dt_flags; 1019 int dt_ref_count; 1020 int dt_map_count; 1021 bus_dma_lock_t *dt_lockfunc; 1022 void * *dt_lockfuncarg; 1023 bus_dma_segment_t *dt_segments; 1024 1025 struct bus_dma_methods *dt_mt; 1026}; 1027 1028int bus_dma_tag_create(bus_dma_tag_t, bus_size_t, bus_size_t, bus_addr_t, 1029 bus_addr_t, bus_dma_filter_t *, void *, bus_size_t, int, bus_size_t, 1030 int, bus_dma_lock_t *, void *, bus_dma_tag_t *); 1031 1032int bus_dma_tag_destroy(bus_dma_tag_t); 1033 1034#define bus_dmamap_create(t, f, p) \ 1035 ((t)->dt_mt->dm_dmamap_create((t), (f), (p))) 1036#define bus_dmamap_destroy(t, p) \ 1037 ((t)->dt_mt->dm_dmamap_destroy((t), (p))) 1038#define bus_dmamap_load(t, m, p, s, cb, cba, f) \ 1039 ((t)->dt_mt->dm_dmamap_load((t), (m), (p), (s), (cb), (cba), (f))) 1040#define bus_dmamap_load_mbuf(t, m, mb, cb, cba, f) \ 1041 ((t)->dt_mt->dm_dmamap_load_mbuf((t), (m), (mb), (cb), (cba), (f))) 1042#define bus_dmamap_load_uio(t, m, ui, cb, cba, f) \ 1043 ((t)->dt_mt->dm_dmamap_load_uio((t), (m), (ui), (cb), (cba), (f))) 1044#define bus_dmamap_unload(t, p) \ 1045 ((t)->dt_mt->dm_dmamap_unload((t), (p))) 1046#define bus_dmamap_sync(t, m, op) \ 1047 ((t)->dt_mt->dm_dmamap_sync((t), (m), (op))) 1048#define bus_dmamem_alloc(t, v, f, m) \ 1049 ((t)->dt_mt->dm_dmamem_alloc((t), (v), (f), (m))) 1050#define bus_dmamem_free(t, v, m) \ 1051 ((t)->dt_mt->dm_dmamem_free((t), (v), (m))) 1052 1053/* 1054 * Generic helper function for manipulating mutexes. 1055 */ 1056void busdma_lock_mutex(void *arg, bus_dma_lock_op_t op); 1057#endif /* !_MACHINE_BUS_H_ */ 1058