1 /** 2 * Copyright (c) 2010-2012 Broadcom. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions, and the following disclaimer, 9 * without modification. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The names of the above-listed copyright holders may not be used 14 * to endorse or promote products derived from this software without 15 * specific prior written permission. 16 * 17 * ALTERNATIVELY, this software may be distributed under the terms of the 18 * GNU General Public License ("GPL") version 2, as published by the Free 19 * Software Foundation. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <interface/compat/vchi_bsd.h> 35 36 #include "interface/vchi/vchi.h" 37 #include "vchiq.h" 38 #include "vchiq_core.h" 39 40 #include "vchiq_util.h" 41 42 #define vchiq_status_to_vchi(status) ((int32_t)status) 43 44 typedef struct { 45 VCHIQ_SERVICE_HANDLE_T handle; 46 47 VCHIU_QUEUE_T queue; 48 49 VCHI_CALLBACK_T callback; 50 void *callback_param; 51 } SHIM_SERVICE_T; 52 53 /* ---------------------------------------------------------------------- 54 * return pointer to the mphi message driver function table 55 * -------------------------------------------------------------------- */ 56 const VCHI_MESSAGE_DRIVER_T * 57 vchi_mphi_message_driver_func_table(void) 58 { 59 return NULL; 60 } 61 62 /* ---------------------------------------------------------------------- 63 * return a pointer to the 'single' connection driver fops 64 * -------------------------------------------------------------------- */ 65 const VCHI_CONNECTION_API_T * 66 single_get_func_table(void) 67 { 68 return NULL; 69 } 70 71 VCHI_CONNECTION_T *vchi_create_connection( 72 const VCHI_CONNECTION_API_T *function_table, 73 const VCHI_MESSAGE_DRIVER_T *low_level) 74 { 75 (void)function_table; 76 (void)low_level; 77 return NULL; 78 } 79 80 /*********************************************************** 81 * Name: vchi_msg_peek 82 * 83 * Arguments: const VCHI_SERVICE_HANDLE_T handle, 84 * void **data, 85 * uint32_t *msg_size, 86 87 88 * VCHI_FLAGS_T flags 89 * 90 * Description: Routine to return a pointer to the current message (to allow in 91 * place processing). The message can be removed using 92 * vchi_msg_remove when you're finished 93 * 94 * Returns: int32_t - success == 0 95 * 96 ***********************************************************/ 97 int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle, 98 void **data, 99 uint32_t *msg_size, 100 VCHI_FLAGS_T flags) 101 { 102 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 103 VCHIQ_HEADER_T *header; 104 105 WARN_ON((flags != VCHI_FLAGS_NONE) && 106 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); 107 108 if (flags == VCHI_FLAGS_NONE) 109 if (vchiu_queue_is_empty(&service->queue)) 110 return -1; 111 112 header = vchiu_queue_peek(&service->queue); 113 114 *data = header->data; 115 *msg_size = header->size; 116 117 return 0; 118 } 119 EXPORT_SYMBOL(vchi_msg_peek); 120 121 /*********************************************************** 122 * Name: vchi_msg_remove 123 * 124 * Arguments: const VCHI_SERVICE_HANDLE_T handle, 125 * 126 * Description: Routine to remove a message (after it has been read with 127 * vchi_msg_peek) 128 * 129 * Returns: int32_t - success == 0 130 * 131 ***********************************************************/ 132 int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle) 133 { 134 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 135 VCHIQ_HEADER_T *header; 136 137 header = vchiu_queue_pop(&service->queue); 138 139 vchiq_release_message(service->handle, header); 140 141 return 0; 142 } 143 EXPORT_SYMBOL(vchi_msg_remove); 144 145 /*********************************************************** 146 * Name: vchi_msg_queue 147 * 148 * Arguments: VCHI_SERVICE_HANDLE_T handle, 149 * const void *data, 150 * uint32_t data_size, 151 * VCHI_FLAGS_T flags, 152 * void *msg_handle, 153 * 154 * Description: Thin wrapper to queue a message onto a connection 155 * 156 * Returns: int32_t - success == 0 157 * 158 ***********************************************************/ 159 int32_t vchi_msg_queue(VCHI_SERVICE_HANDLE_T handle, 160 const void *data, 161 uint32_t data_size, 162 VCHI_FLAGS_T flags, 163 void *msg_handle) 164 { 165 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 166 VCHIQ_ELEMENT_T element = {data, data_size}; 167 VCHIQ_STATUS_T status; 168 169 (void)msg_handle; 170 171 WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); 172 173 status = vchiq_queue_message(service->handle, &element, 1); 174 175 /* vchiq_queue_message() may return VCHIQ_RETRY, so we need to 176 ** implement a retry mechanism since this function is supposed 177 ** to block until queued 178 */ 179 while (status == VCHIQ_RETRY) { 180 msleep(1); 181 status = vchiq_queue_message(service->handle, &element, 1); 182 } 183 184 return vchiq_status_to_vchi(status); 185 } 186 EXPORT_SYMBOL(vchi_msg_queue); 187 188 /*********************************************************** 189 * Name: vchi_bulk_queue_receive 190 * 191 * Arguments: VCHI_BULK_HANDLE_T handle, 192 * void *data_dst, 193 * const uint32_t data_size, 194 * VCHI_FLAGS_T flags 195 * void *bulk_handle 196 * 197 * Description: Routine to setup a rcv buffer 198 * 199 * Returns: int32_t - success == 0 200 * 201 ***********************************************************/ 202 int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle, 203 void *data_dst, 204 uint32_t data_size, 205 VCHI_FLAGS_T flags, 206 void *bulk_handle) 207 { 208 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 209 VCHIQ_BULK_MODE_T mode; 210 VCHIQ_STATUS_T status; 211 212 switch ((int)flags) { 213 case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE 214 | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 215 WARN_ON(!service->callback); 216 mode = VCHIQ_BULK_MODE_CALLBACK; 217 break; 218 case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: 219 mode = VCHIQ_BULK_MODE_BLOCKING; 220 break; 221 case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 222 case VCHI_FLAGS_NONE: 223 mode = VCHIQ_BULK_MODE_NOCALLBACK; 224 break; 225 default: 226 WARN(1, "unsupported message\n"); 227 return vchiq_status_to_vchi(VCHIQ_ERROR); 228 } 229 230 status = vchiq_bulk_receive(service->handle, data_dst, data_size, 231 bulk_handle, mode); 232 233 /* vchiq_bulk_receive() may return VCHIQ_RETRY, so we need to 234 ** implement a retry mechanism since this function is supposed 235 ** to block until queued 236 */ 237 while (status == VCHIQ_RETRY) { 238 msleep(1); 239 status = vchiq_bulk_receive(service->handle, data_dst, 240 data_size, bulk_handle, mode); 241 } 242 243 return vchiq_status_to_vchi(status); 244 } 245 EXPORT_SYMBOL(vchi_bulk_queue_receive); 246 247 /*********************************************************** 248 * Name: vchi_bulk_queue_transmit 249 * 250 * Arguments: VCHI_BULK_HANDLE_T handle, 251 * void *data_src, 252 * uint32_t data_size, 253 * VCHI_FLAGS_T flags, 254 * void *bulk_handle 255 * 256 * Description: Routine to transmit some data 257 * 258 * Returns: int32_t - success == 0 259 * 260 ***********************************************************/ 261 int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle, 262 void *data_src, 263 uint32_t data_size, 264 VCHI_FLAGS_T flags, 265 void *bulk_handle) 266 { 267 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 268 VCHIQ_BULK_MODE_T mode; 269 VCHIQ_STATUS_T status; 270 271 switch ((int)flags) { 272 case VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE 273 | VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 274 WARN_ON(!service->callback); 275 mode = VCHIQ_BULK_MODE_CALLBACK; 276 break; 277 case VCHI_FLAGS_BLOCK_UNTIL_DATA_READ: 278 case VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE: 279 mode = VCHIQ_BULK_MODE_BLOCKING; 280 break; 281 case VCHI_FLAGS_BLOCK_UNTIL_QUEUED: 282 case VCHI_FLAGS_NONE: 283 mode = VCHIQ_BULK_MODE_NOCALLBACK; 284 break; 285 default: 286 WARN(1, "unsupported message\n"); 287 return vchiq_status_to_vchi(VCHIQ_ERROR); 288 } 289 290 status = vchiq_bulk_transmit(service->handle, data_src, data_size, 291 bulk_handle, mode); 292 293 /* vchiq_bulk_transmit() may return VCHIQ_RETRY, so we need to 294 ** implement a retry mechanism since this function is supposed 295 ** to block until queued 296 */ 297 while (status == VCHIQ_RETRY) { 298 msleep(1); 299 status = vchiq_bulk_transmit(service->handle, data_src, 300 data_size, bulk_handle, mode); 301 } 302 303 return vchiq_status_to_vchi(status); 304 } 305 EXPORT_SYMBOL(vchi_bulk_queue_transmit); 306 307 /*********************************************************** 308 * Name: vchi_msg_dequeue 309 * 310 * Arguments: VCHI_SERVICE_HANDLE_T handle, 311 * void *data, 312 * uint32_t max_data_size_to_read, 313 * uint32_t *actual_msg_size 314 * VCHI_FLAGS_T flags 315 * 316 * Description: Routine to dequeue a message into the supplied buffer 317 * 318 * Returns: int32_t - success == 0 319 * 320 ***********************************************************/ 321 int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle, 322 void *data, 323 uint32_t max_data_size_to_read, 324 uint32_t *actual_msg_size, 325 VCHI_FLAGS_T flags) 326 { 327 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 328 VCHIQ_HEADER_T *header; 329 330 WARN_ON((flags != VCHI_FLAGS_NONE) && 331 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); 332 333 if (flags == VCHI_FLAGS_NONE) 334 if (vchiu_queue_is_empty(&service->queue)) 335 return -1; 336 337 header = vchiu_queue_pop(&service->queue); 338 339 memcpy(data, header->data, header->size < max_data_size_to_read ? 340 header->size : max_data_size_to_read); 341 342 *actual_msg_size = header->size; 343 344 vchiq_release_message(service->handle, header); 345 346 return 0; 347 } 348 EXPORT_SYMBOL(vchi_msg_dequeue); 349 350 /*********************************************************** 351 * Name: vchi_msg_queuev 352 * 353 * Arguments: VCHI_SERVICE_HANDLE_T handle, 354 * VCHI_MSG_VECTOR_T *vector, 355 * uint32_t count, 356 * VCHI_FLAGS_T flags, 357 * void *msg_handle 358 * 359 * Description: Thin wrapper to queue a message onto a connection 360 * 361 * Returns: int32_t - success == 0 362 * 363 ***********************************************************/ 364 365 vchiq_static_assert(sizeof(VCHI_MSG_VECTOR_T) == sizeof(VCHIQ_ELEMENT_T)); 366 vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_base) == 367 offsetof(VCHIQ_ELEMENT_T, data)); 368 vchiq_static_assert(offsetof(VCHI_MSG_VECTOR_T, vec_len) == 369 offsetof(VCHIQ_ELEMENT_T, size)); 370 371 int32_t vchi_msg_queuev(VCHI_SERVICE_HANDLE_T handle, 372 VCHI_MSG_VECTOR_T *vector, 373 uint32_t count, 374 VCHI_FLAGS_T flags, 375 void *msg_handle) 376 { 377 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 378 379 (void)msg_handle; 380 381 WARN_ON(flags != VCHI_FLAGS_BLOCK_UNTIL_QUEUED); 382 383 return vchiq_status_to_vchi(vchiq_queue_message(service->handle, 384 (const VCHIQ_ELEMENT_T *)vector, count)); 385 } 386 EXPORT_SYMBOL(vchi_msg_queuev); 387 388 /*********************************************************** 389 * Name: vchi_held_msg_release 390 * 391 * Arguments: VCHI_HELD_MSG_T *message 392 * 393 * Description: Routine to release a held message (after it has been read with 394 * vchi_msg_hold) 395 * 396 * Returns: int32_t - success == 0 397 * 398 ***********************************************************/ 399 int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message) 400 { 401 vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)message->service, 402 (VCHIQ_HEADER_T *)message->message); 403 404 return 0; 405 } 406 EXPORT_SYMBOL(vchi_held_msg_release); 407 408 /*********************************************************** 409 * Name: vchi_msg_hold 410 * 411 * Arguments: VCHI_SERVICE_HANDLE_T handle, 412 * void **data, 413 * uint32_t *msg_size, 414 * VCHI_FLAGS_T flags, 415 * VCHI_HELD_MSG_T *message_handle 416 * 417 * Description: Routine to return a pointer to the current message (to allow 418 * in place processing). The message is dequeued - don't forget 419 * to release the message using vchi_held_msg_release when you're 420 * finished. 421 * 422 * Returns: int32_t - success == 0 423 * 424 ***********************************************************/ 425 int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle, 426 void **data, 427 uint32_t *msg_size, 428 VCHI_FLAGS_T flags, 429 VCHI_HELD_MSG_T *message_handle) 430 { 431 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 432 VCHIQ_HEADER_T *header; 433 434 WARN_ON((flags != VCHI_FLAGS_NONE) && 435 (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); 436 437 if (flags == VCHI_FLAGS_NONE) 438 if (vchiu_queue_is_empty(&service->queue)) 439 return -1; 440 441 header = vchiu_queue_pop(&service->queue); 442 443 *data = header->data; 444 *msg_size = header->size; 445 446 message_handle->service = 447 (struct opaque_vchi_service_t *)service->handle; 448 message_handle->message = header; 449 450 return 0; 451 } 452 EXPORT_SYMBOL(vchi_msg_hold); 453 454 /*********************************************************** 455 * Name: vchi_initialise 456 * 457 * Arguments: VCHI_INSTANCE_T *instance_handle 458 * 459 * Description: Initialises the hardware but does not transmit anything 460 * When run as a Host App this will be called twice hence the need 461 * to malloc the state information 462 * 463 * Returns: 0 if successful, failure otherwise 464 * 465 ***********************************************************/ 466 467 int32_t vchi_initialise(VCHI_INSTANCE_T *instance_handle) 468 { 469 VCHIQ_INSTANCE_T instance; 470 VCHIQ_STATUS_T status; 471 472 status = vchiq_initialise(&instance); 473 474 *instance_handle = (VCHI_INSTANCE_T)instance; 475 476 return vchiq_status_to_vchi(status); 477 } 478 EXPORT_SYMBOL(vchi_initialise); 479 480 /*********************************************************** 481 * Name: vchi_connect 482 * 483 * Arguments: VCHI_CONNECTION_T **connections 484 * const uint32_t num_connections 485 * VCHI_INSTANCE_T instance_handle) 486 * 487 * Description: Starts the command service on each connection, 488 * causing INIT messages to be pinged back and forth 489 * 490 * Returns: 0 if successful, failure otherwise 491 * 492 ***********************************************************/ 493 int32_t vchi_connect(VCHI_CONNECTION_T **connections, 494 const uint32_t num_connections, 495 VCHI_INSTANCE_T instance_handle) 496 { 497 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 498 499 (void)connections; 500 (void)num_connections; 501 502 return vchiq_connect(instance); 503 } 504 EXPORT_SYMBOL(vchi_connect); 505 506 507 /*********************************************************** 508 * Name: vchi_disconnect 509 * 510 * Arguments: VCHI_INSTANCE_T instance_handle 511 * 512 * Description: Stops the command service on each connection, 513 * causing DE-INIT messages to be pinged back and forth 514 * 515 * Returns: 0 if successful, failure otherwise 516 * 517 ***********************************************************/ 518 int32_t vchi_disconnect(VCHI_INSTANCE_T instance_handle) 519 { 520 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 521 return vchiq_status_to_vchi(vchiq_shutdown(instance)); 522 } 523 EXPORT_SYMBOL(vchi_disconnect); 524 525 526 /*********************************************************** 527 * Name: vchi_service_open 528 * Name: vchi_service_create 529 * 530 * Arguments: VCHI_INSTANCE_T *instance_handle 531 * SERVICE_CREATION_T *setup, 532 * VCHI_SERVICE_HANDLE_T *handle 533 * 534 * Description: Routine to open a service 535 * 536 * Returns: int32_t - success == 0 537 * 538 ***********************************************************/ 539 540 static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason, 541 VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user) 542 { 543 SHIM_SERVICE_T *service = 544 (SHIM_SERVICE_T *)VCHIQ_GET_SERVICE_USERDATA(handle); 545 546 if (!service->callback) 547 goto release; 548 549 switch (reason) { 550 case VCHIQ_MESSAGE_AVAILABLE: 551 vchiu_queue_push(&service->queue, header); 552 553 service->callback(service->callback_param, 554 VCHI_CALLBACK_MSG_AVAILABLE, NULL); 555 556 goto done; 557 break; 558 559 case VCHIQ_BULK_TRANSMIT_DONE: 560 service->callback(service->callback_param, 561 VCHI_CALLBACK_BULK_SENT, bulk_user); 562 break; 563 564 case VCHIQ_BULK_RECEIVE_DONE: 565 service->callback(service->callback_param, 566 VCHI_CALLBACK_BULK_RECEIVED, bulk_user); 567 break; 568 569 case VCHIQ_SERVICE_CLOSED: 570 service->callback(service->callback_param, 571 VCHI_CALLBACK_SERVICE_CLOSED, NULL); 572 break; 573 574 case VCHIQ_SERVICE_OPENED: 575 /* No equivalent VCHI reason */ 576 break; 577 578 case VCHIQ_BULK_TRANSMIT_ABORTED: 579 service->callback(service->callback_param, 580 VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, 581 bulk_user); 582 break; 583 584 case VCHIQ_BULK_RECEIVE_ABORTED: 585 service->callback(service->callback_param, 586 VCHI_CALLBACK_BULK_RECEIVE_ABORTED, 587 bulk_user); 588 break; 589 590 default: 591 WARN(1, "not supported\n"); 592 break; 593 } 594 595 release: 596 vchiq_release_message(service->handle, header); 597 done: 598 return VCHIQ_SUCCESS; 599 } 600 601 static SHIM_SERVICE_T *service_alloc(VCHIQ_INSTANCE_T instance, 602 SERVICE_CREATION_T *setup) 603 { 604 SHIM_SERVICE_T *service = kzalloc(sizeof(SHIM_SERVICE_T), GFP_KERNEL); 605 606 (void)instance; 607 608 if (service) { 609 if (vchiu_queue_init(&service->queue, 64)) { 610 service->callback = setup->callback; 611 service->callback_param = setup->callback_param; 612 } else { 613 kfree(service); 614 service = NULL; 615 } 616 } 617 618 return service; 619 } 620 621 static void service_free(SHIM_SERVICE_T *service) 622 { 623 if (service) { 624 vchiu_queue_delete(&service->queue); 625 kfree(service); 626 } 627 } 628 629 int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, 630 SERVICE_CREATION_T *setup, 631 VCHI_SERVICE_HANDLE_T *handle) 632 { 633 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 634 SHIM_SERVICE_T *service = service_alloc(instance, setup); 635 636 *handle = (VCHI_SERVICE_HANDLE_T)service; 637 638 if (service) { 639 VCHIQ_SERVICE_PARAMS_T params; 640 VCHIQ_STATUS_T status; 641 642 memset(¶ms, 0, sizeof(params)); 643 params.fourcc = setup->service_id; 644 params.callback = shim_callback; 645 params.userdata = service; 646 params.version = setup->version.version; 647 params.version_min = setup->version.version_min; 648 649 status = vchiq_open_service(instance, ¶ms, 650 &service->handle); 651 if (status != VCHIQ_SUCCESS) { 652 service_free(service); 653 service = NULL; 654 *handle = NULL; 655 } 656 } 657 658 return (service != NULL) ? 0 : -1; 659 } 660 EXPORT_SYMBOL(vchi_service_open); 661 662 int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle, 663 SERVICE_CREATION_T *setup, 664 VCHI_SERVICE_HANDLE_T *handle) 665 { 666 VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; 667 SHIM_SERVICE_T *service = service_alloc(instance, setup); 668 669 *handle = (VCHI_SERVICE_HANDLE_T)service; 670 671 if (service) { 672 VCHIQ_SERVICE_PARAMS_T params; 673 VCHIQ_STATUS_T status; 674 675 memset(¶ms, 0, sizeof(params)); 676 params.fourcc = setup->service_id; 677 params.callback = shim_callback; 678 params.userdata = service; 679 params.version = setup->version.version; 680 params.version_min = setup->version.version_min; 681 status = vchiq_add_service(instance, ¶ms, &service->handle); 682 683 if (status != VCHIQ_SUCCESS) { 684 service_free(service); 685 service = NULL; 686 *handle = NULL; 687 } 688 } 689 690 return (service != NULL) ? 0 : -1; 691 } 692 EXPORT_SYMBOL(vchi_service_create); 693 694 int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle) 695 { 696 int32_t ret = -1; 697 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 698 if (service) { 699 VCHIQ_STATUS_T status = vchiq_close_service(service->handle); 700 if (status == VCHIQ_SUCCESS) { 701 service_free(service); 702 service = NULL; 703 } 704 705 ret = vchiq_status_to_vchi(status); 706 } 707 return ret; 708 } 709 EXPORT_SYMBOL(vchi_service_close); 710 711 int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle) 712 { 713 int32_t ret = -1; 714 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 715 if (service) { 716 VCHIQ_STATUS_T status = vchiq_remove_service(service->handle); 717 if (status == VCHIQ_SUCCESS) { 718 service_free(service); 719 service = NULL; 720 } 721 722 ret = vchiq_status_to_vchi(status); 723 } 724 return ret; 725 } 726 EXPORT_SYMBOL(vchi_service_destroy); 727 728 int32_t vchi_service_set_option(const VCHI_SERVICE_HANDLE_T handle, 729 VCHI_SERVICE_OPTION_T option, 730 int value) 731 { 732 int32_t ret = -1; 733 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 734 VCHIQ_SERVICE_OPTION_T vchiq_option; 735 switch (option) { 736 case VCHI_SERVICE_OPTION_TRACE: 737 vchiq_option = VCHIQ_SERVICE_OPTION_TRACE; 738 break; 739 case VCHI_SERVICE_OPTION_SYNCHRONOUS: 740 vchiq_option = VCHIQ_SERVICE_OPTION_SYNCHRONOUS; 741 break; 742 default: 743 service = NULL; 744 break; 745 } 746 if (service) { 747 VCHIQ_STATUS_T status = 748 vchiq_set_service_option(service->handle, 749 vchiq_option, 750 value); 751 752 ret = vchiq_status_to_vchi(status); 753 } 754 return ret; 755 } 756 EXPORT_SYMBOL(vchi_service_set_option); 757 758 int32_t vchi_get_peer_version( const VCHI_SERVICE_HANDLE_T handle, short *peer_version ) 759 { 760 int32_t ret = -1; 761 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 762 if(service) 763 { 764 VCHIQ_STATUS_T status = vchiq_get_peer_version(service->handle, peer_version); 765 ret = vchiq_status_to_vchi( status ); 766 } 767 return ret; 768 } 769 EXPORT_SYMBOL(vchi_get_peer_version); 770 771 #ifdef notyet 772 /* ---------------------------------------------------------------------- 773 * read a uint32_t from buffer. 774 * network format is defined to be little endian 775 * -------------------------------------------------------------------- */ 776 uint32_t 777 vchi_readbuf_uint32(const void *_ptr) 778 { 779 const unsigned char *ptr = _ptr; 780 return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); 781 } 782 783 /* ---------------------------------------------------------------------- 784 * write a uint32_t to buffer. 785 * network format is defined to be little endian 786 * -------------------------------------------------------------------- */ 787 void 788 vchi_writebuf_uint32(void *_ptr, uint32_t value) 789 { 790 unsigned char *ptr = _ptr; 791 ptr[0] = (unsigned char)((value >> 0) & 0xFF); 792 ptr[1] = (unsigned char)((value >> 8) & 0xFF); 793 ptr[2] = (unsigned char)((value >> 16) & 0xFF); 794 ptr[3] = (unsigned char)((value >> 24) & 0xFF); 795 } 796 797 /* ---------------------------------------------------------------------- 798 * read a uint16_t from buffer. 799 * network format is defined to be little endian 800 * -------------------------------------------------------------------- */ 801 uint16_t 802 vchi_readbuf_uint16(const void *_ptr) 803 { 804 const unsigned char *ptr = _ptr; 805 return ptr[0] | (ptr[1] << 8); 806 } 807 808 /* ---------------------------------------------------------------------- 809 * write a uint16_t into the buffer. 810 * network format is defined to be little endian 811 * -------------------------------------------------------------------- */ 812 void 813 vchi_writebuf_uint16(void *_ptr, uint16_t value) 814 { 815 unsigned char *ptr = _ptr; 816 ptr[0] = (value >> 0) & 0xFF; 817 ptr[1] = (value >> 8) & 0xFF; 818 } 819 #endif 820 821 /*********************************************************** 822 * Name: vchi_service_use 823 * 824 * Arguments: const VCHI_SERVICE_HANDLE_T handle 825 * 826 * Description: Routine to increment refcount on a service 827 * 828 * Returns: void 829 * 830 ***********************************************************/ 831 int32_t vchi_service_use(const VCHI_SERVICE_HANDLE_T handle) 832 { 833 int32_t ret = -1; 834 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 835 if (service) 836 ret = vchiq_status_to_vchi(vchiq_use_service(service->handle)); 837 return ret; 838 } 839 EXPORT_SYMBOL(vchi_service_use); 840 841 /*********************************************************** 842 * Name: vchi_service_release 843 * 844 * Arguments: const VCHI_SERVICE_HANDLE_T handle 845 * 846 * Description: Routine to decrement refcount on a service 847 * 848 * Returns: void 849 * 850 ***********************************************************/ 851 int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle) 852 { 853 int32_t ret = -1; 854 SHIM_SERVICE_T *service = (SHIM_SERVICE_T *)handle; 855 if (service) 856 ret = vchiq_status_to_vchi( 857 vchiq_release_service(service->handle)); 858 return ret; 859 } 860 EXPORT_SYMBOL(vchi_service_release); 861