1/* $NetBSD: bus.h,v 1.16 2019/09/23 16:17:57 skrll Exp $ */ 2 3/*- 4 * Copyright (c) 1997, 1998, 2000, 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 Carnegie-Mellon University. 35 * All rights reserved. 36 * 37 * Author: Chris G. Demetriou 38 * 39 * Permission to use, copy, modify and distribute this software and 40 * its documentation is hereby granted, provided that both the copyright 41 * notice and this permission notice appear in all copies of the 42 * software, derivative works or modified versions, and any portions 43 * thereof, and that both notices appear in supporting documentation. 44 * 45 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 46 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 47 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 48 * 49 * Carnegie Mellon requests users of this software to return to 50 * 51 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 52 * School of Computer Science 53 * Carnegie Mellon University 54 * Pittsburgh PA 15213-3890 55 * 56 * any improvements or extensions that they make and grant Carnegie the 57 * rights to redistribute these changes. 58 */ 59 60#ifndef _PLAYSTATION2_BUS_H_ 61#define _PLAYSTATION2_BUS_H_ 62 63#include <sys/types.h> 64 65#ifdef _KERNEL 66/* 67 * Turn on BUS_SPACE_DEBUG if the global DEBUG option is enabled. 68 */ 69#if defined(DEBUG) && !defined(BUS_SPACE_DEBUG) 70#define BUS_SPACE_DEBUG 71#endif 72 73#ifdef BUS_SPACE_DEBUG 74#include <sys/systm.h> /* for printf() prototype */ 75/* 76 * Macros for checking the aligned-ness of pointers passed to bus 77 * space ops. Strict alignment is required by the MIPS architecture, 78 * and a trap will occur if unaligned access is performed. These 79 * may aid in the debugging of a broken device driver by displaying 80 * useful information about the problem. 81 */ 82#define __BUS_SPACE_ALIGNED_ADDRESS(p, t) \ 83 ((((u_int32_t)(p)) & (sizeof(t)-1)) == 0) 84 85#define __BUS_SPACE_ADDRESS_SANITY(p, t, d) \ 86({ \ 87 if (__BUS_SPACE_ALIGNED_ADDRESS((p), t) == 0) { \ 88 printf("%s 0x%x not aligned to %u bytes %s:%d\n", \ 89 d, (u_int32_t)(p), (u_int32_t)sizeof(t), __FILE__, \ 90 __LINE__); \ 91 } \ 92 (void) 0; \ 93}) 94 95#define BUS_SPACE_ALIGNED_POINTER(p, t) __BUS_SPACE_ALIGNED_ADDRESS(p, t) 96#else 97#define __BUS_SPACE_ADDRESS_SANITY(p, t, d) (void) 0 98#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t) 99#endif /* BUS_SPACE_DEBUG */ 100#endif /* _KERNEL */ 101 102/* 103 * Addresses (in bus space). 104 */ 105typedef long bus_addr_t; 106typedef long bus_size_t; 107 108#define PRIxBUSADDR "lx" 109#define PRIxBUSSIZE "lx" 110#define PRIuBUSSIZE "lu" 111/* 112 * Access methods for bus space. 113 */ 114typedef const struct playstation2_bus_space *bus_space_tag_t; 115typedef bus_addr_t bus_space_handle_t; 116 117#define PRIxBSH PRIxBUSADDR 118 119struct extent; /* forward declaration */ 120 121struct playstation2_bus_space { 122 struct extent *pbs_extent; 123 bus_addr_t pbs_base_addr; 124 125 /* cookie */ 126 void *pbs_cookie; 127 128 /* mapping/unmapping */ 129 int (*pbs_map)(void *, bus_addr_t, bus_size_t, 130 int, bus_space_handle_t *); 131 void (*pbs_unmap)(void *, bus_space_handle_t, 132 bus_size_t); 133 int (*pbs_subregion)(void *, bus_space_handle_t, 134 bus_size_t, bus_size_t, bus_space_handle_t *); 135 136 /* allocation/deallocation */ 137 int (*pbs_alloc)(void *, bus_addr_t, bus_addr_t, 138 bus_size_t, bus_size_t, bus_size_t, int, 139 bus_addr_t *, bus_space_handle_t *); 140 void (*pbs_free)(void *, bus_space_handle_t, 141 bus_size_t); 142 143 /* get kernel virtual address */ 144 void * (*pbs_vaddr)(void *, bus_space_handle_t); 145 146 /* read (single) */ 147 u_int8_t (*pbs_r_1)(void *, bus_space_handle_t, 148 bus_size_t); 149 u_int16_t (*pbs_r_2)(void *, bus_space_handle_t, 150 bus_size_t); 151 u_int32_t (*pbs_r_4)(void *, bus_space_handle_t, 152 bus_size_t); 153 u_int64_t (*pbs_r_8)(void *, bus_space_handle_t, 154 bus_size_t); 155 156 /* read multiple */ 157 void (*pbs_rm_1)(void *, bus_space_handle_t, 158 bus_size_t, u_int8_t *, bus_size_t); 159 void (*pbs_rm_2)(void *, bus_space_handle_t, 160 bus_size_t, u_int16_t *, bus_size_t); 161 void (*pbs_rm_4)(void *, bus_space_handle_t, 162 bus_size_t, u_int32_t *, bus_size_t); 163 void (*pbs_rm_8)(void *, bus_space_handle_t, 164 bus_size_t, u_int64_t *, bus_size_t); 165 166 /* read region */ 167 void (*pbs_rr_1)(void *, bus_space_handle_t, 168 bus_size_t, u_int8_t *, bus_size_t); 169 void (*pbs_rr_2)(void *, bus_space_handle_t, 170 bus_size_t, u_int16_t *, bus_size_t); 171 void (*pbs_rr_4)(void *, bus_space_handle_t, 172 bus_size_t, u_int32_t *, bus_size_t); 173 void (*pbs_rr_8)(void *, bus_space_handle_t, 174 bus_size_t, u_int64_t *, bus_size_t); 175 176 /* write (single) */ 177 void (*pbs_w_1)(void *, bus_space_handle_t, 178 bus_size_t, u_int8_t); 179 void (*pbs_w_2)(void *, bus_space_handle_t, 180 bus_size_t, u_int16_t); 181 void (*pbs_w_4)(void *, bus_space_handle_t, 182 bus_size_t, u_int32_t); 183 void (*pbs_w_8)(void *, bus_space_handle_t, 184 bus_size_t, u_int64_t); 185 186 /* write multiple */ 187 void (*pbs_wm_1)(void *, bus_space_handle_t, 188 bus_size_t, const u_int8_t *, bus_size_t); 189 void (*pbs_wm_2)(void *, bus_space_handle_t, 190 bus_size_t, const u_int16_t *, bus_size_t); 191 void (*pbs_wm_4)(void *, bus_space_handle_t, 192 bus_size_t, const u_int32_t *, bus_size_t); 193 void (*pbs_wm_8)(void *, bus_space_handle_t, 194 bus_size_t, const u_int64_t *, bus_size_t); 195 196 /* write region */ 197 void (*pbs_wr_1)(void *, bus_space_handle_t, 198 bus_size_t, const u_int8_t *, bus_size_t); 199 void (*pbs_wr_2)(void *, bus_space_handle_t, 200 bus_size_t, const u_int16_t *, bus_size_t); 201 void (*pbs_wr_4)(void *, bus_space_handle_t, 202 bus_size_t, const u_int32_t *, bus_size_t); 203 void (*pbs_wr_8)(void *, bus_space_handle_t, 204 bus_size_t, const u_int64_t *, bus_size_t); 205 206 /* set multiple */ 207 void (*pbs_sm_1)(void *, bus_space_handle_t, 208 bus_size_t, u_int8_t, bus_size_t); 209 void (*pbs_sm_2)(void *, bus_space_handle_t, 210 bus_size_t, u_int16_t, bus_size_t); 211 void (*pbs_sm_4)(void *, bus_space_handle_t, 212 bus_size_t, u_int32_t, bus_size_t); 213 void (*pbs_sm_8)(void *, bus_space_handle_t, 214 bus_size_t, u_int64_t, bus_size_t); 215 216 /* set region */ 217 void (*pbs_sr_1)(void *, bus_space_handle_t, 218 bus_size_t, u_int8_t, bus_size_t); 219 void (*pbs_sr_2)(void *, bus_space_handle_t, 220 bus_size_t, u_int16_t, bus_size_t); 221 void (*pbs_sr_4)(void *, bus_space_handle_t, 222 bus_size_t, u_int32_t, bus_size_t); 223 void (*pbs_sr_8)(void *, bus_space_handle_t, 224 bus_size_t, u_int64_t, bus_size_t); 225 226 /* copy */ 227 void (*pbs_c_1)(void *, bus_space_handle_t, bus_size_t, 228 bus_space_handle_t, bus_size_t, bus_size_t); 229 void (*pbs_c_2)(void *, bus_space_handle_t, bus_size_t, 230 bus_space_handle_t, bus_size_t, bus_size_t); 231 void (*pbs_c_4)(void *, bus_space_handle_t, bus_size_t, 232 bus_space_handle_t, bus_size_t, bus_size_t); 233 void (*pbs_c_8)(void *, bus_space_handle_t, bus_size_t, 234 bus_space_handle_t, bus_size_t, bus_size_t); 235}; 236 237#ifdef _KERNEL 238#define _wbflush() __asm volatile("sync.l") 239#ifdef _PLAYSTATION2_BUS_SPACE_PRIVATE 240 241#ifndef __read_1 242#define __read_1(a) (*(volatile u_int8_t *)(a)) 243#endif 244#ifndef __read_2 245#define __read_2(a) (*(volatile u_int16_t *)(a)) 246#endif 247#ifndef __read_4 248#define __read_4(a) (*(volatile u_int32_t *)(a)) 249#endif 250#ifndef __read_8 251#define __read_8(a) \ 252({ \ 253 u_int32_t lo, hi; \ 254 __asm volatile( \ 255 ".set noreorder;" \ 256 ".set push;" \ 257 ".set mips3;" \ 258 "ld $8, (%2);" \ 259 "dsra %1, $8, 32;" \ 260 "dsll %0, $8, 32;" \ 261 "dsra %0, %0, 32;" \ 262 ".set pop;" \ 263 ".set reorder;" \ 264 : "=r"(lo), "=r"(hi) : "r"(a) : "$8"); \ 265 ((u_int64_t)hi << 32) | lo; \ 266}) 267#endif 268#define __read_16(a) "error. not yet" 269 270#ifndef __write_1 271#define __write_1(a, v) { \ 272 *(volatile u_int8_t *)(a) = (v); \ 273 _wbflush(); \ 274} 275#endif 276#ifndef __write_2 277#define __write_2(a, v) { \ 278 *(volatile u_int16_t *)(a) = (v); \ 279 _wbflush(); \ 280} 281#endif 282#ifndef __write_4 283#define __write_4(a, v) { \ 284 *(volatile u_int32_t *)(a) = (v); \ 285 _wbflush(); \ 286} 287#endif 288#ifdef EE_GCC 289#ifndef __write_8 290#define __write_8(a, v) (*(volatile u_int64_t *)(a) = (v)) { \ 291 _wbflush(); \ 292} 293#endif 294#ifndef __write_16 295#define __write_16(a, v) (*(volatile u_int128_t *)(a) = (v)) { \ 296 _wbflush(); \ 297} 298#endif 299#else /* EE_GCC */ 300#ifdef __write_8 301#error "can't override __write_8" 302#endif 303static __inline void 304__write_8(bus_addr_t a, u_int64_t v) 305{ 306 __asm volatile( 307 ".set noreorder;" 308 ".set push;" 309 ".set arch = r5900;" 310 "pextlw $8, %0, %1;" 311 "sd $8, 0(%2);" 312 "sync.l;" 313 ".set pop;" 314 ".set reorder;" 315 : : "r"((u_int32_t)((u_int64_t)(v) >> 32)), 316 "r"((u_int32_t)(v)), "r"((u_int32_t)(a)) : "$8"); 317} 318#define _write_16(a) "error. not yet" 319#endif /* EE_GCC */ 320 321#define __TYPENAME(BITS) u_int##BITS##_t 322 323#define _BUS_SPACE_READ(PREFIX, BYTES, BITS) \ 324static __TYPENAME(BITS) \ 325PREFIX##_read_##BYTES(void *, bus_space_handle_t, bus_size_t); \ 326static __TYPENAME(BITS) \ 327PREFIX##_read_##BYTES(void *tag, bus_space_handle_t bsh, \ 328 bus_size_t offset) \ 329{ \ 330 return __read_##BYTES(VADDR(bsh, offset)); \ 331} 332 333#define _BUS_SPACE_READ_MULTI(PREFIX, BYTES, BITS) \ 334static void \ 335PREFIX##_read_multi_##BYTES(void *, bus_space_handle_t, bus_size_t, \ 336 __TYPENAME(BITS) *, bus_size_t); \ 337static void \ 338PREFIX##_read_multi_##BYTES(void *tag, bus_space_handle_t bsh, \ 339 bus_size_t offset, __TYPENAME(BITS) *addr, bus_size_t count) \ 340{ \ 341 bus_addr_t a = VADDR(bsh, offset); \ 342 while (count--) \ 343 *addr++ = __read_##BYTES(a); \ 344} 345 346#define _BUS_SPACE_READ_REGION(PREFIX, BYTES, BITS) \ 347static void \ 348PREFIX##_read_region_##BYTES(void *, bus_space_handle_t, bus_size_t, \ 349 __TYPENAME(BITS) *, bus_size_t); \ 350static void \ 351PREFIX##_read_region_##BYTES(void *tag, bus_space_handle_t bsh, \ 352 bus_size_t offset, __TYPENAME(BITS) *addr, bus_size_t count) \ 353{ \ 354 while (count--) { \ 355 *addr++ = __read_##BYTES(VADDR(bsh, offset)); \ 356 offset += BYTES; \ 357 } \ 358} 359 360#define _BUS_SPACE_WRITE(PREFIX, BYTES, BITS) \ 361static void \ 362PREFIX##_write_##BYTES(void *, bus_space_handle_t, bus_size_t, \ 363 __TYPENAME(BITS)); \ 364static void \ 365PREFIX##_write_##BYTES(void *tag, bus_space_handle_t bsh, \ 366 bus_size_t offset, __TYPENAME(BITS) value) \ 367{ \ 368 __write_##BYTES(VADDR(bsh, offset), value); \ 369} 370 371#define _BUS_SPACE_WRITE_MULTI(PREFIX, BYTES, BITS) \ 372static void \ 373PREFIX##_write_multi_##BYTES(void *, bus_space_handle_t, bus_size_t, \ 374 const __TYPENAME(BITS) *, bus_size_t); \ 375static void \ 376PREFIX##_write_multi_##BYTES(void *tag, bus_space_handle_t bsh, \ 377 bus_size_t offset, const __TYPENAME(BITS) *addr, bus_size_t count) \ 378{ \ 379 bus_addr_t a = VADDR(bsh, offset); \ 380 while (count--) { \ 381 __write_##BYTES(a, *addr++); \ 382 } \ 383} 384 385#define _BUS_SPACE_WRITE_REGION(PREFIX, BYTES, BITS) \ 386static void \ 387PREFIX##_write_region_##BYTES(void *, bus_space_handle_t, bus_size_t, \ 388 const __TYPENAME(BITS) *, bus_size_t); \ 389static void \ 390PREFIX##_write_region_##BYTES(void *tag, bus_space_handle_t bsh, \ 391 bus_size_t offset, const __TYPENAME(BITS) *addr, bus_size_t count) \ 392{ \ 393 while (count--) { \ 394 __write_##BYTES(VADDR(bsh, offset), *addr++); \ 395 offset += BYTES; \ 396 } \ 397} 398 399#define _BUS_SPACE_SET_MULTI(PREFIX, BYTES, BITS) \ 400static void \ 401PREFIX##_set_multi_##BYTES(void *, bus_space_handle_t, bus_size_t, \ 402 __TYPENAME(BITS), bus_size_t); \ 403static void \ 404PREFIX##_set_multi_##BYTES(void *tag, bus_space_handle_t bsh, \ 405 bus_size_t offset, __TYPENAME(BITS) value, bus_size_t count) \ 406{ \ 407 bus_addr_t a = VADDR(bsh, offset); \ 408 while (count--) { \ 409 __write_##BYTES(a, value); \ 410 } \ 411} 412 413#define _BUS_SPACE_SET_REGION(PREFIX, BYTES, BITS) \ 414static void \ 415PREFIX##_set_region_##BYTES(void *, bus_space_handle_t, bus_size_t, \ 416 __TYPENAME(BITS), bus_size_t); \ 417static void \ 418PREFIX##_set_region_##BYTES(void *tag, bus_space_handle_t bsh, \ 419 bus_size_t offset, __TYPENAME(BITS) value, bus_size_t count) \ 420{ \ 421 while (count--) { \ 422 __write_##BYTES(VADDR(bsh, offset), value); \ 423 offset += BYTES; \ 424 } \ 425} 426 427#define _BUS_SPACE_COPY_REGION(PREFIX, BYTES, BITS) \ 428static void \ 429PREFIX##_copy_region_##BYTES(void *, bus_space_handle_t, bus_size_t, \ 430 bus_space_handle_t, bus_size_t, bus_size_t); \ 431static void \ 432PREFIX##_copy_region_##BYTES(void *t, bus_space_handle_t h1, \ 433 bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) \ 434{ \ 435 bus_size_t o; \ 436 if ((h1 + o1) >= (h2 + o2)) { \ 437 /* src after dest: copy forward */ \ 438 for (o = 0; c != 0; c--, o += BYTES) \ 439 __write_##BYTES(VADDR(h2, o2 + o), \ 440 __read_##BYTES(VADDR(h1, o1 + o))); \ 441 } else { \ 442 /* dest after src: copy backwards */ \ 443 for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES) \ 444 __write_##BYTES(VADDR(h2, o2 + o), \ 445 __read_##BYTES(VADDR(h1, o1 + o))); \ 446 } \ 447} 448 449#define _BUS_SPACE_NO_MAP \ 450 (int (*)(void *, bus_addr_t, bus_size_t, int, \ 451 bus_space_handle_t *))_bus_space_invalid_access 452#define _BUS_SPACE_NO_UNMAP \ 453 (void (*)(void *, bus_space_handle_t, bus_size_t)) \ 454 _bus_space_invalid_access 455#define _BUS_SPACE_NO_SUBREGION \ 456 (int (*)(void *, bus_space_handle_t, bus_size_t, bus_size_t, \ 457 bus_space_handle_t *))_bus_space_invalid_access 458#define _BUS_SPACE_NO_ALLOC \ 459 (int (*)(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t,\ 460 bus_size_t, int, bus_addr_t *, bus_space_handle_t *)) \ 461 _bus_space_invalid_access 462#define _BUS_SPACE_NO_FREE \ 463 (void (*)(void *, bus_space_handle_t, bus_size_t)) \ 464 _bus_space_invalid_access 465#define _BUS_SPACE_NO_VADDR \ 466 (void *(*)(void *, bus_space_handle_t))_bus_space_invalid_access 467#define _BUS_SPACE_NO_READ(BYTES, BITS) \ 468 (u_int##BITS##_t (*)(void *, bus_space_handle_t, bus_size_t)) \ 469 _bus_space_invalid_access 470#define _BUS_SPACE_NO_READ_MULTI(BYTES, BITS) \ 471 (void (*)(void *, bus_space_handle_t, bus_size_t, \ 472 u_int##BITS##_t *, bus_size_t))_bus_space_invalid_access 473#define _BUS_SPACE_NO_READ_REGION(BYTES, BITS) \ 474 (void (*)(void *, bus_space_handle_t, bus_size_t, \ 475 u_int##BITS##_t *, bus_size_t))_bus_space_invalid_access 476#define _BUS_SPACE_NO_WRITE(BYTES, BITS) \ 477 (void (*)(void *, bus_space_handle_t, bus_size_t, \ 478 u_int##BITS##_t))_bus_space_invalid_access 479#define _BUS_SPACE_NO_WRITE_MULTI(BYTES, BITS) \ 480 (void (*)(void *, bus_space_handle_t, bus_size_t, \ 481 const u_int##BITS##_t *, bus_size_t))_bus_space_invalid_access 482#define _BUS_SPACE_NO_WRITE_REGION(BYTES, BITS) \ 483 (void (*)(void *, bus_space_handle_t, bus_size_t, \ 484 const u_int##BITS##_t *, bus_size_t))_bus_space_invalid_access 485#define _BUS_SPACE_NO_SET_MULTI(BYTES, BITS) \ 486 (void (*)(void *, bus_space_handle_t, bus_size_t, \ 487 u_int##BITS##_t, bus_size_t))_bus_space_invalid_access 488#define _BUS_SPACE_NO_SET_REGION(BYTES, BITS) \ 489 (void (*)(void *, bus_space_handle_t, bus_size_t, \ 490 u_int##BITS##_t, bus_size_t))_bus_space_invalid_access 491#define _BUS_SPACE_NO_COPY_REGION(BYTES, BITS) \ 492 (void (*)(void *, bus_space_handle_t, bus_size_t, \ 493 bus_space_handle_t, bus_size_t, bus_size_t))_bus_space_invalid_access 494 495void _bus_space_invalid_access(void); 496#endif /* _PLAYSTATION2_BUS_SPACE_PRIVATE */ 497 498#define __pbs_c(a,b) __CONCAT(a,b) 499#define __pbs_opname(op,size) __pbs_c(__pbs_c(__pbs_c(pbs_,op),_),size) 500 501#define __pbs_rs(sz, tn, t, h, o) \ 502 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), tn, "bus addr"), \ 503 (*(t)->__pbs_opname(r,sz))((t)->pbs_cookie, h, o)) 504 505#define __pbs_ws(sz, tn, t, h, o, v) \ 506({ \ 507 __BUS_SPACE_ADDRESS_SANITY((h) + (o), tn, "bus addr"); \ 508 (*(t)->__pbs_opname(w,sz))((t)->pbs_cookie, h, o, v); \ 509}) 510 511#define __pbs_nonsingle(type, sz, tn, t, h, o, a, c) \ 512({ \ 513 __BUS_SPACE_ADDRESS_SANITY((a), tn, "buffer"); \ 514 __BUS_SPACE_ADDRESS_SANITY((h) + (o), tn, "bus addr"); \ 515 (*(t)->__pbs_opname(type,sz))((t)->pbs_cookie, h, o, a, c); \ 516}) 517 518#define __pbs_set(type, sz, tn, t, h, o, v, c) \ 519({ \ 520 __BUS_SPACE_ADDRESS_SANITY((h) + (o), tn, "bus addr"); \ 521 (*(t)->__pbs_opname(type,sz))((t)->pbs_cookie, h, o, v, c); \ 522}) 523 524#define __pbs_copy(sz, tn, t, h1, o1, h2, o2, cnt) \ 525({ \ 526 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), tn, "bus addr 1"); \ 527 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), tn, "bus addr 2"); \ 528 (*(t)->__pbs_opname(c,sz))((t)->pbs_cookie, h1, o1, h2, o2, cnt); \ 529}) 530 531/* 532 * Create default bus_space tag. 533 */ 534bus_space_tag_t bus_space_create(bus_space_tag_t, const char *, bus_addr_t, 535 bus_size_t); 536void bus_space_destroy(bus_space_tag_t); 537 538/* 539 * Mapping and unmapping operations. 540 */ 541#define bus_space_map(t, a, s, f, hp) \ 542 (*(t)->pbs_map)((t)->pbs_cookie, (a), (s), (f), (hp)) 543#define bus_space_unmap(t, h, s) \ 544 (*(t)->pbs_unmap)((t)->pbs_cookie, (h), (s)) 545#define bus_space_subregion(t, h, o, s, hp) \ 546 (*(t)->pbs_subregion)((t)->pbs_cookie, (h), (o), (s), (hp)) 547 548#endif /* _KERNEL */ 549 550#define BUS_SPACE_MAP_CACHEABLE 0x01 551#define BUS_SPACE_MAP_LINEAR 0x02 552#define BUS_SPACE_MAP_PREFETCHABLE 0x04 553 554#ifdef _KERNEL 555/* 556 * Allocation and deallocation operations. 557 */ 558#define bus_space_alloc(t, rs, re, s, a, b, f, ap, hp) \ 559 (*(t)->pbs_alloc)((t)->pbs_cookie, (rs), (re), (s), (a), (b), \ 560 (f), (ap), (hp)) 561#define bus_space_free(t, h, s) \ 562 (*(t)->pbs_free)((t)->pbs_cookie, (h), (s)) 563 564/* 565 * Get kernel virtual address for ranges mapped BUS_SPACE_MAP_LINEAR. 566 */ 567#define bus_space_vaddr(t, h) \ 568 (*(t)->pbs_vaddr)((t)->pbs_cookie, (h)) 569 570/* 571 * Bus barrier operations. The playstation2 does not currently require 572 * barriers, but we must provide the flags to MI code. 573 */ 574#define bus_space_barrier(t, h, o, l, f) \ 575({ \ 576 _wbflush(); \ 577}) 578 579 580#define BUS_SPACE_BARRIER_READ 0x01 581#define BUS_SPACE_BARRIER_WRITE 0x02 582 583 584/* 585 * Bus read (single) operations. 586 */ 587#define bus_space_read_1(t, h, o) __pbs_rs(1,u_int8_t,(t),(h),(o)) 588#define bus_space_read_2(t, h, o) __pbs_rs(2,u_int16_t,(t),(h),(o)) 589#define bus_space_read_4(t, h, o) __pbs_rs(4,u_int32_t,(t),(h),(o)) 590#define bus_space_read_8(t, h, o) __pbs_rs(8,u_int64_t,(t),(h),(o)) 591 592 593/* 594 * Bus read multiple operations. 595 */ 596#define bus_space_read_multi_1(t, h, o, a, c) \ 597 __pbs_nonsingle(rm,1,u_int8_t,(t),(h),(o),(a),(c)) 598#define bus_space_read_multi_2(t, h, o, a, c) \ 599 __pbs_nonsingle(rm,2,u_int16_t,(t),(h),(o),(a),(c)) 600#define bus_space_read_multi_4(t, h, o, a, c) \ 601 __pbs_nonsingle(rm,4,u_int32_t,(t),(h),(o),(a),(c)) 602#define bus_space_read_multi_8(t, h, o, a, c) \ 603 __pbs_nonsingle(rm,8,u_int64_t,(t),(h),(o),(a),(c)) 604 605 606/* 607 * Bus read region operations. 608 */ 609#define bus_space_read_region_1(t, h, o, a, c) \ 610 __pbs_nonsingle(rr,1,u_int8_t,(t),(h),(o),(a),(c)) 611#define bus_space_read_region_2(t, h, o, a, c) \ 612 __pbs_nonsingle(rr,2,u_int16_t,(t),(h),(o),(a),(c)) 613#define bus_space_read_region_4(t, h, o, a, c) \ 614 __pbs_nonsingle(rr,4,u_int32_t,(t),(h),(o),(a),(c)) 615#define bus_space_read_region_8(t, h, o, a, c) \ 616 __pbs_nonsingle(rr,8,u_int64_t,(t),(h),(o),(a),(c)) 617 618 619/* 620 * Bus write (single) operations. 621 */ 622#define bus_space_write_1(t, h, o, v) __pbs_ws(1,u_int8_t,(t),(h),(o),(v)) 623#define bus_space_write_2(t, h, o, v) __pbs_ws(2,u_int16_t,(t),(h),(o),(v)) 624#define bus_space_write_4(t, h, o, v) __pbs_ws(4,u_int32_t,(t),(h),(o),(v)) 625#define bus_space_write_8(t, h, o, v) __pbs_ws(8,u_int64_t,(t),(h),(o),(v)) 626 627 628/* 629 * Bus write multiple operations. 630 */ 631#define bus_space_write_multi_1(t, h, o, a, c) \ 632 __pbs_nonsingle(wm,1,u_int8_t,(t),(h),(o),(a),(c)) 633#define bus_space_write_multi_2(t, h, o, a, c) \ 634 __pbs_nonsingle(wm,2,u_int16_t,(t),(h),(o),(a),(c)) 635#define bus_space_write_multi_4(t, h, o, a, c) \ 636 __pbs_nonsingle(wm,4,u_int32_t,(t),(h),(o),(a),(c)) 637#define bus_space_write_multi_8(t, h, o, a, c) \ 638 __pbs_nonsingle(wm,8,u_int64_t,(t),(h),(o),(a),(c)) 639 640 641/* 642 * Bus write region operations. 643 */ 644#define bus_space_write_region_1(t, h, o, a, c) \ 645 __pbs_nonsingle(wr,1,u_int8_t,(t),(h),(o),(a),(c)) 646#define bus_space_write_region_2(t, h, o, a, c) \ 647 __pbs_nonsingle(wr,2,u_int16_t,(t),(h),(o),(a),(c)) 648#define bus_space_write_region_4(t, h, o, a, c) \ 649 __pbs_nonsingle(wr,4,u_int32_t,(t),(h),(o),(a),(c)) 650#define bus_space_write_region_8(t, h, o, a, c) \ 651 __pbs_nonsingle(wr,8,u_int64_t,(t),(h),(o),(a),(c)) 652 653 654/* 655 * Set multiple operations. 656 */ 657#define bus_space_set_multi_1(t, h, o, v, c) \ 658 __pbs_set(sm,1,u_int8_t,(t),(h),(o),(v),(c)) 659#define bus_space_set_multi_2(t, h, o, v, c) \ 660 __pbs_set(sm,2,u_int16_t,(t),(h),(o),(v),(c)) 661#define bus_space_set_multi_4(t, h, o, v, c) \ 662 __pbs_set(sm,4,u_int32_t,(t),(h),(o),(v),(c)) 663#define bus_space_set_multi_8(t, h, o, v, c) \ 664 __pbs_set(sm,8,u_int64_t,(t),(h),(o),(v),(c)) 665 666 667/* 668 * Set region operations. 669 */ 670#define bus_space_set_region_1(t, h, o, v, c) \ 671 __pbs_set(sr,1,u_int8_t,(t),(h),(o),(v),(c)) 672#define bus_space_set_region_2(t, h, o, v, c) \ 673 __pbs_set(sr,2,u_int16_t,(t),(h),(o),(v),(c)) 674#define bus_space_set_region_4(t, h, o, v, c) \ 675 __pbs_set(sr,4,u_int32_t,(t),(h),(o),(v),(c)) 676#define bus_space_set_region_8(t, h, o, v, c) \ 677 __pbs_set(sr,8,u_int64_t,(t),(h),(o),(v),(c)) 678 679 680/* 681 * Copy region operations. 682 */ 683#define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \ 684 __pbs_copy(1, u_int8_t, (t), (h1), (o1), (h2), (o2), (c)) 685#define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \ 686 __pbs_copy(2, u_int16_t, (t), (h1), (o1), (h2), (o2), (c)) 687#define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \ 688 __pbs_copy(4, u_int32_t, (t), (h1), (o1), (h2), (o2), (c)) 689#define bus_space_copy_region_8(t, h1, o1, h2, o2, c) \ 690 __pbs_copy(8, u_int64_t, (t), (h1), (o1), (h2), (o2), (c)) 691 692/* 693 * Bus stream operations--defined in terms of non-stream counterparts 694 */ 695#define __BUS_SPACE_HAS_STREAM_METHODS 1 696#define bus_space_read_stream_1 bus_space_read_1 697#define bus_space_read_stream_2 bus_space_read_2 698#define bus_space_read_stream_4 bus_space_read_4 699#define bus_space_read_stream_8 bus_space_read_8 700#define bus_space_read_multi_stream_1 bus_space_read_multi_1 701#define bus_space_read_multi_stream_2 bus_space_read_multi_2 702#define bus_space_read_multi_stream_4 bus_space_read_multi_4 703#define bus_space_read_multi_stream_8 bus_space_read_multi_8 704#define bus_space_read_region_stream_1 bus_space_read_region_1 705#define bus_space_read_region_stream_2 bus_space_read_region_2 706#define bus_space_read_region_stream_4 bus_space_read_region_4 707#define bus_space_read_region_stream_8 bus_space_read_region_8 708#define bus_space_write_stream_1 bus_space_write_1 709#define bus_space_write_stream_2 bus_space_write_2 710#define bus_space_write_stream_4 bus_space_write_4 711#define bus_space_write_stream_8 bus_space_write_8 712#define bus_space_write_multi_stream_1 bus_space_write_multi_1 713#define bus_space_write_multi_stream_2 bus_space_write_multi_2 714#define bus_space_write_multi_stream_4 bus_space_write_multi_4 715#define bus_space_write_multi_stream_8 bus_space_write_multi_8 716#define bus_space_write_region_stream_1 bus_space_write_region_1 717#define bus_space_write_region_stream_2 bus_space_write_region_2 718#define bus_space_write_region_stream_4 bus_space_write_region_4 719#define bus_space_write_region_stream_8 bus_space_write_region_8 720 721#endif /* _KERNEL */ 722 723/* 724 * Flags used in various bus DMA methods. 725 */ 726#define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */ 727#define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */ 728#define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */ 729#define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */ 730#define BUS_DMA_STREAMING 0x008 /* hint: sequential, unidirectional */ 731#define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */ 732#define BUS_DMA_BUS2 0x020 733#define BUS_DMA_BUS3 0x040 734#define BUS_DMA_BUS4 0x080 735#define BUS_DMA_READ 0x100 /* mapping is device -> memory only */ 736#define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */ 737#define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */ 738 739#define PLAYSTATION2_DMAMAP_COHERENT 0x10000 /* no cache flush necessary on sync */ 740 741/* Forwards needed by prototypes below. */ 742struct mbuf; 743struct uio; 744 745/* 746 * Operations performed by bus_dmamap_sync(). 747 */ 748#define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */ 749#define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */ 750#define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */ 751#define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */ 752 753typedef struct playstation2_bus_dma_tag *bus_dma_tag_t; 754typedef struct playstation2_bus_dmamap *bus_dmamap_t; 755 756#define BUS_DMA_TAG_VALID(t) ((t) != (bus_dma_tag_t)0) 757 758/* 759 * bus_dma_segment_t 760 * 761 * Describes a single contiguous DMA transaction. Values 762 * are suitable for programming into DMA registers. 763 */ 764struct playstation2_bus_dma_segment { 765 bus_addr_t ds_addr; /* DMA address */ 766 bus_size_t ds_len; /* length of transfer */ 767 bus_addr_t _ds_vaddr; /* virtual address, 0 if invalid */ 768}; 769typedef struct playstation2_bus_dma_segment bus_dma_segment_t; 770 771/* 772 * bus_dma_tag_t 773 * 774 * A machine-dependent opaque type describing the implementation of 775 * DMA for a given bus. 776 */ 777 778struct playstation2_bus_dma_tag { 779 /* 780 * DMA mapping methods. 781 */ 782 int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, 783 bus_size_t, bus_size_t, int, bus_dmamap_t *); 784 void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t); 785 int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, 786 bus_size_t, struct proc *, int); 787 int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, 788 struct mbuf *, int); 789 int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, 790 struct uio *, int); 791 int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t, 792 bus_dma_segment_t *, int, bus_size_t, int); 793 void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t); 794 void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, 795 bus_addr_t, bus_size_t, int); 796 797 /* 798 * DMA memory utility functions. 799 */ 800 int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t, 801 bus_size_t, bus_dma_segment_t *, int, int *, int); 802 void (*_dmamem_free)(bus_dma_tag_t, 803 bus_dma_segment_t *, int); 804 int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, 805 int, size_t, void **, int); 806 void (*_dmamem_unmap)(bus_dma_tag_t, void *, size_t); 807 paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, 808 int, off_t, int, int); 809 810 /* 811 * DMA controller private. 812 */ 813 void *_dmachip_cookie; 814}; 815 816#define bus_dmamap_create(t, s, n, m, b, f, p) \ 817 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p)) 818#define bus_dmamap_destroy(t, p) \ 819 (*(t)->_dmamap_destroy)((t), (p)) 820#define bus_dmamap_load(t, m, b, s, p, f) \ 821 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f)) 822#define bus_dmamap_load_mbuf(t, m, b, f) \ 823 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f)) 824#define bus_dmamap_load_uio(t, m, u, f) \ 825 (*(t)->_dmamap_load_uio)((t), (m), (u), (f)) 826#define bus_dmamap_load_raw(t, m, sg, n, s, f) \ 827 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f)) 828#define bus_dmamap_unload(t, p) \ 829 (*(t)->_dmamap_unload)((t), (p)) 830#define bus_dmamap_sync(t, p, o, l, ops) \ 831 (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) 832 833#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \ 834 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f)) 835#define bus_dmamem_free(t, sg, n) \ 836 (*(t)->_dmamem_free)((t), (sg), (n)) 837#define bus_dmamem_map(t, sg, n, s, k, f) \ 838 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f)) 839#define bus_dmamem_unmap(t, k, s) \ 840 (*(t)->_dmamem_unmap)((t), (k), (s)) 841#define bus_dmamem_mmap(t, sg, n, o, p, f) \ 842 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f)) 843 844#define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP 845#define bus_dmatag_destroy(t) 846 847/* 848 * bus_dmamap_t 849 * 850 * Describes a DMA mapping. 851 */ 852struct playstation2_bus_dmamap { 853 /* 854 * PRIVATE MEMBERS: not for use my machine-independent code. 855 */ 856 bus_size_t _dm_size; /* largest DMA transfer mappable */ 857 int _dm_segcnt; /* number of segs this map can map */ 858 bus_size_t _dm_maxmaxsegsz; /* fixed largest possible segment */ 859 bus_size_t _dm_boundary; /* don't cross this */ 860 int _dm_flags; /* misc. flags */ 861 862 /* 863 * PUBLIC MEMBERS: these are used by machine-independent code. 864 */ 865 bus_size_t dm_maxsegsz; /* largest possible segment */ 866 bus_size_t dm_mapsize; /* size of the mapping */ 867 int dm_nsegs; /* # valid segments in mapping */ 868 bus_dma_segment_t dm_segs[1]; /* segments; variable length */ 869}; 870 871#ifdef _PLAYSTATION2_BUS_DMA_PRIVATE 872int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t, 873 bus_size_t, int, bus_dmamap_t *); 874void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t); 875int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, 876 bus_size_t, struct proc *, int); 877int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, 878 struct mbuf *, int); 879int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, 880 struct uio *, int); 881int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, 882 bus_dma_segment_t *, int, bus_size_t, int); 883void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t); 884void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 885 bus_size_t, int); 886 887int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size, 888 bus_size_t alignment, bus_size_t boundary, 889 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags); 890void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs, 891 int nsegs); 892int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs, 893 int nsegs, size_t size, void **kvap, int flags); 894void _bus_dmamem_unmap(bus_dma_tag_t tag, void *kva, 895 size_t size); 896paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs, 897 int nsegs, off_t off, int prot, int flags); 898 899int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size, 900 bus_size_t alignment, bus_size_t boundary, 901 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags, 902 vaddr_t low, vaddr_t high); 903 904extern struct playstation2_bus_dma_tag playstation2_default_bus_dma_tag; 905#endif /* _PLAYSTATION2_BUS_DMA_PRIVATE */ 906 907#endif /* _PLAYSTATION2_BUS_H_ */ 908