1    /*
     2     * Copyright (c) 2012-2013, Texas Instruments Incorporated
     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        /*
   140         * Sizes of the virtqueues (expressed in number of buffers supported,
   141         * and must be power of two)
   142         */
   143        config UInt VQ0_SIZE = 256;
   144        config UInt VQ1_SIZE = 256;
   145    
   146        /* See VirtQueue.c also for other constants:   */
   147        config UInt RP_MSG_NUM_BUFS = VQ0_SIZE; /* must be power of two */
   148    
   149        config UInt PAGE_SIZE = 4096;
   150    
   151        /*
   152         * The alignment to use between consumer and producer parts of vring.
   153         * Note: this is part of the "wire" protocol. If you change this, you need
   154         * to update your BIOS image as well
   155         */
   156        config UInt RP_MSG_VRING_ALIGN = 4096;
   157    
   158       /*!
   159        * ======== startup ========
   160        *
   161        * Plug interrupts, and if host, initialize vring memory and send
   162        * startup sequence events to slave.
   163        */
   164        Void startup(UInt16 remoteProcId, Bool isHost);
   165    
   166    instance:
   167    
   168        /*!
   169         *  @brief      Initialize at runtime the VirtQueue
   170         *
   171         *  Maps to Instance_init function
   172         *
   173         *  @param[in]  remoteProcId    Remote processor ID associated with this VirtQueue.
   174         *
   175         *  @Returns    Returns a handle to a new initialized VirtQueue.
   176         */
   177        @DirectCall
   178        create(UInt16 remoteProcId);
   179    
   180        /*!
   181         *  @brief      Notify other processor of new buffers in the queue.
   182         *
   183         *  After one or more add_buf calls, invoke this to kick the other side.
   184         *
   185         *  @param[in]  vq        the VirtQueue.
   186         *
   187         *  @sa         VirtQueue_addBuf
   188         */
   189        @DirectCall
   190        Void kick();
   191    
   192        /*!
   193         *  @brief      VirtQueue instance returns slave status
   194         *
   195         *  Returns if this VirtQueue instance belongs to a slave
   196         *
   197         *  @param[in]  vq        the VirtQueue.
   198         *
   199         */
   200        @DirectCall
   201        Bool isSlave();
   202    
   203        /*!
   204         *  @brief      VirtQueue instance returns host status
   205         *
   206         *  Returns if this VirtQueue instance belongs to a host
   207         *
   208         *  @param[in]  vq        the VirtQueue.
   209         *
   210         */
   211        @DirectCall
   212        Bool isHost();
   213    
   214        /*!
   215         *  @brief      VirtQueue instance returns queue ID
   216         *
   217         *  Returns VirtQueue instance's queue ID.
   218         *
   219         *  @param[in]  vq        the VirtQueue.
   220         *
   221         */
   222        @DirectCall
   223        UInt16 getId();
   224    
   225        /*!
   226         *  @brief      VirtQueue instance returns Swi handle
   227         *
   228         *  Returns VirtQueue instance Swi handle
   229         *
   230         *  @param[in]  vq        the VirtQueue.
   231         *
   232         */
   233        @DirectCall
   234        Swi.Handle getSwiHandle();
   235    
   236        /*
   237         *  ========================================================================
   238         *  Host Only Functions:
   239         *  ========================================================================
   240         */
   241    
   242        /*!
   243         *  @brief      Add available buffer to virtqueue's available buffer list.
   244         *              Only used by Host.
   245         *
   246         *  @param[in]  vq        the VirtQueue.
   247         *  @param[in]  buf      the buffer to be processed by the slave.
   248         *
   249         *  @return     Remaining capacity of queue or a negative error.
   250         *
   251         *  @sa         VirtQueue_getUsedBuf
   252         */
   253        @DirectCall
   254        Int addAvailBuf(Void *buf);
   255    
   256        /*!
   257         *  @brief      Get the next used buffer.
   258         *              Only used by Host.
   259         *
   260         *  @param[in]  vq        the VirtQueue.
   261         *
   262         *  @return     Returns NULL or the processed buffer.
   263         *
   264         *  @sa         VirtQueue_addAvailBuf
   265         */
   266        @DirectCall
   267        Void *getUsedBuf();
   268    
   269        /*
   270         *  ========================================================================
   271         *  Slave Only Functions:
   272         *  ========================================================================
   273         */
   274    
   275        /*!
   276         *  @brief      Get the next available buffer.
   277         *              Only used by Slave.
   278         *
   279         *  @param[in]  vq        the VirtQueue.
   280         *  @param[out] buf       Pointer to location of available buffer;
   281         *  @param[out] len       Length of the available buffer message.
   282         *
   283         *  @return     Returns a token used to identify the available buffer, to be
   284         *              passed back into VirtQueue_addUsedBuf();
   285         *              token is negative if failure to find an available buffer.
   286         *
   287         *  @sa         VirtQueue_addUsedBuf
   288         */
   289        @DirectCall
   290        Int16 getAvailBuf(Void **buf, Int *len);
   291    
   292        /*!
   293         *  @brief      Add used buffer to virtqueue's used buffer list.
   294         *              Only used by Slave.
   295         *
   296         *  @param[in]  vq        the VirtQueue.
   297         *  @param[in]  token     token of the buffer added to vring used list.
   298         *  @param[in]  len       length of the message being added.
   299         *
   300         *  @return     Remaining capacity of queue or a negative error.
   301         *
   302         *  @sa         VirtQueue_getAvailBuf
   303         */
   304        @DirectCall
   305        Int addUsedBuf(Int16 token, Int len);
   306    
   307        // -------- Handle Parameters --------
   308    
   309        config Fxn callback = null;
   310    
   311        config Int vqId = 0;
   312    
   313        // -------- Handle Functions --------
   314    
   315    internal:   /* not for client use */
   316    
   317        /*! Statically retrieve procIds to avoid doing this at runtime */
   318        config UInt hostProcId  = MultiProc.INVALIDID;
   319        config UInt dspProcId   = MultiProc.INVALIDID;
   320    
   321        /*!
   322         *  ======== hostIsr ========
   323         */
   324        Void hostIsr(UArg msg);
   325    
   326        /*!
   327         *  ======== slaveIsr ========
   328         */
   329        Void slaveIsr(UArg msg);
   330    
   331        /*!
   332         * ======== Module_State ========
   333         * @_nodoc
   334         */
   335        struct Module_State
   336        {
   337            UInt16 hostSlaveSynced;
   338            UInt16 virtQueueInitialized;
   339            UInt32 *queueRegistry;
   340            Ptr    traceBufPtr;
   341        }
   342    
   343        /*!
   344         *  ======== Instance_State ========
   345         *  @_nodoc
   346         */
   347        struct Instance_State {
   348            Bool hostSlaveSynced;
   349            UInt16 id;
   350            Fxn callback;
   351            Void *vringPtr;
   352            UInt16 num_free;
   353            UInt16 last_avail_idx;
   354            UInt16 last_used_idx;
   355            UInt16 procId;
   356            GateAll.Handle gateH;
   357        };
   358    }