#!/usr/bin/perl
#     (c)2007-2011 Broadcom Corporation
#
#  This program is the proprietary software of Broadcom Corporation and/or its licensors,
#  and may only be used, duplicated, modified or distributed pursuant to the terms and
#  conditions of a separate, written license agreement executed between you and Broadcom
#  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
#  no license (express or implied), right to use, or waiver of any kind with respect to the
#  Software, and Broadcom expressly reserves all rights in and to the Software and all
#  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
#  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
#  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
#
#  Except as expressly set forth in the Authorized License,
#
#  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
#  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
#  and to use this information only in connection with your use of Broadcom integrated circuit products.
#
#  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
#  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
#  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
#  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
#  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
#  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
#  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
#  USE OR PERFORMANCE OF THE SOFTWARE.
#
#  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
#  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
#  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
#  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
#  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
#  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
#  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
#  ANY LIMITED REMEDY.
#
# $brcm_Workfile: bapi_thunks.pm $
# $brcm_Revision: 3 $
# $brcm_Date: 3/17/11 11:59a $
#
# File Description:
#
# Revision History:
#
# $brcm_Log: /nexus/build/tools/ipcthunk/bapi_thunks.pm $
# 
# 3   3/17/11 11:59a erickson
# SW7346-101: fix NEXUS_StopCallbacks for secondary destructors
#  (specifically, NEXUS_Playpump_ClosePidChannel)
#
# 2   1/19/11 2:03p erickson
# SW7420-1123: socket-based usermode IPC
#
# 1   9/29/10 9:34a erickson
# SW7420-1123: add linux usermode IPC
#
# 8   9/22/09 1:54p gmohile
# SW7405-3060 : Export kernel symbols
#
# 7   3/28/08 10:47a vsilyaev
# PR 40863: Call NEXUS_StopCalbacks prior to the 'destructor' call, since
#  StopCallback is sticky it would prevent further callback to fire
#
# 6   3/24/08 6:58p vsilyaev
# PR 40863: Changed order of calls to NEXUS_StopCallbacks and
#  "destructors" in ordder to stop callbacks that were fired during call
#  to the destructor function
#
# 5   3/24/08 6:42p vsilyaev
# PR 40863: Added injection of NEXUS_StopCallbacks into all destructors
#
# 4   3/21/08 11:57a vsilyaev
# PR 38682: Fixed typo in description
#
# 3   1/25/08 4:24p vsilyaev
# PR 38682: Reduce code size of the generated code
#
# 2   1/24/08 4:34p vsilyaev
# PR 38682: Reduced size and made optional tracing of thunk layer
#
# 1   1/18/08 2:15p jgarrett
# PR 38808: Merging to main branch
#
# Nexus_Devel/5   10/15/07 2:53p vsilyaev
# PR 35824: Fixed handling of (void) functions
#
# Nexus_Devel/4   10/12/07 11:49a erickson
# PR36066: added "or die" to file opens
#
# Nexus_Devel/3   10/8/07 3:21p erickson
# PR35395: added params and retval to trace
#
# Nexus_Devel/2   10/3/07 12:14p erickson
# PR35395: enable thunk trace
#
# Nexus_Devel/1   9/27/07 1:33p erickson
# PR35395: initial impl
#
#############################################################################
use strict;

package bapi_thunks;
use bapi_common;

