bus.h revision 115343
1/* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */ 2 3/*- 4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40/* 41 * Copyright (c) 1996 Charles M. Hannum. All rights reserved. 42 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by Christopher G. Demetriou 55 * for the NetBSD Project. 56 * 4. The name of the author may not be used to endorse or promote products 57 * derived from this software without specific prior written permission 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 60 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 61 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 62 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 63 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 64 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 65 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 66 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 67 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 68 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 69 */ 70/* $FreeBSD: head/sys/ia64/include/bus.h 115343 2003-05-27 04:59:59Z scottl $ */ 71 72#ifndef _MACHINE_BUS_H_ 73#define _MACHINE_BUS_H_ 74 75/* 76 * Platform notes: 77 * o We don't use the _MACHINE_BUS_PIO_H_ and _MACHINE_BUS_MEMIO_H_ 78 * macros to conditionally compile for I/O port, memory mapped I/O 79 * or both. It's a micro-optimization that is not worth the pain 80 * because there is no I/O port space. I/O ports are emulated by 81 * doing memory mapped I/O in a special memory range. The address 82 * translation is slightly magic for I/O port accesses, but it does 83 * not warrant the overhead. 84 * 85 */ 86#define _MACHINE_BUS_MEMIO_H_ 87#define _MACHINE_BUS_PIO_H_ 88 89#include <machine/cpufunc.h> 90 91/* 92 * Values for the ia64 bus space tag, not to be used directly by MI code. 93 */ 94#define IA64_BUS_SPACE_IO 0 /* space is i/o space */ 95#define IA64_BUS_SPACE_MEM 1 /* space is mem space */ 96 97/* 98 * Bus address and size types 99 */ 100typedef u_long bus_addr_t; 101typedef u_long bus_size_t; 102 103#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF 104#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF 105#define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFF 106#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF 107#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF 108#define BUS_SPACE_MAXADDR 0xFFFFFFFF 109 110#define BUS_SPACE_UNRESTRICTED (~0) 111 112/* 113 * Access methods for bus resources and address space. 114 */ 115typedef int bus_space_tag_t; 116typedef u_long bus_space_handle_t; 117 118 119/* 120 * Map a region of device bus space into CPU virtual address space. 121 */ 122#define BUS_SPACE_MAP_CACHEABLE 0x01 123#define BUS_SPACE_MAP_LINEAR 0x02 124 125int 126bus_space_map(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size, int flags, 127 bus_space_handle_t *bshp); 128 129 130/* 131 * Unmap a region of device bus space. 132 */ 133static __inline void 134bus_space_unmap(bus_space_tag_t bst __unused, bus_space_handle_t bsh __unused, 135 bus_size_t size __unused) 136{ 137} 138 139 140/* 141 * Get a new handle for a subregion of an already-mapped area of bus space. 142 */ 143static __inline int 144bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh, 145 bus_size_t ofs, bus_size_t size, bus_space_handle_t *nbshp) 146{ 147 *nbshp = bsh + ofs; 148 return (0); 149} 150 151 152/* 153 * Allocate a region of memory that is accessible to devices in bus space. 154 */ 155int 156bus_space_alloc(bus_space_tag_t bst, bus_addr_t rstart, bus_addr_t rend, 157 bus_size_t size, bus_size_t align, bus_size_t boundary, int flags, 158 bus_addr_t *addrp, bus_space_handle_t *bshp); 159 160 161/* 162 * Free a region of bus space accessible memory. 163 */ 164void 165bus_space_free(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t size); 166 167 168/* 169 * Bus read/write barrier method. 170 */ 171#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 172#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 173 174static __inline void 175bus_space_barrier(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs, 176 bus_size_t size, int flags) 177{ 178 ia64_mf_a(); 179 ia64_mf(); 180} 181 182 183/* 184 * Read 1 unit of data from bus space described by the tag, handle and ofs 185 * tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 186 * data is returned. 187 */ 188static __inline uint8_t 189bus_space_read_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs) 190{ 191 uint8_t __volatile *bsp; 192 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 193 __MEMIO_ADDR(bsh + ofs); 194 return (*bsp); 195} 196 197static __inline uint16_t 198bus_space_read_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs) 199{ 200 uint16_t __volatile *bsp; 201 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 202 __MEMIO_ADDR(bsh + ofs); 203 return (*bsp); 204} 205 206static __inline uint32_t 207bus_space_read_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs) 208{ 209 uint32_t __volatile *bsp; 210 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 211 __MEMIO_ADDR(bsh + ofs); 212 return (*bsp); 213} 214 215static __inline uint64_t 216bus_space_read_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs) 217{ 218 uint64_t __volatile *bsp; 219 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 220 __MEMIO_ADDR(bsh + ofs); 221 return (*bsp); 222} 223 224 225/* 226 * Write 1 unit of data to bus space described by the tag, handle and ofs 227 * tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 228 * data is passed by value. 229 */ 230static __inline void 231bus_space_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs, 232 uint8_t val) 233{ 234 uint8_t __volatile *bsp; 235 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 236 __MEMIO_ADDR(bsh + ofs); 237 *bsp = val; 238} 239 240static __inline void 241bus_space_write_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs, 242 uint16_t val) 243{ 244 uint16_t __volatile *bsp; 245 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 246 __MEMIO_ADDR(bsh + ofs); 247 *bsp = val; 248} 249 250static __inline void 251bus_space_write_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs, 252 uint32_t val) 253{ 254 uint32_t __volatile *bsp; 255 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 256 __MEMIO_ADDR(bsh + ofs); 257 *bsp = val; 258} 259 260static __inline void 261bus_space_write_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs, 262 uint64_t val) 263{ 264 uint64_t __volatile *bsp; 265 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 266 __MEMIO_ADDR(bsh + ofs); 267 *bsp = val; 268} 269 270 271/* 272 * Read count units of data from bus space described by the tag, handle and 273 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 274 * data is returned in the buffer passed by reference. 275 */ 276static __inline void 277bus_space_read_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh, 278 bus_size_t ofs, uint8_t *bufp, size_t count) 279{ 280 uint8_t __volatile *bsp; 281 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 282 __MEMIO_ADDR(bsh + ofs); 283 while (count-- > 0) 284 *bufp++ = *bsp; 285} 286 287static __inline void 288bus_space_read_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, 289 bus_size_t ofs, uint16_t *bufp, size_t count) 290{ 291 uint16_t __volatile *bsp; 292 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 293 __MEMIO_ADDR(bsh + ofs); 294 while (count-- > 0) 295 *bufp++ = *bsp; 296} 297 298static __inline void 299bus_space_read_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, 300 bus_size_t ofs, uint32_t *bufp, size_t count) 301{ 302 uint32_t __volatile *bsp; 303 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 304 __MEMIO_ADDR(bsh + ofs); 305 while (count-- > 0) 306 *bufp++ = *bsp; 307} 308 309static __inline void 310bus_space_read_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh, 311 bus_size_t ofs, uint64_t *bufp, size_t count) 312{ 313 uint64_t __volatile *bsp; 314 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 315 __MEMIO_ADDR(bsh + ofs); 316 while (count-- > 0) 317 *bufp++ = *bsp; 318} 319 320 321/* 322 * Write count units of data to bus space described by the tag, handle and 323 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 324 * data is read from the buffer passed by reference. 325 */ 326static __inline void 327bus_space_write_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh, 328 bus_size_t ofs, const uint8_t *bufp, size_t count) 329{ 330 uint8_t __volatile *bsp; 331 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 332 __MEMIO_ADDR(bsh + ofs); 333 while (count-- > 0) 334 *bsp = *bufp++; 335} 336 337static __inline void 338bus_space_write_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, 339 bus_size_t ofs, const uint16_t *bufp, size_t count) 340{ 341 uint16_t __volatile *bsp; 342 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 343 __MEMIO_ADDR(bsh + ofs); 344 while (count-- > 0) 345 *bsp = *bufp++; 346} 347 348static __inline void 349bus_space_write_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, 350 bus_size_t ofs, const uint32_t *bufp, size_t count) 351{ 352 uint32_t __volatile *bsp; 353 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 354 __MEMIO_ADDR(bsh + ofs); 355 while (count-- > 0) 356 *bsp = *bufp++; 357} 358 359static __inline void 360bus_space_write_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh, 361 bus_size_t ofs, const uint64_t *bufp, size_t count) 362{ 363 uint64_t __volatile *bsp; 364 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 365 __MEMIO_ADDR(bsh + ofs); 366 while (count-- > 0) 367 *bsp = *bufp++; 368} 369 370 371/* 372 * Read count units of data from bus space described by the tag, handle and 373 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 374 * data is written to the buffer passed by reference and read from successive 375 * bus space addresses. Access is unordered. 376 */ 377static __inline void 378bus_space_read_region_1(bus_space_tag_t bst, bus_space_handle_t bsh, 379 bus_size_t ofs, uint8_t *bufp, size_t count) 380{ 381 uint8_t __volatile *bsp; 382 while (count-- > 0) { 383 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 384 __MEMIO_ADDR(bsh + ofs); 385 *bufp++ = *bsp; 386 ofs += 1; 387 } 388} 389 390static __inline void 391bus_space_read_region_2(bus_space_tag_t bst, bus_space_handle_t bsh, 392 bus_size_t ofs, uint16_t *bufp, size_t count) 393{ 394 uint16_t __volatile *bsp; 395 while (count-- > 0) { 396 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 397 __MEMIO_ADDR(bsh + ofs); 398 *bufp++ = *bsp; 399 ofs += 2; 400 } 401} 402 403static __inline void 404bus_space_read_region_4(bus_space_tag_t bst, bus_space_handle_t bsh, 405 bus_size_t ofs, uint32_t *bufp, size_t count) 406{ 407 uint32_t __volatile *bsp; 408 while (count-- > 0) { 409 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 410 __MEMIO_ADDR(bsh + ofs); 411 *bufp++ = *bsp; 412 ofs += 4; 413 } 414} 415 416static __inline void 417bus_space_read_region_8(bus_space_tag_t bst, bus_space_handle_t bsh, 418 bus_size_t ofs, uint64_t *bufp, size_t count) 419{ 420 uint64_t __volatile *bsp; 421 while (count-- > 0) { 422 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 423 __MEMIO_ADDR(bsh + ofs); 424 *bufp++ = *bsp; 425 ofs += 8; 426 } 427} 428 429 430/* 431 * Write count units of data from bus space described by the tag, handle and 432 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 433 * data is read from the buffer passed by reference and written to successive 434 * bus space addresses. Access is unordered. 435 */ 436static __inline void 437bus_space_write_region_1(bus_space_tag_t bst, bus_space_handle_t bsh, 438 bus_size_t ofs, const uint8_t *bufp, size_t count) 439{ 440 uint8_t __volatile *bsp; 441 while (count-- > 0) { 442 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 443 __MEMIO_ADDR(bsh + ofs); 444 *bsp = *bufp++; 445 ofs += 1; 446 } 447} 448 449static __inline void 450bus_space_write_region_2(bus_space_tag_t bst, bus_space_handle_t bsh, 451 bus_size_t ofs, const uint16_t *bufp, size_t count) 452{ 453 uint16_t __volatile *bsp; 454 while (count-- > 0) { 455 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 456 __MEMIO_ADDR(bsh + ofs); 457 *bsp = *bufp++; 458 ofs += 2; 459 } 460} 461 462static __inline void 463bus_space_write_region_4(bus_space_tag_t bst, bus_space_handle_t bsh, 464 bus_size_t ofs, const uint32_t *bufp, size_t count) 465{ 466 uint32_t __volatile *bsp; 467 while (count-- > 0) { 468 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 469 __MEMIO_ADDR(bsh + ofs); 470 *bsp = *bufp++; 471 ofs += 4; 472 } 473} 474 475static __inline void 476bus_space_write_region_8(bus_space_tag_t bst, bus_space_handle_t bsh, 477 bus_size_t ofs, const uint64_t *bufp, size_t count) 478{ 479 uint64_t __volatile *bsp; 480 while (count-- > 0) { 481 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 482 __MEMIO_ADDR(bsh + ofs); 483 *bsp = *bufp++; 484 ofs += 8; 485 } 486} 487 488 489/* 490 * Write count units of data from bus space described by the tag, handle and 491 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 492 * data is passed by value. Writes are unordered. 493 */ 494static __inline void 495bus_space_set_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh, 496 bus_size_t ofs, uint8_t val, size_t count) 497{ 498 uint8_t __volatile *bsp; 499 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 500 __MEMIO_ADDR(bsh + ofs); 501 while (count-- > 0) 502 *bsp = val; 503} 504 505static __inline void 506bus_space_set_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, 507 bus_size_t ofs, uint16_t val, size_t count) 508{ 509 uint16_t __volatile *bsp; 510 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 511 __MEMIO_ADDR(bsh + ofs); 512 while (count-- > 0) 513 *bsp = val; 514} 515 516static __inline void 517bus_space_set_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, 518 bus_size_t ofs, uint32_t val, size_t count) 519{ 520 uint32_t __volatile *bsp; 521 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 522 __MEMIO_ADDR(bsh + ofs); 523 while (count-- > 0) 524 *bsp = val; 525} 526 527static __inline void 528bus_space_set_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh, 529 bus_size_t ofs, uint64_t val, size_t count) 530{ 531 uint64_t __volatile *bsp; 532 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 533 __MEMIO_ADDR(bsh + ofs); 534 while (count-- > 0) 535 *bsp = val; 536} 537 538 539/* 540 * Write count units of data from bus space described by the tag, handle and 541 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 542 * data is passed by value and written to successive bus space addresses. 543 * Writes are unordered. 544 */ 545static __inline void 546bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t bsh, 547 bus_size_t ofs, uint8_t val, size_t count) 548{ 549 uint8_t __volatile *bsp; 550 while (count-- > 0) { 551 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 552 __MEMIO_ADDR(bsh + ofs); 553 *bsp = val; 554 ofs += 1; 555 } 556} 557 558static __inline void 559bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t bsh, 560 bus_size_t ofs, uint16_t val, size_t count) 561{ 562 uint16_t __volatile *bsp; 563 while (count-- > 0) { 564 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 565 __MEMIO_ADDR(bsh + ofs); 566 *bsp = val; 567 ofs += 2; 568 } 569} 570 571static __inline void 572bus_space_set_region_4(bus_space_tag_t bst, bus_space_handle_t bsh, 573 bus_size_t ofs, uint32_t val, size_t count) 574{ 575 uint32_t __volatile *bsp; 576 while (count-- > 0) { 577 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 578 __MEMIO_ADDR(bsh + ofs); 579 *bsp = val; 580 ofs += 4; 581 } 582} 583 584static __inline void 585bus_space_set_region_8(bus_space_tag_t bst, bus_space_handle_t bsh, 586 bus_size_t ofs, uint64_t val, size_t count) 587{ 588 uint64_t __volatile *bsp; 589 while (count-- > 0) { 590 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 591 __MEMIO_ADDR(bsh + ofs); 592 *bsp = val; 593 ofs += 8; 594 } 595} 596 597 598/* 599 * Copy count units of data from bus space described by the tag and the first 600 * handle and ofs pair to bus space described by the tag and the second handle 601 * and ofs pair. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. 602 * The data is read from successive bus space addresses and also written to 603 * successive bus space addresses. Both reads and writes are unordered. 604 */ 605static __inline void 606bus_space_copy_region_1(bus_space_tag_t bst, bus_space_handle_t bsh1, 607 bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count) 608{ 609 bus_addr_t dst, src; 610 uint8_t __volatile *dstp, *srcp; 611 src = bsh1 + ofs1; 612 dst = bsh2 + ofs2; 613 if (dst > src) { 614 src += count - 1; 615 dst += count - 1; 616 while (count-- > 0) { 617 if (bst == IA64_BUS_SPACE_IO) { 618 srcp = __PIO_ADDR(src); 619 dstp = __PIO_ADDR(dst); 620 } else { 621 srcp = __MEMIO_ADDR(src); 622 dstp = __MEMIO_ADDR(dst); 623 } 624 *dstp = *srcp; 625 src -= 1; 626 dst -= 1; 627 } 628 } else { 629 while (count-- > 0) { 630 if (bst == IA64_BUS_SPACE_IO) { 631 srcp = __PIO_ADDR(src); 632 dstp = __PIO_ADDR(dst); 633 } else { 634 srcp = __MEMIO_ADDR(src); 635 dstp = __MEMIO_ADDR(dst); 636 } 637 *dstp = *srcp; 638 src += 1; 639 dst += 1; 640 } 641 } 642} 643 644static __inline void 645bus_space_copy_region_2(bus_space_tag_t bst, bus_space_handle_t bsh1, 646 bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count) 647{ 648 bus_addr_t dst, src; 649 uint16_t __volatile *dstp, *srcp; 650 src = bsh1 + ofs1; 651 dst = bsh2 + ofs2; 652 if (dst > src) { 653 src += (count - 1) << 1; 654 dst += (count - 1) << 1; 655 while (count-- > 0) { 656 if (bst == IA64_BUS_SPACE_IO) { 657 srcp = __PIO_ADDR(src); 658 dstp = __PIO_ADDR(dst); 659 } else { 660 srcp = __MEMIO_ADDR(src); 661 dstp = __MEMIO_ADDR(dst); 662 } 663 *dstp = *srcp; 664 src -= 2; 665 dst -= 2; 666 } 667 } else { 668 while (count-- > 0) { 669 if (bst == IA64_BUS_SPACE_IO) { 670 srcp = __PIO_ADDR(src); 671 dstp = __PIO_ADDR(dst); 672 } else { 673 srcp = __MEMIO_ADDR(src); 674 dstp = __MEMIO_ADDR(dst); 675 } 676 *dstp = *srcp; 677 src += 2; 678 dst += 2; 679 } 680 } 681} 682 683static __inline void 684bus_space_copy_region_4(bus_space_tag_t bst, bus_space_handle_t bsh1, 685 bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count) 686{ 687 bus_addr_t dst, src; 688 uint32_t __volatile *dstp, *srcp; 689 src = bsh1 + ofs1; 690 dst = bsh2 + ofs2; 691 if (dst > src) { 692 src += (count - 1) << 2; 693 dst += (count - 1) << 2; 694 while (count-- > 0) { 695 if (bst == IA64_BUS_SPACE_IO) { 696 srcp = __PIO_ADDR(src); 697 dstp = __PIO_ADDR(dst); 698 } else { 699 srcp = __MEMIO_ADDR(src); 700 dstp = __MEMIO_ADDR(dst); 701 } 702 *dstp = *srcp; 703 src -= 4; 704 dst -= 4; 705 } 706 } else { 707 while (count-- > 0) { 708 if (bst == IA64_BUS_SPACE_IO) { 709 srcp = __PIO_ADDR(src); 710 dstp = __PIO_ADDR(dst); 711 } else { 712 srcp = __MEMIO_ADDR(src); 713 dstp = __MEMIO_ADDR(dst); 714 } 715 *dstp = *srcp; 716 src += 4; 717 dst += 4; 718 } 719 } 720} 721 722static __inline void 723bus_space_copy_region_8(bus_space_tag_t bst, bus_space_handle_t bsh1, 724 bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count) 725{ 726 bus_addr_t dst, src; 727 uint64_t __volatile *dstp, *srcp; 728 src = bsh1 + ofs1; 729 dst = bsh2 + ofs2; 730 if (dst > src) { 731 src += (count - 1) << 3; 732 dst += (count - 1) << 3; 733 while (count-- > 0) { 734 if (bst == IA64_BUS_SPACE_IO) { 735 srcp = __PIO_ADDR(src); 736 dstp = __PIO_ADDR(dst); 737 } else { 738 srcp = __MEMIO_ADDR(src); 739 dstp = __MEMIO_ADDR(dst); 740 } 741 *dstp = *srcp; 742 src -= 8; 743 dst -= 8; 744 } 745 } else { 746 while (count-- > 0) { 747 if (bst == IA64_BUS_SPACE_IO) { 748 srcp = __PIO_ADDR(src); 749 dstp = __PIO_ADDR(dst); 750 } else { 751 srcp = __MEMIO_ADDR(src); 752 dstp = __MEMIO_ADDR(dst); 753 } 754 *dstp = *srcp; 755 src += 8; 756 dst += 8; 757 } 758 } 759} 760 761 762/* 763 * Stream accesses are the same as normal accesses on ia64; there are no 764 * supported bus systems with an endianess different from the host one. 765 */ 766#define bus_space_read_stream_1(t, h, o) \ 767 bus_space_read_1(t, h, o) 768#define bus_space_read_stream_2(t, h, o) \ 769 bus_space_read_2(t, h, o) 770#define bus_space_read_stream_4(t, h, o) \ 771 bus_space_read_4(t, h, o) 772#define bus_space_read_stream_8(t, h, o) \ 773 bus_space_read_8(t, h, o) 774 775#define bus_space_read_multi_stream_1(t, h, o, a, c) \ 776 bus_space_read_multi_1(t, h, o, a, c) 777#define bus_space_read_multi_stream_2(t, h, o, a, c) \ 778 bus_space_read_multi_2(t, h, o, a, c) 779#define bus_space_read_multi_stream_4(t, h, o, a, c) \ 780 bus_space_read_multi_4(t, h, o, a, c) 781#define bus_space_read_multi_stream_8(t, h, o, a, c) \ 782 bus_space_read_multi_8(t, h, o, a, c) 783 784#define bus_space_write_stream_1(t, h, o, v) \ 785 bus_space_write_1(t, h, o, v) 786#define bus_space_write_stream_2(t, h, o, v) \ 787 bus_space_write_2(t, h, o, v) 788#define bus_space_write_stream_4(t, h, o, v) \ 789 bus_space_write_4(t, h, o, v) 790#define bus_space_write_stream_8(t, h, o, v) \ 791 bus_space_write_8(t, h, o, v) 792 793#define bus_space_write_multi_stream_1(t, h, o, a, c) \ 794 bus_space_write_multi_1(t, h, o, a, c) 795#define bus_space_write_multi_stream_2(t, h, o, a, c) \ 796 bus_space_write_multi_2(t, h, o, a, c) 797#define bus_space_write_multi_stream_4(t, h, o, a, c) \ 798 bus_space_write_multi_4(t, h, o, a, c) 799#define bus_space_write_multi_stream_8(t, h, o, a, c) \ 800 bus_space_write_multi_8(t, h, o, a, c) 801 802#define bus_space_set_multi_stream_1(t, h, o, v, c) \ 803 bus_space_set_multi_1(t, h, o, v, c) 804#define bus_space_set_multi_stream_2(t, h, o, v, c) \ 805 bus_space_set_multi_2(t, h, o, v, c) 806#define bus_space_set_multi_stream_4(t, h, o, v, c) \ 807 bus_space_set_multi_4(t, h, o, v, c) 808#define bus_space_set_multi_stream_8(t, h, o, v, c) \ 809 bus_space_set_multi_8(t, h, o, v, c) 810 811#define bus_space_read_region_stream_1(t, h, o, a, c) \ 812 bus_space_read_region_1(t, h, o, a, c) 813#define bus_space_read_region_stream_2(t, h, o, a, c) \ 814 bus_space_read_region_2(t, h, o, a, c) 815#define bus_space_read_region_stream_4(t, h, o, a, c) \ 816 bus_space_read_region_4(t, h, o, a, c) 817#define bus_space_read_region_stream_8(t, h, o, a, c) \ 818 bus_space_read_region_8(t, h, o, a, c) 819 820#define bus_space_write_region_stream_1(t, h, o, a, c) \ 821 bus_space_write_region_1(t, h, o, a, c) 822#define bus_space_write_region_stream_2(t, h, o, a, c) \ 823 bus_space_write_region_2(t, h, o, a, c) 824#define bus_space_write_region_stream_4(t, h, o, a, c) \ 825 bus_space_write_region_4(t, h, o, a, c) 826#define bus_space_write_region_stream_8(t, h, o, a, c) \ 827 bus_space_write_region_8(t, h, o, a, c) 828 829#define bus_space_set_region_stream_1(t, h, o, v, c) \ 830 bus_space_set_region_1(t, h, o, v, c) 831#define bus_space_set_region_stream_2(t, h, o, v, c) \ 832 bus_space_set_region_2(t, h, o, v, c) 833#define bus_space_set_region_stream_4(t, h, o, v, c) \ 834 bus_space_set_region_4(t, h, o, v, c) 835#define bus_space_set_region_stream_8(t, h, o, v, c) \ 836 bus_space_set_region_8(t, h, o, v, c) 837 838#define bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) \ 839 bus_space_copy_region_1(t, h1, o1, h2, o2, c) 840#define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \ 841 bus_space_copy_region_2(t, h1, o1, h2, o2, c) 842#define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \ 843 bus_space_copy_region_4(t, h1, o1, h2, o2, c) 844#define bus_space_copy_region_stream_8(t, h1, o1, h2, o2, c) \ 845 bus_space_copy_region_8(t, h1, o1, h2, o2, c) 846 847 848/* 849 * Flags used in various bus DMA methods. 850 */ 851#define BUS_DMA_WAITOK 0x00 /* safe to sleep (pseudo-flag) */ 852#define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */ 853#define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */ 854#define BUS_DMAMEM_NOSYNC 0x04 /* map memory to not require sync */ 855#define BUS_DMA_ISA 0x10 /* map memory for ISA dma */ 856#define BUS_DMA_BUS2 0x20 /* placeholders for bus functions... */ 857#define BUS_DMA_BUS3 0x40 858#define BUS_DMA_BUS4 0x80 859 860/* Forwards needed by prototypes below. */ 861struct mbuf; 862struct uio; 863 864/* 865 * Operations performed by bus_dmamap_sync(). 866 */ 867typedef int bus_dmasync_op_t; 868#define BUS_DMASYNC_PREREAD 1 869#define BUS_DMASYNC_POSTREAD 2 870#define BUS_DMASYNC_PREWRITE 4 871#define BUS_DMASYNC_POSTWRITE 8 872 873/* 874 * bus_dma_tag_t 875 * 876 * A machine-dependent opaque type describing the characteristics 877 * of how to perform DMA mappings. This structure encapsultes 878 * information concerning address and alignment restrictions, number 879 * of S/G segments, amount of data per S/G segment, etc. 880 */ 881typedef struct bus_dma_tag *bus_dma_tag_t; 882 883/* 884 * bus_dmamap_t 885 * 886 * DMA mapping instance information. 887 */ 888typedef struct bus_dmamap *bus_dmamap_t; 889 890/* 891 * bus_dma_segment_t 892 * 893 * Describes a single contiguous DMA transaction. Values 894 * are suitable for programming into DMA registers. 895 */ 896typedef struct bus_dma_segment { 897 bus_addr_t ds_addr; /* DMA address */ 898 bus_size_t ds_len; /* length of transfer */ 899} bus_dma_segment_t; 900 901/* 902 * A function that returns 1 if the address cannot be accessed by 903 * a device and 0 if it can be. 904 */ 905typedef int bus_dma_filter_t(void *, bus_addr_t); 906 907/* 908 * Allocate a device specific dma_tag encapsulating the constraints of 909 * the parent tag in addition to other restrictions specified: 910 * 911 * alignment: alignment for segments. 912 * boundary: Boundary that segments cannot cross. 913 * lowaddr: Low restricted address that cannot appear in a mapping. 914 * highaddr: High restricted addr. that cannot appear in a mapping. 915 * filtfunc: An optional function to further test if an address 916 * within the range of lowaddr and highaddr cannot appear 917 * in a mapping. 918 * filtfuncarg: An argument that will be passed to filtfunc in addition 919 * to the address to test. 920 * maxsize: Maximum mapping size supported by this tag. 921 * nsegments: Number of discontinuities allowed in maps. 922 * maxsegsz: Maximum size of a segment in the map. 923 * flags: Bus DMA flags. 924 * dmat: A pointer to set to a valid dma tag should the return 925 * value of this function indicate success. 926 */ 927/* XXX Should probably allow specification of alignment */ 928int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignemnt, 929 bus_size_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, 930 bus_dma_filter_t *filtfunc, void *filtfuncarg, bus_size_t maxsize, 931 int nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat); 932 933int bus_dma_tag_destroy(bus_dma_tag_t dmat); 934 935/* 936 * Allocate a handle for mapping from kva/uva/physical 937 * address space into bus device space. 938 */ 939int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp); 940 941/* 942 * Destroy a handle for mapping from kva/uva/physical 943 * address space into bus device space. 944 */ 945int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map); 946 947/* 948 * Allocate a piece of memory that can be efficiently mapped into 949 * bus device space based on the constraints lited in the dma tag. 950 * A dmamap to for use with dmamap_load is also allocated. 951 */ 952int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, 953 bus_dmamap_t *mapp); 954 955/* 956 * Free a piece of memory and it's allociated dmamap, that was allocated 957 * via bus_dmamem_alloc. 958 */ 959void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); 960 961/* 962 * A function that processes a successfully loaded dma map or an error 963 * from a delayed load map. 964 */ 965typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); 966 967/* 968 * Map the buffer buf into bus space using the dmamap map. 969 */ 970int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 971 bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, 972 int flags); 973 974/* 975 * Like bus_dmamap_callback but includes map size in bytes. This is 976 * defined as a separate interface to maintain compatiiblity for users 977 * of bus_dmamap_callback_t--at some point these interfaces should be merged. 978 */ 979typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, 980 bus_size_t, int); 981 982/* 983 * Like bus_dmamap_load but for mbufs. Note the use of the 984 * bus_dmamap_callback2_t interface. 985 */ 986int bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, 987 struct mbuf *mbuf, bus_dmamap_callback2_t *callback, void *callback_arg, 988 int flags); 989 990/* 991 * Like bus_dmamap_load but for uios. Note the use of the 992 * bus_dmamap_callback2_t interface. 993 */ 994int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *ui, 995 bus_dmamap_callback2_t *callback, void *callback_arg, int flags); 996 997/* 998 * Perform a syncronization operation on the given map. 999 */ 1000void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, int); 1001static __inline void 1002bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t dmamap, bus_dmasync_op_t op) 1003{ 1004 if ((dmamap) != NULL) 1005 _bus_dmamap_sync(dmat, dmamap, op); 1006} 1007 1008/* 1009 * Release the mapping held by map. 1010 */ 1011void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map); 1012static __inline void 1013bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t dmamap) 1014{ 1015 if ((dmamap) != NULL) 1016 _bus_dmamap_unload(dmat, dmamap); 1017} 1018 1019#endif /* _MACHINE_BUS_H_ */ 1020