1 /* $NetBSD: bus.h,v 1.22 2010/03/19 14:20:56 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 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 * bus_space(9) and bus_dma(9) interface for NetBSD/x68k. 35 */ 36 37 #ifndef _X68K_BUS_H_ 38 #define _X68K_BUS_H_ 39 40 #ifndef X68K_BUS_PERFORMANCE_HACK 41 #if defined(__GNUC__) && defined(__STDC__) 42 #define X68K_BUS_PERFORMANCE_HACK 1 43 #else 44 #define X68K_BUS_PERFORMANCE_HACK 0 45 #endif 46 #endif 47 48 /* 49 * Bus address and size types 50 */ 51 typedef u_long bus_addr_t; 52 typedef u_long bus_size_t; 53 typedef u_long bus_space_handle_t; 54 55 /* 56 * Bus space descripter 57 */ 58 typedef struct x68k_bus_space *bus_space_tag_t; 59 60 struct x68k_bus_space { 61 #if 0 62 enum { 63 X68K_INTIO_BUS, 64 X68K_PCI_BUS, 65 X68K_NEPTUNE_BUS 66 } x68k_bus_type; 67 #endif 68 69 int (*x68k_bus_space_map)( 70 bus_space_tag_t, 71 bus_addr_t, 72 bus_size_t, 73 int, /* flags */ 74 bus_space_handle_t *); 75 void (*x68k_bus_space_unmap)( 76 bus_space_tag_t, 77 bus_space_handle_t, 78 bus_size_t); 79 int (*x68k_bus_space_subregion)( 80 bus_space_tag_t, 81 bus_space_handle_t, 82 bus_size_t, /* offset */ 83 bus_size_t, /* size */ 84 bus_space_handle_t *); 85 86 int (*x68k_bus_space_alloc)( 87 bus_space_tag_t, 88 bus_addr_t, /* reg_start */ 89 bus_addr_t, /* reg_end */ 90 bus_size_t, 91 bus_size_t, /* alignment */ 92 bus_size_t, /* boundary */ 93 int, /* flags */ 94 bus_addr_t *, 95 bus_space_handle_t *); 96 void (*x68k_bus_space_free)( 97 bus_space_tag_t, 98 bus_space_handle_t, 99 bus_size_t); 100 101 #if 0 102 void (*x68k_bus_space_barrier)( 103 bus_space_tag_t, 104 bus_space_handle_t, 105 bus_size_t, /* offset */ 106 bus_size_t, /* length */ 107 int); /* flags */ 108 #endif 109 110 struct device *x68k_bus_device; 111 }; 112 113 int x68k_bus_space_alloc(bus_space_tag_t, bus_addr_t, bus_addr_t, bus_size_t, 114 bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *); 115 void x68k_bus_space_free(bus_space_tag_t, bus_space_handle_t, bus_size_t); 116 117 /* 118 * bus_space(9) interface 119 */ 120 121 #define bus_space_map(t, a, s, f, h) \ 122 ((*((t)->x68k_bus_space_map)) ((t), (a), (s), (f), (h))) 123 #define bus_space_unmap(t, h, s) \ 124 ((*((t)->x68k_bus_space_unmap)) ((t), (h), (s))) 125 #define bus_space_subregion(t, h, o, s, p) \ 126 ((*((t)->x68k_bus_space_subregion)) ((t), (h), (o), (s), (p))) 127 #define BUS_SPACE_MAP_CACHEABLE 0x0001 128 #define BUS_SPACE_MAP_LINEAR 0x0002 129 #define BUS_SPACE_MAP_PREFETCHABLE 0x0004 130 /* 131 * For simpler hadware, many x68k devices are mapped with shifted address 132 * i.e. only on even or odd addresses. 133 */ 134 #define BUS_SPACE_MAP_SHIFTED_MASK 0x1001 135 #define BUS_SPACE_MAP_SHIFTED_ODD 0x1001 136 #define BUS_SPACE_MAP_SHIFTED_EVEN 0x1000 137 #define BUS_SPACE_MAP_SHIFTED BUS_SPACE_MAP_SHIFTED_ODD 138 139 #define bus_space_alloc(t, rs, re, s, a, b, f, r, h) \ 140 ((*((t)->x68k_bus_space_alloc)) ((t), \ 141 (rs), (re), (s), (a), (b), (f), (r), (h))) 142 #define bus_space_free(t, h, s) \ 143 ((*((t)->x68k_bus_space_free)) ((t), (h), (s))) 144 145 /* 146 * Note: the 680x0 does not currently require barriers, but we must 147 * provide the flags to MI code. 148 */ 149 #define bus_space_barrier(t, h, o, l, f) \ 150 ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f))) 151 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */ 152 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */ 153 154 #define bus_space_read_1(t,h,o) _bus_space_read_1(t,h,o) 155 #define bus_space_read_2(t,h,o) _bus_space_read_2(t,h,o) 156 #define bus_space_read_4(t,h,o) _bus_space_read_4(t,h,o) 157 158 #define bus_space_read_multi_1(t,h,o,p,c) _bus_space_read_multi_1(t,h,o,p,c) 159 #define bus_space_read_multi_2(t,h,o,p,c) _bus_space_read_multi_2(t,h,o,p,c) 160 #define bus_space_read_multi_4(t,h,o,p,c) _bus_space_read_multi_4(t,h,o,p,c) 161 162 #define bus_space_read_region_1(t,h,o,p,c) _bus_space_read_region_1(t,h,o,p,c) 163 #define bus_space_read_region_2(t,h,o,p,c) _bus_space_read_region_2(t,h,o,p,c) 164 #define bus_space_read_region_4(t,h,o,p,c) _bus_space_read_region_4(t,h,o,p,c) 165 166 #define bus_space_write_1(t,h,o,v) _bus_space_write_1(t,h,o,v) 167 #define bus_space_write_2(t,h,o,v) _bus_space_write_2(t,h,o,v) 168 #define bus_space_write_4(t,h,o,v) _bus_space_write_4(t,h,o,v) 169 170 #define bus_space_write_multi_1(t,h,o,p,c) _bus_space_write_multi_1(t,h,o,p,c) 171 #define bus_space_write_multi_2(t,h,o,p,c) _bus_space_write_multi_2(t,h,o,p,c) 172 #define bus_space_write_multi_4(t,h,o,p,c) _bus_space_write_multi_4(t,h,o,p,c) 173 174 #define bus_space_write_region_1(t,h,o,p,c) \ 175 _bus_space_write_region_1(t,h,o,p,c) 176 #define bus_space_write_region_2(t,h,o,p,c) \ 177 _bus_space_write_region_2(t,h,o,p,c) 178 #define bus_space_write_region_4(t,h,o,p,c) \ 179 _bus_space_write_region_4(t,h,o,p,c) 180 181 #define bus_space_set_region_1(t,h,o,v,c) _bus_space_set_region_1(t,h,o,v,c) 182 #define bus_space_set_region_2(t,h,o,v,c) _bus_space_set_region_2(t,h,o,v,c) 183 #define bus_space_set_region_4(t,h,o,v,c) _bus_space_set_region_4(t,h,o,v,c) 184 185 #define bus_space_copy_region_1(t,sh,so,dh,do,c) \ 186 _bus_space_copy_region_1(t,sh,so,dh,do,c) 187 #define bus_space_copy_region_2(t,sh,so,dh,do,c) \ 188 _bus_space_copy_region_2(t,sh,so,dh,do,c) 189 #define bus_space_copy_region_4(t,sh,so,dh,do,c) \ 190 _bus_space_copy_region_4(t,sh,so,dh,do,c) 191 192 static __inline uint8_t _bus_space_read_1 193 (bus_space_tag_t, bus_space_handle_t bsh, bus_size_t offset); 194 static __inline uint16_t _bus_space_read_2 195 (bus_space_tag_t, bus_space_handle_t, bus_size_t); 196 static __inline uint32_t _bus_space_read_4 197 (bus_space_tag_t, bus_space_handle_t, bus_size_t); 198 199 static __inline void _bus_space_read_multi_1 200 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 201 uint8_t *, bus_size_t); 202 static __inline void _bus_space_read_multi_2 203 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 204 uint16_t *, bus_size_t); 205 static __inline void _bus_space_read_multi_4 206 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 207 uint32_t *, bus_size_t); 208 209 static __inline void _bus_space_read_region_1 210 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 211 uint8_t *, bus_size_t); 212 static __inline void _bus_space_read_region_2 213 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 214 uint16_t *, bus_size_t); 215 static __inline void _bus_space_read_region_4 216 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 217 uint32_t *, bus_size_t); 218 219 static __inline void _bus_space_write_1 220 (bus_space_tag_t, bus_space_handle_t, bus_size_t, uint8_t); 221 static __inline void _bus_space_write_2 222 (bus_space_tag_t, bus_space_handle_t, bus_size_t, uint16_t); 223 static __inline void _bus_space_write_4 224 (bus_space_tag_t, bus_space_handle_t, bus_size_t, uint32_t); 225 226 static __inline void _bus_space_write_multi_1 227 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 228 const uint8_t *, bus_size_t); 229 static __inline void _bus_space_write_multi_2 230 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 231 const uint16_t *, bus_size_t); 232 static __inline void _bus_space_write_multi_4 233 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 234 const uint32_t *, bus_size_t); 235 236 static __inline void _bus_space_write_region_1 237 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 238 const uint8_t *, bus_size_t); 239 static __inline void _bus_space_write_region_2 240 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 241 const uint16_t *, bus_size_t); 242 static __inline void _bus_space_write_region_4 243 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 244 const uint32_t *, bus_size_t); 245 246 static __inline void _bus_space_set_region_1 247 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 248 uint8_t, bus_size_t); 249 static __inline void _bus_space_set_region_2 250 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 251 uint16_t, bus_size_t); 252 static __inline void _bus_space_set_region_4 253 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 254 uint32_t, bus_size_t); 255 256 static __inline void _bus_space_copy_region_1 257 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 258 bus_space_handle_t, bus_size_t, bus_size_t); 259 static __inline void _bus_space_copy_region_2 260 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 261 bus_space_handle_t, bus_size_t, bus_size_t); 262 static __inline void _bus_space_copy_region_4 263 (bus_space_tag_t, bus_space_handle_t, bus_size_t, 264 bus_space_handle_t, bus_size_t, bus_size_t); 265 266 267 #define __X68K_BUS_ADDR(tag, handle, offset) \ 268 (((long)(handle) < 0 ? (offset) * 2 : (offset)) \ 269 + ((handle) & 0x7fffffff)) 270 271 static __inline uint8_t 272 _bus_space_read_1(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset) 273 { 274 275 return *((volatile uint8_t *) __X68K_BUS_ADDR(t, bsh, offset)); 276 } 277 278 static __inline uint16_t 279 _bus_space_read_2(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset) 280 { 281 282 return *((volatile uint16_t *) __X68K_BUS_ADDR(t, bsh, offset)); 283 } 284 285 static __inline uint32_t 286 _bus_space_read_4(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t offset) 287 { 288 289 return *((volatile uint32_t *) __X68K_BUS_ADDR(t, bsh, offset)); 290 } 291 292 static __inline void 293 _bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t bsh, 294 bus_size_t offset, uint8_t *datap, bus_size_t count) 295 { 296 #if X68K_BUS_PERFORMANCE_HACK 297 uint8_t *regadr = (uint8_t *) __X68K_BUS_ADDR(t, bsh, offset); 298 299 for (; count; count--) { 300 __asm("| avoid optim. _bus_space_read_multi_1" : : : "memory"); 301 *datap++ = *regadr; 302 } 303 #else 304 305 while (count-- > 0) { 306 *datap++ = *(volatile uint8_t *) 307 __X68K_BUS_ADDR(t, bsh, offset); 308 } 309 #endif 310 } 311 312 static __inline void 313 _bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t bsh, 314 bus_size_t offset, uint16_t *datap, bus_size_t count) 315 { 316 #if X68K_BUS_PERFORMANCE_HACK 317 uint16_t *regadr = (uint16_t *) __X68K_BUS_ADDR(t, bsh, offset); 318 319 for (; count; count--) { 320 __asm("| avoid optim. _bus_space_read_multi_2" : : : "memory"); 321 *datap++ = *regadr; 322 } 323 #else 324 325 while (count-- > 0) { 326 *datap++ = *(volatile uint16_t *) 327 __X68K_BUS_ADDR(t, bsh, offset); 328 } 329 #endif 330 } 331 332 static __inline void 333 _bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t bsh, 334 bus_size_t offset, uint32_t *datap, bus_size_t count) 335 { 336 #if X68K_BUS_PERFORMANCE_HACK 337 uint32_t *regadr = (uint32_t *) __X68K_BUS_ADDR(t, bsh, offset); 338 339 for (; count; count--) { 340 __asm("| avoid optim. _bus_space_read_multi_4" : : : "memory"); 341 *datap++ = *regadr; 342 } 343 #else 344 345 while (count-- > 0) { 346 *datap++ = *(volatile uint32_t *) 347 __X68K_BUS_ADDR(t, bsh, offset); 348 } 349 #endif 350 } 351 352 static __inline void 353 _bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t bsh, 354 bus_size_t offset, uint8_t *datap, bus_size_t count) 355 { 356 #if X68K_BUS_PERFORMANCE_HACK 357 uint8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 358 359 for (; count; count--) { 360 __asm("| avoid optim. _bus_space_read_region_1" : : : "memory"); 361 *datap++ = *addr++; 362 } 363 #else 364 volatile uint8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 365 366 while (count-- > 0) { 367 *datap++ = *addr++; 368 } 369 #endif 370 } 371 372 static __inline void 373 _bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t bsh, 374 bus_size_t offset, uint16_t *datap, bus_size_t count) 375 { 376 #if X68K_BUS_PERFORMANCE_HACK 377 uint16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 378 379 for (; count; count--) { 380 __asm("| avoid optim. _bus_space_read_region_2" : : : "memory"); 381 *datap++ = *addr++; 382 } 383 #else 384 volatile uint16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 385 386 while (count-- > 0) { 387 *datap++ = *addr++; 388 } 389 #endif 390 } 391 392 static __inline void 393 _bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t bsh, 394 bus_size_t offset, uint32_t *datap, bus_size_t count) 395 { 396 #if X68K_BUS_PERFORMANCE_HACK 397 uint32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 398 399 for (; count; count--) { 400 __asm("| avoid optim. _bus_space_read_region_4" : : : "memory"); 401 *datap++ = *addr++; 402 } 403 #else 404 volatile uint32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 405 406 while (count-- > 0) { 407 *datap++ = *addr++; 408 } 409 #endif 410 } 411 412 static __inline void 413 _bus_space_write_1(bus_space_tag_t t, bus_space_handle_t bsh, 414 bus_size_t offset, uint8_t value) 415 { 416 417 *(volatile uint8_t *) __X68K_BUS_ADDR(t, bsh, offset) = value; 418 } 419 420 static __inline void 421 _bus_space_write_2(bus_space_tag_t t, bus_space_handle_t bsh, 422 bus_size_t offset, uint16_t value) 423 { 424 425 *(volatile uint16_t *) __X68K_BUS_ADDR(t, bsh, offset) = value; 426 } 427 428 static __inline void 429 _bus_space_write_4(bus_space_tag_t t, bus_space_handle_t bsh, 430 bus_size_t offset, uint32_t value) 431 { 432 433 *(volatile uint32_t *) __X68K_BUS_ADDR(t, bsh, offset) = value; 434 } 435 436 static __inline void 437 _bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t bsh, 438 bus_size_t offset, const uint8_t *datap, bus_size_t count) 439 { 440 #if X68K_BUS_PERFORMANCE_HACK 441 uint8_t *regadr = (uint8_t *) __X68K_BUS_ADDR(t, bsh, offset); 442 443 for (; count; count--) { 444 __asm("| avoid optim. _bus_space_write_multi_1" : : : "memory"); 445 *regadr = *datap++; 446 } 447 #else 448 449 while (count-- > 0) { 450 *(volatile uint8_t *) __X68K_BUS_ADDR(t, bsh, offset) 451 = *datap++; 452 } 453 #endif 454 } 455 456 static __inline void 457 _bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t bsh, 458 bus_size_t offset, const uint16_t *datap, bus_size_t count) 459 { 460 #if X68K_BUS_PERFORMANCE_HACK 461 uint16_t *regadr = (uint16_t *) __X68K_BUS_ADDR(t, bsh, offset); 462 463 for (; count; count--) { 464 __asm("| avoid optim. _bus_space_write_multi_2" : : : "memory"); 465 *regadr = *datap++; 466 } 467 #else 468 469 while (count-- > 0) { 470 *(volatile uint16_t *) __X68K_BUS_ADDR(t, bsh, offset) 471 = *datap++; 472 } 473 #endif 474 } 475 476 static __inline void 477 _bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t bsh, 478 bus_size_t offset, const uint32_t *datap, bus_size_t count) 479 { 480 #if X68K_BUS_PERFORMANCE_HACK 481 uint32_t *regadr = (uint32_t *) __X68K_BUS_ADDR(t, bsh, offset); 482 483 for (; count; count--) { 484 __asm("| avoid optim. _bus_space_write_multi_4" : : : "memory"); 485 *regadr = *datap++; 486 } 487 #else 488 489 while (count-- > 0) { 490 *(volatile uint32_t *) __X68K_BUS_ADDR(t, bsh, offset) 491 = *datap++; 492 } 493 #endif 494 } 495 496 static __inline void 497 _bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t bsh, 498 bus_size_t offset, const uint8_t *datap, bus_size_t count) 499 { 500 #if X68K_BUS_PERFORMANCE_HACK 501 uint8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 502 503 for (; count; count--) { 504 __asm("| avoid optim. _bus_space_write_region_1": : : "memory"); 505 *addr++ = *datap++; 506 } 507 #else 508 volatile uint8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 509 510 while (count-- > 0) { 511 *addr++ = *datap++; 512 } 513 #endif 514 } 515 516 static __inline void 517 _bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t bsh, 518 bus_size_t offset, const uint16_t *datap, bus_size_t count) 519 { 520 #if X68K_BUS_PERFORMANCE_HACK 521 uint16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 522 523 for (; count; count--) { 524 __asm("| avoid optim. _bus_space_write_region_2": : : "memory"); 525 *addr++ = *datap++; 526 } 527 #else 528 volatile uint16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 529 530 while (count-- > 0) { 531 *addr++ = *datap++; 532 } 533 #endif 534 } 535 536 static __inline void 537 _bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t bsh, 538 bus_size_t offset, const uint32_t *datap, bus_size_t count) 539 { 540 #if X68K_BUS_PERFORMANCE_HACK 541 uint32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 542 543 for (; count; count--) { 544 __asm("| avoid optim. _bus_space_write_region_4": : : "memory"); 545 *addr++ = *datap++; 546 } 547 #else 548 volatile uint32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 549 550 while (count-- > 0) { 551 *addr++ = *datap++; 552 } 553 #endif 554 } 555 556 static __inline void 557 _bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t bsh, 558 bus_size_t offset, uint8_t value, bus_size_t count) 559 { 560 #if X68K_BUS_PERFORMANCE_HACK 561 uint8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 562 563 for (; count; count--) { 564 __asm("| avoid optim. _bus_space_set_region_1" : : : "memory"); 565 *addr++ = value; 566 } 567 #else 568 volatile uint8_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 569 570 while (count-- > 0) { 571 *addr++ = value; 572 } 573 #endif 574 } 575 576 static __inline void 577 _bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t bsh, 578 bus_size_t offset, uint16_t value, bus_size_t count) 579 { 580 #if X68K_BUS_PERFORMANCE_HACK 581 uint16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 582 583 for (; count; count--) { 584 __asm("| avoid optim. _bus_space_set_region_2" : : : "memory"); 585 *addr++ = value; 586 } 587 #else 588 volatile uint16_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 589 590 while (count-- > 0) { 591 *addr++ = value; 592 } 593 #endif 594 } 595 596 static __inline void 597 _bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t bsh, 598 bus_size_t offset, uint32_t value, bus_size_t count) 599 { 600 #if X68K_BUS_PERFORMANCE_HACK 601 uint32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 602 603 for (; count; count--) { 604 __asm("| avoid optim. _bus_space_set_region_4" : : : "memory"); 605 *addr++ = value; 606 } 607 #else 608 volatile uint32_t *addr = (void *) __X68K_BUS_ADDR(t, bsh, offset); 609 610 while (count-- > 0) { 611 *addr++ = value; 612 } 613 #endif 614 } 615 616 static __inline void 617 _bus_space_copy_region_1(bus_space_tag_t t, 618 bus_space_handle_t sbsh, bus_size_t soffset, 619 bus_space_handle_t dbsh, bus_size_t doffset, 620 bus_size_t count) 621 { 622 volatile uint8_t *saddr = (void *) (sbsh + soffset); 623 volatile uint8_t *daddr = (void *) (dbsh + doffset); 624 625 if ((uint32_t) saddr >= (uint32_t) daddr) 626 while (count-- > 0) 627 *daddr++ = *saddr++; 628 else { 629 saddr += count; 630 daddr += count; 631 while (count-- > 0) 632 *--daddr = *--saddr; 633 } 634 } 635 636 static __inline void 637 _bus_space_copy_region_2(bus_space_tag_t t, 638 bus_space_handle_t sbsh, bus_size_t soffset, 639 bus_space_handle_t dbsh, bus_size_t doffset, 640 bus_size_t count) 641 { 642 volatile uint16_t *saddr = (void *) (sbsh + soffset); 643 volatile uint16_t *daddr = (void *) (dbsh + doffset); 644 645 if ((uint32_t) saddr >= (uint32_t) daddr) 646 while (count-- > 0) 647 *daddr++ = *saddr++; 648 else { 649 saddr += count; 650 daddr += count; 651 while (count-- > 0) 652 *--daddr = *--saddr; 653 } 654 } 655 656 static __inline void 657 _bus_space_copy_region_4(bus_space_tag_t t, 658 bus_space_handle_t sbsh, bus_size_t soffset, 659 bus_space_handle_t dbsh, bus_size_t doffset, 660 bus_size_t count) 661 { 662 volatile uint32_t *saddr = (void *) (sbsh + soffset); 663 volatile uint32_t *daddr = (void *) (dbsh + doffset); 664 665 if ((uint32_t) saddr >= (uint32_t) daddr) 666 while (count-- > 0) 667 *daddr++ = *saddr++; 668 else { 669 saddr += count; 670 daddr += count; 671 while (count-- > 0) 672 *--daddr = *--saddr; 673 } 674 } 675 676 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) 677 678 /* 679 * DMA segment 680 */ 681 struct x68k_bus_dma_segment { 682 bus_addr_t ds_addr; 683 bus_size_t ds_len; 684 }; 685 typedef struct x68k_bus_dma_segment bus_dma_segment_t; 686 687 /* 688 * DMA descriptor 689 */ 690 /* Forwards needed by prototypes below. */ 691 struct mbuf; 692 struct uio; 693 694 typedef struct x68k_bus_dma *bus_dma_tag_t; 695 typedef struct x68k_bus_dmamap *bus_dmamap_t; 696 697 #define BUS_DMA_TAG_VALID(t) ((t) != (bus_dma_tag_t)0) 698 699 struct x68k_bus_dma { 700 /* 701 * The `bounce threshold' is checked while we are loading 702 * the DMA map. If the physical address of the segment 703 * exceeds the threshold, an error will be returned. The 704 * caller can then take whatever action is necessary to 705 * bounce the transfer. If this value is 0, it will be 706 * ignored. 707 */ 708 bus_addr_t _bounce_thresh; 709 710 /* 711 * DMA mapping methods. 712 */ 713 int (*x68k_dmamap_create)(bus_dma_tag_t, bus_size_t, int, 714 bus_size_t, bus_size_t, int, bus_dmamap_t *); 715 void (*x68k_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); 716 int (*x68k_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, 717 bus_size_t, struct proc *, int); 718 int (*x68k_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, 719 struct mbuf *, int); 720 int (*x68k_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, 721 struct uio *, int); 722 int (*x68k_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, 723 bus_dma_segment_t *, int, bus_size_t, int); 724 void (*x68k_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); 725 void (*x68k_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, 726 bus_addr_t, bus_size_t, int); 727 728 /* 729 * DMA memory utility functions. 730 */ 731 int (*x68k_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, 732 bus_size_t, bus_dma_segment_t *, int, int *, int); 733 void (*x68k_dmamem_free)(bus_dma_tag_t, 734 bus_dma_segment_t *, int); 735 int (*x68k_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, 736 int, size_t, void **, int); 737 void (*x68k_dmamem_unmap)(bus_dma_tag_t, void *, size_t); 738 paddr_t (*x68k_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, 739 int, off_t, int, int); 740 }; 741 742 /* 743 * bus_dmamap_t 744 * 745 * Describes a DMA mapping. 746 */ 747 struct x68k_bus_dmamap { 748 /* 749 * PRIVATE MEMBERS: not for use my machine-independent code. 750 */ 751 bus_size_t x68k_dm_size; /* largest DMA transfer mappable */ 752 int x68k_dm_segcnt; /* number of segs this map can map */ 753 bus_size_t x68k_dm_maxmaxsegsz; /* fixed largest possible segment*/ 754 bus_size_t x68k_dm_boundary; /* don't cross this */ 755 bus_addr_t x68k_dm_bounce_thresh; /* bounce threshold */ 756 int x68k_dm_flags; /* misc. flags */ 757 758 void *x68k_dm_cookie; /* cookie for bus-specific functions */ 759 760 /* 761 * PUBLIC MEMBERS: these are used by machine-independent code. 762 */ 763 bus_size_t dm_maxsegsz; /* largest possible segment */ 764 bus_size_t dm_mapsize; /* size of the mapping */ 765 int dm_nsegs; /* # valid segments in mapping */ 766 bus_dma_segment_t dm_segs[1]; /* segments; variable length */ 767 }; 768 769 int x68k_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, 770 bus_size_t, int, bus_dmamap_t *); 771 void x68k_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); 772 int x68k_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, 773 bus_size_t, struct proc *, int); 774 int x68k_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, 775 struct mbuf *, int); 776 int x68k_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, 777 struct uio *, int); 778 int x68k_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, 779 bus_dma_segment_t *, int, bus_size_t, int); 780 void x68k_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); 781 void x68k_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 782 bus_size_t, int); 783 784 int x68k_bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, 785 bus_size_t alignment, bus_size_t boundary, 786 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags); 787 void x68k_bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, 788 int nsegs); 789 int x68k_bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, 790 int nsegs, size_t size, void **kvap, int flags); 791 void x68k_bus_dmamem_unmap(bus_dma_tag_t tag, void *kva, 792 size_t size); 793 paddr_t x68k_bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs, 794 int nsegs, off_t off, int prot, int flags); 795 796 int x68k_bus_dmamap_load_buffer(bus_dmamap_t, void *, 797 bus_size_t buflen, struct proc *, int, paddr_t *, int *, int); 798 int x68k_bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size, 799 bus_size_t alignment, bus_size_t boundary, 800 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, 801 paddr_t low, paddr_t high); 802 803 #define bus_dmamap_create(t,s,n,m,b,f,p) \ 804 ((*((t)->x68k_dmamap_create)) ((t),(s),(n),(m),(b),(f),(p))) 805 #define bus_dmamap_destroy(t,p) \ 806 ((*((t)->x68k_dmamap_destroy)) ((t),(p))) 807 #define bus_dmamap_load(t,m,b,s,p,f) \ 808 ((*((t)->x68k_dmamap_load)) ((t),(m),(b),(s),(p),(f))) 809 #define bus_dmamap_load_mbuf(t,m,b,f) \ 810 ((*((t)->x68k_dmamap_load_mbuf)) ((t),(m),(b),(f))) 811 #define bus_dmamap_load_uio(t,m,u,f) \ 812 ((*((t)->x68k_dmamap_load_uio)) ((t),(m),(u),(f))) 813 #define bus_dmamap_load_raw(t,m,sg,n,s,f) \ 814 ((*((t)->x68k_dmamap_load_raw)) ((t),(m),(sg),(n),(s),(f))) 815 #define bus_dmamap_unload(t,p) \ 816 ((*((t)->x68k_dmamap_unload)) ((t),(p))) 817 #define bus_dmamap_sync(t,p,o,l,ops) \ 818 ((*((t)->x68k_dmamap_sync)) ((t),(p),(o),(l),(ops))) 819 820 #define bus_dmamem_alloc(t,s,a,b,sg,n,r,f) \ 821 ((*((t)->x68k_dmamem_alloc)) ((t),(s),(a),(b),(sg),(n),(r),(f))) 822 #define bus_dmamem_free(t,sg,n) \ 823 ((*((t)->x68k_dmamem_free)) ((t),(sg),(n))) 824 #define bus_dmamem_map(t,sg,n,s,k,f) \ 825 ((*((t)->x68k_dmamem_map)) ((t),(sg),(n),(s),(k),(f))) 826 #define bus_dmamem_unmap(t,k,s) \ 827 ((*((t)->x68k_dmamem_unmap)) ((t),(k),(s))) 828 #define bus_dmamem_mmap(t,sg,n,o,p,f) \ 829 ((*((t)->x68k_dmamem_mmap)) ((t),(sg),(n),(o),(p),(f))) 830 831 #define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP 832 #define bus_dmatag_destroy(t) 833 834 /* 835 * Flags used in various bus DMA methods. 836 */ 837 #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ 838 #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ 839 #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ 840 #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ 841 #define BUS_DMA_STREAMING 0x008 /* hint: sequential, unidirectional */ 842 #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ 843 #define BUS_DMA_BUS2 0x020 844 #define BUS_DMA_BUS3 0x040 845 #define BUS_DMA_BUS4 0x080 846 #define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ 847 #define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ 848 #define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */ 849 850 /* 851 * Operations performed by bus_dmamap_sync(). 852 */ 853 #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ 854 #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ 855 #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ 856 #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ 857 858 #endif /* _X68K_BUS_H_ */ 859