bus.h revision 104486
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 104486 2002-10-04 20:40:39Z sam $ 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 (128 * 1024) /* Maximum supported size */ 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 *cookie; 127 bus_space_tag_t parent; 128 int type; 129 130 void (*bus_barrier)(bus_space_tag_t, bus_space_handle_t, 131 bus_size_t, bus_size_t, int); 132}; 133 134/* 135 * Helpers 136 */ 137int sparc64_bus_mem_map(bus_space_tag_t, bus_space_handle_t, bus_size_t, 138 int, vm_offset_t, void **); 139int sparc64_bus_mem_unmap(void *, bus_size_t); 140bus_space_handle_t sparc64_fake_bustag(int, bus_addr_t, 141 struct bus_space_tag *); 142 143/* 144 * Bus space function prototypes. 145 */ 146static void bus_space_barrier(bus_space_tag_t, bus_space_handle_t, bus_size_t, 147 bus_size_t, int); 148 149/* This macro finds the first "upstream" implementation of method `f' */ 150#define _BS_CALL(t,f) \ 151 while (t->f == NULL) \ 152 t = t->parent; \ 153 return (*(t)->f) 154 155static __inline void 156bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 157 bus_size_t s, int f) 158{ 159 _BS_CALL(t, bus_barrier)(t, h, o, s, f); 160} 161 162/* flags for bus space map functions */ 163#define BUS_SPACE_MAP_CACHEABLE 0x0001 164#define BUS_SPACE_MAP_LINEAR 0x0002 165#define BUS_SPACE_MAP_READONLY 0x0004 166#define BUS_SPACE_MAP_PREFETCHABLE 0x0008 167/* placeholders for bus functions... */ 168#define BUS_SPACE_MAP_BUS1 0x0100 169#define BUS_SPACE_MAP_BUS2 0x0200 170#define BUS_SPACE_MAP_BUS3 0x0400 171#define BUS_SPACE_MAP_BUS4 0x0800 172 173/* flags for bus_space_barrier() */ 174#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 175#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 176 177#ifdef BUS_SPACE_DEBUG 178#define KTR_BUS KTR_CT2 179#define BUS_HANDLE_MIN UPA_MEMSTART 180#define __BUS_DEBUG_ACCESS(h, o, desc, sz) do { \ 181 CTR4(KTR_BUS, "bus space: %s %d: handle %#lx, offset %#lx", \ 182 (desc), (sz), (h), (o)); \ 183 if ((h) + (o) < BUS_HANDLE_MIN) \ 184 panic("bus space access at %#lx out of range", \ 185 (h) + (o)); \ 186} while (0) 187#else 188#define __BUS_DEBUG_ACCESS(h, o, desc, sz) 189#endif 190 191static __inline uint8_t 192bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 193{ 194 195 __BUS_DEBUG_ACCESS(h, o, "read", 1); 196 return (lduba_nc((caddr_t)(h + o), bus_type_asi[t->type])); 197} 198 199static __inline uint16_t 200bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 201{ 202 203 __BUS_DEBUG_ACCESS(h, o, "read", 2); 204 return (lduha_nc((caddr_t)(h + o), bus_type_asi[t->type])); 205} 206 207static __inline uint32_t 208bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 209{ 210 211 __BUS_DEBUG_ACCESS(h, o, "read", 4); 212 return (lduwa_nc((caddr_t)(h + o), bus_type_asi[t->type])); 213} 214 215static __inline uint64_t 216bus_space_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 217{ 218 219 __BUS_DEBUG_ACCESS(h, o, "read", 8); 220 return (ldxa_nc((caddr_t)(h + o), bus_type_asi[t->type])); 221} 222 223static __inline void 224bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 225 uint8_t *a, size_t c) 226{ 227 228 while (c-- > 0) 229 *a++ = bus_space_read_1(t, h, o); 230} 231 232static __inline void 233bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 234 uint16_t *a, size_t c) 235{ 236 237 while (c-- > 0) 238 *a++ = bus_space_read_2(t, h, o); 239} 240 241static __inline void 242bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 243 uint32_t *a, size_t c) 244{ 245 246 while (c-- > 0) 247 *a++ = bus_space_read_4(t, h, o); 248} 249 250static __inline void 251bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 252 uint64_t *a, size_t c) 253{ 254 255 while (c-- > 0) 256 *a++ = bus_space_read_8(t, h, o); 257} 258 259static __inline void 260bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 261 uint8_t v) 262{ 263 264 __BUS_DEBUG_ACCESS(h, o, "write", 1); 265 stba_nc((caddr_t)(h + o), bus_type_asi[t->type], v); 266} 267 268static __inline void 269bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 270 uint16_t v) 271{ 272 273 __BUS_DEBUG_ACCESS(h, o, "write", 2); 274 stha_nc((caddr_t)(h + o), bus_type_asi[t->type], v); 275} 276 277static __inline void 278bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 279 uint32_t v) 280{ 281 282 __BUS_DEBUG_ACCESS(h, o, "write", 4); 283 stwa_nc((caddr_t)(h + o), bus_type_asi[t->type], v); 284} 285 286static __inline void 287bus_space_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 288 uint64_t v) 289{ 290 291 __BUS_DEBUG_ACCESS(h, o, "write", 8); 292 stxa_nc((caddr_t)(h + o), bus_type_asi[t->type], v); 293} 294 295static __inline void 296bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 297 uint8_t *a, size_t c) 298{ 299 300 while (c-- > 0) 301 bus_space_write_1(t, h, o, *a++); 302} 303 304static __inline void 305bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 306 uint16_t *a, size_t c) 307{ 308 309 while (c-- > 0) 310 bus_space_write_2(t, h, o, *a++); 311} 312 313static __inline void 314bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 315 uint32_t *a, size_t c) 316{ 317 318 while (c-- > 0) 319 bus_space_write_4(t, h, o, *a++); 320} 321 322static __inline void 323bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 324 uint64_t *a, size_t c) 325{ 326 327 while (c-- > 0) 328 bus_space_write_8(t, h, o, *a++); 329} 330 331static __inline void 332bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 333 uint8_t v, size_t c) 334{ 335 336 while (c-- > 0) 337 bus_space_write_1(t, h, o, v); 338} 339 340static __inline void 341bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 342 uint16_t v, size_t c) 343{ 344 345 while (c-- > 0) 346 bus_space_write_2(t, h, o, v); 347} 348 349static __inline void 350bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 351 uint32_t v, size_t c) 352{ 353 354 while (c-- > 0) 355 bus_space_write_4(t, h, o, v); 356} 357 358static __inline void 359bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 360 uint64_t v, size_t c) 361{ 362 363 while (c-- > 0) 364 bus_space_write_8(t, h, o, v); 365} 366 367static __inline void 368bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 369 u_int8_t *a, bus_size_t c) 370{ 371 for (; c; a++, c--, o++) 372 *a = bus_space_read_1(t, h, o); 373} 374 375static __inline void 376bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 377 u_int16_t *a, bus_size_t c) 378{ 379 for (; c; a++, c--, o+=2) 380 *a = bus_space_read_2(t, h, o); 381} 382 383static __inline void 384bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 385 u_int32_t *a, bus_size_t c) 386{ 387 for (; c; a++, c--, o+=4) 388 *a = bus_space_read_4(t, h, o); 389} 390 391static __inline void 392bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 393 u_int64_t *a, bus_size_t c) 394{ 395 for (; c; a++, c--, o+=8) 396 *a = bus_space_read_8(t, h, o); 397} 398 399static __inline void 400bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 401 const u_int8_t *a, bus_size_t c) 402{ 403 for (; c; a++, c--, o++) 404 bus_space_write_1(t, h, o, *a); 405} 406 407static __inline void 408bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 409 const u_int16_t *a, bus_size_t c) 410{ 411 for (; c; a++, c--, o+=2) 412 bus_space_write_2(t, h, o, *a); 413} 414 415static __inline void 416bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 417 const u_int32_t *a, bus_size_t c) 418{ 419 for (; c; a++, c--, o+=4) 420 bus_space_write_4(t, h, o, *a); 421} 422 423static __inline void 424bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 425 const u_int64_t *a, bus_size_t c) 426{ 427 for (; c; a++, c--, o+=8) 428 bus_space_write_8(t, h, o, *a); 429} 430 431static __inline void 432bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 433 const u_int8_t v, bus_size_t c) 434{ 435 for (; c; c--, o++) 436 bus_space_write_1(t, h, o, v); 437} 438 439static __inline void 440bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 441 const u_int16_t v, bus_size_t c) 442{ 443 for (; c; c--, o+=2) 444 bus_space_write_2(t, h, o, v); 445} 446 447static __inline void 448bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 449 const u_int32_t v, bus_size_t c) 450{ 451 for (; c; c--, o+=4) 452 bus_space_write_4(t, h, o, v); 453} 454 455static __inline void 456bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 457 const u_int64_t v, bus_size_t c) 458{ 459 for (; c; c--, o+=8) 460 bus_space_write_8(t, h, o, v); 461} 462 463static __inline void 464bus_space_copy_region_1(bus_space_tag_t t, bus_space_handle_t h1, 465 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 466{ 467 for (; c; c--, o1++, o2++) 468 bus_space_write_1(t, h1, o1, bus_space_read_1(t, h2, o2)); 469} 470 471static __inline void 472bus_space_copy_region_2(bus_space_tag_t t, bus_space_handle_t h1, 473 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 474{ 475 for (; c; c--, o1+=2, o2+=2) 476 bus_space_write_2(t, h1, o1, bus_space_read_2(t, h2, o2)); 477} 478 479static __inline void 480bus_space_copy_region_4(bus_space_tag_t t, bus_space_handle_t h1, 481 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 482{ 483 for (; c; c--, o1+=4, o2+=4) 484 bus_space_write_4(t, h1, o1, bus_space_read_4(t, h2, o2)); 485} 486 487static __inline void 488bus_space_copy_region_8(bus_space_tag_t t, bus_space_handle_t h1, 489 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 490{ 491 for (; c; c--, o1+=8, o2+=8) 492 bus_space_write_8(t, h1, o1, bus_space_read_8(t, h2, o2)); 493} 494 495static __inline uint8_t 496bus_space_read_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 497{ 498 499 __BUS_DEBUG_ACCESS(h, o, "read stream", 1); 500 return (lduba_nc((caddr_t)(h + o), bus_stream_asi[t->type])); 501} 502 503static __inline uint16_t 504bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 505{ 506 507 __BUS_DEBUG_ACCESS(h, o, "read stream", 2); 508 return (lduha_nc((caddr_t)(h + o), bus_stream_asi[t->type])); 509} 510 511static __inline uint32_t 512bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 513{ 514 515 __BUS_DEBUG_ACCESS(h, o, "read stream", 4); 516 return (lduwa_nc((caddr_t)(h + o), bus_stream_asi[t->type])); 517} 518 519static __inline uint64_t 520bus_space_read_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o) 521{ 522 523 __BUS_DEBUG_ACCESS(h, o, "read stream", 8); 524 return (ldxa_nc((caddr_t)(h + o), bus_stream_asi[t->type])); 525} 526 527static __inline void 528bus_space_read_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, 529 bus_size_t o, uint8_t *a, size_t c) 530{ 531 532 while (c-- > 0) 533 *a++ = bus_space_read_stream_1(t, h, o); 534} 535 536static __inline void 537bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, 538 bus_size_t o, uint16_t *a, size_t c) 539{ 540 541 while (c-- > 0) 542 *a++ = bus_space_read_stream_2(t, h, o); 543} 544 545static __inline void 546bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, 547 bus_size_t o, uint32_t *a, size_t c) 548{ 549 550 while (c-- > 0) 551 *a++ = bus_space_read_stream_4(t, h, o); 552} 553 554static __inline void 555bus_space_read_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, 556 bus_size_t o, uint64_t *a, size_t c) 557{ 558 559 while (c-- > 0) 560 *a++ = bus_space_read_stream_8(t, h, o); 561} 562 563static __inline void 564bus_space_write_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 565 uint8_t v) 566{ 567 568 __BUS_DEBUG_ACCESS(h, o, "write stream", 1); 569 stba_nc((caddr_t)(h + o), bus_stream_asi[t->type], v); 570} 571 572static __inline void 573bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 574 uint16_t v) 575{ 576 577 __BUS_DEBUG_ACCESS(h, o, "write stream", 2); 578 stha_nc((caddr_t)(h + o), bus_stream_asi[t->type], v); 579} 580 581static __inline void 582bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 583 uint32_t v) 584{ 585 586 __BUS_DEBUG_ACCESS(h, o, "write stream", 4); 587 stwa_nc((caddr_t)(h + o), bus_stream_asi[t->type], v); 588} 589 590static __inline void 591bus_space_write_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 592 uint64_t v) 593{ 594 595 __BUS_DEBUG_ACCESS(h, o, "write stream", 8); 596 stxa_nc((caddr_t)(h + o), bus_stream_asi[t->type], v); 597} 598 599static __inline void 600bus_space_write_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, 601 bus_size_t o, uint8_t *a, size_t c) 602{ 603 604 while (c-- > 0) 605 bus_space_write_stream_1(t, h, o, *a++); 606} 607 608static __inline void 609bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, 610 bus_size_t o, uint16_t *a, size_t c) 611{ 612 613 while (c-- > 0) 614 bus_space_write_stream_2(t, h, o, *a++); 615} 616 617static __inline void 618bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, 619 bus_size_t o, uint32_t *a, size_t c) 620{ 621 622 while (c-- > 0) 623 bus_space_write_stream_4(t, h, o, *a++); 624} 625 626static __inline void 627bus_space_write_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, 628 bus_size_t o, uint64_t *a, size_t c) 629{ 630 631 while (c-- > 0) 632 bus_space_write_stream_8(t, h, o, *a++); 633} 634 635static __inline void 636bus_space_set_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h, 637 bus_size_t o, uint8_t v, size_t c) 638{ 639 640 while (c-- > 0) 641 bus_space_write_stream_1(t, h, o, v); 642} 643 644static __inline void 645bus_space_set_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h, 646 bus_size_t o, uint16_t v, size_t c) 647{ 648 649 while (c-- > 0) 650 bus_space_write_stream_2(t, h, o, v); 651} 652 653static __inline void 654bus_space_set_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h, 655 bus_size_t o, uint32_t v, size_t c) 656{ 657 658 while (c-- > 0) 659 bus_space_write_stream_4(t, h, o, v); 660} 661 662static __inline void 663bus_space_set_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h, 664 bus_size_t o, uint64_t v, size_t c) 665{ 666 667 while (c-- > 0) 668 bus_space_write_stream_8(t, h, o, v); 669} 670 671static __inline void 672bus_space_read_region_stream_1(bus_space_tag_t t, bus_space_handle_t h, 673 bus_size_t o, u_int8_t *a, bus_size_t c) 674{ 675 for (; c; a++, c--, o++) 676 *a = bus_space_read_stream_1(t, h, o); 677} 678 679static __inline void 680bus_space_read_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, 681 bus_size_t o, u_int16_t *a, bus_size_t c) 682{ 683 for (; c; a++, c--, o+=2) 684 *a = bus_space_read_stream_2(t, h, o); 685} 686 687static __inline void 688bus_space_read_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, 689 bus_size_t o, u_int32_t *a, bus_size_t c) 690{ 691 for (; c; a++, c--, o+=4) 692 *a = bus_space_read_stream_4(t, h, o); 693} 694 695static __inline void 696bus_space_read_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, 697 bus_size_t o, u_int64_t *a, bus_size_t c) 698{ 699 for (; c; a++, c--, o+=8) 700 *a = bus_space_read_stream_8(t, h, o); 701} 702 703static __inline void 704bus_space_write_region_stream_1(bus_space_tag_t t, bus_space_handle_t h, 705 bus_size_t o, const u_int8_t *a, bus_size_t c) 706{ 707 for (; c; a++, c--, o++) 708 bus_space_write_stream_1(t, h, o, *a); 709} 710 711static __inline void 712bus_space_write_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, 713 bus_size_t o, const u_int16_t *a, bus_size_t c) 714{ 715 for (; c; a++, c--, o+=2) 716 bus_space_write_stream_2(t, h, o, *a); 717} 718 719static __inline void 720bus_space_write_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, 721 bus_size_t o, const u_int32_t *a, bus_size_t c) 722{ 723 for (; c; a++, c--, o+=4) 724 bus_space_write_stream_4(t, h, o, *a); 725} 726 727static __inline void 728bus_space_write_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, 729 bus_size_t o, const u_int64_t *a, bus_size_t c) 730{ 731 for (; c; a++, c--, o+=8) 732 bus_space_write_stream_8(t, h, o, *a); 733} 734 735static __inline void 736bus_space_set_region_stream_1(bus_space_tag_t t, bus_space_handle_t h, 737 bus_size_t o, const u_int8_t v, bus_size_t c) 738{ 739 for (; c; c--, o++) 740 bus_space_write_stream_1(t, h, o, v); 741} 742 743static __inline void 744bus_space_set_region_stream_2(bus_space_tag_t t, bus_space_handle_t h, 745 bus_size_t o, const u_int16_t v, bus_size_t c) 746{ 747 for (; c; c--, o+=2) 748 bus_space_write_stream_2(t, h, o, v); 749} 750 751static __inline void 752bus_space_set_region_stream_4(bus_space_tag_t t, bus_space_handle_t h, 753 bus_size_t o, const u_int32_t v, bus_size_t c) 754{ 755 for (; c; c--, o+=4) 756 bus_space_write_stream_4(t, h, o, v); 757} 758 759static __inline void 760bus_space_set_region_stream_8(bus_space_tag_t t, bus_space_handle_t h, 761 bus_size_t o, const u_int64_t v, bus_size_t c) 762{ 763 for (; c; c--, o+=8) 764 bus_space_write_stream_8(t, h, o, v); 765} 766 767static __inline void 768bus_space_copy_region_stream_1(bus_space_tag_t t, bus_space_handle_t h1, 769 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 770{ 771 for (; c; c--, o1++, o2++) 772 bus_space_write_stream_1(t, h1, o1, bus_space_read_stream_1(t, h2, 773 o2)); 774} 775 776static __inline void 777bus_space_copy_region_stream_2(bus_space_tag_t t, bus_space_handle_t h1, 778 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 779{ 780 for (; c; c--, o1+=2, o2+=2) 781 bus_space_write_stream_2(t, h1, o1, bus_space_read_stream_2(t, h2, 782 o2)); 783} 784 785static __inline void 786bus_space_copy_region_stream_4(bus_space_tag_t t, bus_space_handle_t h1, 787 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 788{ 789 for (; c; c--, o1+=4, o2+=4) 790 bus_space_write_stream_4(t, h1, o1, bus_space_read_stream_4(t, h2, 791 o2)); 792} 793 794static __inline void 795bus_space_copy_region_stream_8(bus_space_tag_t t, bus_space_handle_t h1, 796 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) 797{ 798 for (; c; c--, o1+=8, o2+=8) 799 bus_space_write_stream_8(t, h1, o1, bus_space_read_8(t, h2, o2)); 800} 801 802/* Back-compat functions for old ISA drivers */ 803extern bus_space_tag_t isa_io_bt; 804extern bus_space_handle_t isa_io_hdl; 805extern bus_space_tag_t isa_mem_bt; 806extern bus_space_handle_t isa_mem_hdl; 807 808#define inb(o) bus_space_read_1(isa_io_bt, isa_io_hdl, o) 809#define inw(o) bus_space_read_2(isa_io_bt, isa_io_hdl, o) 810#define inl(o) bus_space_read_4(isa_io_bt, isa_io_hdl, o) 811#define outb(o, v) bus_space_write_1(isa_io_bt, isa_io_hdl, o, v) 812#define outw(o, v) bus_space_write_2(isa_io_bt, isa_io_hdl, o, v) 813#define outl(o, v) bus_space_write_4(isa_io_bt, isa_io_hdl, o, v) 814 815#define readb(o) bus_space_read_1(isa_mem_bt, isa_mem_hdl, o) 816#define readw(o) bus_space_read_2(isa_mem_bt, isa_mem_hdl, o) 817#define readl(o) bus_space_read_4(isa_mem_bt, isa_mem_hdl, o) 818#define writeb(o, v) bus_space_write_1(isa_mem_bt, isa_mem_hdl, o, v) 819#define writew(o, v) bus_space_write_2(isa_mem_bt, isa_mem_hdl, o, v) 820#define writel(o, v) bus_space_write_4(isa_mem_bt, isa_mem_hdl, o, v) 821 822#define insb(o, a, c) \ 823 bus_space_read_multi_1(isa_io_bt, isa_io_hdl, o, (void*)a, c) 824#define insw(o, a, c) \ 825 bus_space_read_multi_2(isa_io_bt, isa_io_hdl, o, (void*)a, c) 826#define insl(o, a, c) \ 827 bus_space_read_multi_4(isa_io_bt, isa_io_hdl, o, (void*)a, c) 828#define outsb(o, a, c) \ 829 bus_space_write_multi_1(isa_io_bt, isa_io_hdl, o, (void*)a, c) 830#define outsw(o, a, c) \ 831 bus_space_write_multi_2(isa_io_bt, isa_io_hdl, o, (void*)a, c) 832#define outsl(o, a, c) \ 833 bus_space_write_multi_4(isa_io_bt, isa_io_hdl, o, (void*)a, c) 834 835#define memcpy_fromio(d, s, c) \ 836 bus_space_read_region_1(isa_mem_bt, isa_mem_hdl, s, d, c) 837#define memcpy_toio(d, s, c) \ 838 bus_space_write_region_1(isa_mem_bt, isa_mem_hdl, d, s, c) 839#define memcpy_io(d, s, c) \ 840 bus_space_copy_region_1(isa_mem_bt, isa_mem_hdl, s, isa_mem_hdl, d, c) 841#define memset_io(d, v, c) \ 842 bus_space_set_region_1(isa_mem_bt, isa_mem_hdl, d, v, c) 843#define memsetw_io(d, v, c) \ 844 bus_space_set_region_2(isa_mem_bt, isa_mem_hdl, d, v, c) 845 846static __inline void 847memsetw(void *d, int val, size_t size) 848{ 849 u_int16_t *sp = d; 850 851 while (size--) 852 *sp++ = val; 853} 854 855/* DMA support */ 856 857/* 858 * Flags used in various bus DMA methods. 859 */ 860#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ 861#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ 862#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ 863#define BUS_DMAMEM_NOSYNC 0x004 /* map memory to not require sync */ 864#define BUS_DMA_NOWRITE 0x008 865#define BUS_DMA_BUS1 0x010 866#define BUS_DMA_BUS2 0x020 867#define BUS_DMA_BUS3 0x040 868#define BUS_DMA_BUS4 0x080 869/* 870 * The following flags are from NetBSD, but are not implemented for all 871 * architetures, and should therefore not be used in MI code. 872 * Some have different values than under NetBSD. 873 */ 874#define BUS_DMA_STREAMING 0x100 /* hint: sequential, unidirectional */ 875#define BUS_DMA_READ 0x200 /* mapping is device -> memory only */ 876#define BUS_DMA_WRITE 0x400 /* mapping is memory -> device only */ 877#define BUS_DMA_COHERENT 0x800 /* hint: map memory DMA coherent */ 878 879#define BUS_DMA_NOCACHE BUS_DMA_BUS1 880/* Don't bother with alignment */ 881#define BUS_DMA_DVMA BUS_DMA_BUS2 882 883/* Forwards needed by prototypes below. */ 884struct mbuf; 885struct uio; 886 887typedef enum { 888 BUS_DMASYNC_PREREAD, 889 BUS_DMASYNC_POSTREAD, 890 BUS_DMASYNC_PREWRITE, 891 BUS_DMASYNC_POSTWRITE, 892} bus_dmasync_op_t; 893 894/* 895 * A function that returns 1 if the address cannot be accessed by 896 * a device and 0 if it can be. 897 */ 898typedef int bus_dma_filter_t(void *, bus_addr_t); 899 900typedef struct bus_dma_tag *bus_dma_tag_t; 901typedef struct bus_dmamap *bus_dmamap_t; 902 903struct bus_dma_segment { 904 bus_addr_t ds_addr; /* DVMA address */ 905 bus_size_t ds_len; /* length of transfer */ 906}; 907typedef struct bus_dma_segment bus_dma_segment_t; 908 909/* 910 * A function that processes a successfully loaded dma map or an error 911 * from a delayed load map. 912 */ 913typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); 914 915/* 916 * Like bus_dmamap_callback but includes map size in bytes. This is 917 * defined as a separate interface to maintain compatiiblity for users 918 * of bus_dmamap_callback_t--at some point these interfaces should be merged. 919 */ 920typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, bus_size_t, int); 921 922/* 923 * bus_dma_tag_t 924 * 925 * A machine-dependent opaque type describing the implementation of 926 * DMA for a given bus. 927 */ 928struct bus_dma_tag { 929 void *cookie; /* cookie used in the guts */ 930 bus_dma_tag_t parent; 931 bus_size_t alignment; 932 bus_size_t boundary; 933 bus_addr_t lowaddr; 934 bus_addr_t highaddr; 935 bus_dma_filter_t *filter; 936 void *filterarg; 937 bus_size_t maxsize; 938 u_int nsegments; 939 bus_size_t maxsegsz; 940 int flags; 941 int ref_count; 942 int map_count; 943 944 /* 945 * DMA mapping methods. 946 */ 947 int (*dmamap_create)(bus_dma_tag_t, bus_dma_tag_t, int, 948 bus_dmamap_t *); 949 int (*dmamap_destroy)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); 950 int (*dmamap_load)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, 951 void *, bus_size_t, bus_dmamap_callback_t *, void *, int); 952 int (*dmamap_load_mbuf)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, 953 struct mbuf *, bus_dmamap_callback2_t *, void *, int); 954 int (*dmamap_load_uio)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, 955 struct uio *, bus_dmamap_callback2_t *, void *, int); 956 void (*dmamap_unload)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t); 957 void (*dmamap_sync)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t, 958 bus_dmasync_op_t); 959 960 /* 961 * DMA memory utility functions. 962 */ 963 int (*dmamem_alloc)(bus_dma_tag_t, bus_dma_tag_t, void **, int, 964 bus_dmamap_t *); 965 void (*dmamem_free)(bus_dma_tag_t, bus_dma_tag_t, void *, 966 bus_dmamap_t); 967}; 968 969/* 970 * XXX: This is a kluge. It would be better to handle dma tags in a hierarchical 971 * way, and have a BUS_GET_DMA_TAG(); however, since this is not currently the 972 * case, save a root tag in the relevant bus attach function and use that. 973 * Keep the hierarchical structure, it might become needed in the future. 974 */ 975extern bus_dma_tag_t sparc64_root_dma_tag; 976 977int bus_dma_tag_create(bus_dma_tag_t, bus_size_t, bus_size_t, bus_addr_t, 978 bus_addr_t, bus_dma_filter_t *, void *, bus_size_t, int, bus_size_t, 979 int, bus_dma_tag_t *); 980 981int bus_dma_tag_destroy(bus_dma_tag_t); 982 983int sparc64_dmamem_alloc_map(bus_dma_tag_t dmat, bus_dmamap_t *mapp); 984void sparc64_dmamem_free_map(bus_dma_tag_t dmat, bus_dmamap_t map); 985 986static __inline int 987sparc64_dmamap_create(bus_dma_tag_t pt, bus_dma_tag_t dt, int f, 988 bus_dmamap_t *p) 989{ 990 bus_dma_tag_t lt; 991 992 for (lt = pt; lt->dmamap_create == NULL; lt = lt->parent) 993 ; 994 return ((*lt->dmamap_create)(lt, dt, f, p)); 995} 996#define bus_dmamap_create(t, f, p) \ 997 sparc64_dmamap_create((t), (t), (f), (p)) 998 999static __inline int 1000sparc64_dmamap_destroy(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t p) 1001{ 1002 bus_dma_tag_t lt; 1003 1004 for (lt = pt; lt->dmamap_destroy == NULL; lt = lt->parent) 1005 ; 1006 return ((*lt->dmamap_destroy)(lt, dt, p)); 1007} 1008#define bus_dmamap_destroy(t, p) \ 1009 sparc64_dmamap_destroy((t), (t), (p)) 1010 1011static __inline int 1012sparc64_dmamap_load(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m, 1013 void *p, bus_size_t s, bus_dmamap_callback_t *cb, void *cba, int f) 1014{ 1015 bus_dma_tag_t lt; 1016 1017 for (lt = pt; lt->dmamap_load == NULL; lt = lt->parent) 1018 ; 1019 return ((*lt->dmamap_load)(lt, dt, m, p, s, cb, cba, f)); 1020} 1021#define bus_dmamap_load(t, m, p, s, cb, cba, f) \ 1022 sparc64_dmamap_load((t), (t), (m), (p), (s), (cb), (cba), (f)) 1023 1024static __inline int 1025sparc64_dmamap_load_mbuf(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m, 1026 struct mbuf *mb, bus_dmamap_callback2_t *cb, void *cba, int f) 1027{ 1028 bus_dma_tag_t lt; 1029 1030 for (lt = pt; lt->dmamap_load == NULL; lt = lt->parent) 1031 ; 1032 return ((*lt->dmamap_load_mbuf)(lt, dt, m, mb, cb, cba, f)); 1033} 1034#define bus_dmamap_load_mbuf(t, m, mb, cb, cba, f) \ 1035 sparc64_dmamap_load_mbuf((t), (t), (m), (mb), (cb), (cba), (f)) 1036 1037static __inline int 1038sparc64_dmamap_load_uio(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m, 1039 struct uio *ui, bus_dmamap_callback2_t *cb, void *cba, int f) 1040{ 1041 bus_dma_tag_t lt; 1042 1043 for (lt = pt; lt->dmamap_load == NULL; lt = lt->parent) 1044 ; 1045 return ((*lt->dmamap_load_uio)(lt, dt, m, ui, cb, cba, f)); 1046} 1047#define bus_dmamap_load_uio(t, m, ui, cb, cba, f) \ 1048 sparc64_dmamap_load_uio((t), (t), (m), (ui), (cb), (cba), (f)) 1049 1050static __inline void 1051sparc64_dmamap_unload(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t p) 1052{ 1053 bus_dma_tag_t lt; 1054 1055 for (lt = pt; lt->dmamap_unload == NULL; lt = lt->parent) 1056 ; 1057 (*lt->dmamap_unload)(lt, dt, p); 1058} 1059#define bus_dmamap_unload(t, p) \ 1060 sparc64_dmamap_unload((t), (t), (p)) 1061 1062static __inline void 1063sparc64_dmamap_sync(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m, 1064 bus_dmasync_op_t op) 1065{ 1066 bus_dma_tag_t lt; 1067 1068 for (lt = pt; lt->dmamap_sync == NULL; lt = lt->parent) 1069 ; 1070 (*lt->dmamap_sync)(lt, dt, m, op); 1071} 1072#define bus_dmamap_sync(t, m, op) \ 1073 sparc64_dmamap_sync((t), (t), (m), (op)) 1074 1075static __inline int 1076sparc64_dmamem_alloc(bus_dma_tag_t pt, bus_dma_tag_t dt, void **v, int f, 1077 bus_dmamap_t *m) 1078{ 1079 bus_dma_tag_t lt; 1080 1081 for (lt = pt; lt->dmamem_alloc == NULL; lt = lt->parent) 1082 ; 1083 return ((*lt->dmamem_alloc)(lt, dt, v, f, m)); 1084} 1085#define bus_dmamem_alloc(t, v, f, m) \ 1086 sparc64_dmamem_alloc((t), (t), (v), (f), (m)) 1087 1088static __inline void 1089sparc64_dmamem_free(bus_dma_tag_t pt, bus_dma_tag_t dt, void *v, 1090 bus_dmamap_t m) 1091{ 1092 bus_dma_tag_t lt; 1093 1094 for (lt = pt; lt->dmamem_free == NULL; lt = lt->parent) 1095 ; 1096 (*lt->dmamem_free)(lt, dt, v, m); 1097} 1098#define bus_dmamem_free(t, v, m) \ 1099 sparc64_dmamem_free((t), (t), (v), (m)) 1100 1101#endif /* !_MACHINE_BUS_H_ */ 1102