#!/bin/bash 
#*****************************************************************************
# Copyright 2004-2011 NetApp, Inc.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation,  version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#*****************************************************************************
#  Script %name:	mppBusRescan26p %
#  Instance:		WIC_1
#  %version:		25 %
#  Description:		
#  %created_by:		somasunk %
#  %date_created:	Mon Apr 16 15:26:33 2012 %
#  Description:         This script is called to scan any new NetApp E-Series 
#                       devices that are added after the system reboot.
#*****************************************************************************
#  Function:   mppLnx_isIscsiDriverLoaded
#  Description:  Check if software iscsi initiator is running on the system
#      return 0 -- if it is not running
#             1 -- if the old version of Linux software iSCSI initiator is running
#             2 -- if the newer version of Linux software iSCSI initiator or open
#                  iscsi software initiator is running
#*****************************************************************************
mppLnx_isIscsiDriverLoaded()
{
   OLD_ISCSI_SYS_HOST_DIR=/sys/class/scsi_host/iscsi
   NEW_ISCSI_SYS_HOST_DIR=/sys/class/iscsi_host
   if [ -d ${OLD_ISCSI_SYS_HOST_DIR} ]
   then
      echo "1"
   elif [ -d ${NEW_ISCSI_SYS_HOST_DIR} ]
   then
      echo "2"
   else
      echo "0"
   fi
}

