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