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