#!/bin/sh
#
# Name: hp_rescan
# Copyright: (c)2003 Hewlett-Packard Company
#
# Description
#
# Script performs a LUN rescan on one or all
# QLogic adapters in the system
#
# Modification History
#
# Chad Dupuis	07/29/03 Initial Development
# Chad Dupuis   02/18/04 Changed multiplier for the times
#                        to wait for the QLogic adapter
#                        rescan to complete to 6
# Chad Dupuis   06/11/04 Changes for SLES 9 (2.6 kernel)
# Chad Dupuis   02/01/05 Add option to do scan in a different order
# Chad Dupuis   02/02/05 fix bug where script not waiting long enough
#                        in some larger configurations
# Chad Dupuis	03/23/05 remove -d option
# Chad Dupuis	11/14/05 Added code to list and scan Emulex adapters;
#			 added -n and -h options
# Chad Dupuis	08/30/06 Changes for SLES 10

#
# defines
#

PROBELUNS="/opt/hp/hp_fibreutils/probe-luns"
KERNELVER=`uname -r | cut -c 1-3`

# set the multiplier for the amount of seconds to wait
# for the QLogic adapter rescan to complete.  The amount
# of time to wait is number of adapters * multiplier

MULTIPLIER=6

#
# functions
#

# print usage statement

print_usage () {

 echo "hp_rescan: rescans LUNs on HP supported FC adapters"
 echo "Usage: hp_rescan -ailh[n]"
 echo ""
 echo "-a: rescan all adapters"
 echo "-i: rescan a specific adapter instance"
 echo "-l: lists all FC adapters"
 echo "-n: do not perform \"scsi remove-single-device\" when executing probe-luns"
 echo "-h: help"
 exit 0
}

# read command line arguments

read_args () {
 # set default values for output flags

 AFLAG=0
 IFLAG=0
 LFLAG=0
 NFLAG=0
 HFLAG=0

 # parse command line into arguments

 getopt lai:nh $* 1>/dev/null 2>/dev/null

 # check result of parsing

 if [ $? != 0 ]
 then
	echo "Bad argument or missing argument"
	exit 1
 fi

 set -- `getopt lai:nh $*`

 while [ $1 != -- ]
 do
 	case $1 in
 		-l) LFLAG=1;;
		-a) AFLAG=1;;
		-i) IFLAG=1
	    	    INSTNUM=$2
            	    shift;;
		-n) NFLAG=1;;
		-h) HFLAG=1;;
 	esac
 	shift   # next flag
 done

 shift   # skip --
}

# Name: sysfs_elx_list
# Description: Returns a list of directories that corrospond to Emulex adapters in
#              sysfs
# In: none
# Out: List of sysfs Emulex adapters
# Returns: none

sysfs_elx_list () {
        # Directory of SCSI hosts
        SCSIHOSTDIR=/sys/class/scsi_host

        # List of hosts in scsi host directory
        HOSTLIST=`ls $SCSIHOSTDIR 2>/dev/null`

        # List of emulex adapters to return
        SYSFS_ELX_LIST=""

        # Look for lpfc host adapters.  These will be the ones with the lpfc_log_verbose
        # file

        for i in $HOSTLIST
        do
                if test -f ${SCSIHOSTDIR}/${i}/lpfc_log_verbose
                then
                        SYSFS_ELX_LIST=$SYSFS_ELX_LIST" $SCSIHOSTDIR/${i}"
                fi
        done
}

# list all FC adapters in system

list_adapters () {
 ARG=$1
 QADAPTLIST="" # QLogic adapters
 EADAPTLIST="" # Emulex adapters

 # find QLogic adapters
 QADAPTLIST=`find /proc/scsi | grep /[0-9/].* | grep qla | sort -u`

 # find Emulex adapters; the methods for scanning for Emulex adapters are
 # different depending on what kernel is being used

 if [ "$KERNELVER" = "2.6" ]
 then
        sysfs_elx_list
        EADAPTLIST=$SYSFS_ELX_LIST
 else
        EADAPTLIST="`find /proc/scsi | grep /[0-9/].* | grep lpfc | sort -u`"
 fi

 if [ "$ARG" = "print" ]
 then
 	echo "QLogic adapters:"
	echo  $QADAPTLIST
	echo "Emulex adapters:"
	echo  $EADAPTLIST
 fi
}


# rescan all adapters on system

rescan_all () {
 list_adapters # produce list of adapters on system

 for i in $QADAPTLIST
 do
 	echo "Sending rescan signal to $i..."
 	echo "scsi-qlascan" > $i
 done

 NUMOFADAPTERS=`echo $QADAPTLIST | wc -w`

 SEC=`expr $NUMOFADAPTERS \* $MULTIPLIER`

 sleep $SEC # insert wait to allow rescans to be queued and
            # executed

 # the arguments to probe-luns vary depending on whether a "-n" was
 # passed at the command line to hp_rescan

 if [ $NFLAG -eq 1 ]
 then
 	$PROBELUNS -an
 else
 	$PROBELUNS -a
 fi
}


# rescan a particular adapter instance

rescan_inst () {
 ARG=$1

 #
 # See if a path to the host instance number actually exists

 # First check /proc

 FILENAME=`find /proc/scsi -name $ARG -print`

 # Now check /sys if the /proc search didn't turn up anything

 if [ "$KERNELVER" = "2.6" ] && [ "$FILENAME" = "" ]
 then
	FILENAME=`find /sys/class/scsi_host -name host${ARG} -print`
 fi

 # if the instance number doesn't exist, just return here

 if [ "$FILENAME" = "" ]
 then
	return
 fi

 # check to see if the instance number given is a QLogic adapter

 if [ "`echo $FILENAME | grep qla`" != "" ]
 then
 	echo "Sending rescan signal to $FILENAME..."
 	echo "scsi-qlascan" > $FILENAME
	sleep $MULTIPLIER # wait for command to be queued and completed
 fi

 if [ $NFLAG -eq 1 ]
 then
 	$PROBELUNS -i $ARG -n
 else
 	$PROBELUNS -i $ARG
 fi
}

#
# Script main
#

# check number of arguments

if [ $# -lt 1 ]
then
 print_usage
 exit 1
fi

read_args $*

# parse argument that is passed in

if [ $HFLAG -eq 1 ]
then
 print_usage
elif [ $LFLAG -eq 1 ]
then
 list_adapters print
 exit 0
elif [ $AFLAG -eq 1 ]
then
 rescan_all
 exit 0
elif [ $IFLAG ]
then
 rescan_inst $INSTNUM
else
 echo "Invalid argument"
 exit 1
fi
