1 /* $NetBSD: bus.h,v 1.31 2008/04/28 20:23:39 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997, 1998, 2001 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 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1996 Charles M. Hannum. All rights reserved. 35 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by Christopher G. Demetriou 48 * for the NetBSD Project. 49 * 4. The name of the author may not be used to endorse or promote products 50 * derived from this software without specific prior written permission 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 54 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 55 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 56 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 57 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 61 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64 #ifndef _VAX_BUS_H_ 65 #define _VAX_BUS_H_ 66 67 #ifdef BUS_SPACE_DEBUG 68 #include <sys/systm.h> /* for printf() prototype */ 69 /* 70 * Macros for sanity-checking the aligned-ness of pointers passed to 71 * bus space ops. These are not strictly necessary on the VAX, but 72 * could lead to performance improvements, and help catch problems 73 * with drivers that would creep up on other architectures. 74 */ 75 #define __BUS_SPACE_ALIGNED_ADDRESS(p, t) \ 76 ((((u_long)(p)) & (sizeof(t)-1)) == 0) 77 78 #define __BUS_SPACE_ADDRESS_SANITY(p, t, d) \ 79 ({ \ 80 if (__BUS_SPACE_ALIGNED_ADDRESS((p), t) == 0) { \ 81 printf("%s 0x%lx not aligned to %d bytes %s:%d\n", \ 82 d, (u_long)(p), sizeof(t), __FILE__, __LINE__); \ 83 } \ 84 (void) 0; \ 85 }) 86 87 #define BUS_SPACE_ALIGNED_POINTER(p, t) __BUS_SPACE_ALIGNED_ADDRESS(p, t) 88 #else 89 #define __BUS_SPACE_ADDRESS_SANITY(p,t,d) (void) 0 90 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) 91 #endif /* BUS_SPACE_DEBUG */ 92 93 /* 94 * Bus address and size types 95 */ 96 typedef paddr_t bus_addr_t; 97 typedef psize_t bus_size_t; 98 99 /* 100 * Access methods for bus resources and address space. 101 */ 102 typedef struct vax_bus_space *bus_space_tag_t; 103 typedef vaddr_t bus_space_handle_t; 104 105 struct vax_bus_space { 106 /* cookie */ 107 void *vbs_cookie; 108 109 /* mapping/unmapping */ 110 int (*vbs_map)(void *, bus_addr_t, bus_size_t, int, 111 bus_space_handle_t *, int); 112 void (*vbs_unmap)(void *, bus_space_handle_t, bus_size_t, 113 int); 114 int (*vbs_subregion)(void *, bus_space_handle_t, bus_size_t, 115 bus_size_t, bus_space_handle_t *); 116 117 /* allocation/deallocation */ 118 int (*vbs_alloc)(void *, bus_addr_t, bus_addr_t, bus_size_t, 119 bus_size_t, bus_size_t, int, bus_addr_t *, 120 bus_space_handle_t *); 121 void (*vbs_free)(void *, bus_space_handle_t, bus_size_t); 122 /* mmap bus space for user */ 123 paddr_t (*vbs_mmap)(void *, bus_addr_t, off_t, int, int); 124 }; 125 126 /* 127 * int bus_space_map(bus_space_tag_t t, bus_addr_t addr, 128 * bus_size_t size, int flags, bus_space_handle_t *bshp); 129 * 130 * Map a region of bus space. 131 */ 132 133 #define BUS_SPACE_MAP_CACHEABLE 0x01 134 #define BUS_SPACE_MAP_LINEAR 0x02 135 #define BUS_SPACE_MAP_PREFETCHABLE 0x04 136 137 #define bus_space_map(t, a, s, f, hp) \ 138 (*(t)->vbs_map)((t)->vbs_cookie, (a), (s), (f), (hp), 1) 139 #define vax_bus_space_map_noacct(t, a, s, f, hp) \ 140 (*(t)->vbs_map)((t)->vbs_cookie, (a), (s), (f), (hp), 0) 141 142 /* 143 * int bus_space_unmap(bus_space_tag_t t, 144 * bus_space_handle_t bsh, bus_size_t size); 145 * 146 * Unmap a region of bus space. 147 */ 148 149 #define bus_space_unmap(t, h, s) \ 150 (*(t)->vbs_unmap)((t)->vbs_cookie, (h), (s), 1) 151 #define vax_bus_space_unmap_noacct(t, h, s) \ 152 (*(t)->vbs_unmap)((t)->vbs_cookie, (h), (s), 0) 153 154 /* 155 * int bus_space_subregion(bus_space_tag_t t, 156 * bus_space_handle_t bsh, bus_size_t offset, bus_size_t size, 157 * bus_space_handle_t *nbshp); 158 * 159 * Get a new handle for a subregion of an already-mapped area of bus space. 160 */ 161 162 #define bus_space_subregion(t, h, o, s, nhp) \ 163 (*(t)->vbs_subregion)((t)->vbs_cookie, (h), (o), (s), (nhp)) 164 165 /* 166 * int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, 167 * bus_addr_t rend, bus_size_t size, bus_size_t align, 168 * bus_size_t boundary, int flags, bus_addr_t *addrp, 169 * bus_space_handle_t *bshp); 170 * 171 * Allocate a region of bus space. 172 */ 173 174 #define bus_space_alloc(t, rs, re, s, a, b, f, ap, hp) \ 175 (*(t)->vbs_alloc)((t)->vbs_cookie, (rs), (re), (s), (a), (b), \ 176 (f), (ap), (hp)) 177 178 /* 179 * int bus_space_free(bus_space_tag_t t, 180 * bus_space_handle_t bsh, bus_size_t size); 181 * 182 * Free a region of bus space. 183 */ 184 185 #define bus_space_free(t, h, s) \ 186 (*(t)->vbs_free)((t)->vbs_cookie, (h), (s)) 187 188 /* 189 * Mmap bus space for a user application. 190 */ 191 #define bus_space_mmap(t, a, o, p, f) \ 192 (*(t)->vbs_mmap)((t)->vbs_cookie, (a), (o), (p), (f)) 193 194 195 /* 196 * u_intN_t bus_space_read_N(bus_space_tag_t tag, 197 * bus_space_handle_t bsh, bus_size_t offset); 198 * 199 * Read a 1, 2, 4, or 8 byte quantity from bus space 200 * described by tag/handle/offset. 201 */ 202 203 #define bus_space_read_1(t, h, o) \ 204 (*(volatile uint8_t *)((h) + (o))) 205 206 #define bus_space_read_2(t, h, o) \ 207 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"), \ 208 (*(volatile uint16_t *)((h) + (o)))) 209 210 #define bus_space_read_4(t, h, o) \ 211 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"), \ 212 (*(volatile uint32_t *)((h) + (o)))) 213 214 #if 0 /* Cause a link error for bus_space_read_8 */ 215 #define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!! 216 #endif 217 218 /* 219 * void bus_space_read_multi_N(bus_space_tag_t tag, 220 * bus_space_handle_t bsh, bus_size_t offset, 221 * u_intN_t *addr, size_t count); 222 * 223 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 224 * described by tag/handle/offset and copy into buffer provided. 225 */ 226 static __inline void 227 vax_mem_read_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 228 uint8_t *, size_t), 229 vax_mem_read_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 230 uint16_t *, size_t), 231 vax_mem_read_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 232 uint32_t *, size_t); 233 234 #define bus_space_read_multi_1(t, h, o, a, c) \ 235 vax_mem_read_multi_1((t), (h), (o), (a), (c)) 236 237 #define bus_space_read_multi_2(t, h, o, a, c) \ 238 do { \ 239 __BUS_SPACE_ADDRESS_SANITY((a), uint16_t, "buffer"); \ 240 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 241 vax_mem_read_multi_2((t), (h), (o), (a), (c)); \ 242 } while (0) 243 244 #define bus_space_read_multi_4(t, h, o, a, c) \ 245 do { \ 246 __BUS_SPACE_ADDRESS_SANITY((a), uint32_t, "buffer"); \ 247 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 248 vax_mem_read_multi_4((t), (h), (o), (a), (c)); \ 249 } while (0) 250 251 #if 0 /* Cause a link error for bus_space_read_multi_8 */ 252 #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!! 253 #endif 254 255 static __inline void 256 vax_mem_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 257 uint8_t *a, size_t c) 258 { 259 const bus_addr_t addr = h + o; 260 261 for (; c != 0; c--, a++) 262 *a = *(volatile uint8_t *)(addr); 263 } 264 265 static __inline void 266 vax_mem_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 267 uint16_t *a, size_t c) 268 { 269 const bus_addr_t addr = h + o; 270 271 for (; c != 0; c--, a++) 272 *a = *(volatile uint16_t *)(addr); 273 } 274 275 static __inline void 276 vax_mem_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 277 uint32_t *a, size_t c) 278 { 279 const bus_addr_t addr = h + o; 280 281 for (; c != 0; c--, a++) 282 *a = *(volatile uint32_t *)(addr); 283 } 284 285 /* 286 * void bus_space_read_region_N(bus_space_tag_t tag, 287 * bus_space_handle_t bsh, bus_size_t offset, 288 * u_intN_t *addr, size_t count); 289 * 290 * Read `count' 1, 2, 4, or 8 byte quantities from bus space 291 * described by tag/handle and starting at `offset' and copy into 292 * buffer provided. 293 */ 294 295 static __inline void vax_mem_read_region_1(bus_space_tag_t, 296 bus_space_handle_t, bus_size_t, uint8_t *, size_t); 297 static __inline void vax_mem_read_region_2(bus_space_tag_t, 298 bus_space_handle_t, bus_size_t, uint16_t *, size_t); 299 static __inline void vax_mem_read_region_4(bus_space_tag_t, 300 bus_space_handle_t, bus_size_t, uint32_t *, size_t); 301 302 #define bus_space_read_region_1(t, h, o, a, c) \ 303 do { \ 304 vax_mem_read_region_1((t), (h), (o), (a), (c)); \ 305 } while (0) 306 307 #define bus_space_read_region_2(t, h, o, a, c) \ 308 do { \ 309 __BUS_SPACE_ADDRESS_SANITY((a), uint16_t, "buffer"); \ 310 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 311 vax_mem_read_region_2((t), (h), (o), (a), (c)); \ 312 } while (0) 313 314 #define bus_space_read_region_4(t, h, o, a, c) \ 315 do { \ 316 __BUS_SPACE_ADDRESS_SANITY((a), uint32_t, "buffer"); \ 317 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 318 vax_mem_read_region_4((t), (h), (o), (a), (c)); \ 319 } while (0) 320 321 #if 0 /* Cause a link error for bus_space_read_region_8 */ 322 #define bus_space_read_region_8 \ 323 !!! bus_space_read_region_8 unimplemented !!! 324 #endif 325 326 static __inline void 327 vax_mem_read_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 328 uint8_t *a, size_t c) 329 { 330 bus_addr_t addr = h + o; 331 332 for (; c != 0; c--, addr++, a++) 333 *a = *(volatile uint8_t *)(addr); 334 } 335 336 static __inline void 337 vax_mem_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 338 uint16_t *a, size_t c) 339 { 340 bus_addr_t addr = h + o; 341 342 for (; c != 0; c--, addr += 2, a++) 343 *a = *(volatile uint16_t *)(addr); 344 } 345 346 static __inline void 347 vax_mem_read_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 348 uint32_t *a, size_t c) 349 { 350 bus_addr_t addr = h + o; 351 352 for (; c != 0; c--, addr += 4, a++) 353 *a = *(volatile uint32_t *)(addr); 354 } 355 356 /* 357 * void bus_space_write_N(bus_space_tag_t tag, 358 * bus_space_handle_t bsh, bus_size_t offset, 359 * u_intN_t value); 360 * 361 * Write the 1, 2, 4, or 8 byte value `value' to bus space 362 * described by tag/handle/offset. 363 */ 364 365 #define bus_space_write_1(t, h, o, v) \ 366 do { \ 367 ((void)(*(volatile uint8_t *)((h) + (o)) = (v))); \ 368 } while (0) 369 370 #define bus_space_write_2(t, h, o, v) \ 371 do { \ 372 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 373 ((void)(*(volatile uint16_t *)((h) + (o)) = (v))); \ 374 } while (0) 375 376 #define bus_space_write_4(t, h, o, v) \ 377 do { \ 378 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 379 ((void)(*(volatile uint32_t *)((h) + (o)) = (v))); \ 380 } while (0) 381 382 #if 0 /* Cause a link error for bus_space_write_8 */ 383 #define bus_space_write_8 !!! bus_space_write_8 not implemented !!! 384 #endif 385 386 /* 387 * void bus_space_write_multi_N(bus_space_tag_t tag, 388 * bus_space_handle_t bsh, bus_size_t offset, 389 * const u_intN_t *addr, size_t count); 390 * 391 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer 392 * provided to bus space described by tag/handle/offset. 393 */ 394 static __inline void 395 vax_mem_write_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 396 const uint8_t *, size_t), 397 vax_mem_write_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 398 const uint16_t *, size_t), 399 vax_mem_write_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 400 const uint32_t *, size_t); 401 402 #define bus_space_write_multi_1(t, h, o, a, c) \ 403 do { \ 404 vax_mem_write_multi_1((t), (h), (o), (a), (c)); \ 405 } while (0) 406 407 #define bus_space_write_multi_2(t, h, o, a, c) \ 408 do { \ 409 __BUS_SPACE_ADDRESS_SANITY((a), uint16_t, "buffer"); \ 410 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 411 vax_mem_write_multi_2((t), (h), (o), (a), (c)); \ 412 } while (0) 413 414 #define bus_space_write_multi_4(t, h, o, a, c) \ 415 do { \ 416 __BUS_SPACE_ADDRESS_SANITY((a), uint32_t, "buffer"); \ 417 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 418 vax_mem_write_multi_4((t), (h), (o), (a), (c)); \ 419 } while (0) 420 421 #if 0 /* Cause a link error for bus_space_write_multi_8 */ 422 #define bus_space_write_multi_8(t, h, o, a, c) \ 423 !!! bus_space_write_multi_8 unimplemented !!! 424 #endif 425 426 static __inline void 427 vax_mem_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 428 const uint8_t *a, size_t c) 429 { 430 const bus_addr_t addr = h + o; 431 432 for (; c != 0; c--, a++) 433 *(volatile uint8_t *)(addr) = *a; 434 } 435 436 static __inline void 437 vax_mem_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 438 const uint16_t *a, size_t c) 439 { 440 const bus_addr_t addr = h + o; 441 442 for (; c != 0; c--, a++) 443 *(volatile uint16_t *)(addr) = *a; 444 } 445 446 static __inline void 447 vax_mem_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 448 const uint32_t *a, size_t c) 449 { 450 const bus_addr_t addr = h + o; 451 452 for (; c != 0; c--, a++) 453 *(volatile uint32_t *)(addr) = *a; 454 } 455 456 /* 457 * void bus_space_write_region_N(bus_space_tag_t tag, 458 * bus_space_handle_t bsh, bus_size_t offset, 459 * const u_intN_t *addr, size_t count); 460 * 461 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided 462 * to bus space described by tag/handle starting at `offset'. 463 */ 464 static __inline void 465 vax_mem_write_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 466 const uint8_t *, size_t), 467 vax_mem_write_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 468 const uint16_t *, size_t), 469 vax_mem_write_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 470 const uint32_t *, size_t); 471 472 #define bus_space_write_region_1(t, h, o, a, c) \ 473 vax_mem_write_region_1((t), (h), (o), (a), (c)) 474 475 #define bus_space_write_region_2(t, h, o, a, c) \ 476 do { \ 477 __BUS_SPACE_ADDRESS_SANITY((a), uint16_t, "buffer"); \ 478 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 479 vax_mem_write_region_2((t), (h), (o), (a), (c)); \ 480 } while (0) 481 482 #define bus_space_write_region_4(t, h, o, a, c) \ 483 do { \ 484 __BUS_SPACE_ADDRESS_SANITY((a), uint32_t, "buffer"); \ 485 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 486 vax_mem_write_region_4((t), (h), (o), (a), (c)); \ 487 } while (0) 488 489 #if 0 /* Cause a link error for bus_space_write_region_8 */ 490 #define bus_space_write_region_8 \ 491 !!! bus_space_write_region_8 unimplemented !!! 492 #endif 493 494 static __inline void 495 vax_mem_write_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 496 const uint8_t *a, size_t c) 497 { 498 bus_addr_t addr = h + o; 499 500 for (; c != 0; c--, addr++, a++) 501 *(volatile uint8_t *)(addr) = *a; 502 } 503 504 static __inline void 505 vax_mem_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 506 const uint16_t *a, size_t c) 507 { 508 bus_addr_t addr = h + o; 509 510 for (; c != 0; c--, addr++, a++) 511 *(volatile uint16_t *)(addr) = *a; 512 } 513 514 static __inline void 515 vax_mem_write_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 516 const uint32_t *a, size_t c) 517 { 518 bus_addr_t addr = h + o; 519 520 for (; c != 0; c--, addr++, a++) 521 *(volatile uint32_t *)(addr) = *a; 522 } 523 524 /* 525 * void bus_space_set_multi_N(bus_space_tag_t tag, 526 * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, 527 * size_t count); 528 * 529 * Write the 1, 2, 4, or 8 byte value `val' to bus space described 530 * by tag/handle/offset `count' times. 531 */ 532 533 static __inline void 534 vax_mem_set_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 535 uint8_t, size_t), 536 vax_mem_set_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 537 uint16_t, size_t), 538 vax_mem_set_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 539 uint32_t, size_t); 540 541 #define bus_space_set_multi_1(t, h, o, v, c) \ 542 vax_mem_set_multi_1((t), (h), (o), (v), (c)) 543 544 #define bus_space_set_multi_2(t, h, o, v, c) \ 545 do { \ 546 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 547 vax_mem_set_multi_2((t), (h), (o), (v), (c)); \ 548 } while (0) 549 550 #define bus_space_set_multi_4(t, h, o, v, c) \ 551 do { \ 552 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 553 vax_mem_set_multi_4((t), (h), (o), (v), (c)); \ 554 } while (0) 555 556 static __inline void 557 vax_mem_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 558 uint8_t v, size_t c) 559 { 560 bus_addr_t addr = h + o; 561 562 while (c--) 563 *(volatile uint8_t *)(addr) = v; 564 } 565 566 static __inline void 567 vax_mem_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 568 uint16_t v, size_t c) 569 { 570 bus_addr_t addr = h + o; 571 572 while (c--) 573 *(volatile uint16_t *)(addr) = v; 574 } 575 576 static __inline void 577 vax_mem_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 578 uint32_t v, size_t c) 579 { 580 bus_addr_t addr = h + o; 581 582 while (c--) 583 *(volatile uint32_t *)(addr) = v; 584 } 585 586 #if 0 /* Cause a link error for bus_space_set_multi_8 */ 587 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!! 588 #endif 589 590 /* 591 * void bus_space_set_region_N(bus_space_tag_t tag, 592 * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val, 593 * size_t count); 594 * 595 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described 596 * by tag/handle starting at `offset'. 597 */ 598 599 static __inline void 600 vax_mem_set_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 601 uint8_t, size_t), 602 vax_mem_set_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 603 uint16_t, size_t), 604 vax_mem_set_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 605 uint32_t, size_t); 606 607 #define bus_space_set_region_1(t, h, o, v, c) \ 608 vax_mem_set_region_1((t), (h), (o), (v), (c)) 609 610 #define bus_space_set_region_2(t, h, o, v, c) \ 611 do { \ 612 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \ 613 vax_mem_set_region_2((t), (h), (o), (v), (c)); \ 614 } while (0) 615 616 #define bus_space_set_region_4(t, h, o, v, c) \ 617 do { \ 618 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \ 619 vax_mem_set_region_4((t), (h), (o), (v), (c)); \ 620 } while (0) 621 622 static __inline void 623 vax_mem_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 624 uint8_t v, size_t c) 625 { 626 bus_addr_t addr = h + o; 627 628 for (; c != 0; c--, addr++) 629 *(volatile uint8_t *)(addr) = v; 630 } 631 632 static __inline void 633 vax_mem_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 634 uint16_t v, size_t c) 635 { 636 bus_addr_t addr = h + o; 637 638 for (; c != 0; c--, addr += 2) 639 *(volatile uint16_t *)(addr) = v; 640 } 641 642 static __inline void 643 vax_mem_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 644 uint32_t v, size_t c) 645 { 646 bus_addr_t addr = h + o; 647 648 for (; c != 0; c--, addr += 4) 649 *(volatile uint32_t *)(addr) = v; 650 } 651 652 #if 0 /* Cause a link error for bus_space_set_region_8 */ 653 #define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!! 654 #endif 655 656 /* 657 * void bus_space_copy_region_N(bus_space_tag_t tag, 658 * bus_space_handle_t bsh1, bus_size_t off1, 659 * bus_space_handle_t bsh2, bus_size_t off2, 660 * size_t count); 661 * 662 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting 663 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. 664 */ 665 666 static __inline void 667 vax_mem_copy_region_1(bus_space_tag_t, bus_space_handle_t, bus_size_t, 668 bus_space_handle_t, bus_size_t, size_t), 669 vax_mem_copy_region_2(bus_space_tag_t, bus_space_handle_t, bus_size_t, 670 bus_space_handle_t, bus_size_t, size_t), 671 vax_mem_copy_region_4(bus_space_tag_t, bus_space_handle_t, bus_size_t, 672 bus_space_handle_t, bus_size_t, size_t); 673 674 #define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \ 675 vax_mem_copy_region_1((t), (h1), (o1), (h2), (o2), (c)) 676 677 #define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \ 678 do { \ 679 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint16_t, "bus addr 1"); \ 680 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint16_t, "bus addr 2"); \ 681 vax_mem_copy_region_2((t), (h1), (o1), (h2), (o2), (c)); \ 682 } while (0) 683 684 #define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \ 685 do { \ 686 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint32_t, "bus addr 1"); \ 687 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint32_t, "bus addr 2"); \ 688 vax_mem_copy_region_4((t), (h1), (o1), (h2), (o2), (c)); \ 689 } while (0) 690 691 static __inline void 692 vax_mem_copy_region_1(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, 693 bus_space_handle_t h2, bus_size_t o2, size_t c) 694 { 695 bus_addr_t addr1 = h1 + o1; 696 bus_addr_t addr2 = h2 + o2; 697 698 if (addr1 >= addr2) { 699 /* src after dest: copy forward */ 700 for (; c != 0; c--, addr1++, addr2++) 701 *(volatile uint8_t *)(addr2) = 702 *(volatile uint8_t *)(addr1); 703 } else { 704 /* dest after src: copy backwards */ 705 for (addr1 += (c - 1), addr2 += (c - 1); 706 c != 0; c--, addr1--, addr2--) 707 *(volatile uint8_t *)(addr2) = 708 *(volatile uint8_t *)(addr1); 709 } 710 } 711 712 static __inline void 713 vax_mem_copy_region_2(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, 714 bus_space_handle_t h2, bus_size_t o2, size_t c) 715 { 716 bus_addr_t addr1 = h1 + o1; 717 bus_addr_t addr2 = h2 + o2; 718 719 if (addr1 >= addr2) { 720 /* src after dest: copy forward */ 721 for (; c != 0; c--, addr1 += 2, addr2 += 2) 722 *(volatile uint16_t *)(addr2) = 723 *(volatile uint16_t *)(addr1); 724 } else { 725 /* dest after src: copy backwards */ 726 for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1); 727 c != 0; c--, addr1 -= 2, addr2 -= 2) 728 *(volatile uint16_t *)(addr2) = 729 *(volatile uint16_t *)(addr1); 730 } 731 } 732 733 static __inline void 734 vax_mem_copy_region_4(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1, 735 bus_space_handle_t h2, bus_size_t o2, size_t c) 736 { 737 bus_addr_t addr1 = h1 + o1; 738 bus_addr_t addr2 = h2 + o2; 739 740 if (addr1 >= addr2) { 741 /* src after dest: copy forward */ 742 for (; c != 0; c--, addr1 += 4, addr2 += 4) 743 *(volatile uint32_t *)(addr2) = 744 *(volatile uint32_t *)(addr1); 745 } else { 746 /* dest after src: copy backwards */ 747 for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1); 748 c != 0; c--, addr1 -= 4, addr2 -= 4) 749 *(volatile uint32_t *)(addr2) = 750 *(volatile uint32_t *)(addr1); 751 } 752 } 753 754 #if 0 /* Cause a link error for bus_space_copy_8 */ 755 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!! 756 #endif 757 758 759 /* 760 * Bus read/write barrier methods. 761 * 762 * void bus_space_barrier(bus_space_tag_t tag, 763 * bus_space_handle_t bsh, bus_size_t offset, 764 * bus_size_t len, int flags); 765 * 766 * Note: the vax does not currently require barriers, but we must 767 * provide the flags to MI code. 768 */ 769 #define bus_space_barrier(t, h, o, l, f) \ 770 ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f))) 771 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 772 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 773 774 775 /* 776 * Flags used in various bus DMA methods. 777 */ 778 #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ 779 #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ 780 #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ 781 #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ 782 #define BUS_DMA_STREAMING 0x008 /* hint: sequential, unidirectional */ 783 #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ 784 #define BUS_DMA_BUS2 0x020 785 #define BUS_DMA_BUS3 0x040 786 #define BUS_DMA_BUS4 0x080 787 #define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ 788 #define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ 789 #define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */ 790 791 #define VAX_BUS_DMA_SPILLPAGE BUS_DMA_BUS1 /* VS4000 kludge */ 792 /* 793 * Private flags stored in the DMA map. 794 */ 795 #define DMAMAP_HAS_SGMAP 0x80000000 /* sgva/len are valid */ 796 797 /* Forwards needed by prototypes below. */ 798 struct mbuf; 799 struct uio; 800 struct vax_sgmap; 801 802 /* 803 * Operations performed by bus_dmamap_sync(). 804 */ 805 #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ 806 #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ 807 #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ 808 #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ 809 810 /* 811 * vax_bus_t 812 * 813 * Busses supported by NetBSD/vax, used by internal 814 * utility functions. NOT TO BE USED BY MACHINE-INDEPENDENT 815 * CODE! 816 */ 817 typedef enum { 818 VAX_BUS_MAINBUS, 819 VAX_BUS_SBI, 820 VAX_BUS_MASSBUS, 821 VAX_BUS_UNIBUS, /* Also handles QBUS */ 822 VAX_BUS_BI, 823 VAX_BUS_XMI, 824 VAX_BUS_TURBOCHANNEL 825 } vax_bus_t; 826 827 typedef struct vax_bus_dma_tag *bus_dma_tag_t; 828 typedef struct vax_bus_dmamap *bus_dmamap_t; 829 830 #define BUS_DMA_TAG_VALID(t) ((t) != (bus_dma_tag_t)0) 831 832 /* 833 * bus_dma_segment_t 834 * 835 * Describes a single contiguous DMA transaction. Values 836 * are suitable for programming into DMA registers. 837 */ 838 struct vax_bus_dma_segment { 839 bus_addr_t ds_addr; /* DMA address */ 840 bus_size_t ds_len; /* length of transfer */ 841 }; 842 typedef struct vax_bus_dma_segment bus_dma_segment_t; 843 844 struct proc; 845 846 /* 847 * bus_dma_tag_t 848 * 849 * A machine-dependent opaque type describing the implementation of 850 * DMA for a given bus. 851 */ 852 struct vax_bus_dma_tag { 853 void *_cookie; /* cookie used in the guts */ 854 bus_addr_t _wbase; /* DMA window base */ 855 bus_size_t _wsize; /* DMA window size */ 856 857 /* 858 * Some chipsets have a built-in boundary constraint, independent 859 * of what the device requests. This allows that boundary to 860 * be specified. If the device has a more restrictive constraint, 861 * the map will use that, otherwise this boundary will be used. 862 * This value is ignored if 0. 863 */ 864 bus_size_t _boundary; 865 866 /* 867 * A bus may have more than one SGMAP window, so SGMAP 868 * windows also get a pointer to their SGMAP state. 869 */ 870 struct vax_sgmap *_sgmap; 871 872 /* 873 * Internal-use only utility methods. NOT TO BE USED BY 874 * MACHINE-INDEPENDENT CODE! 875 */ 876 bus_dma_tag_t (*_get_tag)(bus_dma_tag_t, vax_bus_t); 877 878 /* 879 * DMA mapping methods. 880 */ 881 int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, 882 bus_size_t, bus_size_t, int, bus_dmamap_t *); 883 void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); 884 int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, 885 bus_size_t, struct proc *, int); 886 int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, 887 struct mbuf *, int); 888 int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, 889 struct uio *, int); 890 int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, 891 bus_dma_segment_t *, int, bus_size_t, int); 892 void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); 893 void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, 894 bus_addr_t, bus_size_t, int); 895 896 /* 897 * DMA memory utility functions. 898 */ 899 int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, 900 bus_size_t, bus_dma_segment_t *, int, int *, int); 901 void (*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int); 902 int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, 903 int, size_t, void **, int); 904 void (*_dmamem_unmap)(bus_dma_tag_t, void *, size_t); 905 paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, 906 int, off_t, int, int); 907 }; 908 909 #define vaxbus_dma_get_tag(t, b) \ 910 (*(t)->_get_tag)(t, b) 911 912 #define bus_dmamap_create(t, s, n, m, b, f, p) \ 913 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) 914 #define bus_dmamap_destroy(t, p) \ 915 (*(t)->_dmamap_destroy)((t), (p)) 916 #define bus_dmamap_load(t, m, b, s, p, f) \ 917 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) 918 #define bus_dmamap_load_mbuf(t, m, b, f) \ 919 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) 920 #define bus_dmamap_load_uio(t, m, u, f) \ 921 (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) 922 #define bus_dmamap_load_raw(t, m, sg, n, s, f) \ 923 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) 924 #define bus_dmamap_unload(t, p) \ 925 (*(t)->_dmamap_unload)((t), (p)) 926 #define bus_dmamap_sync(t, p, o, l, ops) \ 927 (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) 928 #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ 929 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) 930 #define bus_dmamem_free(t, sg, n) \ 931 (*(t)->_dmamem_free)((t), (sg), (n)) 932 #define bus_dmamem_map(t, sg, n, s, k, f) \ 933 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) 934 #define bus_dmamem_unmap(t, k, s) \ 935 (*(t)->_dmamem_unmap)((t), (k), (s)) 936 #define bus_dmamem_mmap(t, sg, n, o, p, f) \ 937 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) 938 939 #define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP 940 #define bus_dmatag_destroy(t) 941 942 /* 943 * bus_dmamap_t 944 * 945 * Describes a DMA mapping. 946 */ 947 struct vax_bus_dmamap { 948 /* 949 * PRIVATE MEMBERS: not for use my machine-independent code. 950 */ 951 bus_size_t _dm_size; /* largest DMA transfer mappable */ 952 int _dm_segcnt; /* number of segs this map can map */ 953 bus_size_t _dm_maxmaxsegsz; /* fixed largest possible segment */ 954 bus_size_t _dm_boundary; /* don't cross this */ 955 int _dm_flags; /* misc. flags */ 956 957 /* 958 * This is used only for SGMAP-mapped DMA, but we keep it 959 * here to avoid pointless indirection. 960 */ 961 int _dm_pteidx; /* PTE index */ 962 int _dm_ptecnt; /* PTE count */ 963 u_long _dm_sgva; /* allocated sgva */ 964 bus_size_t _dm_sgvalen; /* svga length */ 965 966 /* 967 * PUBLIC MEMBERS: these are used by machine-independent code. 968 */ 969 bus_size_t dm_maxsegsz; /* largest possible segment */ 970 bus_size_t dm_mapsize; /* size of the mapping */ 971 int dm_nsegs; /* # valid segments in mapping */ 972 bus_dma_segment_t dm_segs[1]; /* segments; variable length */ 973 }; 974 975 /*#ifdef _VAX_BUS_DMA_PRIVATE */ 976 int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, 977 bus_size_t, int, bus_dmamap_t *); 978 void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); 979 980 int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, 981 void *, bus_size_t, struct proc *, int); 982 int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int); 983 int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int); 984 int _bus_dmamap_load_raw(bus_dma_tag_t, 985 bus_dmamap_t, bus_dma_segment_t *, int, bus_size_t, int); 986 987 void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); 988 void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 989 bus_size_t, int); 990 991 int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, 992 bus_size_t alignment, bus_size_t boundary, 993 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags); 994 void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, int nsegs); 995 int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, 996 int nsegs, size_t size, void **kvap, int flags); 997 void _bus_dmamem_unmap(bus_dma_tag_t tag, void *kva, size_t size); 998 paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs, 999 int nsegs, off_t off, int prot, int flags); 1000 /*#endif*/ /* _VAX_BUS_DMA_PRIVATE */ 1001 1002 #endif /* _VAX_BUS_H_ */ 1003