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    @InstanceInitError
    97    @Template("./VirtQueue.xdt")
    98    
    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        /*!
   170         *  ======== cacheWb ========
   171         *  Flush the SysMin trace buffer
   172         *
   173         *  This function should be configured as an idle function.
   174         *
   175         *  @p(code)
   176         *  var Idle = xdc.useModule('ti.sysbios.knl.Idle');
   177         *  Idle.addFunc('&VirtQueue_cacheWb');
   178         *  @p
   179         */
   180        Void cacheWb();
   181    
   182    instance:
   183    
   184        /*!
   185         *  @brief      Initialize at runtime the VirtQueue
   186         *
   187         *  Maps to Instance_init function
   188         *
   189         *  @param[in]  remoteProcId    Remote processor ID associated with this VirtQueue.
   190         *
   191         *  @Returns    Returns a handle to a new initialized VirtQueue.
   192         */
   193        @DirectCall
   194        create(UInt16 remoteProcId);
   195    
   196        /*!
   197         *  @brief      Notify other processor of new buffers in the queue.
   198         *
   199         *  After one or more add_buf calls, invoke this to kick the other side.
   200         *
   201         *  @param[in]  vq        the VirtQueue.
   202         *
   203         *  @sa         VirtQueue_addBuf
   204         */
   205        @DirectCall
   206        Void kick();
   207    
   208        /*!
   209         *  @brief      VirtQueue instance returns slave status
   210         *
   211         *  Returns if this VirtQueue instance belongs to a slave
   212         *
   213         *  @param[in]  vq        the VirtQueue.
   214         *
   215         */
   216        @DirectCall
   217        Bool isSlave();
   218    
   219        /*!
   220         *  @brief      VirtQueue instance returns host status
   221         *
   222         *  Returns if this VirtQueue instance belongs to a host
   223         *
   224         *  @param[in]  vq        the VirtQueue.
   225         *
   226         */
   227        @DirectCall
   228        Bool isHost();
   229    
   230        /*!
   231         *  @brief      VirtQueue instance returns queue ID
   232         *
   233         *  Returns VirtQueue instance's queue ID.
   234         *
   235         *  @param[in]  vq        the VirtQueue.
   236         *
   237         */
   238        @DirectCall
   239        UInt16 getId();
   240    
   241        /*!
   242         *  @brief      VirtQueue instance returns Swi handle
   243         *
   244         *  Returns VirtQueue instance Swi handle
   245         *
   246         *  @param[in]  vq        the VirtQueue.
   247         *
   248         */
   249        @DirectCall
   250        Swi.Handle getSwiHandle();
   251    
   252        /*
   253         *  ========================================================================
   254         *  Host Only Functions:
   255         *  ========================================================================
   256         */
   257    
   258        /*!
   259         *  @brief      Add available buffer to virtqueue's available buffer list.
   260         *              Only used by Host.
   261         *
   262         *  @param[in]  vq        the VirtQueue.
   263         *  @param[in]  buf      the buffer to be processed by the slave.
   264         *
   265         *  @return     Remaining capacity of queue or a negative error.
   266         *
   267         *  @sa         VirtQueue_getUsedBuf
   268         */
   269        @DirectCall
   270        Int addAvailBuf(Void *buf);
   271    
   272        /*!
   273         *  @brief      Get the next used buffer.
   274         *              Only used by Host.
   275         *
   276         *  @param[in]  vq        the VirtQueue.
   277         *
   278         *  @return     Returns NULL or the processed buffer.
   279         *
   280         *  @sa         VirtQueue_addAvailBuf
   281         */
   282        @DirectCall
   283        Void *getUsedBuf();
   284    
   285        /*
   286         *  ========================================================================
   287         *  Slave Only Functions:
   288         *  ========================================================================
   289         */
   290    
   291        /*!
   292         *  @brief      Get the next available buffer.
   293         *              Only used by Slave.
   294         *
   295         *  @param[in]  vq        the VirtQueue.
   296         *  @param[out] buf       Pointer to location of available buffer;
   297         *  @param[out] len       Length of the available buffer message.
   298         *
   299         *  @return     Returns a token used to identify the available buffer, to be
   300         *              passed back into VirtQueue_addUsedBuf();
   301         *              token is negative if failure to find an available buffer.
   302         *
   303         *  @sa         VirtQueue_addUsedBuf
   304         */
   305        @DirectCall
   306        Int16 getAvailBuf(Void **buf, Int *len);
   307    
   308        /*!
   309         *  @brief      Add used buffer to virtqueue's used buffer list.
   310         *              Only used by Slave.
   311         *
   312         *  @param[in]  vq        the VirtQueue.
   313         *  @param[in]  token     token of the buffer added to vring used list.
   314         *  @param[in]  len       length of the message being added.
   315         *
   316         *  @return     Remaining capacity of queue or a negative error.
   317         *
   318         *  @sa         VirtQueue_getAvailBuf
   319         */
   320        @DirectCall
   321        Int addUsedBuf(Int16 token, Int len);
   322    
   323        // -------- Handle Parameters --------
   324    
   325        config Bool host = false;
   326    
   327        config Fxn callback = null;
   328    
   329        config Swi.Handle swiHandle = null;
   330    
   331        config UInt intVectorId = ~1u;
   332    
   333        config Int vqId = 0;
   334    
   335        // -------- Handle Functions --------
   336    
   337    internal:   /* not for client use */
   338    
   339        void init();
   340    
   341        /*!
   342         *  ======== hostIsr ========
   343         */
   344        Void hostIsr(UArg msg);
   345    
   346        /*!
   347         *  ======== slaveIsr ========
   348         */
   349        Void slaveIsr(UArg msg);
   350    
   351        /*!
   352         * ======== Module_State ========
   353         * @_nodoc
   354         */
   355        struct Module_State
   356        {
   357            UInt16 hostSlaveSynced;
   358            UInt16 virtQueueInitialized;
   359            UInt32 *queueRegistry;
   360            Ptr    traceBufPtr;
   361        }
   362    
   363        /*!
   364         *  ======== Instance_State ========
   365         *  @_nodoc
   366         */
   367        struct Instance_State {
   368            Bool hostSlaveSynced;
   369            UInt16 id;
   370            Fxn callback;
   371            Swi.Handle swiHandle;
   372            Void *vringPtr;
   373            UInt16 num_free;
   374            UInt16 last_avail_idx;
   375            UInt16 last_used_idx;
   376            UInt16 procId;
   377            GateAll.Handle gateH;
   378        };
   379    }