#!/bin/sh
#########################################################################
#                                                                       #
#                               NOTICE                                  #
#                                                                       #
#                  COPYRIGHT1999-2014 QLOGIC CORPORATION                #
#                        ALL RIGHTS RESERVED                            #
#                                                                       #
#  This script is CONFIDENTIAL  and contains TRADE SECRETS of           #
#  QLOGIC CORPORATION.  The  receipt or possession of this program does #
#  not convey any rights to reproduce or disclose  its contents,  or to #
#  manufacture, use, or sell anything that it may describe, in whole or #
#  in part, without the specific written consent of QLOGIC CORPORATION. #
#  Any reproduction of this program without the express written consent #
#  of QLOGIC CORPORATION  is a violation of the copyright laws and  may #
#  subject you to civil liability and criminal prosecution.             #
#                                                                       #
#########################################################################
#  set -x

SCRERR=200
ALLARGS=$*
VERSION=1.0.3
PROC=$$
export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
VERBOSE_MODE=0

#global variables
THIS_SCRIPT=$0
THIS_NIC_DRIVER=qlcnic
THIS_NIC_DRIVER_KO=${THIS_NIC_DRIVER}.ko
THIS_TEMP_DRIVER=${THIS_NIC_DRIVER}
THIS_TEMP_DRIVER_KO=${THIS_TEMP_DRIVER}.ko
TMP_SETUP_FILE=./qlflash.setup.tmp
LOCK_FILE=/tmp/.qlflash_lock_file
LOCK_ACTIVE=1
LOCK_VERBOSE=1

##Commands##

ETHTOOL=`type ethtool | awk '/is/{print $3}'`
LSPCI=`type lspci | awk '/is/{print $3}'`
INSMOD=`type insmod | awk '/is/{print $3}'`
RMMOD=`type rmmod | awk '/is/{print $3}'`
MODPROBE=`type modprobe | awk '/is/{print $3}'`
QLFLASH="./netscli -flashsupport"
SRCIPT_NAME=qlflash
MAIN_BIN=./netscli
RESTORED_TEMP_DRIVER=0
UNINSTALL_RESTORED_TEMP_DRIVER=1

##Global Modules

fn_init_QL_CNIC()
{
	nodriver_flag=0

	QL_CNIC=`grep -w "${THIS_NIC_DRIVER}" /proc/modules`
	if [ "$QL_CNIC" != "" ];then
		QL_CNIC=${THIS_NIC_DRIVER}
	fi

	if [ "$QL_CNIC" == "" ]; then
        	nodriver_flag=1
	fi

}
fn_init_QL_CNIC;
QL_CNIC_ONSTART=$QL_CNIC
QL_XDRV=""
QL_CNIC_PATH=""
QL_CNIC_CHECK=0

D_SWITCH_EXCEPTION=1
D_SWITCH_PRESENT=0
fn_check_d_switch()
{

	if [[ "$D_SWITCH_EXCEPTION" -eq 1 ]]; then

		#
		## check if -d is present 
		#

		MOD_ARGS=""
		ARGS=$*
		idx=1
		ARGSCNT=$#
		D_SWITCH_PRESENT=0

		while [[ $idx -le $ARGSCNT  ]];
		do	
			o=${!idx};

			# echo "step 1: processing option: $o";

			if [[ "-d" == "${o}" || "-D" == "${o}"  || "/d" == "${o}"  || "/D" == "${o}"  ]]; then
				D_SWITCH_PRESENT=1
				# echo "Switch $o found."
			fi

        		idx=$((idx + 1));
		done

	fi
}
fn_check_d_switch $*;

MYPATH=`readlink -f $0`
MYPATH="${MYPATH%/*}"

OPT_FILE_PRESENT=0
OPT_FILE=""
OPT_NOXDRV_PRESENT=0

ret_flag=0
nodowngrade=1
pci_map_fbd=-1
device_string=""
initsetupdone=0
rqmts=0
ethstr=""
pci=""

cmdstring=""
has_ip=0
int_index=0

## end ##

fn_check_log_switch()
{

                #
                ## check if -log is present
                #

                MOD_ARGS=""
                ARGS=$*
                idx=1
                ARGSCNT=$#
                LOG_SWITCH_PRESENT=0

                while [[ $idx -le $ARGSCNT  ]];
                do
                        o=${!idx};

                        # echo "step 1: processing option: $o";

                        if [[ "--log" == "${o}" || "-l" == "${o}"  ]]; then
                                LOG_SWITCH_PRESENT=1
                                # echo "Switch $o found."
                        fi

                        idx=$((idx + 1));
                done

}

fn_check_log_switch $*


if [[ "${LOG_SWITCH_PRESENT}" -eq 1 ]]; then

	if [[ "${QLFLASH_LOG}" != "" ]]; then
		QLFLASH_LOG=${QLFLASH_LOG}
	else
		QLFLASH_LOG=./qlflash.log
	fi
else
	QLFLASH_LOG=/dev/null
fi

fn_log()
{

	if [[ "$VERBOSE_MODE" -eq 1 ]]; then
		echo "$SRCIPT_NAME: "$*;
	else
		echo "$SRCIPT_NAME: "$* >> $QLFLASH_LOG
	fi
}


fn_log_n()
{
	if [[ "$VERBOSE_MODE" -eq 1 ]]; then
		echo -n $*;
	else
		echo -n $* >> $QLFLASH_LOG
	fi
}



err_log()
{
	if [[ "$VERBOSE_MODE" -eq 1 ]]; then
		echo "$SRCIPT_NAME: *** *** *** ERROR: "$*;
	else
		echo "$SRCIPT_NAME: *** *** *** ERROR: "$*  >> $QLFLASH_LOG;
	fi
}