sub build_thunks
{
    my ($module, $filename, $funcs) = @_;
    my $func;
    my $destructors = bapi_common::get_destructors $funcs;
    open FILE, ">$filename" or die;

    print FILE "/*********************************\n";
    print FILE "*\n";
    print FILE "* This file is autogenerated by the Nexus Platform makefile.\n";
    print FILE "*\n";
    print FILE "* This file acquires the module lock for every public API call into that module. The actual implementation of each function is remapped to _impl.\n";
    print FILE "*\n";
    print FILE "*********************************/\n";
    print FILE "#define NEXUS_THUNK_LAYER\n";
    print FILE "#include \"nexus_${module}_module.h\"\n";
    if(scalar keys %$destructors) {
        print FILE "#include \"nexus_core_utils.h\"\n";
    }
    print FILE "BDBG_MODULE(nexus_${module}_thunks);\n";
    print FILE "#define BDBG_MSG_TRACE(x) \n";
    print FILE "/* use local static function in order to reduce size of compiled code, size would reduce since NEXUS_XXXModule expanded to function call with three arguments (where at least one is a global symbol) */\n";
    print FILE "static void module_lock(void) { NEXUS_LockModule();}\n";
    print FILE "static void module_unlock(void) { NEXUS_UnlockModule();}\n";


    # generate prototypes for all the _impl functions
    for $func (@$funcs) {
        # NOTE: If there's an exception and a function does not belong in the thunk layer, add it here.

        my $impl = $func->{PROTOTYPE};
        $impl =~ s/$func->{FUNCNAME}/$func->{FUNCNAME}_impl/;
        print FILE "$impl;\n";
    }

    # generate the actual thunk layer functions which call the impl functions
    for $func (@$funcs) {
        my $params = $func->{PARAMS};
        my $param;

        print FILE "$func->{PROTOTYPE}\n\{\n";
        if ($func->{RETTYPE} eq "void") {
        }
        else {
            print FILE "  $func->{RETTYPE} result;\n";
        }

        # enter MSG
        print FILE "  BDBG_MSG_TRACE((\">%s\(";
        for $param (@$params) {
            print FILE "%#lx";
            if ($param != $params->[-1]) { print FILE ", "; }
        }
        print FILE ")\" ";
        print FILE ", \"$func->{FUNCNAME}\"";
        for $param (@$params) {
            print FILE ", ";
            print FILE "(unsigned long)$param->{NAME}";
        }
        print FILE "));\n";

        my $stopcallbacks_handle = bapi_common::get_stopcallbacks_handle $func, $destructors;
        if (defined $stopcallbacks_handle) {
            print FILE "  NEXUS_StopCallbacks($stopcallbacks_handle);\n";
        }

        # make call
        print FILE "  module_lock();\n";
        if ($func->{RETTYPE} eq "void") {
            print FILE "  $func->{FUNCNAME}_impl(";
        }
        else {
            print FILE "  result = $func->{FUNCNAME}_impl(";
        }
        for $param (@$params) {
            print FILE "$param->{NAME}";
            if ($param != $params->[-1]) { print FILE ", "; }
        }
        print FILE ");\n";
        print FILE "  module_unlock();\n";

        # leave MSG and return value
        if ($func->{RETTYPE} eq "void") {
            print FILE "  BDBG_MSG_TRACE((\"<%s\", \"$func->{FUNCNAME}\"));\n";
            print FILE "  return;\n";
        }
        else {
            print FILE "  BDBG_MSG_TRACE((\"<%s\=%#lx\", \"$func->{FUNCNAME}\", (unsigned long)result));\n";
            print FILE "  return result;\n";
        }
        print FILE "}\n\n";
    }
    close FILE;
}

sub build_remapping
{
    my ($filename, $funcs) = @_;
    my $func;
    open FILE, ">$filename" or die;

    print FILE "/*********************************\n";
    print FILE "*\n";
    print FILE "* This file is autogenerated by the Nexus Platform makefile.\n";
    print FILE "*\n";
    print FILE "* This file remaps every public API function to _impl. This allows the Nexus modules to call their own public API without reacquiring the module lock.\n";
    print FILE "*\n";
    print FILE "*********************************/\n";
    print FILE "#ifndef NEXUS_THUNK_LAYER\n";

    for $func (@$funcs) {
        print FILE "#define $func->{FUNCNAME} $func->{FUNCNAME}_impl\n";
    }
    print FILE "#endif\n";
    print FILE "\n";
    close FILE;
}

1;
