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