bus.h revision 116541
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 116541 2003-06-18 16:41:36Z tmm $ 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 814/* Back-compat functions for old ISA drivers */ 815extern bus_space_tag_t isa_io_bt; 816extern bus_space_handle_t isa_io_hdl; 817extern bus_space_tag_t isa_mem_bt; 818extern bus_space_handle_t isa_mem_hdl; 819 820#define inb(o) bus_space_read_1(isa_io_bt, isa_io_hdl, o) 821#define inw(o) bus_space_read_2(isa_io_bt, isa_io_hdl, o) 822#define inl(o) bus_space_read_4(isa_io_bt, isa_io_hdl, o) 823#define outb(o, v) bus_space_write_1(isa_io_bt, isa_io_hdl, o, v) 824#define outw(o, v) bus_space_write_2(isa_io_bt, isa_io_hdl, o, v) 825#define outl(o, v) bus_space_write_4(isa_io_bt, isa_io_hdl, o, v) 826 827#define readb(o) bus_space_read_1(isa_mem_bt, isa_mem_hdl, o) 828#define readw(o) bus_space_read_2(isa_mem_bt, isa_mem_hdl, o) 829#define readl(o) bus_space_read_4(isa_mem_bt, isa_mem_hdl, o) 830#define writeb(o, v) bus_space_write_1(isa_mem_bt, isa_mem_hdl, o, v) 831#define writew(o, v) bus_space_write_2(isa_mem_bt, isa_mem_hdl, o, v) 832#define writel(o, v) bus_space_write_4(isa_mem_bt, isa_mem_hdl, o, v) 833 834#define insb(o, a, c) \ 835 bus_space_read_multi_1(isa_io_bt, isa_io_hdl, o, (void*)a, c) 836#define insw(o, a, c) \ 837 bus_space_read_multi_2(isa_io_bt, isa_io_hdl, o, (void*)a, c) 838#define insl(o, a, c) \ 839 bus_space_read_multi_4(isa_io_bt, isa_io_hdl, o, (void*)a, c) 840#define outsb(o, a, c) \ 841 bus_space_write_multi_1(isa_io_bt, isa_io_hdl, o, (void*)a, c) 842#define outsw(o, a, c) \ 843 bus_space_write_multi_2(isa_io_bt, isa_io_hdl, o, (void*)a, c) 844#define outsl(o, a, c) \ 845 bus_space_write_multi_4(isa_io_bt, isa_io_hdl, o, (void*)a, c) 846 847#define memcpy_fromio(d, s, c) \ 848 bus_space_read_region_1(isa_mem_bt, isa_mem_hdl, s, d, c) 849#define memcpy_toio(d, s, c) \ 850 bus_space_write_region_1(isa_mem_bt, isa_mem_hdl, d, s, c) 851#define memcpy_io(d, s, c) \ 852 bus_space_copy_region_1(isa_mem_bt, isa_mem_hdl, s, isa_mem_hdl, d, c) 853#define memset_io(d, v, c) \ 854 bus_space_set_region_1(isa_mem_bt, isa_mem_hdl, d, v, c) 855#define memsetw_io(d, v, c) \ 856 bus_space_set_region_2(isa_mem_bt, isa_mem_hdl, d, v, c) 857 858static __inline void 859memsetw(void *d, int val, size_t size) 860{ 861 u_int16_t *sp = d; 862 863 while (size--) 864 *sp++ = val; 865} 866 867/* DMA support */ 868 869/* 870 * Flags used in various bus DMA methods. 871 */ 872#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ 873#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ 874#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ 875#define BUS_DMA_COHERENT 0x004 /* hint: map memory in a coherent way */ 876#define BUS_DMA_NOWRITE 0x008 877#define BUS_DMA_BUS1 0x010 878#define BUS_DMA_BUS2 0x020 879#define BUS_DMA_BUS3 0x040 880#define BUS_DMA_BUS4 0x080 881/* 882 * The following flags are from NetBSD, but are not implemented for all 883 * architetures, and should therefore not be used in MI code. 884 * Some have different values than under NetBSD. 885 */ 886#define BUS_DMA_STREAMING 0x100 /* hint: sequential, unidirectional */ 887#define BUS_DMA_READ 0x200 /* mapping is device -> memory only */ 888#define BUS_DMA_WRITE 0x400 /* mapping is memory -> device only */ 889 890#define BUS_DMA_NOCACHE BUS_DMA_BUS1 891/* Don't bother with alignment */ 892#define BUS_DMA_DVMA BUS_DMA_BUS2 893 894/* Forwards needed by prototypes below. */ 895struct mbuf; 896struct uio; 897 898typedef int bus_dmasync_op_t; 899#define BUS_DMASYNC_PREREAD 1 900#define BUS_DMASYNC_POSTREAD 2 901#define BUS_DMASYNC_PREWRITE 4 902#define BUS_DMASYNC_POSTWRITE 8 903 904/* 905 * A function that returns 1 if the address cannot be accessed by 906 * a device and 0 if it can be. 907 */ 908typedef int bus_dma_filter_t(void *, bus_addr_t); 909 910typedef struct bus_dma_tag *bus_dma_tag_t; 911typedef struct bus_dmamap *bus_dmamap_t; 912 913struct bus_dma_segment { 914 bus_addr_t ds_addr; /* DVMA address */ 915 bus_size_t ds_len; /* length of transfer */ 916}; 917typedef struct bus_dma_segment bus_dma_segment_t; 918 919/* 920 * A function that processes a successfully loaded dma map or an error 921 * from a delayed load map. 922 */ 923typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); 924 925/* 926 * Like bus_dmamap_callback but includes map size in bytes. This is 927 * defined as a separate interface to maintain compatiiblity for users 928 * of bus_dmamap_callback_t--at some point these interfaces should be merged. 929 */ 930typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, bus_size_t, int); 931 932/* 933 * Method table for a bus_dma_tag. 934 */ 935struct bus_dma_methods { 936 int (*dm_dmamap_create)(bus_dma_tag_t, int, bus_dmamap_t *); 937 int (*dm_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); 938 int (*dm_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, 939 bus_size_t, bus_dmamap_callback_t *, void *, int); 940 int (*dm_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, 941 struct mbuf *, bus_dmamap_callback2_t *, void *, int); 942 int (*dm_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, struct uio *, 943 bus_dmamap_callback2_t *, void *, int); 944 void (*dm_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); 945 void (*dm_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, 946 bus_dmasync_op_t); 947 int (*dm_dmamem_alloc)(bus_dma_tag_t, void **, int, bus_dmamap_t *); 948 void (*dm_dmamem_free)(bus_dma_tag_t, void *, bus_dmamap_t); 949}; 950 951/* 952 * bus_dma_tag_t 953 * 954 * A machine-dependent opaque type describing the implementation of 955 * DMA for a given bus. 956 */ 957struct bus_dma_tag { 958 void *dt_cookie; /* cookie used in the guts */ 959 bus_dma_tag_t dt_parent; 960 bus_size_t dt_alignment; 961 bus_size_t dt_boundary; 962 bus_addr_t dt_lowaddr; 963 bus_addr_t dt_highaddr; 964 bus_dma_filter_t *dt_filter; 965 void *dt_filterarg; 966 bus_size_t dt_maxsize; 967 int dt_nsegments; 968 bus_size_t dt_maxsegsz; 969 int dt_flags; 970 int dt_ref_count; 971 int dt_map_count; 972 973 struct bus_dma_methods *dt_mt; 974}; 975 976int bus_dma_tag_create(bus_dma_tag_t, bus_size_t, bus_size_t, bus_addr_t, 977 bus_addr_t, bus_dma_filter_t *, void *, bus_size_t, int, bus_size_t, 978 int, bus_dma_tag_t *); 979 980int bus_dma_tag_destroy(bus_dma_tag_t); 981 982#define bus_dmamap_create(t, f, p) \ 983 ((t)->dt_mt->dm_dmamap_create((t), (f), (p))) 984#define bus_dmamap_destroy(t, p) \ 985 ((t)->dt_mt->dm_dmamap_destroy((t), (p))) 986#define bus_dmamap_load(t, m, p, s, cb, cba, f) \ 987 ((t)->dt_mt->dm_dmamap_load((t), (m), (p), (s), (cb), (cba), (f))) 988#define bus_dmamap_load_mbuf(t, m, mb, cb, cba, f) \ 989 ((t)->dt_mt->dm_dmamap_load_mbuf((t), (m), (mb), (cb), (cba), (f))) 990#define bus_dmamap_load_uio(t, m, ui, cb, cba, f) \ 991 ((t)->dt_mt->dm_dmamap_load_uio((t), (m), (ui), (cb), (cba), (f))) 992#define bus_dmamap_unload(t, p) \ 993 ((t)->dt_mt->dm_dmamap_unload((t), (p))) 994#define bus_dmamap_sync(t, m, op) \ 995 ((t)->dt_mt->dm_dmamap_sync((t), (m), (op))) 996#define bus_dmamem_alloc(t, v, f, m) \ 997 ((t)->dt_mt->dm_dmamem_alloc((t), (v), (f), (m))) 998#define bus_dmamem_free(t, v, m) \ 999 ((t)->dt_mt->dm_dmamem_free((t), (v), (m))) 1000 1001#endif /* !_MACHINE_BUS_H_ */ 1002