fn_lock()
{
	if [[ "$LOCK_ACTIVE" != "1" ]]; then
		return 0
	fi

	fn_check_lock

	if [[ "$LOCK_VERBOSE" -eq 1 ]]; then 
		fn_log "Locking ..."
	fi

	mkdir $LOCK_FILE
	mkdir $LOCK_FILE/$PROC
}

fn_unlock()
{
	if [[ "$LOCK_ACTIVE" != "1" ]]; then
		return 0
	fi


	if [[ "$LOCK_VERBOSE" -eq 1 ]]; then 
		fn_log "Unlocking ..."
	fi

	if [[ "$1" == 1 ]]; then
		rm -rf $LOCK_FILE
	else

		# if [[ -f "$LOCK_FILE/$PROC" || -d "$LOCK_FILE/$PROC" ]]; then
		# 	rm -rf $LOCK_FILE
		# fi

		rm -rf $LOCK_FILE
	fi
}

fn_unlock_f()
{
	if [[ "$LOCK_VERBOSE" -eq 1 ]]; then 
		fn_log "Unlocking ..."
	fi

	rm -rf $LOCK_FILE
}


fn_lock_f()
{
	if [[ "$LOCK_VERBOSE" -eq 1 ]]; then 
		fn_log "Locking ..."
	fi

        mkdir $LOCK_FILE
        mkdir $LOCK_FILE/$PROC

}




fn_check_lock()
{

if [[ "$LOCK_ACTIVE" != "1" ]]; then
	return 0
fi

if [[ -f "$LOCK_FILE" || -d "$LOCK_FILE" ]]; then

	echo "Warning: Either another qlflash tool is already running, or your last session did not close gracefully."
	echo -e -n "$SRCIPT_NAME: Do you want to proceed anyway ? (Y/N)"
	read choice
	case $choice in
		[Yy])
			fn_unlock 1
			;;
		[nN])
			fn_log "Exiting....."
			exit "${SCRERR}"
			;;
		*)
			fn_log "Invalid choice. Exiting....."
			exit "${SCRERR}"
			;;
	esac
fi

}

fn_contains_in_args()
{
found=0
values=$*

for o in  $ARGS
do
	for p in $values
	do
		if [[ "${o}" == "${p}" ]]; then
			found=1
			break;
		fi
	done
done

return $found
}

fn_version()
{
	$QLFLASH -v	
}

fn_ei()
{
	$QLFLASH -ei
	echo "  ${SCRERR} qlflash script on error exit"
}

fn_usage()
{

fn_log ;
echo  "

NOTE: features --file and -noxdrv are available on Linux only
      See point 4.1 for more details

qlflash options:
==============================
-v | --version                    // Display version
-h | --help                       // Display help
-ei| --error-info                 // display error information

-noxdrv | --no-xdriver-swapping   // Skip driver uninstall/install
--file  <path/qlcnic.ko>          // Path/qlcnic.ko driver file
   NOTE: If a qlcnic driver is currently installed, the path/qlcnic.ko must be different than the path of currently installed driver
   NOTE: The above two options (-noxdrv,--file) are valid only for Linux OS and must precede all other options.
   NOTE: --file and -noxdrv Linux OS options are exclusive.
   NOTE: If neither --file  nor -noxdrv options are used, QLFlash will attempt to use a driver named ./qlnic.ko if in the same directory.
   NOTE: On Linux OS, the QLogic network interfaces may go offline during flash update unless the -noxdrv switch is specified.
   NOTE: The following exception was introduced:
           When --file is specified for discovery mode only (-d), the driver 
           specified by the --file switch will NOT be used unless there is no existing driver installed.

-verbose --verbose-mode           // display extra messages from the script

-asn | --activate <serial_number> // Activate flash update on adapter with specified serial number

-i | --interface <Bus:Device.Function>   // Set application interface prior to the following switches:
                                         // -a -info -w0 -w1 -p0 -p1 -val or equivallent full command switch name
                                         // The <Bus:Device.Function> information is displayed by -vi or -info switch

// The option -a is the primary command line option to update firmware flash image on the card
-a | --all [ql_romimage]          // Burn/update (all flash regions)
                                  // if file is not specified, the default file with name: ql_romimage
                                  // from working dir will be used, if present
-val | --validate  [ql_romimage]  // validate flash on the adapter vs. the flash in the file
-info | --information             // Display info for specified interface
                                  // (or all discovered adapters when interface not specified for -info)

// The options -d and -u are the primary commands used to interface with applications 
// that required XML input/output to discover and update firmware flash image on the card.
// See also -a as primary option to update firmware flash image on the card
-d | -D | /d | /D <flash_file>  [out_xml_file] [-p3]                    // Discovery with xml report
-u | -U | /u | /U <flash_file>  <input_xml_file>  [out_xml_file] [-p3]  // Flash update and xml report
                                                                        // -p3 is used for backwards
                                                                        // compatibility of xml structure of 
-w0 | --wol-off                   // Set Wake on LAN off
-w1 | --wol-on                    // Set Wake on LAN on
-p0 | --pxe-off                   // Set PXE LAN off
-p1 | --pxe-on                    // Set PXE LAN on

extras:

-vi | --view-all-interfaces       // view all available interfaces
-s | --supported <flash_file>     // display which of the installed adapters are supported by the specified flash file
-l | --log                        // Log extra information created by qlflash to ./qlflash.log 
                                  // --log needs to be first or last switch on the command line
                                  // The default name of the log may be renamed with evn. variable: export QLFLASH_LOG=qlflash.log
-verbose | --verbose-mode        // display messages generated by qlflash script

NOTE: There are no current plans to support the feature: "Restore flash using backup romimage".

NOTE: The following exception was introduced: 
           when --file is specified for discovery mode only (-d), 
           the driver specified by the --file switch will NOT be used unless there is no existing driver!
"

}

