bus.h revision 139790
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 139790 2005-01-06 22:18:23Z imp $ */ 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 123static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr, 124 bus_size_t size, int flags, 125 bus_space_handle_t *bshp); 126 127static __inline int 128bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr, 129 bus_size_t size __unused, int flags __unused, 130 bus_space_handle_t *bshp) 131{ 132 133 *bshp = addr; 134 return (0); 135} 136 137/* 138 * Unmap a region of device bus space. 139 */ 140static __inline void 141bus_space_unmap(bus_space_tag_t bst __unused, bus_space_handle_t bsh __unused, 142 bus_size_t size __unused) 143{ 144} 145 146 147/* 148 * Get a new handle for a subregion of an already-mapped area of bus space. 149 */ 150static __inline int 151bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh, 152 bus_size_t ofs, bus_size_t size, bus_space_handle_t *nbshp) 153{ 154 *nbshp = bsh + ofs; 155 return (0); 156} 157 158 159/* 160 * Allocate a region of memory that is accessible to devices in bus space. 161 */ 162int 163bus_space_alloc(bus_space_tag_t bst, bus_addr_t rstart, bus_addr_t rend, 164 bus_size_t size, bus_size_t align, bus_size_t boundary, int flags, 165 bus_addr_t *addrp, bus_space_handle_t *bshp); 166 167 168/* 169 * Free a region of bus space accessible memory. 170 */ 171void 172bus_space_free(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t size); 173 174 175/* 176 * Bus read/write barrier method. 177 */ 178#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 179#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 180 181static __inline void 182bus_space_barrier(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs, 183 bus_size_t size, int flags) 184{ 185 ia64_mf_a(); 186 ia64_mf(); 187} 188 189 190/* 191 * Read 1 unit of data from bus space described by the tag, handle and ofs 192 * tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 193 * data is returned. 194 */ 195static __inline uint8_t 196bus_space_read_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs) 197{ 198 uint8_t __volatile *bsp; 199 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 200 __MEMIO_ADDR(bsh + ofs); 201 return (*bsp); 202} 203 204static __inline uint16_t 205bus_space_read_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs) 206{ 207 uint16_t __volatile *bsp; 208 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 209 __MEMIO_ADDR(bsh + ofs); 210 return (*bsp); 211} 212 213static __inline uint32_t 214bus_space_read_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs) 215{ 216 uint32_t __volatile *bsp; 217 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 218 __MEMIO_ADDR(bsh + ofs); 219 return (*bsp); 220} 221 222static __inline uint64_t 223bus_space_read_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs) 224{ 225 uint64_t __volatile *bsp; 226 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 227 __MEMIO_ADDR(bsh + ofs); 228 return (*bsp); 229} 230 231 232/* 233 * Write 1 unit of data to bus space described by the tag, handle and ofs 234 * tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 235 * data is passed by value. 236 */ 237static __inline void 238bus_space_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs, 239 uint8_t val) 240{ 241 uint8_t __volatile *bsp; 242 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 243 __MEMIO_ADDR(bsh + ofs); 244 *bsp = val; 245} 246 247static __inline void 248bus_space_write_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs, 249 uint16_t val) 250{ 251 uint16_t __volatile *bsp; 252 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 253 __MEMIO_ADDR(bsh + ofs); 254 *bsp = val; 255} 256 257static __inline void 258bus_space_write_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs, 259 uint32_t val) 260{ 261 uint32_t __volatile *bsp; 262 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 263 __MEMIO_ADDR(bsh + ofs); 264 *bsp = val; 265} 266 267static __inline void 268bus_space_write_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs, 269 uint64_t val) 270{ 271 uint64_t __volatile *bsp; 272 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 273 __MEMIO_ADDR(bsh + ofs); 274 *bsp = val; 275} 276 277 278/* 279 * Read count units of data from bus space described by the tag, handle and 280 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 281 * data is returned in the buffer passed by reference. 282 */ 283static __inline void 284bus_space_read_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh, 285 bus_size_t ofs, uint8_t *bufp, size_t count) 286{ 287 uint8_t __volatile *bsp; 288 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 289 __MEMIO_ADDR(bsh + ofs); 290 while (count-- > 0) 291 *bufp++ = *bsp; 292} 293 294static __inline void 295bus_space_read_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, 296 bus_size_t ofs, uint16_t *bufp, size_t count) 297{ 298 uint16_t __volatile *bsp; 299 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 300 __MEMIO_ADDR(bsh + ofs); 301 while (count-- > 0) 302 *bufp++ = *bsp; 303} 304 305static __inline void 306bus_space_read_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, 307 bus_size_t ofs, uint32_t *bufp, size_t count) 308{ 309 uint32_t __volatile *bsp; 310 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 311 __MEMIO_ADDR(bsh + ofs); 312 while (count-- > 0) 313 *bufp++ = *bsp; 314} 315 316static __inline void 317bus_space_read_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh, 318 bus_size_t ofs, uint64_t *bufp, size_t count) 319{ 320 uint64_t __volatile *bsp; 321 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 322 __MEMIO_ADDR(bsh + ofs); 323 while (count-- > 0) 324 *bufp++ = *bsp; 325} 326 327 328/* 329 * Write count units of data to bus space described by the tag, handle and 330 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 331 * data is read from the buffer passed by reference. 332 */ 333static __inline void 334bus_space_write_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh, 335 bus_size_t ofs, const uint8_t *bufp, size_t count) 336{ 337 uint8_t __volatile *bsp; 338 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 339 __MEMIO_ADDR(bsh + ofs); 340 while (count-- > 0) 341 *bsp = *bufp++; 342} 343 344static __inline void 345bus_space_write_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, 346 bus_size_t ofs, const uint16_t *bufp, size_t count) 347{ 348 uint16_t __volatile *bsp; 349 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 350 __MEMIO_ADDR(bsh + ofs); 351 while (count-- > 0) 352 *bsp = *bufp++; 353} 354 355static __inline void 356bus_space_write_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, 357 bus_size_t ofs, const uint32_t *bufp, size_t count) 358{ 359 uint32_t __volatile *bsp; 360 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 361 __MEMIO_ADDR(bsh + ofs); 362 while (count-- > 0) 363 *bsp = *bufp++; 364} 365 366static __inline void 367bus_space_write_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh, 368 bus_size_t ofs, const uint64_t *bufp, size_t count) 369{ 370 uint64_t __volatile *bsp; 371 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 372 __MEMIO_ADDR(bsh + ofs); 373 while (count-- > 0) 374 *bsp = *bufp++; 375} 376 377 378/* 379 * Read count units of data from bus space described by the tag, handle and 380 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 381 * data is written to the buffer passed by reference and read from successive 382 * bus space addresses. Access is unordered. 383 */ 384static __inline void 385bus_space_read_region_1(bus_space_tag_t bst, bus_space_handle_t bsh, 386 bus_size_t ofs, uint8_t *bufp, size_t count) 387{ 388 uint8_t __volatile *bsp; 389 while (count-- > 0) { 390 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 391 __MEMIO_ADDR(bsh + ofs); 392 *bufp++ = *bsp; 393 ofs += 1; 394 } 395} 396 397static __inline void 398bus_space_read_region_2(bus_space_tag_t bst, bus_space_handle_t bsh, 399 bus_size_t ofs, uint16_t *bufp, size_t count) 400{ 401 uint16_t __volatile *bsp; 402 while (count-- > 0) { 403 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 404 __MEMIO_ADDR(bsh + ofs); 405 *bufp++ = *bsp; 406 ofs += 2; 407 } 408} 409 410static __inline void 411bus_space_read_region_4(bus_space_tag_t bst, bus_space_handle_t bsh, 412 bus_size_t ofs, uint32_t *bufp, size_t count) 413{ 414 uint32_t __volatile *bsp; 415 while (count-- > 0) { 416 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 417 __MEMIO_ADDR(bsh + ofs); 418 *bufp++ = *bsp; 419 ofs += 4; 420 } 421} 422 423static __inline void 424bus_space_read_region_8(bus_space_tag_t bst, bus_space_handle_t bsh, 425 bus_size_t ofs, uint64_t *bufp, size_t count) 426{ 427 uint64_t __volatile *bsp; 428 while (count-- > 0) { 429 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 430 __MEMIO_ADDR(bsh + ofs); 431 *bufp++ = *bsp; 432 ofs += 8; 433 } 434} 435 436 437/* 438 * Write count units of data from bus space described by the tag, handle and 439 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 440 * data is read from the buffer passed by reference and written to successive 441 * bus space addresses. Access is unordered. 442 */ 443static __inline void 444bus_space_write_region_1(bus_space_tag_t bst, bus_space_handle_t bsh, 445 bus_size_t ofs, const uint8_t *bufp, size_t count) 446{ 447 uint8_t __volatile *bsp; 448 while (count-- > 0) { 449 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 450 __MEMIO_ADDR(bsh + ofs); 451 *bsp = *bufp++; 452 ofs += 1; 453 } 454} 455 456static __inline void 457bus_space_write_region_2(bus_space_tag_t bst, bus_space_handle_t bsh, 458 bus_size_t ofs, const uint16_t *bufp, size_t count) 459{ 460 uint16_t __volatile *bsp; 461 while (count-- > 0) { 462 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 463 __MEMIO_ADDR(bsh + ofs); 464 *bsp = *bufp++; 465 ofs += 2; 466 } 467} 468 469static __inline void 470bus_space_write_region_4(bus_space_tag_t bst, bus_space_handle_t bsh, 471 bus_size_t ofs, const uint32_t *bufp, size_t count) 472{ 473 uint32_t __volatile *bsp; 474 while (count-- > 0) { 475 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 476 __MEMIO_ADDR(bsh + ofs); 477 *bsp = *bufp++; 478 ofs += 4; 479 } 480} 481 482static __inline void 483bus_space_write_region_8(bus_space_tag_t bst, bus_space_handle_t bsh, 484 bus_size_t ofs, const uint64_t *bufp, size_t count) 485{ 486 uint64_t __volatile *bsp; 487 while (count-- > 0) { 488 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 489 __MEMIO_ADDR(bsh + ofs); 490 *bsp = *bufp++; 491 ofs += 8; 492 } 493} 494 495 496/* 497 * Write count units of data from bus space described by the tag, handle and 498 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 499 * data is passed by value. Writes are unordered. 500 */ 501static __inline void 502bus_space_set_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh, 503 bus_size_t ofs, uint8_t val, size_t count) 504{ 505 uint8_t __volatile *bsp; 506 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 507 __MEMIO_ADDR(bsh + ofs); 508 while (count-- > 0) 509 *bsp = val; 510} 511 512static __inline void 513bus_space_set_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh, 514 bus_size_t ofs, uint16_t val, size_t count) 515{ 516 uint16_t __volatile *bsp; 517 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 518 __MEMIO_ADDR(bsh + ofs); 519 while (count-- > 0) 520 *bsp = val; 521} 522 523static __inline void 524bus_space_set_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh, 525 bus_size_t ofs, uint32_t val, size_t count) 526{ 527 uint32_t __volatile *bsp; 528 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 529 __MEMIO_ADDR(bsh + ofs); 530 while (count-- > 0) 531 *bsp = val; 532} 533 534static __inline void 535bus_space_set_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh, 536 bus_size_t ofs, uint64_t val, size_t count) 537{ 538 uint64_t __volatile *bsp; 539 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 540 __MEMIO_ADDR(bsh + ofs); 541 while (count-- > 0) 542 *bsp = val; 543} 544 545 546/* 547 * Write count units of data from bus space described by the tag, handle and 548 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The 549 * data is passed by value and written to successive bus space addresses. 550 * Writes are unordered. 551 */ 552static __inline void 553bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t bsh, 554 bus_size_t ofs, uint8_t val, size_t count) 555{ 556 uint8_t __volatile *bsp; 557 while (count-- > 0) { 558 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 559 __MEMIO_ADDR(bsh + ofs); 560 *bsp = val; 561 ofs += 1; 562 } 563} 564 565static __inline void 566bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t bsh, 567 bus_size_t ofs, uint16_t val, size_t count) 568{ 569 uint16_t __volatile *bsp; 570 while (count-- > 0) { 571 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 572 __MEMIO_ADDR(bsh + ofs); 573 *bsp = val; 574 ofs += 2; 575 } 576} 577 578static __inline void 579bus_space_set_region_4(bus_space_tag_t bst, bus_space_handle_t bsh, 580 bus_size_t ofs, uint32_t val, size_t count) 581{ 582 uint32_t __volatile *bsp; 583 while (count-- > 0) { 584 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 585 __MEMIO_ADDR(bsh + ofs); 586 *bsp = val; 587 ofs += 4; 588 } 589} 590 591static __inline void 592bus_space_set_region_8(bus_space_tag_t bst, bus_space_handle_t bsh, 593 bus_size_t ofs, uint64_t val, size_t count) 594{ 595 uint64_t __volatile *bsp; 596 while (count-- > 0) { 597 bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) : 598 __MEMIO_ADDR(bsh + ofs); 599 *bsp = val; 600 ofs += 8; 601 } 602} 603 604 605/* 606 * Copy count units of data from bus space described by the tag and the first 607 * handle and ofs pair to bus space described by the tag and the second handle 608 * and ofs pair. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. 609 * The data is read from successive bus space addresses and also written to 610 * successive bus space addresses. Both reads and writes are unordered. 611 */ 612static __inline void 613bus_space_copy_region_1(bus_space_tag_t bst, bus_space_handle_t bsh1, 614 bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count) 615{ 616 bus_addr_t dst, src; 617 uint8_t __volatile *dstp, *srcp; 618 src = bsh1 + ofs1; 619 dst = bsh2 + ofs2; 620 if (dst > src) { 621 src += count - 1; 622 dst += count - 1; 623 while (count-- > 0) { 624 if (bst == IA64_BUS_SPACE_IO) { 625 srcp = __PIO_ADDR(src); 626 dstp = __PIO_ADDR(dst); 627 } else { 628 srcp = __MEMIO_ADDR(src); 629 dstp = __MEMIO_ADDR(dst); 630 } 631 *dstp = *srcp; 632 src -= 1; 633 dst -= 1; 634 } 635 } else { 636 while (count-- > 0) { 637 if (bst == IA64_BUS_SPACE_IO) { 638 srcp = __PIO_ADDR(src); 639 dstp = __PIO_ADDR(dst); 640 } else { 641 srcp = __MEMIO_ADDR(src); 642 dstp = __MEMIO_ADDR(dst); 643 } 644 *dstp = *srcp; 645 src += 1; 646 dst += 1; 647 } 648 } 649} 650 651static __inline void 652bus_space_copy_region_2(bus_space_tag_t bst, bus_space_handle_t bsh1, 653 bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count) 654{ 655 bus_addr_t dst, src; 656 uint16_t __volatile *dstp, *srcp; 657 src = bsh1 + ofs1; 658 dst = bsh2 + ofs2; 659 if (dst > src) { 660 src += (count - 1) << 1; 661 dst += (count - 1) << 1; 662 while (count-- > 0) { 663 if (bst == IA64_BUS_SPACE_IO) { 664 srcp = __PIO_ADDR(src); 665 dstp = __PIO_ADDR(dst); 666 } else { 667 srcp = __MEMIO_ADDR(src); 668 dstp = __MEMIO_ADDR(dst); 669 } 670 *dstp = *srcp; 671 src -= 2; 672 dst -= 2; 673 } 674 } else { 675 while (count-- > 0) { 676 if (bst == IA64_BUS_SPACE_IO) { 677 srcp = __PIO_ADDR(src); 678 dstp = __PIO_ADDR(dst); 679 } else { 680 srcp = __MEMIO_ADDR(src); 681 dstp = __MEMIO_ADDR(dst); 682 } 683 *dstp = *srcp; 684 src += 2; 685 dst += 2; 686 } 687 } 688} 689 690static __inline void 691bus_space_copy_region_4(bus_space_tag_t bst, bus_space_handle_t bsh1, 692 bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count) 693{ 694 bus_addr_t dst, src; 695 uint32_t __volatile *dstp, *srcp; 696 src = bsh1 + ofs1; 697 dst = bsh2 + ofs2; 698 if (dst > src) { 699 src += (count - 1) << 2; 700 dst += (count - 1) << 2; 701 while (count-- > 0) { 702 if (bst == IA64_BUS_SPACE_IO) { 703 srcp = __PIO_ADDR(src); 704 dstp = __PIO_ADDR(dst); 705 } else { 706 srcp = __MEMIO_ADDR(src); 707 dstp = __MEMIO_ADDR(dst); 708 } 709 *dstp = *srcp; 710 src -= 4; 711 dst -= 4; 712 } 713 } else { 714 while (count-- > 0) { 715 if (bst == IA64_BUS_SPACE_IO) { 716 srcp = __PIO_ADDR(src); 717 dstp = __PIO_ADDR(dst); 718 } else { 719 srcp = __MEMIO_ADDR(src); 720 dstp = __MEMIO_ADDR(dst); 721 } 722 *dstp = *srcp; 723 src += 4; 724 dst += 4; 725 } 726 } 727} 728 729static __inline void 730bus_space_copy_region_8(bus_space_tag_t bst, bus_space_handle_t bsh1, 731 bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count) 732{ 733 bus_addr_t dst, src; 734 uint64_t __volatile *dstp, *srcp; 735 src = bsh1 + ofs1; 736 dst = bsh2 + ofs2; 737 if (dst > src) { 738 src += (count - 1) << 3; 739 dst += (count - 1) << 3; 740 while (count-- > 0) { 741 if (bst == IA64_BUS_SPACE_IO) { 742 srcp = __PIO_ADDR(src); 743 dstp = __PIO_ADDR(dst); 744 } else { 745 srcp = __MEMIO_ADDR(src); 746 dstp = __MEMIO_ADDR(dst); 747 } 748 *dstp = *srcp; 749 src -= 8; 750 dst -= 8; 751 } 752 } else { 753 while (count-- > 0) { 754 if (bst == IA64_BUS_SPACE_IO) { 755 srcp = __PIO_ADDR(src); 756 dstp = __PIO_ADDR(dst); 757 } else { 758 srcp = __MEMIO_ADDR(src); 759 dstp = __MEMIO_ADDR(dst); 760 } 761 *dstp = *srcp; 762 src += 8; 763 dst += 8; 764 } 765 } 766} 767 768 769/* 770 * Stream accesses are the same as normal accesses on ia64; there are no 771 * supported bus systems with an endianess different from the host one. 772 */ 773#define bus_space_read_stream_1(t, h, o) \ 774 bus_space_read_1(t, h, o) 775#define bus_space_read_stream_2(t, h, o) \ 776 bus_space_read_2(t, h, o) 777#define bus_space_read_stream_4(t, h, o) \ 778 bus_space_read_4(t, h, o) 779#define bus_space_read_stream_8(t, h, o) \ 780 bus_space_read_8(t, h, o) 781 782#define bus_space_read_multi_stream_1(t, h, o, a, c) \ 783 bus_space_read_multi_1(t, h, o, a, c) 784#define bus_space_read_multi_stream_2(t, h, o, a, c) \ 785 bus_space_read_multi_2(t, h, o, a, c) 786#define bus_space_read_multi_stream_4(t, h, o, a, c) \ 787 bus_space_read_multi_4(t, h, o, a, c) 788#define bus_space_read_multi_stream_8(t, h, o, a, c) \ 789 bus_space_read_multi_8(t, h, o, a, c) 790 791#define bus_space_write_stream_1(t, h, o, v) \ 792 bus_space_write_1(t, h, o, v) 793#define bus_space_write_stream_2(t, h, o, v) \ 794 bus_space_write_2(t, h, o, v) 795#define bus_space_write_stream_4(t, h, o, v) \ 796 bus_space_write_4(t, h, o, v) 797#define bus_space_write_stream_8(t, h, o, v) \ 798 bus_space_write_8(t, h, o, v) 799 800#define bus_space_write_multi_stream_1(t, h, o, a, c) \ 801 bus_space_write_multi_1(t, h, o, a, c) 802#define bus_space_write_multi_stream_2(t, h, o, a, c) \ 803 bus_space_write_multi_2(t, h, o, a, c) 804#define bus_space_write_multi_stream_4(t, h, o, a, c) \ 805 bus_space_write_multi_4(t, h, o, a, c) 806#define bus_space_write_multi_stream_8(t, h, o, a, c) \ 807 bus_space_write_multi_8(t, h, o, a, c) 808 809#define bus_space_set_multi_stream_1(t, h, o, v, c) \ 810 bus_space_set_multi_1(t, h, o, v, c) 811#define bus_space_set_multi_stream_2(t, h, o, v, c) \ 812 bus_space_set_multi_2(t, h, o, v, c) 813#define bus_space_set_multi_stream_4(t, h, o, v, c) \ 814 bus_space_set_multi_4(t, h, o, v, c) 815#define bus_space_set_multi_stream_8(t, h, o, v, c) \ 816 bus_space_set_multi_8(t, h, o, v, c) 817 818#define bus_space_read_region_stream_1(t, h, o, a, c) \ 819 bus_space_read_region_1(t, h, o, a, c) 820#define bus_space_read_region_stream_2(t, h, o, a, c) \ 821 bus_space_read_region_2(t, h, o, a, c) 822#define bus_space_read_region_stream_4(t, h, o, a, c) \ 823 bus_space_read_region_4(t, h, o, a, c) 824#define bus_space_read_region_stream_8(t, h, o, a, c) \ 825 bus_space_read_region_8(t, h, o, a, c) 826 827#define bus_space_write_region_stream_1(t, h, o, a, c) \ 828 bus_space_write_region_1(t, h, o, a, c) 829#define bus_space_write_region_stream_2(t, h, o, a, c) \ 830 bus_space_write_region_2(t, h, o, a, c) 831#define bus_space_write_region_stream_4(t, h, o, a, c) \ 832 bus_space_write_region_4(t, h, o, a, c) 833#define bus_space_write_region_stream_8(t, h, o, a, c) \ 834 bus_space_write_region_8(t, h, o, a, c) 835 836#define bus_space_set_region_stream_1(t, h, o, v, c) \ 837 bus_space_set_region_1(t, h, o, v, c) 838#define bus_space_set_region_stream_2(t, h, o, v, c) \ 839 bus_space_set_region_2(t, h, o, v, c) 840#define bus_space_set_region_stream_4(t, h, o, v, c) \ 841 bus_space_set_region_4(t, h, o, v, c) 842#define bus_space_set_region_stream_8(t, h, o, v, c) \ 843 bus_space_set_region_8(t, h, o, v, c) 844 845#define bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) \ 846 bus_space_copy_region_1(t, h1, o1, h2, o2, c) 847#define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \ 848 bus_space_copy_region_2(t, h1, o1, h2, o2, c) 849#define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \ 850 bus_space_copy_region_4(t, h1, o1, h2, o2, c) 851#define bus_space_copy_region_stream_8(t, h1, o1, h2, o2, c) \ 852 bus_space_copy_region_8(t, h1, o1, h2, o2, c) 853 854 855/* 856 * Flags used in various bus DMA methods. 857 */ 858#define BUS_DMA_WAITOK 0x00 /* safe to sleep (pseudo-flag) */ 859#define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */ 860#define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */ 861#define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 862#define BUS_DMA_ZERO 0x08 /* allocate zero'ed memory */ 863#define BUS_DMA_ISA 0x10 /* map memory for ISA dma */ 864#define BUS_DMA_BUS2 0x20 /* placeholders for bus functions... */ 865#define BUS_DMA_BUS3 0x40 866#define BUS_DMA_BUS4 0x80 867 868/* Forwards needed by prototypes below. */ 869struct mbuf; 870struct uio; 871 872/* 873 * Operations performed by bus_dmamap_sync(). 874 */ 875typedef int bus_dmasync_op_t; 876#define BUS_DMASYNC_PREREAD 1 877#define BUS_DMASYNC_POSTREAD 2 878#define BUS_DMASYNC_PREWRITE 4 879#define BUS_DMASYNC_POSTWRITE 8 880 881/* 882 * bus_dma_tag_t 883 * 884 * A machine-dependent opaque type describing the characteristics 885 * of how to perform DMA mappings. This structure encapsultes 886 * information concerning address and alignment restrictions, number 887 * of S/G segments, amount of data per S/G segment, etc. 888 */ 889typedef struct bus_dma_tag *bus_dma_tag_t; 890 891/* 892 * bus_dmamap_t 893 * 894 * DMA mapping instance information. 895 */ 896typedef struct bus_dmamap *bus_dmamap_t; 897 898/* 899 * bus_dma_segment_t 900 * 901 * Describes a single contiguous DMA transaction. Values 902 * are suitable for programming into DMA registers. 903 */ 904typedef struct bus_dma_segment { 905 bus_addr_t ds_addr; /* DMA address */ 906 bus_size_t ds_len; /* length of transfer */ 907} bus_dma_segment_t; 908 909/* 910 * A function that returns 1 if the address cannot be accessed by 911 * a device and 0 if it can be. 912 */ 913typedef int bus_dma_filter_t(void *, bus_addr_t); 914 915/* 916 * A function that performs driver-specific syncronization on behalf of 917 * busdma. 918 */ 919typedef enum { 920 BUS_DMA_LOCK = 0x01, 921 BUS_DMA_UNLOCK = 0x02, 922} bus_dma_lock_op_t; 923 924typedef void bus_dma_lock_t(void *, bus_dma_lock_op_t); 925 926/* 927 * Allocate a device specific dma_tag encapsulating the constraints of 928 * the parent tag in addition to other restrictions specified: 929 * 930 * alignment: alignment for segments. 931 * boundary: Boundary that segments cannot cross. 932 * lowaddr: Low restricted address that cannot appear in a mapping. 933 * highaddr: High restricted addr. that cannot appear in a mapping. 934 * filtfunc: An optional function to further test if an address 935 * within the range of lowaddr and highaddr cannot appear 936 * in a mapping. 937 * filtfuncarg: An argument that will be passed to filtfunc in addition 938 * to the address to test. 939 * maxsize: Maximum mapping size supported by this tag. 940 * nsegments: Number of discontinuities allowed in maps. 941 * maxsegsz: Maximum size of a segment in the map. 942 * flags: Bus DMA flags. 943 * lockfunc: An optional function to handle driver-defined lock 944 * operations. 945 * lockfuncarg: An argument that will be passed to lockfunc in addition 946 * to the lock operation. 947 * dmat: A pointer to set to a valid dma tag should the return 948 * value of this function indicate success. 949 */ 950/* XXX Should probably allow specification of alignment */ 951int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignemnt, 952 bus_size_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, 953 bus_dma_filter_t *filtfunc, void *filtfuncarg, bus_size_t maxsize, 954 int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc, 955 void *lockfuncarg, bus_dma_tag_t *dmat); 956 957int bus_dma_tag_destroy(bus_dma_tag_t dmat); 958 959/* 960 * Allocate a handle for mapping from kva/uva/physical 961 * address space into bus device space. 962 */ 963int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp); 964 965/* 966 * Destroy a handle for mapping from kva/uva/physical 967 * address space into bus device space. 968 */ 969int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map); 970 971/* 972 * Allocate a piece of memory that can be efficiently mapped into 973 * bus device space based on the constraints lited in the dma tag. 974 * A dmamap to for use with dmamap_load is also allocated. 975 */ 976int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, 977 bus_dmamap_t *mapp); 978 979/* 980 * Free a piece of memory and it's allociated dmamap, that was allocated 981 * via bus_dmamem_alloc. 982 */ 983void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map); 984 985/* 986 * A function that processes a successfully loaded dma map or an error 987 * from a delayed load map. 988 */ 989typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int); 990 991/* 992 * Map the buffer buf into bus space using the dmamap map. 993 */ 994int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, 995 bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, 996 int flags); 997 998/* 999 * Like bus_dmamap_callback but includes map size in bytes. This is 1000 * defined as a separate interface to maintain compatiiblity for users 1001 * of bus_dmamap_callback_t--at some point these interfaces should be merged. 1002 */ 1003typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, 1004 bus_size_t, int); 1005 1006/* 1007 * Like bus_dmamap_load but for mbufs. Note the use of the 1008 * bus_dmamap_callback2_t interface. 1009 */ 1010int bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, 1011 struct mbuf *mbuf, bus_dmamap_callback2_t *callback, void *callback_arg, 1012 int flags); 1013 1014/* 1015 * Like bus_dmamap_load but for uios. Note the use of the 1016 * bus_dmamap_callback2_t interface. 1017 */ 1018int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *ui, 1019 bus_dmamap_callback2_t *callback, void *callback_arg, int flags); 1020 1021/* 1022 * Perform a syncronization operation on the given map. 1023 */ 1024void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, int); 1025static __inline void 1026bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t dmamap, bus_dmasync_op_t op) 1027{ 1028 if ((dmamap) != NULL) 1029 _bus_dmamap_sync(dmat, dmamap, op); 1030} 1031 1032/* 1033 * Release the mapping held by map. 1034 */ 1035void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map); 1036static __inline void 1037bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t dmamap) 1038{ 1039 if ((dmamap) != NULL) 1040 _bus_dmamap_unload(dmat, dmamap); 1041} 1042 1043/* 1044 * Generic helper function for manipulating mutexes. 1045 */ 1046void busdma_lock_mutex(void *arg, bus_dma_lock_op_t op); 1047#endif /* _MACHINE_BUS_H_ */ 1048