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