1    /*
     2     * Copyright (c) 2013-2015 Texas Instruments Incorporated - http://www.ti.com
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     *
    32     */
    33    /** ============================================================================
    34     *  @file       VirtQueue.xdc
    35     *
    36     *  @brief      Virtio Queue interface for BIOS
    37     *
    38     *  Differences between BIOS version and Linux kernel (include/linux/virtio.h):
    39     *  - Renamed module from virtio.h to VirtQueue.h to match the API prefixes;
    40     *  - BIOS (XDC) types and CamelCasing used;
    41     *  - virtio_device concept removed (i.e, assumes no containing device);
    42     *  - removed scatterlist;
    43     *  - VirtQueues are created statically here, so just added a VirtQueue_init()
    44     *    fxn to take the place of the Virtio vring_new_virtqueue() API;
    45     *  - The notify function is implicit in the implementation, and not provided
    46     *    by the client, as it is in Linux virtio.
    47     *  - Broke into APIs to add/get used and avail buffers, as the API is
    48     *    assymmetric.
    49     *
    50     *  Usage:
    51     *     This IPC only works between one processor designated as the Host (Linux)
    52     *     and one or more Slave processors (BIOS).
    53     *
    54     *     For any Host/Slave pair, there are 2 VirtQueues (aka Vrings);
    55     *     Only the Host adds new buffers to the avail list of a vring;
    56     *     Available buffers can be empty or full, depending on direction;
    57     *     Used buffer means "processed" (emptied or filled);
    58     *
    59     *  Host:
    60     *    - To send buffer to the slave processor:
    61     *          add_avail_buf(slave_virtqueue);
    62     *          kick(slave_virtqueue);
    63     *          get_used_buf(slave_virtqueue);
    64     *    - To receive buffer from slave processor:
    65     *          add_avail_buf(host_virtqueue);
    66     *          kick(host_virtqueue);
    67     *          get_used_buf(host_virtqueue);
    68     *
    69     *  Slave:
    70     *    - To send buffer to the host:
    71     *          get_avail_buf(host_virtqueue);
    72     *          add_used_buf(host_virtqueue);
    73     *          kick(host_virtqueue);
    74     *    - To receive buffer from the host:
    75     *          get_avail_buf(slave_virtqueue);
    76     *          add_used_buf(slave_virtqueue);
    77     *          kick(slave_virtqueue);
    78     *
    79     *  All VirtQueue operations can be called in any context.
    80     *
    81     *  The virtio header should be included in an application as follows:
    82     *  @code
    83     *  #include <ti/ipc/rpmsg/VirtQueue.h>
    84     *  @endcode
    85     *
    86     *  ============================================================================
    87     */
    88    
    89    import  ti.sysbios.knl.Swi;
    90    import  ti.sdo.utils.MultiProc;
    91    import  ti.sysbios.gates.GateAll;
    92    
    93    /*!
    94     *  ======== VirtQueue ========
    95     *
    96     */
    97    
    98    @InstanceInitError
    99    module VirtQueue
   100    {
   101        // -------- Module Constants --------
   102    
   103        // -------- Module Types --------
   104    
   105    
   106        /*!
   107         *  ======== BasicView ========
   108         *  @_nodoc
   109         */
   110        metaonly struct BasicView {
   111    
   112        };
   113    
   114        /*!
   115         *  ======== ModuleView ========
   116         *  @_nodoc
   117         */
   118        metaonly struct ModuleView {
   119    
   120        };
   121    
   122        /*!
   123         *  ======== rovViewInfo ========
   124         *  @_nodoc
   125         */
   126    /*    @Facet
   127        metaonly config ViewInfo.Instance rovViewInfo =
   128            xdc.rov.ViewInfo.create({
   129                viewMap: [
   130                    ['Basic',  {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitBasic',  structName: 'BasicView'}],
   131                    ['Module', {type: ViewInfo.MODULE,   viewInitFxn: 'viewInitModule', structName: 'ModuleView'}]
   132                ]
   133             });
   134    */
   135        // -------- Module Proxies --------
   136    
   137        // -------- Module Parameters --------
   138    
   139        /* Per Core offset of start of VRING control structures from CORE0 */
   140        config UInt32 VRING_OFFSET = 0x00080000;
   141    
   142        /*
   143         * Sizes of the virtqueues (expressed in number of buffers supported,
   144         * and must be power of two)
   145         */
   146        config UInt VQ0_SIZE = 256;
   147        config UInt VQ1_SIZE = 256;
   148    
   149        /* See VirtQueue.c also for other constants:   */
   150        config UInt RP_MSG_NUM_BUFS = VQ0_SIZE; /* must be power of two */
   151    
   152        config UInt PAGE_SIZE = 4096;
   153    
   154        /*
   155         * The alignment to use between consumer and producer parts of vring.
   156         * Note: this is part of the "wire" protocol. If you change this, you need
   157         * to update your BIOS image as well
   158         */
   159        config UInt RP_MSG_VRING_ALIGN = 4096;
   160    
   161       /*!
   162        * ======== startup ========
   163        *
   164        * Plug interrupts, and if host, initialize vring memory and send
   165        * startup sequence events to slave.
   166        */
   167        Void startup(UInt16 remoteProcId, Bool isHost);
   168    
   169    instance:
   170    
   171        /*!
   172         *  @brief      Initialize at runtime the VirtQueue
   173         *
   174         *  Maps to Instance_init function
   175         *
   176         *  @param[in]  remoteProcId    Remote processor ID associated with this VirtQueue.
   177         *
   178         *  @Returns    Returns a handle to a new initialized VirtQueue.
   179         */
   180        @DirectCall
   181        create(UInt16 remoteProcId);
   182    
   183        /*!
   184         *  @brief      Notify other processor of new buffers in the queue.
   185         *
   186         *  After one or more add_buf calls, invoke this to kick the other side.
   187         *
   188         *  @param[in]  vq        the VirtQueue.
   189         *
   190         *  @sa         VirtQueue_addBuf
   191         */
   192        @DirectCall
   193        Void kick();
   194    
   195        /*!
   196         *  @brief      VirtQueue instance returns slave status
   197         *
   198         *  Returns if this VirtQueue instance belongs to a slave
   199         *
   200         *  @param[in]  vq        the VirtQueue.
   201         *
   202         */
   203        @DirectCall
   204        Bool isSlave();
   205    
   206        /*!
   207         *  @brief      VirtQueue instance returns host status
   208         *
   209         *  Returns if this VirtQueue instance belongs to a host
   210         *
   211         *  @param[in]  vq        the VirtQueue.
   212         *
   213         */
   214        @DirectCall
   215        Bool isHost();
   216    
   217        /*!
   218         *  @brief      VirtQueue instance returns queue ID
   219         *
   220         *  Returns VirtQueue instance's queue ID.
   221         *
   222         *  @param[in]  vq        the VirtQueue.
   223         *
   224         */
   225        @DirectCall
   226        UInt16 getId();
   227    
   228        /*!
   229         *  @brief      VirtQueue instance returns Swi handle
   230         *
   231         *  Returns VirtQueue instance Swi handle
   232         *
   233         *  @param[in]  vq        the VirtQueue.
   234         *
   235         */
   236        @DirectCall
   237        Swi.Handle getSwiHandle();
   238    
   239        /*
   240         *  ========================================================================
   241         *  Host Only Functions:
   242         *  ========================================================================
   243         */
   244    
   245        /*!
   246         *  @brief      Add available buffer to virtqueue's available buffer list.
   247         *              Only used by Host.
   248         *
   249         *  @param[in]  vq        the VirtQueue.
   250         *  @param[in]  buf      the buffer to be processed by the slave.
   251         *
   252         *  @return     Remaining capacity of queue or a negative error.
   253         *
   254         *  @sa         VirtQueue_getUsedBuf
   255         */
   256        @DirectCall
   257        Int addAvailBuf(Void *buf);
   258    
   259        /*!
   260         *  @brief      Get the next used buffer.
   261         *              Only used by Host.
   262         *
   263         *  @param[in]  vq        the VirtQueue.
   264         *
   265         *  @return     Returns NULL or the processed buffer.
   266         *
   267         *  @sa         VirtQueue_addAvailBuf
   268         */
   269        @DirectCall
   270        Void *getUsedBuf();
   271    
   272        /*
   273         *  ========================================================================
   274         *  Slave Only Functions:
   275         *  ========================================================================
   276         */
   277    
   278        /*!
   279         *  @brief      Get the next available buffer.
   280         *              Only used by Slave.
   281         *
   282         *  @param[in]  vq        the VirtQueue.
   283         *  @param[out] buf       Pointer to location of available buffer;
   284         *  @param[out] len       Length of the available buffer message.
   285         *
   286         *  @return     Returns a token used to identify the available buffer, to be
   287         *              passed back into VirtQueue_addUsedBuf();
   288         *              token is negative if failure to find an available buffer.
   289         *
   290         *  @sa         VirtQueue_addUsedBuf
   291         */
   292        @DirectCall
   293        Int16 getAvailBuf(Void **buf, Int *len);
   294    
   295        /*!
   296         *  @brief      Add used buffer to virtqueue's used buffer list.
   297         *              Only used by Slave.
   298         *
   299         *  @param[in]  vq        the VirtQueue.
   300         *  @param[in]  token     token of the buffer added to vring used list.
   301         *  @param[in]  len       length of the message being added.
   302         *
   303         *  @return     Remaining capacity of queue or a negative error.
   304         *
   305         *  @sa         VirtQueue_getAvailBuf
   306         */
   307        @DirectCall
   308        Int addUsedBuf(Int16 token, Int len);
   309    
   310        // -------- Handle Parameters --------
   311    
   312        config Bool host = false;
   313    
   314        config Fxn callback = null;
   315    
   316        config Swi.Handle swiHandle = null;
   317    
   318        config UInt intVectorId = ~1u;
   319    
   320        config Int vqId = 0;
   321    
   322        // -------- Handle Functions --------
   323    
   324    internal:   /* not for client use */
   325    
   326        void init();
   327    
   328        /*!
   329         *  ======== hostIsr ========
   330         */
   331        Void hostIsr(UArg msg);
   332    
   333        /*!
   334         *  ======== slaveIsr ========
   335         */
   336        Void slaveIsr(UArg msg);
   337    
   338        /*!
   339         * ======== Module_State ========
   340         * @_nodoc
   341         */
   342        struct Module_State
   343        {
   344            UInt16 hostSlaveSynced;
   345            UInt16 virtQueueInitialized;
   346            UInt32 *queueRegistry;
   347            Ptr    traceBufPtr;
   348        }
   349    
   350        /*!
   351         *  ======== Instance_State ========
   352         *  @_nodoc
   353         */
   354        struct Instance_State {
   355            Bool hostSlaveSynced;
   356            UInt16 id;
   357            Fxn callback;
   358            Swi.Handle swiHandle;
   359            Void *vringPtr;
   360            UInt16 num_free;
   361            UInt16 last_avail_idx;
   362            UInt16 last_used_idx;
   363            UInt16 procId;
   364            GateAll.Handle gateH;
   365        };
   366    }