fn_hh()
{
# used only for int testing
# hidden features

fn_log ;

echo "
-ldop | --list-driver-on-port
-di | --driver-info

-lp | --list-ports
-std | --setup-temp-driver
-unstd | --unsetup-temp-drivers
"

}

fn_file()
{
	OPT_FILE_PRESENT=1
	OPT_FILE=$1
	
        if [ $# -ne 1 ] ; then
                err_log "Invalid values following --file options. Expecting path/driver_file_name. Use --help (-h) for usage."
                exit "${SCRERR}"
        fi

	if [ ! -f "$OPT_FILE" ]; then
		err_log "File: $OPT_FILE does not exist"
		exit "${SCRERR}"
	fi 

	FN=`basename $OPT_FILE`

	if [[ "$FN" != "${THIS_TEMP_DRIVER_KO}" ]]; then
		err_log "User entered file name: " `basename $OPT_FILE` "; Expecting file name: " `basename ${THIS_TEMP_DRIVER_KO}` 
		exit "${SCRERR}"
	fi

}

fn_verbose()
{
	VERBOSE_MODE=1
}


fn_set_verbose()
{
	fn_log "Setting verbose ... "
	ARGSCNT=$#
	idx=1

        while [[ $idx -le $ARGSCNT  ]];
        do
                o=${!idx};

		if [[ "-verbose" == "${o}"  ||  "--verbose-mode" == "${o}" ]]; then
			fn_verbose;
			break; 
		elif [[ "-h" == "${o}" || "--help" == "${o}" ]]; then
			fn_verbose;
			break; 
		elif [[ "-ei" == "${o}" || "--error-info" == "${o}" ]]; then
			#fn_verbose;
			fn_ei;
			ret=$?
			exit $ret
			break; 
		elif [[ "-hh" == "${o}"  ]]; then
			fn_verbose;
			break; 
		elif [[ "-v" == "${o}" || "--version" == "${o}" ]] ; then
			fn_verbose;
			break; 
		elif [[ "-ldop" == "${o}" || "--list-driver-on-port" == "${o}" ]] ; then
			fn_verbose;
			break; 
		elif [[ "-lp" == "${o}" || "--list-ports" == "${o}" ]] ; then
			fn_verbose;
			break; 
		elif [[ "-di" == "${o}" || "--driver-info" == "${o}" ]] ; then
			fn_verbose;
			break; 
		elif [[ "-t" == "${o}" || "--test" == "${o}" ]] ; then
			fn_verbose;
			break; 
		fi

		idx=$((idx + 1))
	done


}

fn_noxdrv()
{
	OPT_NOXDRV_PRESENT=1
}


fn_check_components()
{

	if [[ ! -f "$MAIN_BIN"  ]]; then
		err_log "Required component: $MAIN_BIN is missing"
		exit "${SCRERR}"
	fi

}

fn_check_driver_installation()
{
        nic=`grep -w "${THIS_NIC_DRIVER}" /proc/modules`
	tmp=`grep -w "${THIS_TEMP_DRIVER}" /proc/modules`

        if [[ "$nic" == "" || "$tmp" == ""  ]]; then
		fn_log "Warning: QLogic driver is not installed"
        fi

}



fn_get_err_from_xml_results()
{

	if [[ "${LOG_SWITCH_PRESENT}" -eq 0 && "${VERBOSE_MODE}" -eq 0 ]]; then
		return 0;
	fi

	# echo "Args: " $#

	if [[ $# -lt 4 ]]; then
		return 0
	fi



         #
         ## check if -d is present
         #

         MOD_ARGS=""
         ARGS=$*
         idx=0
         ARGSCNT=$#
         D_SWITCH_IDX=-1
	 xml_file=""

         while [[ $idx -le $ARGSCNT  ]];
         do
              o=${!idx};

              # echo "step 1: processing option: $o";

              if [[ "-u" == "${o}" || "-U" == "${o}"  || "/u" == "${o}"  || "/U" == "${o}"  ]]; then
                     D_SWITCH_IDX=${idx}
                     # echo "Switch $o found. D_SWITCH_IDX: ${D_SWITCH_IDX}"
              fi

	      if [[ "${D_SWITCH_IDX}" -ge 0   ]]; then
			xml_idx=$((D_SWITCH_IDX+3));
			if [[ "${xml_idx}" < "$#" ]]; then
				xml_file="${!xml_idx}" 
				break;
			fi

	      fi

              idx=$((idx + 1));
         done


	if [[ "${xml_file}" != "" ]]; then
		if [[ -f "${xml_file}" ]]; then

			str=`grep "message value" ${xml_file} | grep -i error 2> /dev/null`
			if [[ "${str}" != "" ]]; then
				err_log "Error message(s) in ${xml_file} "
				err_log "${str}"
			fi
		fi
	fi

}


fn_main_execute()
{
	args=$*
	qlflash_ret=1

	fn_lock


	fn_check_components;

	if [[  "$OPT_NOXDRV_PRESENT" == 1 ]]; then

		fn_log "About to execute args: $args"
		sync
		fn_check_driver_installation;
		$QLFLASH $args
		qlflash_ret=$?

	else

		fn_InitSetup
		if [ "$?" != "0" ]; then
			err_log "Failed to Initialize Setup."
			fn_ClearSetup 0
			exit "${SCRERR}"
		fi

		fn_log "About to execute args (with updated driver): $args"
		sync
		fn_check_driver_installation;
		$QLFLASH $args
		qlflash_ret=$?

		fn_ClearSetup 0

	fi

	fn_uninstall_restored_temp_driver;


	if [ "$qlflash_ret" != "0" ]; then	
		err_log "Failed to execute args: $args"		
		fn_get_err_from_xml_results $args
	else
		fn_log "Succesfully executed args: $args"		
	fi


	fn_unlock

	exit $qlflash_ret
}



fn_test()
{
        args=$*

	i=0
	max=12
	while [[ "$i" -lt "$max" ]] 
	do
		fn_log "Sleeping 1 sec (${i}) of $max"
		sleep 1;
		i=$(( i + 1 ))
	done


        ret=$?
        return $ret
}



fn_ld()
{
	DEVICES=$(awk '/:/ && !/\<lo\>/ { print substr($1,0,index($1,":")-1)}'  /proc/net/dev);
	
	for dev in $DEVICES
	do
		echo ""
		fn_log ">>>   Checking: $dev"
		ethtool -i $dev 

		ver=$( ethtool -i $dev | grep -i "^version" |  cut -d':'  -f 2)
		ver=$( echo $ver )
		fn_log "ver=\"$ver\""
	done
}


fn_get_ver()
{
	dev=$1
	ver=$( ethtool -i $dev | grep -i "^version" |  cut -d':'  -f 2)
        RET_VER=$( echo $ver )
}

fn_save_cfg()
{
	echo "initsetupdone=$initsetupdone" > $TMP_SETUP_FILE
	echo "QL_CNIC_CHECK=$QL_CNIC_CHECK"  >> $TMP_SETUP_FILE
}


fn_setup_temp_drivers()
{
	fn_log "Initializing temporary setup."
	fn_InitSetup;
	fn_save_cfg
}

fn_unsetup_temp_drivers()
{
	fn_log "Clearing temporary setup."
	if [ -f $TMP_SETUP_FILE ]; then
		. ./$TMP_SETUP_FILE
		fn_ClearSetup 0
		fn_save_cfg
	fi
}

fn_Display_Ports()
{
	devices=`$LSPCI -d 4040:|wc -l`
	k=0
	iterator=1;
	pslot_orig="255";

	if [ $devices -eq 0 ] ; then
		fn_log "No QLogic Devices found on the Machine"
		exit 0
	fi

	fn_log ""
	fn_log "Valid Device Numbers are:"
	fn_log ""
	while [ $k -lt $devices ]
	do
		pslot=`$LSPCI -d4040: | awk ' /:/ {print $1 }'|sed -n "$iterator"p | cut -d: -f1`
		function_id=`$LSPCI -d4040: | awk ' /:/ {print $1 }'|sed -n "$iterator"p | cut -d: -f2|cut -d . -f2`	
	        fbd_local=`/sbin/lspci -d4040: |cut -d " " -f 1 |sed -n "$iterator"p`
		if [ "$pslot" != "$pslot_orig" ]
		then
			pslot_orig=$pslot;
			i=0;
		fi
		check_mgmt=`$LSPCI -d4040: | grep "Mgmt" |sed -n "$iterator"p|wc -l`
		if [ $check_mgmt -eq 0 ]; then
			
		fn_log "[$k] " `$LSPCI -d 4040: -v | grep Subsystem | cut -d " " -f4-12 |sed -n "$iterator"p` "[PCI slot $pslot function $function_id]" "[Corresponding BDF $fbd_local]"
		fn_log ""
		i=$(($i+1));
		k=`expr $k + 1`
		else
			devices=`expr $devices - 1`	
		fi
		iterator=`expr $iterator + 1`
	done
}

fn_driver_info()
{
#
# ###
#

	fn_log ""
	fn_log "Looking for ${THIS_NIC_DRIVER} driver ... "

	fnd=0

	fn_log "Lookin in /proc/modules ..."
	nic=`grep -w "${THIS_NIC_DRIVER}" /proc/modules`
	fn_log "nic in /proc/modules: $nic"
	if [ "$nic" != "" ]; then
		nic=${THIS_NIC_DRIVER}
	fi

	v=$(modinfo ${nic} 2>/dev/null | grep "^version" |cut -d':' -f 2)

	if [[ "$nic" != "" ]]; then
		fn_log "Found> Loaded driver: $nic version: $v"
		fnd=1
	fi

	if [[ "$fnd" -eq 0 ]]; then
		fn_log "... not found"
	fi


#
# ###
#

	fnd=0

	fn_log ""
	fn_log "Looking in list generated by lsmod ..."
	nic=`lsmod | grep -w "${THIS_NIC_DRIVER}" `
	fn_log "nic in list generated by lsmod: $nic"
	if [ "$nic" != "" ]; then
		nic=${THIS_NIC_DRIVER}
	fi

	v=$(modinfo ${nic} 2>/dev/null | grep "^version" |cut -d':' -f 2)

	if [[ "$nic" != "" ]]; then
		fn_log "Found> Loaded driver: $nic version: $v"
		fnd=1
	fi

	if [[ "$fnd" -eq 0 ]]; then
		fn_log "... not found"
	fi



#
# ###
#
	fnd=0

	kernel=$( echo /lib/modules/`uname -r` )
	fn_log ""
	fn_log "Looking in kernel: $kernel ..." 
	locs=$( echo `find $kernel -name ${THIS_NIC_DRIVER_KO} ` )

	for loc in $locs
	do
		v=$(modinfo ${loc} 2>/dev/null | grep "^version" |cut -d':' -f 2)
		fn_log "Found> Installed driver: $loc version: $v"
		fnd=1
	done

	if [[ "$fnd" -eq 0 ]]; then
		fn_log "... not found"
	fi

#
# ###
#
	fnd=0


	dir=`dirname $THIS_SCRIPT`
	loc=$dir/${THIS_NIC_DRIVER_KO}
	fn_log ""
	fn_log "Looking in QLFlash package for ${loc}  ..."
	v=$(modinfo ${loc} 2>/dev/null | grep "^version" |cut -d':' -f 2)

	if [[ "$loc" != "" && -f "$loc" ]]; then

		fn_log "Found> In-package driver: $loc version: $v"
		fnd=1
	fi

	if [[ "$fnd" -eq 0 ]]; then
		fn_log "... not found"
	fi


}

fn_check_and_process_args()
{


	if [[ $# -lt 1 ]] ; then
		fn_verbose;
		err_log "Invalid options. Use --help (-h) for usage."
		exit "${SCRERR}"
	elif [[ $# -eq 1 ]] ; then
		fn_contains_in_args -verbose --verbose-mode
		contains_verbose=$?
		if [[ "$contains_verbose" -eq 1 ]]; then
			fn_verbose;
			err_log "Invalid options. Use --help (-h) for usage."
			exit "${SCRERR}"
		fi
	fi


	MOD_ARGS=""
	ARGS=$*
	idx=1
	ARGSCNT=$#

	while [[ $idx -le $ARGSCNT  ]];
	do	

		o=${!idx};

		# fn_log "step 1: processing option: $o";

		if [[ "-h" == "${o}" || "--help" == "${o}" ]]; then
			fn_usage;
			exit 0
		elif [[ "-hh" == "${o}"  ]]; then
			fn_hh;
			exit 0
		elif [[ "-unlock" == "${o}"  ]]; then
			fn_unlock_f;
			exit 0
		elif [[ "-lock" == "${o}"  ]]; then
			fn_lock_f;
			exit 0
		elif [[ "-verbose" == "${o}"  ||  "--verbose-mode" == "${o}" ]]; then
			fn_verbose;
		elif [[ "-v" == "${o}" || "--version" == "${o}" ]] ; then
			fn_version;
			exit 0
		elif [[ "--file" == "${o}"  ]]; then
        		idx=$((idx + 1));
			if [[ "$D_SWITCH_EXCEPTION" -eq 1 && "$nodriver_flag" == "0" && "$D_SWITCH_PRESENT"  -eq 1 ]]; then
				fn_log "Ignoring switch ${o} as exception during discovery ..."
			else
                        	fn_file ${!idx} ; 
			fi
		elif [[ "--no-xdriver-swapping" == "${o}" ||  "-noxdrv" == "${o}" ]]; then
                        fn_noxdrv;
		elif [[ "-t" == "${o}" || "-test" == "${o}"  ]]; then
			fn_test $ARGS
			ret=$?
			exit $ret
#
### extras
#

		elif [[ "-ldop" == "${o}" || "--list-driver-on-port" == "${o}" ]] ; then
			fn_ld;
			ret=$?
			exit $ret
		elif [[ "-lp" == "${o}" || "--list-ports" == "${o}" ]] ; then
			fn_Display_Ports;
			ret=$?
			exit $ret
		elif [[ "-di" == "${o}" || "--driver-info" == "${o}" ]] ; then
			fn_driver_info;
			ret=$?
			exit $ret
		elif [[ "--log" == "${o}" || "-l"  == "${o}" ]] ; then
			dummy=dummy;
		else
			MOD_ARGS="$MOD_ARGS ${o} "
		fi

        	idx=$((idx + 1));

	done

	
	if [[ "$OPT_FILE_PRESENT" -eq 1 && "$OPT_NOXDRV_PRESENT" -eq 1 ]]; then
		err_log "Optons --file and -noxdrv are exclusive. Use --help (-h) for usage."
		exit "${SCRERR}"
	fi


	if [[ "$OPT_FILE_PRESENT" -eq 0 && "$OPT_NOXDRV_PRESENT" -eq 0 ]]; then


		if [ "$QL_CNIC" != "" ]; then
			OPT_NOXDRV_PRESENT=1
		else

			kernel=$( echo /lib/modules/`uname -r` )
                        nx_xport_loc=$( echo `find $kernel -name ${THIS_TEMP_DRIVER_KO} ` )

			if [[ "$nx_xport_loc" != "" ]]; then
				v=$(modinfo ${nx_xport_loc} 2>/dev/null | grep "^version" |cut -d':' -f 2)
				if [[ "$v" != "" ]]; then
					fn_log "Atempting to load $nx_xport_loc driver version: $v"
				else
					fn_log "Atempting to load $nx_xport_loc driver"
				fi
                        	$INSMOD $nx_xport_loc > /dev/null 2>&1
                        	if [ "$?" != "0" ]; then
					fn_log "Warning: Attempt to load $nx_xport_loc failed"	
				else
					RESTORED_TEMP_DRIVER=1
					fn_log "Loaded $nx_xport_loc driver"	
				fi
			fi

			fn_init_QL_CNIC;

			if [ "$QL_CNIC" != "" ]; then
				OPT_NOXDRV_PRESENT=1
			else

				driver_file=./$THIS_TEMP_DRIVER_KO
				if [ -f $driver_file  ]; then
					fn_log "Attempting to use driver file: $driver_file"
					OPT_FILE_PRESENT=1
					OPT_FILE=$driver_file
				else
					err_log "One of --file <path/${THIS_TEMP_DRIVER_KO}> or -noxdrv must be specified as first parameter. Use --help (-h) for usage."
					exit "${SCRERR}"
				fi
			fi
		fi
	fi


	# fn_log "MOD_ARGS=\"$MOD_ARGS\"" ;

	fn_check_and_process_args_step2 $MOD_ARGS;


}

fn_check_and_process_args_step2()
{

	MOD_ARGS=$*
	idx=1
	argcnt=$#
	while [[ "$idx" -le "$argcnt"  ]];
	do
		o=${!idx};
		# fn_log "step 2: Processing ${o}"

		if [[ "--interface" == "${o}" || "-i" == "${o}" ]]; then
			fn_main_execute $MOD_ARGS;
		elif [[ "-vi" == "${o}" ||  "--view-all-interfaces" == "${o}" ]]; then
                        fn_main_execute $MOD_ARGS;
		elif [[ "-bh" == "${o}" ||  "--boardcfg-help" == "${o}" ]]; then
                        fn_main_execute $MOD_ARGS;
		elif [[ "-b" == "${o}" ||  "--boardcfg" == "${o}" ]]; then
                        fn_main_execute $MOD_ARGS;
		elif [[ "--all" == "${o}" || "-a" == "${o}" ]]; then
			fn_main_execute $MOD_ARGS;
		elif [[ "--validate" == "${o}" || "-val" == "${o}" ]]; then
			fn_main_execute $MOD_ARGS;
		elif [[ "--information" == "${o}" || "-info" == "${o}" ]]; then
			fn_main_execute $MOD_ARGS;
		elif [[ "--wol-off" == "${o}" || "-w0" == "${o}" ]]; then
			fn_main_execute $MOD_ARGS;
		elif [[ "--wol-on" == "${o}" || "-w1" == "${o}" ]]; then
			fn_main_execute $MOD_ARGS;
		elif [[ "--pxe-off" == "${o}" || "-p0" == "${o}" ]]; then
			fn_main_execute $MOD_ARGS;
		elif [[ "--pxe-on" == "${o}" || "-p1" == "${o}" ]]; then
			fn_main_execute $MOD_ARGS;
		elif [[ "-d" == "${o}" || "-D" == "${o}"  || "/d" == "${o}"  || "/D" == "${o}"  ]]; then
			fn_main_execute $MOD_ARGS;
		elif [[ "-s" == "${o}" ||  "--supported" == "${o}" ]]; then
			fn_main_execute $MOD_ARGS;
		elif [[ "-asn" == "${o}" ||  "--activate" == "${o}" ]]; then
        		# idx=$((idx + 1));
			# o=${!idx};
			# MOD_ARGS="$MOD_ARGS ${o}"
			fn_main_execute $MOD_ARGS;
		elif [[ "-u" == "${o}" || "-U" == "${o}" || "/u" == "${o}" || "/U" == "${o}"  ]]; then
			fn_main_execute $MOD_ARGS;
#
### extras
#
		elif [[ "-std" == "${o}" || "--setup-temp-driver" == "${o}" ]] ; then
			fn_setup_temp_drivers;
			ret=$?
			exit $ret
		elif [[ "-unstd" == "${o}" || "--unsetup-temp-drivers" == "${o}" ]] ; then
			fn_unsetup_temp_drivers;
			ret=$?
			exit $ret
		else
			MOD_ARGS="$MOD_ARGS ${o} "
			err_log "Unexpected option \"${o}\". Use --help (-h) for usage."
			exit "${SCRERR}"
		fi

		idx=$((idx +1)):

	done

}

fn_restore_driver()
{

	if [[ $QL_CNIC_CHECK -eq 1 ]]
	then
		for qlogic_path in $QL_CNIC_PATH
		do
			DIRNAME=`dirname ${qlogic_path}`
			mv -f $DIRNAME/qlogic.${THIS_NIC_DRIVER_KO} $DIRNAME/${THIS_NIC_DRIVER_KO}
	 		QL_CNIC_CHECK=0
		done
	fi

}



fn_load_drivers()
{

	fn_log "Restoring drivers ..."
	ret=0

	fn_restore_driver

	if [ "$QL_CNIC" != "" ]; then
		grep -q ${THIS_NIC_DRIVER} /proc/modules
		if [ $? -eq 0 ] ; then
			$RMMOD ${THIS_NIC_DRIVER}
		fi	
		$MODPROBE ${THIS_NIC_DRIVER}
		if [ "$?" != "0" ]; then
			err_log ${THIS_NIC_DRIVER} "driver failed to load."
			ret=1
		fi
	fi


       if [ $has_ip -eq 1 ]; then
		i=0
		fn_log "Restoring IP addresses"
		while [ $i -lt $int_index ]
		do
			echo ${cmdstring[$i]}
			`${cmdstring[$i]}`
			i=`expr $i + 1`
		done
	fi


	if [ "$ret" == 0 ]; then
		v=$(modinfo ${THIS_NIC_DRIVER} 2>/dev/null | grep "^version" |cut -d':' -f 2)
		if [[ "$v" != "" ]]; then
			fn_log "Restored ${THIS_NIC_DRIVER} driver version: $v"
		else
			fn_log "Restored ${THIS_NIC_DRIVER} driver"
		fi
	fi

        return $ret
}



fn_get_absolute_path()
{
	file=$1
	RET_FILE=""

	if [[ "${file}" == "" ]]; then
		return 1;
	fi

	if [[ ! -f ${file} ]]; then 
		return 1;
	fi

	ch=`echo ${file}| cut -c 1 2>/dev/null`

	if [[ ${ch} == "/" ]]; then
		RET_FILE=${file}
	else
		cur_dir=`pwd  2>/dev/null`
		dname=`dirname ${file}  2>/dev/null`
		fname=`basename ${file}  2>/dev/null`

		if [[ -d "${dname}" && -f "${fname}" ]]; then

			cd $dname;
			cdir=`pwd`

			fle=${cdir}/${fname}
			if [[ "${fle}" != "" && -f "${fle}" ]]; then
				RET_FILE=${fle}
			fi

			# fle=`find $cdir -name $fname 2>/dev/null `;
			# if [[ "${fle}" != "" ]]; then
			# 	# echo "fle: $fle"
			# 	RET_FILE=${fle}
			# fi
		fi

		cd ${cur_dir}
	fi


	return 0;
}

fn_check_driver_used_by_user()
{
        installed_driver=$1
        after_file_switch_driver=${OPT_FILE}

	fn_get_absolute_path ${installed_driver};
	installed_driver_abspath=${RET_FILE}

	fn_get_absolute_path ${after_file_switch_driver};
	after_file_switch_driver_abspath=${RET_FILE}


	if [[ ${installed_driver_abspath} != "" && ${after_file_switch_driver_abspath} != "" ]]; then

		if [[ "${installed_driver_abspath}" == "${after_file_switch_driver_abspath}" ]]; then
			# display eror only when both paths are valid and same
			fn_log "Specified file: ${after_file_switch_driver_abspath}"
			fn_log "AND installed driver: ${installed_driver_abspath} have SAME location"
			fn_log "The user is expected to specify a different driver location following --file switch"
			return 1
		fi
	fi

	# fn_log "INFO:"
	# fn_log "installed_driver: ${installed_driver}; installed_driver_abspath: ${installed_driver_abspath} "
	# fn_log "after_file_switch_driver: ${after_file_switch_driver}; after_file_switch_driver_abspath: ${after_file_switch_driver_abspath} "

}


fn_save_driver()
{
	type=$1
	kernel=$(echo /lib/modules/`uname -r` )

	v=$(modinfo ${THIS_NIC_DRIVER} 2>/dev/null | grep "^version" |cut -d':' -f 2)
	if [[ "$v" != "" ]]; then
		fn_log "Saving qlnic driver version: $v"
	else
		fn_log "Saving qlnic driver"
	fi

	if [[ $type == "${THIS_NIC_DRIVER}" ]]
	then
		 QL_CNIC_PATH=$( echo `find $kernel -name ${THIS_NIC_DRIVER_KO}` )
		 if [[ $QL_CNIC_PATH != "" ]]
		 then
			for qlogic_path in  $QL_CNIC_PATH
			do
				fn_log "NIC driver ${THIS_NIC_DRIVER} will be temporarily unloaded. "
				DIRNAME=`dirname ${qlogic_path}`
				fn_check_driver_used_by_user $DIRNAME/${THIS_NIC_DRIVER_KO}
				if [ "$?" != "0" ]; then
					fn_log "Skipping save driver operation. The driver specified by --file switch points to the installed driver"
					return 1;
				fi
			 	mv -f  $DIRNAME/${THIS_NIC_DRIVER_KO} $DIRNAME/qlogic.${THIS_NIC_DRIVER_KO}
				QL_CNIC_CHECK=1
			done
		fi 
	fi

}


fn_unload_drivers()
{

	ALLDEV=$(awk '/:/ && !/\<lo\>/ { print substr($1,0,index($1,":")-1)}' /proc/net/dev)
	
	ret_flag=0
	fn_log_n "$SRCIPT_NAME: Closing interfaces: "
	for dev in $ALLDEV
	do
		drv=$($ETHTOOL -i $dev 2>/dev/null | awk '/^driver/ {print $2}')
		case $drv in
			"${THIS_NIC_DRIVER}")
				QL_CNIC="${THIS_NIC_DRIVER}"
				;;
			*)
				continue
				;;
		esac
		fn_log_n "$dev "
		interface=$dev
		ip_addr=`ifconfig $interface | grep "inet addr:" | awk '{ print $2 }'|cut -d : -f2`
		ip6_addr=`ifconfig $interface | grep "inet6 addr:" | grep "Global" |awk '{ print $3 }'`
		mask=`ifconfig $interface | grep "inet addr:" | awk '{ print $4 }'|cut -d : -f2`
		temp=`echo "ifconfig $interface $ip_addr netmask $mask up"`
		temp6=`echo "/sbin/ip -6 addr add $ip6_addr  dev $interface"`
		#echo $temp
		if [ "$ip_addr" != "" ]; then
			has_ip=1;
			cmdstring[$int_index]=$temp
			int_index=`expr $int_index + 1`
		fi

		if [ "$ip6_addr" != "" ]; then
			has_ip=1;
			local_temp=`echo "ifconfig $interface up"`
			cmdstring[$int_index]=$local_temp
			int_index=`expr $int_index + 1`
			cmdstring[$int_index]=$temp6
			int_index=`expr $int_index + 1`
		fi

		ifconfig $dev down
		if [  "$?" != "0" ]; then
		       fn_log_n "[failed] "
		       ret_flag=1
		fi

	done
	echo ""
	fn_log ""

	if [ "$ret_flag" -eq "1" ]; then
		exit "${SCRERR}"
	fi


	if [ "$QL_CNIC" != "" ]; then
	fn_save_driver ${THIS_NIC_DRIVER}
	$RMMOD ${THIS_NIC_DRIVER}
		if [ "$?" != "0" ]; then
		err_log ${THIS_NIC_DRIVER} "driver failed to unload."
		ret_flag=1;
		fi
	fi

	if [ "$ret_flag" -eq "1" ]; then
		fn_restore_driver
		exit "${SCRERR}"
	fi
}


fn_InitSetup()
{

	if [ $initsetupdone -eq 1 ]; then
		return 0
	fi

	#if [[ "$D_SWITCH_EXCEPTION" -eq 1 && "$nodriver_flag" == "0" && "$D_SWITCH_PRESENT"  -eq 1 ]]; then
	#	return 0
	#fi


	if [ "$nodriver_flag" == "0" ]; then
		fn_unload_drivers
	fi

	xport_file_location=${THIS_TEMP_DRIVER}

	if [ "$QL_XDRV" == "" ]; then

		xport_file_location=$OPT_FILE
		if [ "$xport_file_location" != "" ]; then
			nx_xport_loc=$xport_file_location
			$INSMOD $nx_xport_loc > /dev/null 2>&1
			if [ "$?" != "0" ]; then
				err_log "Failed to load QLogic ${THIS_TEMP_DRIVER_KO} Driver from $OPT_FILE" 
				err_log "Please use --file option to provide path to QLogic ${THIS_TEMP_DRIVER_KO} Driver."
				return 1
			fi
		else
			fn_log "Please use --file option to provide path to QLogic ${THIS_TEMP_DRIVER_KO} Driver."
			return 1
		fi

	fi

	v=$(modinfo  ${xport_file_location} 2>/dev/null | grep "^version" |cut -d':' -f 2)
	fn_log "Installed temp ${THIS_NIC_DRIVER} driver version $v"
	initsetupdone=1
	return 0

}


fn_uninstall_restored_temp_driver()
{
	if [[ $UNINSTALL_RESTORED_TEMP_DRIVER -eq 1 ]]; then
		if [[ $RESTORED_TEMP_DRIVER -eq  1 && "$QL_CNIC_ONSTART" == ""  ]]; then

        		v=$(modinfo ${THIS_NIC_DRIVER} 2>/dev/null | grep "^version" |cut -d':' -f 2)

        		grep -q ${THIS_TEMP_DRIVER} /proc/modules
        		if [ $? -eq 0 ]; then

        			if [[ "$v" != "" ]]; then
					fn_log "Uninstalling temporarily restored driver version: $v."
        			else
					fn_log "Uninstalling temporarily restored driver."
        			fi

                		$RMMOD ${THIS_TEMP_DRIVER}
				if [[ "$?" == "0" ]]; then
					RESTORED_TEMP_DRIVER=0
				fi
			fi
		fi
	fi
}



fn_ClearSetup()
{

	if [ "$1" != "0" ]; then
		echo -e  "\n"
		fn_log "Received a signal ........"
	fi

	grep -q ${THIS_TEMP_DRIVER} /proc/modules
	if [ $? -eq 0 ]; then
		v=$(modinfo  ${xport_file_location} 2>/dev/null | grep "^version" |cut -d':' -f 2)
		if [[ "$v" != "" ]]; then
			fn_log "Removed temp driver: ${THIS_TEMP_DRIVER} version: $v"
		else
			fn_log "Removed temp driver: ${THIS_TEMP_DRIVER}"
		fi
		$RMMOD ${THIS_TEMP_DRIVER}
	fi

	if [ "$nodriver_flag" == "0" ]; then
		fn_log "Please wait while QLogic drivers are being restored ..."
		fn_load_drivers
		ret=$?

		if [[ "$ret" == "0" ]]; then
			fn_log "Successfully restored drivers."
		else
			err_log "Failed ot load drivers."
		fi
	fi
	initsetupdone=0
	if [ "$1" != "0" ]; then
		fn_unlock
                exit "${SCRERR}"
        fi


	fn_uninstall_restored_temp_driver;

	fn_unlock
}



fn_main()
{

	trap fn_ClearSetup SIGINT SIGTERM

    # delete $QLFLASH_LOG

        trimmed_log=`echo "${QLFLASH_LOG}" | sed -e 's/^[ \t]*//'`

        if [[ "${QLFLASH_LOG}" != "/dev/null" ]]; then
                if [[  "${trimmed_log}" != "/dev/null"  ]]; then
                        if [[ -f "${trimmed_log}" ]]; then
                                rm -f $QLFLASH_LOG
                        fi
                else
                        donotdelete=donotdelete
                fi
        else
                donotdelete=donotdelete
        fi


	# clear

	ARGS=$*

	fn_set_verbose $ARGS

	ver=` $QLFLASH -v 2>/dev/null`

	fn_contains_in_args -v --version
	contains_v=$?
	fn_contains_in_args -verbose --verbose-mode
	contains_verbose=$?

	if [[ "$contains_v" -eq "1" && "$contains_verbose" -eq "0" ]]; then
		skip=skip
	else

		if [[ "$ver" !=  "" ]]; then
			fn_log "QLFlash version: $ver"
		else
			fn_log "QLFlash"
		fi
	fi

	IS_ROOT=`whoami`

	if [ "$IS_ROOT" != "root" ]; then
		err_log "root privileges required to run this application."
                exit "${SCRERR}"
	fi

	fn_check_and_process_args $ARGS;

}

#
#####
#

# fn_main $* 2>&1 | tee qlflash.log ;
fn_main $*  ;

