The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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(&params, 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, &params,
  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(&params, 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, &params, &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);

Cache object: f05519d955c7fbe06aeff019f28d06ed


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.