1 /* $NetBSD: sifbios.c,v 1.2 2001/10/19 05:47:41 shin Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * PlayStation 2 SIF BIOS Version 2.0 interface. 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 46 #include <playstation2/playstation2/sifbios.h> 47 #include <playstation2/playstation2/interrupt.h> 48 49 #ifdef DEBUG 50 #define STATIC 51 #else 52 #define STATIC static 53 #endif 54 55 #define SIFBIOS_ENTRY_PTR MIPS_PHYS_TO_KSEG0(0x00001000) 56 #define SIFBIOS_SIGNATURE_PTR MIPS_PHYS_TO_KSEG1(0x00001004) 57 #define SIFBIOS_SIGNATURE (('P' << 0)|('S' << 8)|('2' << 16)|('b' << 24)) 58 59 STATIC int (*__sifbios_call)(int, void *); 60 #define CALL(t, n, a) ((t)(*__sifbios_call)((n), (void *)(a))) 61 62 STATIC void sifbios_rpc_callback(void *, int); 63 STATIC int sifbios_rpc_call(int, void *, int *); 64 65 void 66 sifbios_init() 67 { 68 /* check BIOS exits */ 69 if (*(u_int32_t *)SIFBIOS_SIGNATURE_PTR != SIFBIOS_SIGNATURE) 70 panic("SIFBIOS not found"); 71 72 __sifbios_call = *((int (**)(int, void*))SIFBIOS_ENTRY_PTR); 73 } 74 75 int 76 sifbios_rpc_call(int callno, void *arg, int *result) 77 { 78 __volatile__ int done = 0; 79 int retry; 80 struct { 81 int result; 82 void *arg; 83 void (*callback)(void *, int); 84 void *callback_arg; 85 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 86 arg: arg, 87 callback: sifbios_rpc_callback, 88 callback_arg: (void *)&done, 89 }; 90 91 /* call SIF BIOS */ 92 retry = 100; 93 while (CALL(int, callno, &sifbios_arg) != 0 && --retry > 0) 94 delay(20000); /* .02 sec. for slow IOP */ 95 96 if (retry == 0) { 97 printf("SIF BIOS call %d failed\n", callno); 98 goto error; 99 } 100 101 /* wait IOP response (1 sec.) */ 102 _sif_call_start(); 103 retry = 10000; 104 while (!done && --retry > 0) 105 delay(100); 106 _sif_call_end(); 107 108 if (retry == 0) { 109 printf("IOP not respond (callno = %d)\n", callno); 110 goto error; 111 } 112 113 *result = sifbios_arg.result; 114 115 return (0); 116 117 error: 118 return (-1); 119 } 120 121 void 122 sifbios_rpc_callback(void *arg, int result) 123 { 124 int *done = (int *)arg; 125 126 *done = 1; 127 } 128 129 /* 130 * System misc. 131 */ 132 int 133 sifbios_getver() 134 { 135 136 return CALL(int, 0, 0); 137 } 138 139 void 140 sifbios_halt(int mode) 141 { 142 int sifbios_arg = mode; 143 144 CALL(void, 1, &sifbios_arg); 145 } 146 147 void 148 sifbios_setdve(int mode) 149 { 150 int sifbios_arg = mode; 151 152 CALL(void, 2, &sifbios_arg); 153 } 154 155 void 156 sifbios_putchar(int c) 157 { 158 int sifbios_arg = c; 159 160 CALL(void, 3, &sifbios_arg); 161 } 162 163 int 164 sifbios_getchar() 165 { 166 167 return CALL(int, 4, 0); 168 } 169 170 /* 171 * SIF DMA 172 */ 173 int 174 sifdma_init() 175 { 176 177 return CALL(int, 16, 0); 178 } 179 180 void 181 sifdma_exit() 182 { 183 184 CALL(void, 17, 0); 185 } 186 187 /* queue DMA request to SIFBIOS. returns queue identifier. */ 188 sifdma_id_t 189 sifdma_queue(struct sifdma_transfer *arg, int n) 190 { 191 struct { 192 void *arg; /* pointer to sifdma_transfer array */ 193 int n; /* # of elements */ 194 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 195 arg: arg, 196 n: n 197 }; 198 199 return CALL(sifdma_id_t, 18, &sifbios_arg); 200 } 201 202 /* 203 * status of DMA 204 * >0 ... queued. not kicked. 205 * 0 ... DMA executing. 206 * <0 ... DMA done. 207 */ 208 int 209 sifdma_stat(sifdma_id_t id) 210 { 211 u_int32_t sifbios_arg = id; 212 213 return CALL(int, 19, &sifbios_arg); 214 } 215 216 /* reset DMA channel */ 217 void 218 sifdma_reset() 219 { 220 221 CALL(void, 20, 0); 222 } 223 224 /* 225 * SIF CMD 226 */ 227 int 228 sifcmd_init() 229 { 230 231 return CALL(int, 32, 0); 232 } 233 234 void 235 sifcmd_exit() 236 { 237 238 CALL(void, 33, 0); 239 } 240 241 sifdma_id_t 242 sifcmd_queue(sifcmd_sw_t sw, vaddr_t cmd_pkt_addr, size_t cmd_pkt_sz, 243 vaddr_t src_addr, vaddr_t dst_addr, vsize_t buf_sz) 244 { 245 struct { 246 sifcmd_sw_t sw; 247 vaddr_t cmd_pkt_addr; /* command buffer */ 248 size_t cmd_pkt_sz; 249 vaddr_t src_addr; /* data buffer */ 250 vaddr_t dst_addr; 251 vsize_t buf_sz; 252 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 253 sw: sw, 254 cmd_pkt_addr: cmd_pkt_addr, 255 cmd_pkt_sz: cmd_pkt_sz, 256 src_addr: src_addr, 257 dst_addr: dst_addr, 258 buf_sz: buf_sz, 259 }; 260 261 return CALL(sifdma_id_t, 34, &sifbios_arg); 262 } 263 264 /* interrupt handler of DMAC channel 5 (SIF0) */ 265 int 266 sifcmd_intr(void *arg) 267 { 268 269 CALL(void, 35, 0); 270 271 return (1); 272 } 273 274 void 275 sifcmd_establish(sifcmd_sw_t sw, struct sifcmd_callback_holder *holder) 276 { 277 struct { 278 sifcmd_sw_t sw; 279 sifcmd_callback_t func; 280 void *arg; 281 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 282 sw: sw, 283 func: holder->func, 284 arg: holder->arg, 285 }; 286 287 CALL(void, 36, &sifbios_arg); 288 } 289 290 void 291 sifcmd_disestablish(sifcmd_sw_t sw) 292 { 293 u_int32_t sifbios_arg = sw; 294 295 CALL(void, 37, &sifbios_arg); 296 } 297 298 struct sifcmd_callback_holder * 299 sifcmd_handler_init(struct sifcmd_callback_holder *holder, int n) 300 { 301 struct { 302 void *holder; 303 int n; /* # of slot */ 304 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 305 holder: holder, 306 n: n, 307 }; 308 309 /* returns old holder */ 310 return CALL(struct sifcmd_callback_holder *, 38, &sifbios_arg); 311 } 312 313 /* 314 * SIF RPC 315 */ 316 int 317 sifrpc_init() 318 { 319 320 return CALL(int, 48, 0); 321 } 322 323 void 324 sifrpc_exit() 325 { 326 327 CALL(void, 49, 0); 328 } 329 330 int 331 sifrpc_receive_buffer(struct sifrpc_receive *_cookie, void *src_iop, 332 void *dst_ee, size_t sz, u_int32_t rpc_mode, void (*end_func)(void *), 333 void *end_arg) 334 { 335 struct { 336 void *_cookie; 337 void *src_iop; 338 void *dst_ee; 339 size_t sz; 340 u_int32_t rpc_mode; 341 sifrpc_endfunc_t end_func; 342 void *end_arg; 343 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 344 _cookie: _cookie, 345 src_iop: src_iop, 346 dst_ee: dst_ee, 347 sz: sz, 348 rpc_mode: rpc_mode, 349 end_func: end_func, 350 end_arg: end_arg, 351 }; 352 353 return CALL(int, 50, &sifbios_arg); 354 } 355 356 int 357 sifrpc_bind(struct sifrpc_client *_cookie, sifrpc_id_t rpc_id, 358 u_int32_t rpc_mode, void (*end_func)(void *), void *end_arg) 359 { 360 struct { 361 void *_cookie; /* filled by this call */ 362 sifrpc_id_t rpc_id; /* specify server RPC id */ 363 u_int32_t rpc_mode; 364 sifrpc_endfunc_t end_func; 365 void *end_arg; 366 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 367 _cookie: _cookie, 368 rpc_id: rpc_id, 369 rpc_mode: rpc_mode, 370 end_func: end_func, 371 end_arg: end_arg, 372 }; 373 374 return CALL(int, 51, &sifbios_arg); 375 } 376 377 int 378 sifrpc_call(struct sifrpc_client *_cookie, sifrpc_callno_t call_no, 379 u_int32_t rpc_mode, void *sendbuf, size_t sendbuf_sz, void *recvbuf, 380 size_t recvbuf_sz, void (*end_func)(void *), void *end_arg) 381 { 382 struct { 383 struct sifrpc_client *_cookie; /* binded client cookie */ 384 sifrpc_callno_t call_no; /* passed to service function arg. */ 385 u_int32_t rpc_mode; 386 void *sendbuf; 387 size_t sendbuf_sz; 388 void *recvbuf; 389 size_t recvbuf_sz; 390 sifrpc_endfunc_t end_func; 391 void *end_arg; 392 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 393 _cookie: _cookie, 394 call_no: call_no, 395 rpc_mode: rpc_mode, 396 sendbuf: sendbuf, 397 sendbuf_sz: sendbuf_sz, 398 recvbuf: recvbuf, 399 recvbuf_sz: recvbuf_sz, 400 end_func: end_func, 401 end_arg: end_arg, 402 }; 403 404 return CALL(int, 52, &sifbios_arg); 405 } 406 407 int 408 sifrpc_stat(struct sifrpc_header *_cookie) 409 { 410 void *sifbios_arg = _cookie; 411 412 return CALL(int, 53, &sifbios_arg); 413 } 414 415 void 416 sifrpc_establish(struct sifrpc_server_system *queue, void (*end_func)(void *), 417 void *end_arg) 418 { 419 struct { 420 struct sifrpc_server_system *queue; 421 sifrpc_endfunc_t end_func; 422 void *end_arg; 423 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 424 queue: queue, 425 end_func: end_func, 426 end_arg: end_arg, 427 }; 428 429 CALL(void, 54, &sifbios_arg); 430 } 431 432 void 433 sifrpc_register_service(struct sifrpc_server_system *queue, 434 struct sifrpc_server *server, sifrpc_id_t rpc_id, 435 void *(*service_func)(sifrpc_callno_t, void *, size_t), void *service_arg, 436 void *(*cancel_func)(sifrpc_callno_t, void *, size_t), void *cancel_arg) 437 { 438 struct { 439 void *server; 440 sifrpc_id_t rpc_id; 441 sifrpc_rpcfunc_t service_func; 442 void *service_arg; 443 sifrpc_rpcfunc_t cancel_func; 444 void *cancel_arg; 445 void *receive_queue; 446 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 447 server: server, 448 rpc_id: rpc_id, 449 service_func: service_func, 450 service_arg: service_arg, 451 cancel_func: cancel_func, 452 cancel_arg: cancel_arg, 453 receive_queue: queue, 454 }; 455 456 CALL(void, 55, &sifbios_arg); 457 } 458 459 void 460 sifrpc_unregister_service(struct sifrpc_server_system *queue, 461 struct sifrpc_server *server) 462 { 463 struct { 464 void *server; 465 void *receive_queue; 466 } __attribute__((__packed__, __aligned__(4))) sifbios_arg = { 467 server: server, 468 receive_queue: queue, 469 }; 470 471 CALL(void, 56, &sifbios_arg); 472 } 473 474 void 475 sifrpc_disestablish(struct sifrpc_server_system *queue) 476 { 477 void *sifbios_arg = queue; 478 479 CALL(void, 57, &sifbios_arg); 480 } 481 482 struct sifrpc_server * 483 sifrpc_dequeue(struct sifrpc_server_system *queue) 484 { 485 void *sifbios_arg = queue; 486 487 return CALL(struct sifrpc_server *, 58, &sifbios_arg); 488 } 489 490 void 491 sifrpc_dispatch_service(struct sifrpc_server *server) 492 { 493 void *sifbios_arg = server; 494 495 CALL(void, 59, &sifbios_arg); 496 } 497 498 /* 499 * IOP memory 500 */ 501 int 502 iopmem_init() 503 { 504 int result; 505 506 sifbios_rpc_call(64, 0, &result); 507 508 return (0); 509 } 510 511 paddr_t 512 iopmem_alloc(psize_t sz) 513 { 514 int result, sifbios_arg = sz; 515 516 if (sifbios_rpc_call(65, (void *)&sifbios_arg, &result) < 0) 517 return NULL; 518 /* returns allocated IOP physical addr */ 519 return (paddr_t)result; 520 } 521 522 int 523 iopmem_free(paddr_t addr) 524 { 525 int result, sifbios_arg = addr; 526 527 sifbios_rpc_call(66, (void *)&sifbios_arg, &result); 528 529 return (result); 530 } 531