#*****************************************************************************
#  Function:   mppLnx_init_fn
#  Description:  Initialize and export all needed variables
#*****************************************************************************
mppLnx_init_fn()
{
    IS_SOFTWARE_ISCSI=$(mppLnx_isIscsiDriverLoaded)
    export     IS_SOFTWARE_ISCSI
    # This is to handle the new method by which qla names its /sys interface
    export    QLA_PROC="qla2"
    export    QLA4x_PROC="qla4xxx"
    export    LSI_SCSIHPROC="mptscsih"
    export    LSI_SASPROC="mptsas"
    export    LSI_SAS2PROC="mpt2sas"
    export    LSI_FCPROC="mptfc"
    export    IBM_SCSIPROC="ipr"
    export    EMX_PROC="lpfc"
    export    BFA_PROC="bfa"
    export    CELERITY8FC_PROC="celerity8fc"
    export    BE2ISCSI_PROC="be2iscsi"
    export    MTL_PROC="srp"
    export    MTL_QDR_PROC="mlx4_core"
    export    MTX_PROC="ib_mthca"
    export    ICS_PROC="failover_"
    export    MPP_PROC="mpp"
    export    QLA_SCAN="scsi-qlascan"
    export    QLA4x_SCAN=""
    export    LSI_SCAN=""
    export    IBM_SCAN=""
    export    EMX_SCAN=""
    export    BFA_SCAN=""
    export    CELERITY8FC_SCAN=""
    export    BE2ISCSI_SCAN=""
    export    MTL_SCAN=""
    export    MTX_SCAN=""
    export    ICS_SCAN=""
    export    ICS_PROC_DRIVER="/proc/driver/ics_srp/driver"
    export    ICS_CFG="/etc/sysconfig/ics_srp.cfg"
    export    SCAN_SLEEP_TIME=5
    export    MPPLNX_MAGIC_LINE="mpplnx_magic_line"
    export    NEWLINE=$'\n'
    export    MPPLNX_MAGIC_LINE="mpplnx_magic_line"
    export    TMP_SCRIPT="/tmp/mpp_hotadd$$"
    export    MPP_UPPER_SYS_FILE="/sys/bus/scsi/drivers/mpp"
    export    MPP_PROC_FILE="/proc/scsi/mpp"
    export    LS_MPP_DEVS="/bin/ls -d -1  /sys/bus/scsi/drivers/mpp/*:* 2>/dev/null"
    #SCSI_ENTRY contains a list of all files in /proc/scsi directory
    
    #  SLES9 and AS4 /proc/scsi entries
    #/proc/scsi/mpp/10
    #/proc/scsi/mptfc/3
    #/proc/scsi/mptfc/2
    #/proc/scsi/sg/version
    #/proc/scsi/sg/device_strs
    #/proc/scsi/sg/devices
    #/proc/scsi/sg/device_hdr
    #/proc/scsi/sg/def_reserved_size
    #/proc/scsi/sg/debug
    #/proc/scsi/sg/allow_dio
    #/proc/scsi/device_info
    #/proc/scsi/scsi

    SCSI_ENTRY="$(find /sys/bus/pci/drivers -follow -maxdepth 3 -type d -name 'host*' -print 2>/dev/null)"
    #we need to fake a mpp entry
    if [ -d ${MPP_PROC_FILE} ]
    then
            MPP_HOST_NUMBER=$(ls /proc/scsi/mpp/*|awk -F"/" '{print $NF}')
            MPP_ENTRY="/sys/bus/pci/driver/mpp/location/host${MPP_HOST_NUMBER}"
            SCSI_ENTRY="${SCSI_ENTRY}
                   ${MPP_ENTRY}"
    fi
    export    SYS_HOST_FILE="/sys/class/scsi_host/"
	#03/12/08 - CR137987 - Fix to support larger number of LUNs - by filtering minimum fields from 'ls'	
	#03/12/08 - CR137987 - w.r.t to above change, In mppLnx_report_new_vdev_fn change is done
	if [ $(uname -r | sed 's:\([^\.]*\.[^\.]*\.[^\.\-]*\)\.*.*:\1:' | sed 's:\.::g') -ge 2627 ]
	then
		export    LS_SD_DEVS="ls -d -1 /sys/bus/scsi/drivers/sd/*/block*/*|awk -F\"/\" '{printf(\"%s/%s\\\n\",\$7,\$9)}'|sed 's/block://g'" #CR153361 - To support sles11 and  kernels > 2.6.27
	else
		if [ $(uname -r | sed 's:\([^\.]*\)\.*.*:\1:' | sed 's:\.::g') -ge 3 ]
		then
			export    LS_SD_DEVS="ls -d -1 /sys/bus/scsi/drivers/sd/*/block*/*|awk -F\"/\" '{printf(\"%s/%s\\\n\",\$7,\$9)}'|sed 's/block://g'" 

		else
		export    LS_SD_DEVS="ls -d -1 /sys/bus/scsi/drivers/sd/*/block:*|awk -F\"/\" '{printf(\"%s/%s\\\n\",\$7,\$8)}'|sed 's/block://g'"
		fi
   	fi 
    #if the new version of software iSCSI initiator is running, add its hosts
    # to the SCSI ENTRY. The entries look like
    #          /sys/class/iscsi_host/host4
    #          /sys/class/iscsi_host/host5
    if [ ${IS_SOFTWARE_ISCSI} = 2 ]
    then
        if [ $(uname -r | sed 's:\([^\.]*\.[^\.]*\.[^\.\-]*\)\.*.*:\1:' | sed 's:\.::g') -ge 2627 ]
        then
            SOFT_ISCSI_ENTRY="$(find /sys/class/iscsi_host/host*/device/scsi_host/host*/proc_name -exec grep -v qla4xxx {} \; -print 2>/dev/null | grep -i iscsi_host | cut -d/ -f1-5)"

	else
		if [ $(uname -r | sed 's:\([^\.]*\)\.*.*:\1:' | sed 's:\.::g') -ge 3 ]
		then
			SOFT_ISCSI_ENTRY="$(find /sys/class/iscsi_host/host*/device/scsi_host/host*/proc_name -exec grep -v qla4xxx {} \; -print 2>/dev/null | grep -i iscsi_host | cut -d/ -f1-5)"
        	else
            		SOFT_ISCSI_ENTRY="$(find /sys/class/iscsi_host  -name "host*" -type d)"
		fi
        fi
        SCSI_ENTRY="${SCSI_ENTRY}
                    ${SOFT_ISCSI_ENTRY}"
    fi
    export SCSI_ENTRY

    # pci driver entries ( SLES10, RHEL 5 )
    #/sys/bus/pci/drivers/qla2xxx/0000:02:08.1/host5
    #/sys/bus/pci/drivers/qla2xxx/0000:02:08.0/host4
    # or could be 
    #/sys/bus/pci/drivers/qla2400/0000:02:08.1/host5
    #/sys/bus/pci/drivers/qla2400/0000:02:08.0/host4
    #/sys/bus/pci/drivers/mptfc/0000:01:06.1/host3
    #/sys/bus/pci/drivers/mptfc/0000:01:06.0/host2
    #/sys/bus/pci/drivers/lpfc/0000:01:03.1/host1
    #/sys/bus/pci/drivers/lpfc/0000:01:03.0/host0
    #


}
#
#  Function: qlu_scan_done
#  Description: Wait 10 seconds or until qlogic says scan is done
#    note: 'lifted' from Qlogic ql-dynamic-tgt-lun-disc.sh script
# See if driver scan is done				    #
# Parameter: 						    #
#	$1: Proc file name				    #
#	$2: Host number					    #
# Returns: 			 			    #
#	None						    #
# --------------------------------------------------------- #
qlu_scan_done()
{
	local PROC_FILE=$1
	local HOST=$2
	local DELAY=1
	local ITERATION=10

	while [ $ITERATION -ge 1 ]
	do
		#in any case sleep for 2 secs
		sleep $DELAY
		#look for ( N:NN): Total reqs N, Pending reqs 0, flags
		cat $PROC_FILE | grep -v "\(.*:[[:space:]]\+0\)" | grep "\(.*\): Total.*flags.*\*.*" >& /dev/null
		if [ $? -eq 0 ]; then
			break;
		fi
		(( ITERATION -= 1 ))	
	done
	return
}

#*****************************************************************************
#  Function:  mppLnx_qla_scan_host_fn
#  Description: Scan a qlogic host for devices.
#*****************************************************************************
mppLnx_qla_scan_host_fn()
{
  local HOST=$1 

  echo "scan qla2 HBA host /sys/class/scsi_host/host${HOST}..."
	#Trivial way to check whether its a inbox driver/standard driver
	#If issue_lip present, then inbox driver or its standard driver
	if [ ! -f /sys/class/fc_host/host${HOST}/issue_lip ] ; then
	{
		for QLA_PROCDIR in /proc/scsi/qla2* ; do
			if [ -e ${QLA_PROCDIR}/${HOST} ] ; then
				echo "scsi-qlalip" > ${QLA_PROCDIR}/${HOST}
			fi
		done
	}
	fi
  # And now kick the SCSI class driver.
  if [ -e /sys/class/scsi_host/host${HOST}/scan ] ; then
    echo "- - -" > /sys/class/scsi_host/host${HOST}/scan
  fi
  
}

#*****************************************************************************
#  Function:   mppLnx_build_cmd_fn
#  Description:  Build commands for the physical HBA host scan, mppUtil 
#                     busscan and MPP virtual host scan
#*****************************************************************************
mppLnx_build_cmd_fn()
{
    echo "${SCSI_ENTRY}"|/usr/bin/awk -F"/" -v QLA4x_PROC=${QLA4x_PROC}\
     -v IS_SOFTWARE_ISCSI=${IS_SOFTWARE_ISCSI} \
     -v LSI_SCSIHPROC=${LSI_SCSIHPROC}\
     -v LSI_SASPROC=${LSI_SASPROC}\
     -v LSI_SAS2PROC=${LSI_SAS2PROC}\
     -v LSI_FCPROC=${LSI_FCPROC}\
     -v IBM_SCSIPROC=${IBM_SCSIPROC}\
     -v EMX_PROC=${EMX_PROC}\
     -v BFA_PROC=${BFA_PROC}\
     -v CELERITY8FC_PROC=${CELERITY8FC_PROC}\
     -v BE2ISCSI_PROC=${BE2ISCSI_PROC}\
     -v MTL_PROC=${MTL_PROC}\
     -v MTL_QDR_PROC=${MTL_QDR_PROC}\
     -v MTX_PROC=${MTX_PROC}\
     -v ICS_PROC="${ICS_PROC}"\
     -v SYS_HOST_FILE=${SYS_HOST_FILE}\
     -v MPP_PROC=${MPP_PROC}\
     -v QLA_SCAN=${QLA_SCAN}\
     -v QLA4x_SCAN=${QLA4x_SCAN}\
     -v LSI_SCAN=${LSI_SCAN}\
     -v IBM_SCAN=${IBM_SCAN}\
     -v EMX_SCAN=${EMX_SCAN}\
     -v BFA_SCAN=${BFA_SCAN}\
     -v CELERITY8FC_SCAN=${CELERITY8FC_SCAN}\
     -v BE2ISCSI_SCAN=${BE2ISCSI_SCAN}\
     -v MTL_SCAN="${MTL_SCAN}"\
     -v MTX_SCAN="${MTX_SCAN}"\
     -v ICS_SCAN="${ICS_SCAN}"\
     -v SCAN_SLEEP_TIME=${SCAN_SLEEP_TIME}\
     -v LS_SD_DEVS="${LS_SD_DEVS}"\
     -v LS_MPP_DEVS="${LS_MPP_DEVS}" \
    'BEGIN{ 
        qla_count=0
        qla4x_count=0
        iscsi_count=0
        lsi_scsih_count=0
        lsi_sas_count=0
        lsi_sas2_count=0
        lsi_fc_count=0
	ibm_scsi_count=0
        mpp_count=0
        emx_count=0
        bfa_count=0
        celerity8fc_count=0
        be2iscsi_count=0
        mtl_count=0
        ics_count=0
    }
    {
        host_field=NF
        proc_field=0
        proc_name_field=6
        #files with a host number
        if(    /[0-9]/ && $0 !~ /iscsi/ )
        {
            #QLA hosts
            # This is to handle the new method by which qla names its /sys interface
            if($proc_name_field ~ /'$QLA_PROC'/ )
            {
                qla_hosts[qla_count]=$host_field
                qla_host_procs[qla_count]=$proc_field
                qla_count++
            }
            #QLA iSCSI TOE HBA qla4xxx
            if($proc_name_field == QLA4x_PROC )
            {
                qla4x_hosts[qla4x_count]=$host_field
                qla4x_host_procs[qla4x_count]=$proc_field
                qla4x_count++
            }
            #LSI mpt scshh hosts
            if($proc_name_field == LSI_SCSIHPROC )
            {
                lsi_scsih_hosts[lsi_scsih_count]=$host_field
                lsi_scsih_host_procs[lsi_scsih_count]=$proc_field
                lsi_scsih_count++
            }
            #LSI sas hosts
            if($proc_name_field == LSI_SASPROC )
            {
                lsi_sas_hosts[lsi_sas_count]=$host_field
                lsi_sas_host_procs[lsi_sas_count]=$proc_field
                lsi_sas_count++
            }
            #LSI sas2 hosts
            if($proc_name_field == LSI_SAS2PROC )
            {
                lsi_sas2_hosts[lsi_sas2_count]=$host_field
                lsi_sas2_host_procs[lsi_sas2_count]=$proc_field
                lsi_sas2_count++
            }
            #LSI fc hosts
            if($proc_name_field == LSI_FCPROC )
            {
                lsi_fc_hosts[lsi_fc_count]=$host_field
                lsi_fc_host_procs[lsi_fc_count]=$proc_field
                lsi_fc_count++
            }
            #IBM scsi hosts
            if($proc_name_field == IBM_SCSIPROC )
            {
                ibm_scsi_hosts[ibm_scsi_count]=$host_field
                ibm_scsi_host_procs[ibm_scsi_count]=$proc_field
                ibm_scsi_count++
            }
            #Emulex hosts
            if($proc_name_field == EMX_PROC )
            {
                emx_hosts[emx_count]=$host_field
                emx_host_procs[emx_count]=$proc_field
                emx_count++
            }
            #bfa hosts
            if($proc_name_field == BFA_PROC )
            {
                bfa_hosts[bfa_count]=$host_field
                bfa_host_procs[bfa_count]=$proc_field
                bfa_count++
            }
            #celerity8fc hosts
            if($proc_name_field == CELERITY8FC_PROC )
            {
                celerity8fc_hosts[celerity8fc_count]=$host_field
                celerity8fc_host_procs[celerity8fc_count]=$proc_field
                celerity8fc_count++
            }
            #be2iscsi hosts
            if($proc_name_field == BE2ISCSI_PROC )
            {
                be2iscsi_hosts[be2iscsi_count]=$host_field
                be2iscsi_host_procs[be2iscsi_count]=$proc_field
                be2iscsi_count++
            }
            #Mellanox Infiniband hosts
            if($proc_name_field == MTL_PROC )
            {
                mtl_hosts[mtl_count]=$host_field
                mtl_host_procs[mtl_count]=$proc_field
                mtl_count++
            }
            #Mellanox Infiniband hosts QDR
            if($proc_name_field == MTL_QDR_PROC )
            {
                mtl_hosts[mtl_count]=$host_field
                mtl_host_procs[mtl_count]=$proc_field
                mtl_count++
            }
            #Mellanox Infiniband hosts for XBB2
            if($proc_name_field == MTX_PROC )
            {
                mtl_hosts[mtl_count]=$host_field
                mtl_host_procs[mtl_count]=$proc_field
                mtl_count++
            }
            #SilverStorm Infiniband hosts
	        # Search for substring "failover_"
            if(substr($proc_name_field,1,length(ICS_PROC)) == ICS_PROC )
            {
                ics_hosts[ics_count]=$host_field
                mtl_host_procs[ics_count]=$proc_field
                ics_count++
            }
            #MPP virtual host
            if($proc_name_field == MPP_PROC )
            {
                mpp_hosts[mpp_count]=$host_field
                mpp_host_procs[mpp_count]=$proc_field
                mpp_count++
            }
        }
        
        #handle the new iscsi software initiator case
        if ( /iscsi_host/ && IS_SOFTWARE_ISCSI == 2 )
        {
             iscsi_hosts[iscsi_count]=$5
             iscsi_host_procs[iscsi_count]="iscsi"
             iscsi_count++
        }
        
    } END {
        #**************
        # qla2400, qla2xxx
        #***************
        for(i=0; i<qla_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          qhost=substr(qla_hosts[i],5)
          printf("mppLnx_qla_scan_host_fn %s\n",qhost);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #**************
        # qla4xxx
        #***************
        for(i=0; i<qla4x_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan %s HBA host %s%s...\n",QLA4x_PROC,SYS_HOST_FILE,qla4x_hosts[i]);
          printf("echo \"0 - -\" >%s%s/scan\n",SYS_HOST_FILE,qla4x_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #**************
        # lsi scsih hosts
        #******************
        for(i=0; i<lsi_scsih_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan %s HBA host %s%s...\n",LSI_SCSIHPROC, SYS_HOST_FILE,lsi_scsih_hosts[i]);
          printf("echo \"0 - -\" >%s%s/scan\n",SYS_HOST_FILE,lsi_scsih_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #**************
        # lsi sas hosts
        #******************
        for(i=0; i<lsi_sas_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan %s HBA host %s%s...\n",LSI_SASPROC, SYS_HOST_FILE,lsi_sas_hosts[i]);
          printf("echo \"- - -\" >%s%s/scan\n",SYS_HOST_FILE,lsi_sas_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #**************
        # lsi sas2 hosts
        #******************
        for(i=0; i<lsi_sas2_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan %s HBA host %s%s...\n",LSI_SAS2PROC, SYS_HOST_FILE,lsi_sas2_hosts[i]);
          printf("echo \"- - -\" >%s%s/scan\n",SYS_HOST_FILE,lsi_sas2_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #**************
        # lsi fc hosts
        #******************
        for(i=0; i<lsi_fc_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan %s HBA host %s%s...\n",LSI_FCPROC, SYS_HOST_FILE,lsi_fc_hosts[i]);
          printf("echo \"0 - -\" >%s%s/scan\n",SYS_HOST_FILE,lsi_fc_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #**************
        # ibm scsi hosts
        #******************
        for(i=0; i<ibm_scsi_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan %s HBA host %s%s...\n",IBM_SCSIPROC, SYS_HOST_FILE,ibm_scsi_hosts[i]);
          printf("echo \"- - -\" >%s%s/scan\n",SYS_HOST_FILE,ibm_scsi_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #****************
        # emulex host
        #*****************
        for(i=0; i<emx_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan %s HBA host %s%s...\n",EMX_PROC, SYS_HOST_FILE,emx_hosts[i]);
          printf("echo \"0 - -\" >%s%s/scan\n",SYS_HOST_FILE,emx_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #****************
        # bfa host
        #*****************
        for(i=0; i<bfa_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan %s HBA host %s%s...\n",BFA_PROC, SYS_HOST_FILE,bfa_hosts[i]);
          printf("echo \"0 - -\" >%s%s/scan\n",SYS_HOST_FILE,bfa_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #****************
        # celerity8fc host
        #*****************
        for(i=0; i<celerity8fc_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan %s HBA host %s%s...\n",CELERITY8FC_PROC, SYS_HOST_FILE,celerity8fc_hosts[i]);
          printf("echo \"0 - -\" >%s%s/scan\n",SYS_HOST_FILE,celerity8fc_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #****************
        # be2iscsi host
        #*****************
        for(i=0; i<be2iscsi_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan %s HBA host %s%s...\n",BE2ISCSI_PROC, SYS_HOST_FILE,be2iscsi_hosts[i]);
          printf("echo \"0 - -\" >%s%s/scan\n",SYS_HOST_FILE,be2iscsi_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #****************************
        # Mellanox Infiniband host
        #****************************
        for(i=0; i<mtl_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan Mellanox Host Adapter %s%s...\n", SYS_HOST_FILE,mtl_hosts[i]);
          printf("echo \"0 0 -\" >%s%s/scan\n",SYS_HOST_FILE,mtl_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #****************************
        # Silverstorm Infiniband host
        #****************************
        for(i=0; i<ics_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan SilverStorm Host Adapter %s%s...\n", SYS_HOST_FILE,ics_hosts[i]);
          printf("echo \"0 - -\" >%s%s/scan\n",SYS_HOST_FILE,ics_hosts[i]);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #****************************
        # Old Linux iSCSI software initiator host
        #****************************
        if (IS_SOFTWARE_ISCSI == 1)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("echo scan Linux iSCSI software initiator /sys/class/scsi_host/iscsi...\n");
          printf("echo \"- - -\" > /sys/class/scsi_host/iscsi/scan\n");
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #****************************
        # new Linux iSCSI software initiator host or open-iscsi initiator hosts
        #****************************
        for(i=0; i<iscsi_count; i++)
        {
          printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
          iscsi_host=iscsi_hosts[i];
          printf("echo scan iSCSI software initiator host %s%s...\n", SYS_HOST_FILE, iscsi_host);
          printf("echo \"0 - -\" >%s%s/scan\n",SYS_HOST_FILE,iscsi_host);
          printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
          printf("mppLnx_report_new_pdev_fn \"yes\"\n");
        }
        #****************
        # tell mpp driver to rescan its un-configured devices
        # unconfigured device may become configured. We need to report the device changes
        #****************
        printf("echo run  /usr/sbin/mppUtil -s \"busscan\"...\n")
        printf("export PDEV_BEFORE_SCAN=$(%s)\n",LS_MPP_DEVS);
        printf("export VDEV_BEFORE_SCAN=$(%s)\n",LS_SD_DEVS)
        print("/usr/sbin/mppUtil -s \"busscan\"")
        printf("export PDEV_AFTER_SCAN=$(%s)\n",LS_MPP_DEVS);
        printf("mppLnx_report_new_pdev_fn \"no\"\n");
        printf("export VDEV_AFTER_SCAN=$(%s)\n",LS_SD_DEVS)
        printf("mppLnx_report_new_vdev_fn \"no\"\n");
        #***************
        #mpp host if it is already initialized
        #***************
        for(i=0; i<mpp_count; i++)
        {
          printf("export VDEV_BEFORE_SCAN=$(%s)\n",LS_SD_DEVS)
          printf("echo scan %s virtual host %s%s...\n",MPP_PROC,SYS_HOST_FILE,mpp_hosts[i]);
          printf("echo \"0 - -\" >%s%s/scan\n",SYS_HOST_FILE,mpp_hosts[i]);
          printf("export VDEV_AFTER_SCAN=$(%s)\n",LS_SD_DEVS)
          printf("mppLnx_report_new_vdev_fn \"yes\"\n");
        }
    }' 
}

#*****************************************************************************
#  Function:  mppLnx_report_new_pdev_fn
#  Description:  report what physical devices are discovered after a host rescan
#*****************************************************************************
mppLnx_report_new_pdev_fn()
{
    echo  "${PDEV_BEFORE_SCAN}${NEWLINE}${MPPLNX_MAGIC_LINE}${NEWLINE}${PDEV_AFTER_SCAN}" |\
    /usr/bin/awk \
    -F"/" \
    -v MPPLNX_MAGIC_LINE=${MPPLNX_MAGIC_LINE} \
    -v REPORT_NO_DEVICE="$1"\
    '{
        if( $0 == MPPLNX_MAGIC_LINE )
        {
            before_done=100
        }else
        {
            if(before_done == 100)
            {
                if( devices[$0] != "y")
                {
                    foundany="y"
                    printf("\tfound %s \n",$7)
                }
            }else
            {
                devices[$0] ="y"
            }
        }
    }END{
        if( foundany != "y")
        {
            if( REPORT_NO_DEVICE == "yes")
            {
                printf("\tno new device found\n")
            }
        }
    }'
}
#*****************************************************************************
#  Function:  mppLnx_report_new_vdev_fn
#  Description:  report what virtual devices are discovered after a host rescan
#*****************************************************************************
mppLnx_report_new_vdev_fn()
{
    echo  "${VDEV_BEFORE_SCAN}${NEWLINE}${MPPLNX_MAGIC_LINE}${NEWLINE}${VDEV_AFTER_SCAN}" \
    |/usr/bin/awk -F"/" \
    -v MPPLNX_MAGIC_LINE=${MPPLNX_MAGIC_LINE} \
    -v REPORT_NO_DEVICE="$1"\
    '{
        if( $0 == MPPLNX_MAGIC_LINE )
        {
            before_done=100
        }else
        {
            if(before_done == 100)
            {
                if( devices[$0] != "y")
                {
                    foundany="y"
					printf("\tfound %s->/dev/%s \n",$1,$NF)
                }
            }else
            {
                devices[$0] ="y"
            }
        }
    }END{
        if( foundany != "y")
        {
            if( REPORT_NO_DEVICE == "yes")
            {
                printf("\tno new virtual device found\n")
            }
        }
    }'
}
#*****************************************************************************
#  Function: mppLnx_RevomeDev_fn
#  Description: Process deletion for all Unmaped or not connected devices
#*****************************************************************************

mppLnx_For_Each_mppDelDev_fn()
{
 flag=0
 str=""
     mppLnx_vdevPath_init_fn
    for i in $MPPLNX_VDEV_BLOCK_DEVS
    do
	if [ $(uname -r | sed 's:\([^\.]*\.[^\.]*\.[^\.\-]*\)\.*.*:\1:' | sed 's:\.::g') -ge 2627 ]
	then
           VDEV=$(ls -d -1 /sys/bus/scsi/drivers/sd/$i/block*/* 2>/dev/null|awk -F/ '{print $7"/"$NF}')
	else
 		if [ $(uname -r | sed 's:\([^\.]*\)\.*.*:\1:' | sed 's:\.::g') -ge 3 ]
		then
			VDEV=$(ls -d -1 /sys/bus/scsi/drivers/sd/$i/block*/* 2>/dev/null|awk -F/ '{print $7"/"$NF}')

		else
           		VDEV=$(ls -l /sys/class/scsi_device/$i/device/block* 2>/dev/null|awk -F/ '{print $5"/"$NF}')
		fi
	fi	
           MPP_PDEV_List=`mppUtil -D $i`
           cflag=0
           for j in $MPP_PDEV_List
           do
                firstCol=`echo $j|awk -F"~" '{printf("%s",$1)}'`
                if [ $cflag -eq 0 ] && [ $firstCol == "Status" ]
                then
                    status=`echo $j|awk -F"~" '{printf("%s",$2)}'`
                    if [ $status == "UNMAPPED" ] || [ $status == "NOTCONNECTED"   ]
                    then
                        cflag=1
                        flag=1
                       fi
                 fi
            if [ $cflag -eq 1 ]
            then
                  str1=`echo $j|awk -F"~" '{printf("%s",$1)}'`
                  if [ $str1 == "Path" ]
                  then
                       tmpDev=`echo $j|awk -F"~" '{printf("%s",$2)}'`
                        if [ -d /sys/class/scsi_device/$tmpDev ] && [ -e /sys/class/scsi_device/$tmpDev/device/delete ]
                                 then
                                #   echo  Removing $tmpDev
                                   echo  1 > /sys/class/scsi_device/$tmpDev/device/delete 2>/dev/null
                       fi
                 fi
           fi
        done
       if [ $cflag -eq 1 ]
       then
        echo "Found $VDEV as unmapped/disconnected device. Device removed."
       fi
       done
       if [ $flag -eq 0 ]
       then
                echo "No MPP device found unmapped or disconnected."
       fi
}


build_RevomeDev_cmd_fn()
{
      echo "echo \"Searching for unmapped or disconnected MPP devices.\""
       echo "mppLnx_init_fn"
        echo "mppLnx_For_Each_mppDelDev_fn"
}


mppLnx_RemapDev_fn()
{
    flag=0
     mppLnx_vdevPath_init_fn
        for i in $MPPLNX_VDEV_BLOCK_DEVS
        do
       SecondCol=""
       firstCol=""
       MPP_PDEV_List=`mppUtil -R $i`
        cflag=0
        for j in $MPP_PDEV_List
        do
            firstCol=`echo $j|awk -F"~" '{printf("%s",$1)}'`
            if [ $cflag -eq 0 ] && [ $firstCol == "Status" ]
             then
               SecondCol=`echo $j|awk -F"~" '{printf("%s",$2)}'`
               if [ $SecondCol ==  "WWN_MISMATCH" ]
                then
                   cflag=1
                   flag=1
                   break;
                fi
             fi
       done
       if [ $cflag == 1 ]
       then
               if [ -d /sys/class/scsi_device/$i ] && [ -e /sys/class/scsi_device/$i/device/delete ]
               then
                  echo 1 >/sys/class/scsi_device/$i/device/delete 2>/dev/null
                  host=`echo $i |awk -F: '{print $1}'`
                  channel=`echo $i |awk -F: '{print $2}'`
                  target=`echo $i |awk -F: '{print $3}'`
                  lun=`echo $i |awk -F: '{print $4}'`
                  echo "scsi add-single-device $host $channel $target $lun " > /proc/scsi/scsi
                   if [ -d /sys/class/scsi_device/$i ]
                  then
		    if [ $(uname -r | sed 's:\([^\.]*\.[^\.]*\.[^\.\-]*\)\.*.*:\1:' | sed 's:\.::g') -ge 2627 ]
		    then
                       VDEV=$(ls -d -1 /sys/bus/scsi/drivers/sd/$i/block*/* 2>/dev/null|awk -F/ '{print $7"/"$NF}')
		    else
			if [ $(uname -r | sed 's:\([^\.]*\)\.*.*:\1:' | sed 's:\.::g') -ge 3 ]
			then
				VDEV=$(ls -d -1 /sys/bus/scsi/drivers/sd/$i/block*/* 2>/dev/null|awk -F/ '{print $7"/"$NF}')

		       else
                       		VDEV=$(ls -l /sys/class/scsi_device/$i/device/block* 2>/dev/null|awk -F/ '{print $5"/"$NF}' )
			fi
	
		    fi	
                       echo "Found $VDEV as remapped device. Device updated."

                  else
                      echo "Failed to update."
                   fi
              fi
       fi

done
if [ $flag -eq 0 ]
then
 echo "No MPP device found remapped. "
fi
}

build_RemapDev_cmd_fn()
{
       echo "echo \"Searching for remapped MPP devices.\""
       echo "mppLnx_init_fn"
        echo "mppLnx_RemapDev_fn"
}

mppLnx_vdevPath_init_fn()
{
    HAS_TARGET_OBJECTS=$(ls -l /sys/devices/mppvirtual/mppadapter0/host*/ 2>/dev/null|grep -c target)
    if [ $HAS_TARGET_OBJECTS == "0"  ]
    then
         echo "No MPP Virtual Device found."
         exit 1;
    else
	 MPPDEV_COUNT=$(ls -d -1 /sys/devices/mppvirtual/mppadapter0/host*/target*/*:* 2>/dev/null|wc -l)
         if [ $MPPDEV_COUNT == "0"  ]
         then
            echo "No MPP Virtual Device found."
            exit 1;
         else
            export  MPPLNX_VDEV_BLOCK_DEVS="$(ls -d -1 /sys/devices/mppvirtual/mppadapter0/host*/target*/*:*/block* 2>/dev/null|awk -F'/' '{print $8}' )"
         fi	
    fi
}

mppLnx_RemapVol_main()
{

    mppLnx_init_fn
    echo "#!/bin/bash" >${TMP_SCRIPT}
    echo "export MPPLNX_RUN_SCRIPT=\"168\"" >>${TMP_SCRIPT}
    /bin/cat $0 >>${TMP_SCRIPT}
     build_RemapDev_cmd_fn >>${TMP_SCRIPT}
    /bin/bash ${TMP_SCRIPT}
    /bin/rm -f ${TMP_SCRIPT}
}



#*****************************************************************************
#  Function:  mppLnx_scan_main
#  Description:  The scan main function.
#*****************************************************************************
mppLnx_scan_main()
{
    mppLnx_init_fn
    echo "#!/bin/bash" >${TMP_SCRIPT}
    echo "export MPPLNX_RUN_SCRIPT=\"168\"" >>${TMP_SCRIPT}
    /bin/cat $0 >>${TMP_SCRIPT}
#    #Execute the following commad for SilverStorm HBA
#    if [ -f ${ICS_PROC_DRIVER} ] ; then 
#		echo "cat ${ICS_CFG} > ${ICS_PROC_DRIVER}" >> ${TMP_SCRIPT}
#        echo "sleep ${SCAN_SLEEP_TIME}"
#    fi
    mppLnx_build_cmd_fn >>${TMP_SCRIPT}
    /bin/bash ${TMP_SCRIPT}
    /bin/rm -f ${TMP_SCRIPT}
}
mppLnx_RemoveVol_main()
{
    mppLnx_init_fn
    echo "#!/bin/bash" >${TMP_SCRIPT}
    echo "export MPPLNX_RUN_SCRIPT=\"168\"" >>${TMP_SCRIPT}
    /bin/cat $0 >>${TMP_SCRIPT}
    build_RevomeDev_cmd_fn >>${TMP_SCRIPT}
    /bin/bash ${TMP_SCRIPT}
    /bin/rm -f ${TMP_SCRIPT}
}
#******************************************************************************************************************
#  Function: mppLnx_CapacityDev_fn
#  Description:
#******************************************************************************************************************
mppLnx_CapacityDev_fn()
{
   mppLnx_vdevPath_init_fn
   SIZEFLAG=0
   for i in $MPPLNX_VDEV_BLOCK_DEVS
   do
      if [ $(uname -r | sed 's:\([^\.]*\.[^\.]*\.[^\.\-]*\)\.*.*:\1:' | sed 's:\.::g') -ge 2627 ]	
      then
        blkdev=$(file -F "/" /sys/devices/mppvirtual/mppadapter0/host*/target*/$i/block*/*|awk -F"/" '{printf("%s\n",$10)}')
        VDEV=$(ls -d -1 /sys/bus/scsi/drivers/sd/$i/block*/* 2>/dev/null|awk -F/ '{print $7"/"$NF}')
	else
		if [ $(uname -r | sed 's:\([^\.]*\)\.*.*:\1:' | sed 's:\.::g') -ge 3 ]
		then

			blkdev=$(file -F "/" /sys/devices/mppvirtual/mppadapter0/host*/target*/$i/block*/*|awk -F"/" '{printf("%s\n",$10)}')
			VDEV=$(ls -d -1 /sys/bus/scsi/drivers/sd/$i/block*/* 2>/dev/null|awk -F/ '{print $7"/"$NF}')

      		else
        		blkdev=`ls -l /sys/devices/mppvirtual/mppadapter0/host*/target*/$i/block* 2>/dev/null|awk -F'/' '{print $NF}'`
        		VDEV=$(ls -l /sys/class/scsi_device/$i/device/block* 2>/dev/null|awk -F/ '{print $5"/"$NF}')
		fi
      fi

      BEFORESCAN=`cat /sys/block/$blkdev/size 2> /dev/null`
      if [ -e /sys/class/scsi_device/$i/device/rescan ]
      then
         echo 1 >/sys/class/scsi_device/$i/device/rescan
      fi 
      AFTERSCAN=`cat /sys/block/$blkdev/size 2> /dev/null`
      if [ "$BEFORESCAN" == "" ]
      then
         BEFORESCAN=0
      fi
      if [ "$AFTERSCAN" == "" ]
      then
         AFTERSCAN=0
      fi
      if [ $BEFORESCAN -ne 0 ] && [ $AFTERSCAN -ne 0 ] &&  [ $BEFORESCAN -ne $AFTERSCAN ]
      then
           echo "Found $VDEV with size modified. Device size updated."
           SIZEFLAG=1
      fi
   done
   if [ $SIZEFLAG -eq 0 ]
   then
       echo "No MPP device found with size modified"
   fi
}

build_CapacityDev_cmd_fn()
{
        echo "echo \"Searching for MPP device with size modified \""
        echo "mppLnx_init_fn"
        echo "mppLnx_CapacityDev_fn"
}

mppLnx_CapacityVol_main()
{
    mppLnx_init_fn
    echo "#!/bin/bash" >${TMP_SCRIPT}
    echo "export MPPLNX_RUN_SCRIPT=\"168\"" >>${TMP_SCRIPT}
    /bin/cat $0 >>${TMP_SCRIPT}
    build_CapacityDev_cmd_fn >>${TMP_SCRIPT}
    /bin/bash ${TMP_SCRIPT}
   /bin/rm -f ${TMP_SCRIPT}
}

usages()
{
 echo "hot_add [-d|--delete] [-u|--update] [-c|--capacity|] [-s|--scan] [-h|--help]"
 echo "Usage:"
 echo "-d|--delete   : Remove unmapped or disconnected MPP devices"
 echo "-u|--update   : Update Remapped MPP devices "
 echo "-c|--capacity : Update MPP device size "
 echo "-s|--scan     : Scan for new devices "
 echo "-h|--help     : Help "
}


#******************************************************************************
# This is the script entry
# This script file will be included in the temp script file. The following
#      statements should only execute from the first script invocation.
#******************************************************************************
if [ "${MPPLNX_RUN_SCRIPT}" != "168" ]
then

    MPP_UTIL="/usr/sbin/mppUtil"

    if [ ! -x ${MPP_UTIL} ]
    then
        echo "${MPP_UTIL} is not installed. $0 cannot be executed!"
        exit 1
    fi

    if [ ! -d ${MPP_UPPER_SYS_FILE} ]
    then
        echo "mppUpper.ko is not loaded. $0 cannot be executed!"
        exit 1
    fi

 if [ $# -gt 1 ]
 then
        usages
 	exit 0
 fi
 case $1 in
        -d|--delete)
               mppLnx_RemoveVol_main
           ;;
        -u|--update)
               mppLnx_RemapVol_main
           ;;
        -c|--capacity)
               mppLnx_CapacityVol_main
           ;;
        -s|--scan|"")
              mppLnx_scan_main
           ;;
        *|-h|--help) usages
         ;;
    esac
fi
