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