1    /* 
     2     * Copyright (c) 2010, 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     *  ======== Ipc.xdc ========
    34     *
    35     */
    36     
    37    import xdc.runtime.Error;
    38    import xdc.runtime.Assert;
    39    import xdc.rov.ViewInfo;
    40    import ti.sdo.utils.MultiProc;
    41    
    42    /*!
    43     *  ======== Ipc ========
    44     *  IPC Master Manager
    45     * 
    46     *  @p(html)
    47     *  This module has a common header that can be found in the {@link ti.ipc}
    48     *  package.  Application code should include the common header file (not the 
    49     *  RTSC-generated one):
    50     *
    51     *  <PRE>#include &lt;ti/ipc/Ipc.h></PRE>
    52     *   
    53     *  The RTSC module must be used in the application's RTSC configuration file 
    54     *  (.cfg):
    55     *  
    56     *  <PRE>Ipc = xdc.useModule('ti.sdo.ipc.Ipc');</PRE>
    57     *
    58     *  Documentation for all runtime APIs, instance configuration parameters, 
    59     *  error codes macros and type definitions available to the application 
    60     *  integrator can be found in the 
    61     *  <A HREF="../../../../doxygen/html/files.html">Doxygen documenation</A>
    62     *  for the IPC product.  However, the documentation presented on this page 
    63     *  should be referred to for information specific to the RTSC module, such as
    64     *  module configuration, Errors, and Asserts.
    65     *  @p
    66     *
    67     *  The most common static configuration that is required of the Ipc module
    68     *  is the {@link #procSync} configuration that affects the behavior of the
    69     *  Ipc_start and Ipc_attach runtime APIs.
    70     * 
    71     *  Additionally, certain subsystems of IPC (such as Notify and MessageQ) can
    72     *  be disabled to save resources on a per-connection basis by configuring Ipc
    73     *  using {@link #setEntryMeta}.
    74     *  
    75     */
    76    
    77    @Template ("./Ipc.xdt")
    78    module Ipc
    79    {
    80        /*!
    81         *  ======== ModuleView ========
    82         *  @_nodoc
    83         */
    84        metaonly struct ModuleView {
    85            UInt16  remoteProcId;
    86            Bool    attached;
    87            Bool    setupNotify;
    88            Bool    setupMessageQ;
    89        };
    90        
    91        /*!
    92         *  ======== rovViewInfo ========
    93         *  @_nodoc
    94         */
    95        @Facet
    96        metaonly config xdc.rov.ViewInfo.Instance rovViewInfo = 
    97            xdc.rov.ViewInfo.create({
    98                viewMap: [
    99                    ['Module',
   100                        {
   101                            type: xdc.rov.ViewInfo.MODULE_DATA,
   102                            viewInitFxn: 'viewInitModule',
   103                            structName: 'ModuleView'
   104                        }
   105                    ],
   106                ]
   107            });
   108            
   109        /*!     
   110         *  Various configuration options for {@link #procSync}
   111         *  
   112         *  The values in this enum affect the behavior of the Ipc_start and
   113         *  Ipc_attach runtime APIs. 
   114         * 
   115         *  ProcSync_ALL:  Calling Ipc_start will also internally Ipc_attach to 
   116         *  each remote processor.  The application should never call Ipc_attach.
   117         *  This type of startup and synchronization should be used if all IPC
   118         *  processors on a device start up at the same time and connections should 
   119         *  be established between every possible pair of processors.
   120         *  
   121         *  ProcSync_PAIR (default):  Calling Ipc_start will perform system-wide IPC
   122         *  initialization required on all processor, but connections to remote 
   123         *  processors will not be established (i.e. Ipc_attach will never be 
   124         *  called).  This configuration should be chosen if synchronization is
   125         *  required and some/all these conditions are true:
   126         *  @p(blist)
   127         *  - It is necessary to control when synchronization with each remote
   128         *    processor occurs
   129         *  - Useful work can be done while trying to synchronize with a remote
   130         *    processor by yielding a thread after each attempt to Ipc_attach
   131         *    to the processor.
   132         *  - Connections to all remote processors are unnecessary and connections
   133         *    should selectively be made to save memory
   134         *  @p
   135         *  NOTE: A connection should be made to the owner of region 0 (usually the
   136         *  processor with id = 0) before any connection to any other remote 
   137         *  processor can be made. For example, if there are three processors 
   138         *  configured with MultiProc, #1 should attach to #0 before it can attach
   139         *  to #2.
   140         *
   141         *  ProcSync_NONE:  This should be selected with caution.  Ipc_start will 
   142         *  work exactly as it does with ProcSync_PAIR.  However, Ipc_attach will
   143         *  not synchronize with the remote processor.  Callers of Ipc_attach are
   144         *  bound by the same restrictions imposed by using ProcSync_PAIR. 
   145         *  Additionally, an Ipc_attach to a remote processor whose id is less than
   146         *  our own has to occur *after* the corresponding remote processor has 
   147         *  called attach to the original processor.  For example, processor #2
   148         *  can call 
   149         *  @p(code)
   150         *  Ipc_attach(1); 
   151         *  @p
   152         *  only after processor #1 has called:
   153         *  @p(code)
   154         *  Ipc_attach(2); 
   155         *  @p
   156         *
   157         */
   158        enum ProcSync {
   159            ProcSync_NONE,          /*! ProcSync_PAIR with no synchronization   */
   160            ProcSync_PAIR,          /*! Ipc_start does not Ipc_attach           */
   161            ProcSync_ALL            /*! Ipc_start attach to all remote procs    */
   162        };
   163    
   164        /*!
   165         *  Struct used for configuration via {@link #setEntryMeta}
   166         * 
   167         *  This structure defines the fields that are to be configured
   168         *  between the executing processor and a remote processor.
   169         */
   170        struct Entry {
   171            UInt16 remoteProcId;    /*! Remote processor id                     */
   172            Bool   setupNotify;     /*! Whether to setup Notify                 */
   173            Bool   setupMessageQ;   /*! Whether to setup MessageQ               */
   174        };
   175    
   176        /*
   177         *************************************************************************
   178         *                       Generic IPC Errors/Asserts
   179         *************************************************************************
   180         */
   181        
   182        /*!
   183         *  ======== A_addrNotInSharedRegion ========
   184         *  Assert raised when an address lies outside all known shared regions
   185         */
   186        config Assert.Id A_addrNotInSharedRegion  = {
   187            msg: "A_addrNotInSharedRegion: Address not in any shared region"
   188        };
   189    
   190        /*!
   191         *  ======== A_addrNotCacheAligned ========
   192         *  Error raised when an address is not cache-aligned
   193         */
   194        config Assert.Id A_addrNotCacheAligned  = {
   195            msg: "A_addrNotCacheAligned: Address is not cache aligned"
   196        };
   197    
   198        /*!
   199         *  ======== A_nullArgument ========
   200         *  Assert raised when a required argument is null
   201         */
   202        config Assert.Id A_nullArgument  = {
   203            msg: "A_nullArgument: Required argument is null"
   204        };
   205    
   206        /*!
   207         *  ======== A_nullPointer ========
   208         *  Assert raised when a pointer is null
   209         */
   210        config Assert.Id A_nullPointer  = {
   211            msg: "A_nullPointer: Pointer is null"
   212        };
   213    
   214        /*!
   215         *  ======== A_invArgument ========
   216         *  Assert raised when an argument is invalid
   217         */
   218        config Assert.Id A_invArgument  = {
   219            msg: "A_invArgument: Invalid argument supplied"
   220        };
   221        
   222        /*!
   223         *  ======== A_invParam ========
   224         *  Assert raised when a parameter is invalid
   225         */
   226        config Assert.Id A_invParam  = {
   227            msg: "A_invParam: Invalid configuration parameter supplied"
   228        };
   229        
   230        /*!
   231         *  ======== E_versionMismatch ========
   232         *  Error raised when a version mismatch occurs
   233         * 
   234         *  Error raised in an open call because there is
   235         *  a version mismatch between the opener and the creator
   236         */
   237        config Error.Id E_versionMismatch  = {
   238            msg: "E_versionMismatch: IPC Module version mismatch: creator: %d, opener: %d"
   239        };
   240    
   241        /*!
   242         *  ======== A_internal ========
   243         *  Assert raised when an internal error is encountered
   244         */
   245        config Assert.Id A_internal = {
   246            msg: "A_internal: An internal error has occurred"
   247        };
   248         
   249        /*
   250         *************************************************************************
   251         *                       Module-wide Config Parameters
   252         *************************************************************************
   253         */
   254    
   255        /*!
   256         *  ======== sr0MemorySetup ========
   257         *  Shared memory is present or not for shared region 0 entry.
   258         */
   259        metaonly config Bool sr0MemorySetup;
   260        
   261        /*! @_nodoc
   262         *  ======== hostProcId ========
   263         *  Host processor identifier.
   264         *  
   265         *  Used to specify the host processor's id.  This parameter is only used 
   266         *  in a Syslink system.
   267         */
   268        metaonly config UInt16 hostProcId = MultiProc.INVALIDID;
   269    
   270        /*!
   271         *  ======== procSync ========
   272         *  Affects how Ipc_start and Ipc_attach behave
   273         *
   274         *  Refer to the documentation for the {@link #ProcSync} enum for 
   275         *  information about the various ProcSync options.
   276         */
   277        config ProcSync procSync = Ipc.ProcSync_PAIR;
   278    
   279        /*! @_nodoc
   280         *  ======== generateSlaveDataForHost ========
   281         *  generates the slave's data into a section for the host.
   282         */
   283        config Bool generateSlaveDataForHost;
   284    
   285        /*!
   286         *  ======== userFxn ========
   287         *  Attach and Detach hooks.
   288         */
   289        config UserFxn userFxn;
   290    
   291        /*
   292         *************************************************************************
   293         *                       IPC Functions
   294         *************************************************************************
   295         */
   296    
   297         /*!
   298         *  ======== getEntry ========
   299         *  Gets the properties for attaching to a remote processor.
   300         *
   301         *  This function must be called before Ipc_attach().  The
   302         *  parameter entry->remoteProcId field must be set prior to calling
   303         *  the function.
   304         *
   305         *  @param(entry)       Properties between a pair of processors.
   306         */
   307        Void getEntry(Entry *entry);
   308    
   309        /*!
   310         *  ======== setEntryMeta ========
   311         *  Statically sets the properties for attaching to a remote processor.
   312         *
   313         *  This function allows the user to configure whether Notify and/or
   314         *  MessageQ is setup during Ipc_attach().  If 'setupNotify' is set
   315         *  to 'false', neither the Notify or NameServerRemoteNotify instances
   316         *  are created.  If 'setupMessageQ' is set to 'false', the MessageQ
   317         *  transport instances are not created.  By default, both flags are
   318         *  set to 'true'.
   319         *
   320         *  Note: For any pair of processors, the flags must be the same
   321         *
   322         *  @param(entry)       Properties between a pair of processors.
   323         */
   324        metaonly Void setEntryMeta(Entry entry);
   325    
   326        /*!
   327         *  ======== setEntry ========
   328         *  Sets the properties for attaching to a remote processor.
   329         *
   330         *  This function must be called before Ipc_attach().  It allows
   331         *  the user to configure whether Notify and/or MessageQ is setup
   332         *  during Ipc_attach().  If 'setupNotify' is set to 'FALSE',
   333         *  neither the Notify or NameServerRemoteNotify instances are
   334         *  created.  If 'setupMessageQ' is set to 'FALSE', the MessageQ
   335         *  transport instances are not created.  By default, both flags are
   336         *  set to 'TRUE'.
   337         *
   338         *  Note: For any pair of processors, the flags must be the same
   339         *
   340         *  @param(entry)       Properties between a pair of processors.
   341         */
   342        Void setEntry(Entry *entry);
   343    
   344        /*! @_nodoc
   345         *  This is needed to prevent the Ipc module from being optimized away
   346         *  during the whole_program[_debug] partial link.
   347         */
   348        Void dummy();
   349    
   350    
   351    internal:    
   352        
   353        /* flag for starting processor synchronization */
   354        const UInt32 PROCSYNCSTART  = 1;
   355        
   356        /* flag for finishing processor synchronization */
   357        const UInt32 PROCSYNCFINISH = 2;
   358        
   359        /* flag for detaching */
   360        const UInt32 PROCSYNCDETACH = 3;
   361    
   362        /* Type of Ipc object. Each value needs to be a power of two. */
   363        enum ObjType {
   364            ObjType_CREATESTATIC            = 0x1,
   365            ObjType_CREATESTATIC_REGION     = 0x2,
   366            ObjType_CREATEDYNAMIC           = 0x4,  /* Created by sharedAddr      */
   367            ObjType_CREATEDYNAMIC_REGION    = 0x8,  /* Created by regionId        */
   368            ObjType_OPENDYNAMIC             = 0x10, /* Opened instance            */
   369            ObjType_LOCAL                   = 0x20  /* Local-only instance        */
   370        };
   371    
   372        /*
   373         *  This structure captures Configuration details of a module/instance
   374         *  written by a slave to synchornize with a remote slave/HOST
   375         */
   376        struct ConfigEntry {
   377            Bits32 remoteProcId;
   378            Bits32 localProcId;
   379            Bits32 tag;
   380            Bits32 size;
   381            Bits32 next;
   382        };
   383    
   384        /*!
   385         *  head of the config list 
   386         */
   387        struct ConfigHead {
   388            volatile Bits32 first;
   389        };    
   390    
   391        struct ProcEntry {
   392            Ptr    localConfigList;
   393            Ptr    remoteConfigList;
   394            Ptr    userObj;
   395            Bool   attached;
   396            Entry  entry;
   397        };
   398    
   399        /* The structure used for reserving memory in SharedRegion */
   400        struct Reserved {
   401            volatile Bits32    startedKey;
   402            SharedRegion.SRPtr notifySRPtr;
   403            SharedRegion.SRPtr nsrnSRPtr;
   404            SharedRegion.SRPtr transportSRPtr;
   405            SharedRegion.SRPtr configListHead;
   406        };    
   407    
   408        /*! struct for attach/detach plugs. */
   409        struct UserFxn {
   410            Int (*attach)(Ptr *, UInt16);
   411            Int (*detach)(Ptr *, UInt16);
   412        };
   413    
   414        /* Storage for setup of processors */
   415        metaonly config Entry entry[];
   416    
   417        /*!
   418         *  ======== getMasterAddr() ========
   419         */
   420        Ptr getMasterAddr(UInt16 remoteProcId, Ptr sharedAddr);
   421        
   422        /*!
   423         *  ======== getRegion0ReservedSize ========
   424         *  Returns the amount of memory to be reserved for Ipc in SharedRegion 0.
   425         *
   426         *  This is used for synchronizing processors.
   427         */
   428        SizeT getRegion0ReservedSize();
   429        
   430        /*!
   431         *  ======== getSlaveAddr() ========
   432         */
   433        Ptr getSlaveAddr(UInt16 remoteProcId, Ptr sharedAddr);
   434    
   435        /*!
   436         *  ======== procSyncStart ========
   437         *  Starts the process of synchronizing processors.
   438         *
   439         *  Shared memory in region 0 will be used.  The processor which owns 
   440         *  SharedRegion 0 writes its reserve memory address in region 0
   441         *  to let the other processors know it has started.  It then spins
   442         *  until the other processors start.  The other processors write their
   443         *  reserve memory address in region 0 to let the owner processor
   444         *  know they've started.  The other processors then spin until the
   445         *  owner processor writes to let them know its finished the process
   446         *  of synchronization before continuing.
   447         */
   448        Int procSyncStart(UInt16 remoteProcId, Ptr sharedAddr);
   449    
   450        /*!
   451         *  ======== procSyncFinish ========
   452         *  Finishes the process of synchronizing processors.
   453         *
   454         *  Each processor writes its reserve memory address in SharedRegion 0
   455         *  to let the other processors know its finished the process of
   456         *  synchronization.     
   457         */
   458        Int procSyncFinish(UInt16 remoteProcId, Ptr sharedAddr);
   459    
   460        /*!
   461         *  ======== reservedSizePerProc ========
   462         *  The amount of memory required to be reserved per processor.
   463         */
   464        SizeT reservedSizePerProc();
   465        
   466        /*! Used for populated the 'objType' field in ROV views*/
   467        metaonly String getObjTypeStr$view(ObjType type);
   468    
   469        /* Module state */
   470        struct Module_State {
   471            Ptr       ipcSharedAddr;
   472            Ptr       gateMPSharedAddr;
   473            ProcEntry procEntry[];
   474        };
   475    }
   476    /*
   477     *  @(#) ti.sdo.ipc; 1, 0, 0, 0,445; 8-10-2010 17:48:33; /db/vtree/library/trees/ipc/ipc-e23x/src/
   478     */
   479