#!/bin/bash

# QLogic FC HBA LUN Scan Utility
# Copyright (C) 2006-2014 QLogic Corporation (www.qlogic.com)
#
#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; either version 2 of the License, or
#(at your option) any later version.
#
#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.
#
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

#--------------------------------------------------------------------------# 
#This script is used to scan the QLogic HBAs for all the LUNs. 
#By default find all QLogic HBAs and start scanning all targets and all LUNs
#---------------------------------------------------------------------------#

QL_ATTR_VALUE="Unknown" #Global for storing value
QL_HOST=() #list of QL HBAs
QL_VHOST=() #list of QL Virtual HBAs
QL_TARGETS=()
QL_LUNS=()
DEVICE_TYPES=(disk    tape    printer process worm    cd\/dvd   scanner optical mediumx comms   \(0xa\)   \(0xb\)   storage enclosu "sim dsk" "opti rd" bridge osd adi \(0x13\) \(0x14\) \(0x15\) \(0x16\) \(0x17\) \(0x18\) \(0x19\) \(0x1a\) \(0x1b\) \(0x1c\) \(0x1e\) \(0x18\) \(0x19\) \(0x1a\) \(0x1b\) \(0x1c\) \(0x1e\) wlun "no dev")


QL_KERNEL_VERSION=`uname -r`
QL_K_MAJ_MIN=`echo ${QL_KERNEL_VERSION} | cut -d . -f -2`
QL_PROC_SCSI="/proc/scsi"
QL_DRIVER="qla2xxx"
QL_SCAN_LUNS=256
QL_CHANNEL=0
QL_REFRESH=0
QL_SCAN=0
QL_INTERACTIVE=0
QL_HELP=0
QL_CURRENT_LUNS=0
QL_SUPPORTED_LUNS=4096
QL_SYSFS=1
QL_PROCFS=2
QL_FS=$QL_SYSFS
QL_CALL_RETURNED=2
QL_CALL_AGAIN=3
NOW_FOUND=()
NOW_LOST=()
TEST_UNIT_READY=1
QL_DISTRUCTIVE_REFRESH=0
QLU_VERSION="2.26"
QLU_LUN_SCAN=$0

QL_SUCCESS=0
QL_FAIL=1

QL_TOTAL_HOSTS=0
QL_TOTAL_VHOSTS=0
QL_TOTAL_LUNS=0
QL_TOTAL_TARGETS=0

# Flag to rescan the luns whose disk attributes has changed.
QL_EXTENDED_SCAN=0

# Flags to scan FC/ISCSI HBAs.
QL_FC_SCAN=0
QL_ISCSI_SCAN=1
QL_HBA_SCAN=${QL_FC_SCAN}

#Flags to check which driver is loaded
QL_HBA_FC=0
QL_HBA_ISCSI=1

QL_HBA_TYPE=${QL_HBA_FC}
TYPE_SCAN_ONLY=1
TYPE_SCAN_REFRESH=2
TYPE_EXTENDED_SCAN_ONLY=3

QL_SCAN_TYPE=$TYPE_SCAN_ONLY

# Flags to issue lip on distro drivers
QL_HBA_LIP=0
# Variable To extract the sense key after firing 
#./sg_turs on target devices
SENSE_KEY=""

# To extract Host_status, after firing ./sg_turs
HOST_STATUS=""

SG_TUR_VERBOSE="--verbose"
SG_TURS=""
SG_MAP=""
# QL_SG_VERIFICATION values
#	0 -- not verified
#	1 -- Verified and succesfully
#	2 -- Verification failed
QL_SG_VERIFICATION=0
# --------------------------------------------------------- #
# qlu_sys_find_all_vhost()	                            #
# Find virtual hosts for all the physical hosts detected    #
# Parameter: 						    #
#	None                   				    #
# Returns: 			 			    #
#	Fill up the QL_VHOST array, returns number of vhosts#
#	found						    #
# --------------------------------------------------------- #

function qlu_sys_find_all_vhost()
{
	#for rhel5 systems
	QL_VHOST=( `ls /sys/devices/pci*/*/*/host* 2> /dev/null | grep ^host | sed -e "s/.*host//"` )
	QL_TOTAL_VHOSTS=${#QL_VHOST[@]}

	#for rhel6 systems
	if [ ${#QL_VHOST[@]} -eq 0 ]; then
		QL_PORT=(`ls /sys/class/fc_host/ 2> /dev/null`)
		for PORT in `echo ${QL_PORT[@]}`
		do
			cat /sys/class/fc_host/$PORT/port_type | grep VPORT &> /dev/null
			if [ $? -ne 0 ]; then
				continue
			fi

			# Host is vport, check it if is QLogic vport host
			QL_HOST_LOCAL=(`ls /sys/bus/pci/drivers/$QL_DRIVER/ 2> /dev/null`)
			for HOST_LOCAL in `echo ${QL_HOST_LOCAL[@]}`
			do
				VHOST_LIST=(`ls /sys/bus/pci/drivers/$QL_DRIVER/$HOST_LOCAL/host*/vport-*/ 2> /dev/null`)
				for VHOST in `echo ${VHOST_LIST[@]}`
				do
					if [ $VHOST == $PORT ]; then
						HOST_NM=`echo $PORT | sed -e "s/.*host//"`
						QL_VHOST=(${QL_VHOST[@]} $HOST_NM)
					fi
				done
			done
		done
		QL_TOTAL_VHOSTS=${#QL_VHOST[@]}
	fi
	return
}

# --------------------------------------------------------- #
# qlu_sys_find_all_host()	                            #
# Look into the /sys/bus/pci/drivers/qla*/ dir to find all  #
# HBAs in the system					    #
# Parameter: 						    #
#	None                   				    #
# Returns: 			 			    #
#	Fill up the QL_HOST array, returns number of hosts  #
#	found						    #
# --------------------------------------------------------- #

function qlu_sys_find_all_host()
{
	QL_HOST=( `ls -d /sys/bus/pci/drivers/${SYS_DRIVER}*/*/host* 2> /dev/null | sed -e "s/.*host//"` )
	qlu_sys_find_all_vhost
	# Add Virtual hosts list to the regular array
	QL_HOST=( ${QL_HOST[@]} ${QL_VHOST[@]} )
	QL_TOTAL_HOSTS=${#QL_HOST[@]}
	return
}

# --------------------------------------------------------- #
# qlu_find_all_host()	                                    #
# Look into the /proc/scsi/qla2xxx[qla2300] dir to find all #
# HBAs in the system					    #
# Parameter: 						    #
#	None                   				    #
# Returns: 			 			    #
#	Fill up the QL_HBA array, returns number of hosts   #
#	found						    #
# --------------------------------------------------------- #

function qlu_find_all_host()
{
	#look into proc file to find all the
	#HBAs
	QL_HOST=( `ls ${QL_PROC_SCSI}/${QL_DRIVER}/ 2> /dev/null | grep -v -i "HBA" 2> /dev/null` )	
	QL_TOTAL_HOSTS=${#QL_HOST[@]}
	return 
}

# --------------------------------------------------------- #
# qlu_is_lun_present()	                                    #
# Check to see if the LUN is already discovered             #
# Parameter: 						    #
#	Host:Channel:Device:Lun				    #
# Returns: 			 			    #
#	QL_SUCCESS: If LUN present			    #
#	QL_FAIL:    If LUN absent			    #
# --------------------------------------------------------- #
function qlu_is_lun_present()
{	local LUN
	let IN_HOST=$1
	let IN_CHANNEL=$2
	let IN_DEVICE=$3
	let IN_LUN=$4
	#check the /proc/scsi/scsi to see if the lun is
	#present or not

	#assuming the format of the string would be always
	# Host: scsi0 Channel: 00 Id: 00 Lun: 00

	if [ ${IN_CHANNEL} -lt 10 ]; then
		IN_CHANNEL="0${IN_CHANNEL}"
	fi

	if [ ${IN_DEVICE} -lt 10 ]; then
		IN_DEVICE="0${IN_DEVICE}"
	fi	

	if [ ${IN_LUN} -lt 10 ]; then
		IN_LUN="0${IN_LUN}"
	fi

	LUN_STR="Host: scsi${IN_HOST} Channel: ${IN_CHANNEL} Id: ${IN_DEVICE} Lun: ${IN_LUN}"
	#echo "Looking for LUN: $LUN_STR"
	cat ${QL_PROC_SCSI}/scsi | grep "$LUN_STR" >& /dev/null
	if [ $? -eq 0 ]; then
		return $QL_SUCCESS
	fi

	return ${QL_FAIL}
}

# --------------------------------------------------------- #
# qlu_add_lun()	                   		            #
# Calls the add-single-device                               #
# Parameter: 						    #
#	Host:Channel:Device:Lun				    #
# Returns: 			 			    #
#	None						    #
# --------------------------------------------------------- #
function qlu_add_lun()
{
	echo "scsi add-single-device $*" > $QL_PROC_SCSI/scsi	
}

# --------------------------------------------------------- #
# qlu_remove_lun()	                                    #
# Calls the remove-single-device                            #
# Parameter: 						    #
#	Host:Channel:Device:Lun				    #
# Returns: 			 			    #
#	None						    #
# --------------------------------------------------------- #
function qlu_remove_lun()
{
	echo "scsi remove-single-device $*" > $QL_PROC_SCSI/scsi	
}

# --------------------------------------------------------- #
# 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

	echo -n "..."
	while [ $ITERATION -ge 1 ]
	do
		#in any case sleep for 2 secs
		echo -n "."
		sleep $DELAY
		#look for ( 0:17): Total reqs 0, 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
	echo -e "" 
	return
}


# --------------------------------------------------------- #
# qlu_scan_host()                                    	    #
# Scans the host and uses "add-single-device" to add the    #
# device in OS						    #
# Parameter: 						    #
#	$*: Space separated list of hosts to be scanned	    #
# Returns: 			 			    #
#	None                    			    #
# --------------------------------------------------------- #
function qlu_scan_host() {
	local LUN
	test -z "$1" && echo "Host list empty."  && return 1;

	for HOST in $*
	do
		#2.4 tell driver to do re-scan first
		echo "Scanning HOST: scsi${HOST}"
		PROC_FILE=${QL_PROC_SCSI}/${QL_DRIVER}/${HOST}
		if [ -e "${PROC_FILE}" ]; then
			if [ "${QL_HBA_SCAN}" -eq "${QL_FC_SCAN}" ]; then
				echo "scsi-qlascan" > ${PROC_FILE}
			fi
			#call qlu_scan_done to check if scan finished
			qlu_scan_done ${PROC_FILE} $HOST

			# get target for this host
			DEVICES=( `cat ${PROC_FILE} | grep "\-target\-" | sed "s/.*target-\(.*\)=.*/\1/"` )
		
			if [ ${#DEVICES[@]} -eq 0 ]; then
				echo "No devices attached to HOST: scsi${HOST}"
				echo ""
				continue;
			fi

			for DEVICE in ${DEVICES[@]}
			do

				echo "Scanning DEVICE: ${DEVICE}"
				#scan all the luns	
				for ((LUN=0; ${LUN} <= ${QL_SCAN_LUNS}; LUN++))
				do
					#check id LUN present
					qlu_is_lun_present ${HOST} ${QL_CHANNEL} ${DEVICE} ${LUN}
					WAS_LUN_PRESENT=$?
					#does user wants to refresh
					if [ ${QL_REFRESH} -eq 1 ]; then
						ql_sg_map_n_sg_tur $HOST $DEVICE $LUN

						if [ "$TEST_UNIT_READY" != "0" ]; then
							if [ "$SENSE_KEY" == "Illegal Request" ] || [ "$HOST_STATUS" == "DID_NO_CONNECT" ] || [ $QL_DISTRUCTIVE_REFRESH -eq 1 ]; then
								qlu_remove_lun ${HOST} ${QL_CHANNEL} ${DEVICE} ${LUN}
							fi
						fi

					elif [ ${LUN} -eq 0 ]; then
						qlu_handle_LUNZ ${HOST} ${QL_CHANNEL} ${DEVICE} 
					fi
					qlu_add_lun ${HOST} ${QL_CHANNEL} ${DEVICE} ${LUN}
					#check if a new one found
					qlu_is_lun_present ${HOST} ${QL_CHANNEL} ${DEVICE} ${LUN}
					if [ ${WAS_LUN_PRESENT} -ne $? ] && 
					   [ ${WAS_LUN_PRESENT} -eq ${QL_FAIL} ]; then
						echo "Found LUN: ${LUN} on HOST: scsi${HOST}, DEVICE: ${DEVICE}"
					fi
				done
			done
		else
			echo "Error: ${PROC_FILE} does not exist..."
			echo "Skipping scan for HOST: scsi${HOST}..."
		fi
	done
}

# --------------------------------------------------------- #
# qlu_display_host_info	                        	    #
# Display the values from /proc/scsi/scsi                   #
# Parameter: 						    #
#	$1: Host number					    #
# Returns: 			 			    #
#	None                    			    #
# --------------------------------------------------------- #
function qlu_display_host_info()
{
	DISPLAY_ALL=0
	LOCAL_HOST=( )
	if [ "$1" = "" ]; then
		#display all hosts
		DISPLAY_ALL=1
	fi
	
	if [ ${DISPLAY_ALL} -eq 1 ]; then
		#get list of all hosts first
		if [ $QL_FS -eq $QL_PROCFS ]; then
			qlu_find_all_host
		else 
			qlu_sys_find_all_host
		fi
		if [ ${QL_TOTAL_HOSTS} -eq 0 ]; then
			echo "QLogic Host not found..."
			echo "Please check if QLogic module is loaded or not..."
			echo "Aborting display information..."
			return ${QL_FAIL}
		fi
		LOCAL_HOST=( ${QL_HOST[@]} )	
	else
		LOCAL_HOST=( $1 )
	fi

		#get a local copy of proc
		cat ${QL_PROC_SCSI}/scsi > ./local_scsi.txt
		if [ ! -e "./local_scsi.txt"  ]; then
			echo "Unable to create copy of /proc/scsi/scsi"
			echo "Aborting display information..."
			return ${QL_FAIL}	
		fi
		#read /proc/scsi/scsi for each host
		DISPLAY_NEXT=0
		MAX_DISP_COUNT=2
		DISPLAY_COUNT=0
		DEVICE_FOUND=0
		echo ""
		for HOST in ${LOCAL_HOST[@]}
		do
			while read LINE
			do
				if [ ${DISPLAY_NEXT} -eq 1 ]; then
					if [ ${DISPLAY_COUNT} -eq ${MAX_DISP_COUNT} ]; then
						DISPLAY_NEXT=0	
						DISPLAY_COUNT=0
					else
						echo "$LINE"
						((DISPLAY_COUNT += 1))
					fi
				fi
				echo "$LINE" | grep "scsi${HOST}" >& /dev/null
				if [ $? -eq ${QL_SUCCESS} ]; then
					echo "$LINE"
					DEVICE_FOUND=1
					DISPLAY_NEXT=1
				fi	
			done < ./local_scsi.txt	
			#check if device found
			if [ ${DEVICE_FOUND} -eq 0 ]; then
				echo "No device found on Host ${HOST}"
			else
				#reset DEVICE_FOUND for next host
				DEVICE_FOUND=0
			fi
		done
		rm ./local_scsi.txt >& /dev/null
		echo ""
	
}

# --------------------------------------------------------- #
# qlu_display_current_luns()		                    #
# Displays luns present currently                           #
# Parameter: None. 					    #
# Returns: None.		 			    #
# --------------------------------------------------------- #

function qlu_display_current_luns()
{
	local LUN
	echo ""
	echo_b  "DEVICE"
	echo ""
	echo_b "[H:C:T:L]"
	echo ""
	for HOST in ${QL_HOST[@]}
	do
		get_targets $HOST
		
		for TARGET in ${QL_TARGETS[@]}
		do
			get_luns ${HOST} ${TARGET}    
			if [ ${QL_TOTAL_LUNS} -eq 0 ]; then
				echo "No LUNs on Host$HOST Target$TARGET"
			else
				QL_SORTED_LUNS=(`echo ${QL_LUNS[@]} | sed "s/ /\\n/g" | sort -n`)
				for LUN in ${QL_SORTED_LUNS[@]}
				do
					echo_b "[$HOST:0:$TARGET:$LUN]"
					echo ""
				done
			fi
		done
	done
}

# --------------------------------------------------------- #
# get_targets ()                                            #
# Detects all the targets connected to given host and fills #
# QL_TARGETS array                                          #
# Parameters :                                              #
#              HOST                                         #
# Returns :                                                 #
#           Number of targets                               #
# --------------------------------------------------------- #
function get_targets
{
local HOST=${1}
local TARGET
local TARGETS=()
	if [ "${QL_HBA_SCAN}" -eq "${QL_ISCSI_SCAN}" ]; then
	ls -d /sys/class/scsi_host/host$HOST/device/session*/target* &> /dev/null
	RET=$?
	if [ $RET == 0 ]; then
		TARGETS=(`ls -d /sys/class/scsi_host/host$HOST/device/session*/target$HOST\:0\:* | sed "s/.*target$HOST\:0\://"`)
		for TARGET in ${TARGETS[@]}
		do
			echo "${QL_TARGETS[@]}" | grep -w $TARGET >& /dev/null
			if [ $? -ne 0 ]; then
				QL_TARGETS=(${QL_TARGETS[@]} $TARGET)
			fi
		done
				QL_TOTAL_TARGETS=${#QL_TARGETS[@]}
		return
	fi
	fi

    	if [ -e /sys/class/scsi_host/host$HOST/device/ ]; then
		cd  "/sys/class/scsi_host/host$HOST/device/"

		ls -d rport-$HOST:0-*/target$HOST:0:* &> /dev/null
                if [ $? -eq 0 ]; then
			QL_TARGETS=( `ls -d rport-$HOST:0-*/target$HOST:0:* | sed "s/rport.*target${HOST}:0:\(.*\)/\1/"` )
		else
			ls -d rport-$HOST:0-* &> /dev/null
			if [ $? -eq 0 ]; then
				QL_TARGETS=( `ls -d rport-$HOST:0-* | sed "s/rport-$HOST:0-//"` )
			fi
		fi

                ls -d target$HOST:0:* &> /dev/null
                if [ $? -eq 0 ]; then
                        QL_TARGETS=( `ls -d target$HOST:0:* | sed "s/target$HOST:0://"` )
                fi


		ls -d $HOST:0:* &> /dev/null
		if [ $? -eq 0 ]; then
			TARGETS=`ls -d $HOST:0:* | sed "s/$HOST:0:\(.*\):.*/\1/"`
			for TARGET in ${TARGETS[@]}
			do
				echo "${QL_TARGETS[@]}" | grep -w $TARGET >& /dev/null
				if [ $? -ne 0 ]; then
					QL_TARGETS=(${QL_TARGETS[@]} $TARGET)
				fi
			done
		fi
	QL_TOTAL_TARGETS=${#QL_TARGETS[@]}
	fi
        return 

}

# --------------------------------------------------------- #
# get_proc_targets ()                                       #
# Detects all the targets connected to given host and fills #
# QL_TARGETS array. This works proc based                   #
# Parameters :                                              #
#              HOST                                         #
# Returns :                                                 #
#           Number of targets                               #
# --------------------------------------------------------- #

function get_proc_targets
{
local HOST=$1
local TARGET=""
QL_TARGETS=()
        TARGETS=`cat $HOST | grep "^(.*:" | grep -v "Id:Lun" | sed "s/(\(.*\):.*).*/\1/"`
        for TARGET in $TARGETS
        do
        echo "${QL_TARGETS[@]}" | grep -w $TARGET >& /dev/null
        if [ $? -ne 0 ]; then
        QL_TARGETS=(${QL_TARGETS[@]} $TARGET)
        fi
        done
QL_TOTAL_TARGETS=${#QL_TARGETS[@]}
return 
}

# --------------------------------------------------------- #
# get_proc_luns ()                                          #
# Detects all the LUNS connected to given TARGET and fills  #
# QL_LUNS array, this works on proc based scanning.         #
# Parameters :                                              #
#              <HOST> <TARGET>                              #
# Returns :                                                 #
#           Number of LUNS                                  #
# --------------------------------------------------------- #

function get_proc_luns
{
local HOST=$1
local TARGET=$2
local LUN
QL_LUNS=()
LUNS=`cat $HOST | sed "s/ //g" | grep "^(${TARGET}:" | sed "s/(${TARGET}:\(.*\)).*/\1/"`
	for LUN in $LUNS
	do
		echo "${QL_LUNS}" | grep -w $LUN >& /dev/null
		if [ $? -ne 0 ]; then
			QL_LUNS=(${QL_LUNS[@]} $LUN)
		fi
	done
	QL_TOTAL_LUNS=${#QL_LUNS[@]}
	return 
}

# --------------------------------------------------------- #
# get_luns ()                                               #
# Detects all the LUNS connected to given TARGET and fills  #
# QL_LUNS array                                             #
# Parameters :                                              #
#              <HOST> <TARGET>                              #
# Returns :                                                 #
#           Number of LUNS                                  #
# --------------------------------------------------------- #
function get_luns
{
        local HOST=${1}
        local TARGET=${2}
	local LUNS=()
	
	if [ "${QL_HBA_SCAN}" -eq "${QL_FC_SCAN}" ]; then	
        if [ -e /sys/class/scsi_host/host$HOST/device/target${HOST}:0:${TARGET} ]; then
                cd "/sys/class/scsi_host/host$HOST/device/target${HOST}:0:${TARGET}/"
        elif [ -e /sys/class/scsi_host/host$HOST/device/rport-$HOST:0-$TARGET/target${HOST}:0:${TARGET} ]; then
		cd "/sys/class/scsi_host/host$HOST/device/rport-$HOST:0-$TARGET/target${HOST}:0:${TARGET}/"
        elif [ -e /sys/class/fc_transport/target${HOST}:0:${TARGET}/device ]; then
		cd "/sys/class/fc_transport/target${HOST}:0:${TARGET}/device/"
        fi
	fi

	if [ "${QL_HBA_SCAN}" -eq "${QL_ISCSI_SCAN}" ]; then
		if [ -e /sys/class/scsi_host/host$HOST/device/target${HOST}:0:${TARGET} ]; then
			cd "/sys/class/scsi_host/host$HOST/device/target${HOST}:0:${TARGET}/"
		elif [ -e /sys/class/scsi_host/host$HOST/device/rport-$HOST:0-$TARGET/target${HOST}:0:${TARGET} ]; then
			cd "/sys/class/scsi_host/host$HOST/device/rport-$HOST:0-$TARGET/target${HOST}:0:${TARGET}/"
		elif [ -e /sys/class/scsi_host/host$HOST/device/session*/target${HOST}:0:${TARGET} ]; then

                	QL_LUNS=(`ls -d /sys/class/scsi_host/host$HOST/device/session*/target$HOST\:0\:$TARGET/$HOST\:0\:$TARGET\:* | sed "s/.*$HOST\:0\:$TARGET\://"`)
			QL_TOTAL_LUNS=${#QL_LUNS[@]}			
			return
		


		fi
	fi	
        QL_LUNS=( `ls -d $HOST:0:$TARGET:* 2> /dev/null | sed "s/$HOST:0:$TARGET://"` )
	QL_TOTAL_LUNS=${#QL_LUNS[@]}
        return 
}
 
# --------------------------------------------------------- #
# qlu_proc_display_current_luns()		            #
# Displays luns present currently                           #
# using proc filesystem                                     #
# Parameter: None. 					    #
# Returns: None.		 			    #
# --------------------------------------------------------- #
function qlu_proc_display_current_luns()
{
local LUN

	cd "/proc/scsi/$QL_DRIVER"

#     qlu_scan_host "${QL_HOST[@]}"
#     return $?

for HOST in ${QL_HOST[@]}
do
     get_proc_targets $HOST
     if [ ${QL_TOTAL_TARGETS} -ne 0 ]; then
          echo ""
          echo_b "Device "
          echo ""
          echo_b "[H:C:T:L]"
          echo ""
     fi

     for TARGET in ${QL_TARGETS[@]}
     do
         get_proc_luns $HOST $TARGET
         if [ ${QL_TOTAL_LUNS} -ne 0 ]; then
		QL_SORTED_LUNS=(`echo ${QL_LUNS[@]} | sed "s/ /\\n/g" | sort -n`)          
		for LUN in ${QL_SORTED_LUNS[@]}
		do
		   echo_b "[$HOST:0:$TARGET:$LUN]"
		   echo ""
              done
         else
              echo ""
              return 0
         fi
   done

done
}

#-----------------------------------------------------------#
# qlu_sys_rescan_scsi_devices()                             #
# Rescan the devices connected to qlogic hosts.This         #
# rescans the devices whose disk size has changed.          #
# echo 1 > /sys/block/sd*/device/rescan                     #
# Parameter:                                                #
#	 Host List	                                    #
# Return :                                                  #
#	 None                                               #
#-----------------------------------------------------------#
function qlu_sys_rescan_scsi_devices()
{
	local LUN
	local TARGET
	CWD=`pwd`
	HOST_LIST=(`echo $1`)

        for HOST in ${HOST_LIST[@]}
        do
		get_targets $HOST

		for TARGET in ${QL_TARGETS[@]}
		do
			get_luns ${HOST} ${TARGET}
			if [ ${QL_TOTAL_LUNS} -eq 0 ]; then
				echo "No LUNs on Host$HOST Target$TARGET"
			else
				for ((LUN=0; ${LUN} <= ${QL_SCAN_LUNS}; LUN++))
					do
					if [ -e /sys/class/scsi_device/${HOST}:0:${TARGET}:${LUN}/device ]; then
						sdevice=$(ls block/sd* 2> /dev/null | wc -l)
						cd "/sys/class/scsi_device/${HOST}:0:${TARGET}:${LUN}/device/"
						local MAJOR
						local MINOR
						if [ -e "block/dev" ]; then
							MAJOR=`cat "block/dev" | cut -d ":" -f 1`
							MINOR=`cat "block/dev" | cut -d ":" -f 2`
							DEV_NAME=`ls -l /dev/ | grep -w "$MAJOR,[[:space:]]\+$MINOR" | sed "s/.* \(.*$\)/\/dev\/\1/" | cut -d / -f 3`
							if [ -e /sys/block/$DEV_NAME/device/rescan ]; then
								echo 1 > /sys/block/$DEV_NAME/device/rescan
							fi
						elif [ "$sdevice" != 0 ] ; then
							cd block
							DEV_NAME=`ls | grep ^sd | cut -d : -f 2`
							if [ -e /sys/block/$DEV_NAME/device/rescan ]; then
								echo 1 > /sys/block/$DEV_NAME/device/rescan
							fi

						else
							DEV_NAME=`ls | grep ^block | cut -d : -f 2`
							if [ -e /sys/block/$DEV_NAME/device/rescan ]; then
								echo 1 > /sys/block/$DEV_NAME/device/rescan
							fi
						fi
					
					 fi
				done
			fi
		done
	done
	cd "$CWD"
}

# --------------------------------------------------------- #
# echo_b()		                                    #
# Prints messages in bold				    #
# Parameter: 						    #
#	$1	Message to be printed			    #
# Returns: None.		 			    #
# --------------------------------------------------------- #

function echo_b() {
	echo -en "\033[1m${1}\033[0m"
	tput sgr0
}

# --------------------------------------------------------- #
# qlu_help ()		                                    #
# Prints the help message LUN scan utility                  #
# Parameter: None                                           #
# Returns: None                                             #
# --------------------------------------------------------- #
function qlu_help() {
        echo ""
        echo_b "QLogic Linux LUN Scan Utility v$QLU_VERSION"
        echo ""
        echo ""
        echo "To begin scanning the LUNs issue following command:"
        echo ""
        echo "  # ${QLU_LUN_SCAN}"
        echo ""
        echo "Usage: ${QLU_LUN_SCAN} [OPTIONS]"
        echo ""
	echo "  -al,   --allow-lip"
	echo "                        LIP is not issued by default, even if it is required for scanning new LUNs"
	echo "                        Setting this option, allows the utility to issue LIP."
	echo ""
        echo "  -cl, --current-luns"
        echo "                        Displays LUNS currently present"
	echo ""
	echo "  -e,  --extended-scan"
	echo "                        Use this option as \"-e | --extended-scan\". to rescan"
	echo "                        LUNs. This will identify any change in attributes of"
	echo "                        existing LUNs. This option can be used in combination"
	echo "                        of scan/refresh or max luns"
	echo ""
        echo "  -h,  --help, ?"
	echo "                        Prints this help message"
	echo ""
        echo "  -i,  --interactive"
        echo "                        Use this option to use the menu driven program"
	echo ""
	echo "  -is,  --iscsi "
	echo "                        Use this option to operate on ISCSI HBAs, this option can"
	echo "                        be used in combination of any other supported option."
	echo ""
	echo "  -m,  --max-lun"
        echo "                        To set the maximum LUNs to be scanned"
	echo ""
	echo "  -p,  --proc"
	echo "                        Use PROC file system for LUN scanning"
        echo ""
        echo "  -r,  --refresh"                        
        echo "                        To refresh, that is remove LUNs that are lost"
	echo "                        use the options \"-r|--refresh\". This will"
	echo "                        remove the LUNs which no more exist." 
	echo ""
        echo "  -s,  --scan [ -r|--refresh ]"
        echo "                        The QLogic LUN scan utility re-scans all the"
        echo "                        devices connected to the QLogic HBA"
	echo ""

}

# --------------------------------------------------------- #
# ql_check_distro ()		                            #
# Checks if the driver is not a distro release by checking  #
# for "d" in end                                            #
# Parameter: None                                           #
# Returns: QL_FAIL/QL_SUCCESS                               #
# --------------------------------------------------------- #

function ql_check_distro 
{
local HOST=$1
RET=1
PROC_FILE=${QL_PROC_SCSI}/${QL_DRIVER}/${HOST}
if [ -e ${PROC_FILE} ]; then
	cat /proc/scsi/$QL_DRIVER/$HOST | grep "Driver version" | sed "s/.* version\ //" | grep "d[[:digit:]]" >& /dev/null
	RET=$?
fi
return $RET
}
# --------------------------------------------------------- #
# qlu_main ()		                                    #
# The main function to scan the hosts                       #
# Parameter: None                                           #
# Returns: Return of scan                                   #
# --------------------------------------------------------- #
function qlu_main()
{
if [ $QL_FS == $QL_PROCFS ]; then
	qlu_find_all_host
	if [ ${QL_TOTAL_HOSTS} -eq 0 ]; then
		echo "QLogic Host not found..."
		echo "Please check if QLogic module is loaded or not..."
		exit 1
	fi 
	qlu_scan_host "${QL_HOST[@]}"
	return $?
else
	qlu_sys_find_all_host
	if [ ${QL_TOTAL_HOSTS} -eq 0 ]; then
		echo "QLogic Host not found..."
		echo "Please check if QLogic module is loaded or not..."
		exit 1
	fi

	for HOST in ${QL_HOST[@]}
	do
		PROC_FILE=${QL_PROC_SCSI}/${QL_DRIVER}/${HOST}
		if [ "${QL_HBA_SCAN}" -eq "${QL_FC_SCAN}" ]; then
			if [ -e ${PROC_FILE} ]; then
				echo "scsi-qlascan" > ${PROC_FILE}
			fi
		fi
	done
		#ir-respective of /proc/scsi/qla***/* scan for hosts
		qlu_sys_scan_host "`echo ${QL_HOST[@]}`"

fi
}

#====Menu Start=====

#----------------------------------------#
# qlu_hit_any_key()
# Waits for user to hist a key
# PARAMETERS : NONE
# RETURNS	 : None
#----------------------------------------#
function qlu_hit_any_key()
{
	echo -n "Hit any key to continue.........."
	read -n 1
	clear
}

#----------------------------------------#
# qlu_main_screen()
# Prints the main menu of the program
# PARAMETERS : NONE
# RETURNS	 : QL_SUCCESS or QL
#----------------------------------------#

function qlu_main_screen() {

STATUS=""
echo " Welcome to QLogic LUN Scan Utility"
echo "===================================="
echo ""
echo "MAIN MENU"
echo "	1: ALL HOSTS SCAN"
echo "	2: ALL HOST SCAN & REFRESH"
echo "	3: ALL HOSTS EXTENDED SCAN"
echo "	4: SELECT HOST TO SCAN"
echo "	5: SCAN LUN's UPTO (Current LUN # ${QL_SCAN_LUNS})"
echo "	6: DISPLAY CURRENT LUNS"
echo "	7: QUIT"
echo ""

echo -n "Please select one of the options above : "

read SC1_CHOICE # read user choice for qlu_main_screen

case $SC1_CHOICE in

    	1)
		echo ""
		qlu_main
		echo ""
		qlu_hit_any_key
		return $QL_CALL_AGAIN
	;;

	2)
		echo ""
		QL_REFRESH=1
		qlu_main
		echo ""
		qlu_hit_any_key
		return $QL_CALL_AGAIN
	;;

	3)
		qlu_sys_find_all_host
		if [ ${QL_TOTAL_HOSTS} -eq 0 ]; then
			echo "QLogic Host not found..."
			echo "Please check if QLogic module is loaded or not..."
			exit 1
		fi
		qlu_sys_rescan_scsi_devices "`echo ${QL_HOST[@]}`"
		qlu_hit_any_key
		clear
		return $QL_CALL_AGAIN
	;;

    	4)
		STATUS=$QL_CALL_AGAIN
		clear
		while [ $STATUS -eq $QL_CALL_AGAIN ]
		do
        		qlu_screen_2
			STATUS=$?
		done
		if [ $STATUS -eq $QL_CALL_RETURNED ];then
			clear
			return $QL_CALL_AGAIN
		else 
			return $STATUS
		fi
	;;

    	5)
		echo -n "Enter the value for maximum LUN # : "
        	read MAX_LUN
		qlu_set_max_lun $MAX_LUN
		if [ $? -eq 2 ]; then
			qlu_hit_any_key
		fi
		clear
		return $QL_CALL_AGAIN
	;;

  	 6)
        	if [ $QL_FS == $QL_PROCFS ]; then
                	qlu_find_all_host
			if [ ${QL_TOTAL_HOSTS} -eq 0 ]; then
        	                echo "QLogic Host not found..."
                	        echo "Please check if QLogic module is loaded or not..."
                        	exit 1
                	else
                   	  	qlu_proc_display_current_luns | more
	                fi
#               qlu_scan_host "${QL_HOST[@]}"
#               return $?
        	else
                	qlu_sys_find_all_host
        	        if [ ${QL_TOTAL_HOSTS} -eq 0 ]; then
	                        echo "QLogic Host not found..."
                        	echo "Please check if QLogic module is loaded or not..."
                	        exit 1
	                else
        	               # cd /sys/class/scsi_device
	                        qlu_display_current_luns | more
                	fi
        	fi
			qlu_hit_any_key
			clear
			return $QL_CALL_AGAIN
        ;;

    	7 | q | Q | quit)
        	exit 0 
	;;
 	
   	*)	
		clear
		return $QL_CALL_AGAIN
	;;
esac
}

#----------------------------------------#
# qlu_screen_2()
# Prints the Host list 
# PARAMETERS : NONE
# RETURNS    : NONE
#----------------------------------------#
function qlu_screen_2() {

#HQ=$QL_HOST # HQ for host quantity
HQ=( )
LN=1  # LN for Line Number
if [ $QL_FS == $QL_PROCFS ]; then
	qlu_find_all_host
	RETURN_VAL=${QL_TOTAL_HOSTS}
else
	qlu_sys_find_all_host
	RETURN_VAL=${QL_TOTAL_HOSTS}
fi
if [ $RETURN_VAL -eq 0 ]; then
	echo ""
	echo ""
	echo "No Host found to display"
	echo ""
	echo ""
else 
	echo "List of available Hosts"
fi

HQ=( ${QL_HOST[@]} )

for HOST in ${HQ[@]}
 do
	echo "	$LN. HOST: scsi${HOST}"
	LN=$((LN+1))
 done

if [ $QL_SCAN_TYPE -eq 1 ];then
	SCAN_STATUS="SCAN ONLY"
	QL_REFRESH=0
elif [ $QL_SCAN_TYPE -eq 2 ];then
	SCAN_STATUS="SCAN & REFRESH"
	QL_REFRESH=1
elif [ $QL_SCAN_TYPE -eq 3 ];then
	SCAN_STATUS="EXTENDED SCAN ONLY"
fi

echo "	$LN. SET SCAN TYPE (Current : $SCAN_STATUS) "
echo "	$((LN+1)). GO BACK TO PREVIOUS SCREEN"
echo "	$((LN+2)). QUIT"

echo -n "Please select one of the options above : "
read SC2_CHOICE # read user choice for qlu_screen_2

case $SC2_CHOICE in
	q | Q | quit )
	exit 0
	;;
esac

echo "$SC2_CHOICE" | grep "[0-9]\+" >& /dev/null

if [ $? -ne 0 ];then
	clear
	return $QL_CALL_AGAIN
fi

if [ $SC2_CHOICE -ge 1 ];then 
	if [ $SC2_CHOICE -le $(($LN-1)) ];then
		case $QL_SCAN_TYPE in
	
			1 | 2 )	
				if [ $QL_FS == $QL_PROCFS ]; then
					qlu_scan_host ${HQ[((SC2_CHOICE-1))]}
				else
					qlu_sys_scan_host ${HQ[((SC2_CHOICE-1))]}
				fi
				echo ""
				qlu_hit_any_key
				return $QL_CALL_AGAIN
			;;
					
			3 )
				qlu_sys_rescan_scsi_devices ${HQ[((SC2_CHOICE-1))]}
				echo ""
				qlu_hit_any_key
				return $QL_CALL_AGAIN
			;;

			* )
				clear
				return $QL_CALL_AGAIN
			;;
		esac

	elif [ $SC2_CHOICE -eq $LN ];then

	 	STATUS=$QL_CALL_AGAIN
		clear
		while [ $STATUS -eq $QL_CALL_AGAIN ]
		do
		qlu_screen_4
		STATUS=$?
		done
		if [ $STATUS -eq $QL_CALL_RETURNED ];then
		    clear
		    return $QL_CALL_AGAIN
		else
		    return $STATUS
		fi

	elif [ $SC2_CHOICE -eq $((LN+1)) ];then
		return $QL_CALL_RETURNED

	elif [ $SC2_CHOICE -eq $((LN+2)) ];then
		exit 0
	else 
		return $QL_CALL_AGAIN
	fi
else	
	return $QL_CALL_AGAIN
fi
}

#----------------------------------------#
# qlu_screen_32()
# Prints the Host list  for displaying information
# PARAMETERS : Host count $1
# RETURNS    : QL_SUCCESS/QL_FAIL
#----------------------------------------#
function qlu_screen_32() {

LN=1  # LN for Line Number
echo "List of available Hosts"

if [ $QL_FS == $QL_PROCFS ]; then
	qlu_find_all_host
else
	qlu_sys_find_all_host
fi

if [ ${QL_TOTAL_HOSTS} -eq 0 ]; then
	echo "No QLogic HBA found..."
	echo "Aborting display information..."
	return ${QL_FAIL}
fi
for HOST in ${QL_HOST[@]}
do
echo "	$LN. HOST: scsi${HOST}"
LN=$((LN+1))
done
echo "	$LN. GO BACK TO PREVIOUS SCREEN"
echo "	$((LN+1)). QUIT"
echo -n "Please select one of the options above : "
read SC2_CHOICE # read user choice for qlu_screen_2

case $SC2_CHOICE in
	q | Q | quit )
	exit 0
	;;
esac

if [ $SC2_CHOICE -ge 1 ];then 
	if [ $SC2_CHOICE -le ${#QL_HOST[@]} ];then
		qlu_display_host_info ${QL_HOST[(($SC2_CHOICE - 1))]} | more
		qlu_hit_any_key
		return $QL_CALL_AGAIN
	elif [ $SC2_CHOICE -eq $LN ];then
		return $QL_CALL_RETURNED
	elif [ $SC2_CHOICE -eq $((LN+1)) ];then
		exit 0
	else 
		return $QL_CALL_AGAIN
	fi
else	
	return $QL_CALL_AGAIN
fi
}

  
#----------------------------------------#
# qlu_screen_4()
# Sets value of $QL_REFRESHED as asked by 
# user 
# PARAMETERS : NONE
# RETURNS    : NONE
#----------------------------------------#

function qlu_screen_4() {
echo "SELECT SCAN TYPE"
echo "	1.HOST SCAN & REFRESH"
echo "	2.HOST SCAN ONLY"
echo "	3.HOST EXTENDED SCAN ONLY"
echo -n "Please select one of the options above : "
read SC4_CHOICE

case $SC4_CHOICE in

	1)
		QL_SCAN_TYPE=$TYPE_SCAN_REFRESH
		echo "SCAN TYPE SET TO \"SCAN & REFRESH\""
		return $QL_CALL_RETURNED
	;;
	2)
		QL_SCAN_TYPE=$TYPE_SCAN_ONLY
		echo "SCAN TYPE SET TO \"SCAN ONLY\""
		return $QL_CALL_RETURNED
	;;
	3)
		QL_SCAN_TYPE=$TYPE_EXTENDED_SCAN_ONLY
		echo "SCAN TYPE SET TO \"EXTENDTED SCAN\""
		return $QL_CALL_RETURNED
	;;
	q | Q | quit)
		exit 0
	;;
		
	*)
		return $QL_CALL_AGAIN
	;;
	
	q | Q | quit )
	exit 0
	;;
esac

}
#====Menu End====
#===SysFS Menu===
SG_UTIL_PATH=/tmp/ql/sg_utils
mkdir -p "$SG_UTIL_PATH"
SG_UTL_DIR=`echo sg3_utils* | sed "s/\(.*\)\.tgz/\1/"`

function ql_ask_distructive_scan ()

{
	if [ $QL_DISTRUCTIVE_REFRESH == 1 ]; then
		return 1
	fi

	echo "Would you like to explicitly remove all the devices and rescan ? "
        echo "Note: This may make the system un-usable if the system is using"
        echo "any of the devices attached to the QLogic HBAs"
        echo -n "Proceed? (yes/no): "
        read CHOICE

        case ${CHOICE} in
        yes | y | YES )
                        QL_DISTRUCTIVE_REFRESH=1
			# Reached this point means either proper sg utils was not found
			# or compilation of SG failed, and user still wants to continue.
			QL_SG_VERIFICATION=2
                        return 1
        ;;
        no | n | NO | * )
                        exit 0
        ;;

	esac


}

function ql_compile_sg ()
{

if [ -e "`ls | grep -m 1 sg3_utils`" ]; then
        SG_UTL=`ls | grep -m 1 sg3_utils`
        if [ -d "$SG_UTIL_PATH/$SG_UTL" ]; then
                cd "$SG_UTIL_PATH/$SG_UTL"
        else
                tar zxvf $SG_UTL -C "$SG_UTIL_PATH" &> /dev/null
		cd "$SG_UTIL_PATH/$SG_UTL_DIR"
        fi
        # Everything is fine till here lets build the source
        make sg_map sg_turs &> /dev/null
	RET=$?
	if [ "$RET" -ne 0 ]; then
		ql_ask_distructive_scan
	fi
	return $RET
else
	echo "ERROR: SG3 Utility not found"

	echo "Unable to determine devices to be refreshed."
	ql_ask_distructive_scan
	return 1
fi

}

function ql_execute_sg ()
{
TEST_UNIT_READY=1 # Wash out previous value
local HOST=$1
local TARGET=$2
local LUN=$3
SENSE_KEY=""
HOST_STATUS=""

DISK=`$SG_MAP -x | grep -w "$HOST 0 $TARGET $LUN" | cut -d " " -f 10`

if [ "$DISK" == "" ]; then
	DISK=`$SG_MAP -x | grep -w "$HOST 0 $TARGET $LUN" | cut -d " " -f 1`
fi

if [ "$DISK" != "" ]; then
	DEVICE_TYPE=`$SG_MAP -x | grep -w "$HOST 0 $TARGET $LUN" | cut -d " " -f 8`
	if [ "$DEVICE_TYPE" == "" ]; then
		if [ ! -e /sys/class/scsi_disk/$HOST:0$TARGET:$LUN ]; then
			return;
		fi
	fi

	# Fail TUR deliberately	for controller LUN
	if [ $DEVICE_TYPE != 12 ] || [ $DEVICE_TYPE != 31 ] || [ $DEVICE_TYPE != 3 ]; then

		for ((ITERATION=1; ${ITERATION} <= 3; ITERATION++))
		do
			$SG_TURS $DISK $SG_TUR_VERBOSE >& /tmp/ql-util
			TEST_UNIT_READY=$?
			SENSE_KEY="`cat /tmp/ql-util | grep "Sense key" | sed "s/.*Sense\ key:\ \(.*\)/\1/"`"

			HOST_STATUS=`cat /tmp/ql-util | grep -o "DID_NO_CONNECT"`

			if [ "$SENSE_KEY" == "Unit Attention" ]; then
				sleep 3
				continue
			else
				break
			fi
		done
	fi
else
	ql_ask_distructive_scan
fi

return
}

function ql_sg_map_n_sg_tur ()
{
local HOST=$1
local TARGET=$2
local LUN=$3
local ATLEAST_ONE_VERBOSE=0
if [ "$QL_DISTRUCTIVE_REFRESH" -eq "1" ]; then
	TEST_UNIT_READY=1
	return
fi

# Go thru verification only if its never done before
if [ $QL_SG_VERIFICATION -eq 0 ]; then
	SG_IS_THERE=0 # Assuming by default SG Utility is installed

	# Keep record so we dont end up this function in wrong dir
	CALL_DIR=`pwd`
	cd "$ORG_DIR"

	SG_TURS=`which sg_turs 2> /dev/null`
	if [ $? -eq 0 ]; then
	# Though sg_turs is there; check if verbose option is supported, and also which of the --verbose/-v
	# Checking for --verbose
		$SG_TURS 2> /dev/null | grep -w "\-\-verbose" &> /dev/null
		if [ $? -eq 0 ]; then
			SG_TUR_VERBOSE="--verbose"
			ATLEAST_ONE_VERBOSE=1
		fi
		
	# Checking for -v
		$SG_TURS 2> /dev/null | grep -w "\-v" &> /dev/null
		if [ $? -eq 0 ]; then
			SG_TUR_VERBOSE="-v"
			ATLEAST_ONE_VERBOSE=1
		fi
	# if ATLEAST_ONE_VERBOSE is still 0; this sg_turs is not of our use
		if [ $ATLEAST_ONE_VERBOSE -eq 0 ]; then
			SG_IS_THERE=1 # TUR not there
		fi
		
		SG_MAP=`which sg_map 2> /dev/null`
		if [ $? -ne 0 ]; then
			SG_IS_THERE=1 # map not there
		fi	
	else
		SG_IS_THERE=1 # TUR not there
	fi

	if [ $SG_IS_THERE -eq 1 ]; then
		ql_compile_sg
		if [ $? -ne 0 ]; then
			if [ $QL_DISTRUCTIVE_REFRESH -eq 1 ]; then
				TEST_UNIT_READY=1
			fi
			cd "$CALL_DIR"
			# we are here means sg utils is not available or usable
			SG_TURS=""
			SG_MAPS=""
			return 1 # Neither sg is available nor we are able to compile
		else
			SG_TURS="$SG_UTIL_PATH/$SG_UTL_DIR/sg_turs"
			SG_MAP="$SG_UTIL_PATH/$SG_UTL_DIR/sg_map"
		fi
	fi

	# Check if SG Module is loaded 
	lsmod | cut -d " " -f 1 | grep sg &> /dev/null

	if [ $? -ne 0 ]; then # Try to load the module
		modprobe sg
	fi
	# if we are returning from this point then we have successfully verified sg utils
	# hence no need to do it again for every go
	QL_SG_VERIFICATION=1
	cd "$CALL_DIR"
fi
# Check if TUR
ql_execute_sg $HOST $TARGET $LUN 
return
}

# --------------------------------------------------------- #
# qlu_sys_remove_lun()	                                    #
# Removes the device by echoing 1 to /device/delete         #
# Parameter: 						    #
#	HOST number                                         #
# Returns: 			 			    #
#	None						    #
# --------------------------------------------------------- #

function qlu_sys_remove_lun ()
{
        HOST=$1
        DIR=`pwd`
cd "/sys/class/scsi_device/"

get_targets $HOST
for TARGET in ${QL_TARGETS[@]}
do
	get_luns ${HOST} ${TARGET}
        if [ ${QL_TOTAL_LUNS} -eq 0 ]; then
		echo "No LUNs found for Host $HOST: Target $TARGET pair"
        else
                for ((LUN=0; ${LUN} <= ${QL_SCAN_LUNS}; LUN++))
                do
                        echo ${QL_LUNS[@]} | grep -w $LUN &> /dev/null
                        if [ $? -eq 0 ]; then
				ql_sg_map_n_sg_tur $HOST $TARGET $LUN
				# Remove only if TUR Fails
				if [ "$TEST_UNIT_READY" != "0" ]; then
					# Extract the sense key after firing ./sg_tur.
					# if key is "Illegal Request", Delete the lun
					# This condition avoids deleting offline devices
					if [ "$SENSE_KEY" == "Illegal Request" ] || [ "$HOST_STATUS" == "DID_NO_CONNECT" ] || [ $QL_DISTRUCTIVE_REFRESH -eq 1 ]; then
						if [ -e /sys/class/scsi_device/$HOST:0:$TARGET:$LUN/device/delete ]; then
							cd "/sys/class/scsi_device/"
							echo "1" > $HOST:0:$TARGET:$LUN/device/delete 
						elif [ -e  $HOST:0:$TARGET:$LUN/delete ]; then
							echo "1" > $HOST:0:$TARGET:$LUN/delete
						fi
					fi
				fi
                        fi
                done
	        fi
done

cd "$DIR"
return
}

# --------------------------------------------------------- #
# ql_issue_lip_n_wait()                                     #
# Issues lip and waits for loop state = READY               #
# /sys/class/scsi_host/host$HOST/scan                       #
# Parameter: 						    #
#		HOST	                             	    #
# Returns: 			 			    #
#	None                    			    #
# --------------------------------------------------------- #
function ql_issue_lip_n_wait
{
local HOST=$1
#local LOOP_STATE=1
echo "Issuing LIP on host$HOST"
if [ -f /sys/class/fc_host/host$HOST/issue_lip ]; then
	echo "1" > /sys/class/fc_host/host$HOST/issue_lip
fi
#while [ $LOOP_STATE == 1 ];
#do
#	cat /proc/scsi/$QL_DRIVER/$HOST | grep "loop state = <READY>"
#	if [ $? == 0 ]; then
#		LOOP_STATE=0
#		echo -n "DONE"
#	else 
#		echo -n "."
#		sleep 1
#	fi
#done

}

# --------------------------------------------------------- #
# ql_clean_LUNZ()				            #
# Removes LUN 0 from the list of array if it's LUNZ         #
# (Controller LUN)                                          #
# using proc filesystem                                     #
# Parameter: None. 					    #
# Returns: None.		 			    #
# --------------------------------------------------------- #

function ql_clean_LUNZ ()
{
local LUN
local MODEL
local LUNS_SOURCE=()
local LUNS_TEMP=()

if [ "$1" == "ORG" ]; then
	LUNS_SOURCE=( ${LUNS_ORG[@]} )
else
	LUNS_SOURCE=( ${LUNS_NEW[@]} )
fi
	for LUN in ${LUNS_SOURCE[@]}
	do
		LUN_NO=`echo $LUN | sed "s/.*:.*:.*:\(.*\)/\1/g" 2> /dev/null`
		if [ "$LUN_NO" == 0 ]; then
			MODEL_TEMP=`cat /sys/class/scsi_device/$LUN/device/model 2> /dev/null`
			MODEL=`echo $MODEL_TEMP | sed "s/\ $//g"`
			if [ "$MODEL" != LUNZ ]; then
				LUNS_TEMP=( ${LUNS_TEMP[@]} $LUN )
			fi
		else
				LUNS_TEMP=( ${LUNS_TEMP[@]} $LUN )
		fi
	done

if [ $1 == ORG ]; then
	LUNS_ORG=( ${LUNS_TEMP[@]} )
else
	LUNS_NEW=( ${LUNS_TEMP[@]} )
fi

}

# --------------------------------------------------------- #
# qlu_sys_scan_host()                                       #
# Scans the host by echoing "- - -" to                      #
# /sys/class/scsi_host/host$HOST/scan                       #
# Parameter: 						    #
#		HOST/HOST list                         	    #
# Returns: 			 			    #
#	None                    			    #
# --------------------------------------------------------- #
function qlu_sys_scan_host ()
{
	local TARGET
	local LUN
	HOST_LIST=(`echo $1`)
	local DIR=`pwd`
	cd "/sys/class/scsi_device/"
	echo "SCAN LUNs upto: ${QL_SCAN_LUNS}"
	for HOST in ${HOST_LIST[@]}
	do
		LUNS_ORG=( `ls -d $HOST* 2> /dev/null` )
		ql_clean_LUNZ ORG
		if [ $QL_REFRESH -eq 1 ]; then
			qlu_sys_remove_lun $HOST
		else
			qlu_handle_LUNZ $HOST 
		fi
		if [ "$QL_HBA_LIP" == 1 ]; then	
			if [ "${QL_HBA_SCAN}" -eq "${QL_FC_SCAN}" ]; then
				#ql_check_distro $HOST	
				#if [ $? -eq 0 ]; then
					ql_issue_lip_n_wait $HOST
				#fi
			fi		
		fi

		if [ -e /sys/class/scsi_host/host$HOST/scan ]; then
			echo "Scanning HOST: host${HOST}"
			PROC_FILE=${QL_PROC_SCSI}/${QL_DRIVER}/${HOST}
			if [ -e ${PROC_FILE} ]; then
				#call qlu_scan_done to check if scan finished
				qlu_scan_done ${PROC_FILE} $HOST
			fi

                        #if not equalto default LUNS to scan
			if [ $QL_SCAN_LUNS -ne 256 ]; then 
				for ((LUN=0; ${LUN} <= ${QL_SCAN_LUNS}; LUN++))
				do
					echo "- - ${LUN}" > /sys/class/scsi_host/host$HOST/scan
				done
                        else
				echo '- - -' > /sys/class/scsi_host/host$HOST/scan
                        fi
			
			LUNS_NEW=( `ls -d $HOST* 2> /dev/null` )
			ql_clean_LUNZ NEW
			for LUN in `echo ${LUNS_NEW[@]}`
			do
				echo ${LUNS_ORG[@]} | grep -w $LUN &> /dev/null
				if [ $? -ne 0 ]; then
					NOW_FOUND=( ${NOW_FOUND[@]} "$LUN\\n" )
				fi 
			done
			
			for LUN in `echo ${LUNS_ORG[@]}`
			do
				echo ${LUNS_NEW[@]} | grep -w $LUN &> /dev/null
				if [ $? -ne 0 ]; then
					NOW_LOST=( ${NOW_LOST[@]} "$LUN\\n" )
				fi 
			done
		
			ls $HOST:0:* &> /dev/null 
			if  [ $? -ne 0 ]; then 
				echo "No devices attached to HOST: host${HOST}"
			fi
		else
			echo "Expected Sysfs attribute" 
			echo  "/sys/class/scsi_host/host$HOST/scan not found"
		fi
	done

	if [ ${#NOW_FOUND[@]} -ne  0 ]; then
		echo -e "Found\n ${NOW_FOUND[@]}"
	fi
	
	if [ ${#NOW_LOST[@]} -ne 0 ]; then
		echo -e "Removed\n ${NOW_LOST[@]}"
	fi

	if [ ${#NOW_LOST[@]} -eq  0 ] && [ ${#NOW_FOUND[@]} -eq 0 ]; then
		echo -e "No changes discovered in existing devices."
	fi
	
	# Clean the arrays
	NOW_FOUND=()
	NOW_LOST=()
	cd "$DIR"
}

# --------------------------------------------------------- #
# qlu_handle_LUNZ()                                         #
# Parameter:                                                #
#             HOST/Host:Channel:Device  	            #
# Returns:                                                  #
# 	      None                                          #
# --------------------------------------------------------- #
function qlu_handle_LUNZ ()
{
local HOST=$1
local DIR=`pwd`
if [ $QL_FS != $QL_PROCFS ]; then
	cd "/sys/class/scsi_device/"
	ls  -d $HOST:0:*:0 &> /dev/null
	if [ $? == 0 ]; then
		for LUN in `ls -d $HOST:0:*:0`
		do
			#if clarion(vendor DGC) remove LUNZ
			cat ${LUN}/device/vendor | grep -w DGC > /dev/null 
			if [ $? == 0 ]; then
				cat ${LUN}/device/model | grep -w LUNZ > /dev/null 
				if [ $? == 0 ]; then
					echo 1 > $LUN/device/delete
				fi
			fi
		done
	fi
	cd "$DIR"
else 
	cat /proc/scsi/scsi | grep "scsi$HOST.*Id:[[:space:]].*.*Lun:[[:space:]]00" -A 1 |  grep "Vendor:" | sed "s/Vendor:[[:space:]]\+\(.*\)[[:space:]]\+Model:[[:space:]]\+.*[[:space:]]\+Rev:[[:space:]]\+.*/\1/" | grep -w "DGC"  > /dev/null 
			if [ $? -eq 0  ]; then
		cat /proc/scsi/scsi | grep "scsi$HOST.*Id:[[:space:]].*.*Lun:[[:space:]]00" -A 1 |  grep "Vendor:" | sed "s/Vendor:[[:space:]]\+.*[[:space:]]\+Model:[[:space:]]\+\(.*\)[[:space:]]\+Rev:[[:space:]]\+.*/\1/" | grep -w "LUNZ" > /dev/null
				if [ $? -eq 0  ]; then
					qlu_remove_lun ${HOST} ${QL_CHANNEL} ${DEVICE} 0 
				fi
			fi

fi

return
}

#---------------------------------------------------------- #
# qlu_set_max_lun ()                                        #
# Parameter:                                                #
#		max-luns to scan                            #
# Returns:                                                  #
#		None                                        #
# --------------------------------------------------------- #
function qlu_set_max_lun ()
{
	MAXLUN=$1
	if [ ! -z "$MAXLUN" ]; then
		echo "$MAXLUN" | grep -w "^[0-9]\+$" >& /dev/null
		RET1=$?
		if [ $RET1 -ne 0 ] || [ $MAXLUN -gt $QL_SUPPORTED_LUNS ] || [ $MAXLUN -lt 1 ]; then
			echo "Error: Invalid value, enter the value in the range [1 - $QL_SUPPORTED_LUNS]"
			return $QL_CALL_AGAIN 
		else
			QL_SCAN_LUNS=$MAXLUN	
		fi
	fi
}


#===SysFS Menu End===

# Start

# Lets check our current DIR, so needed if we need to complie SG utility
ORG_DIR=`pwd`

if [ ! -d ${QL_PROC_SCSI}/qla2* ] && [ ! -d /sys/module/qla2xxx ]; then
	QL_HBA_SCAN=${QL_ISCSI_SCAN}
else
	QL_HBA_TYPE=$QL_HBA_ISCSI
fi

if [ $QL_HBA_TYPE -eq $QL_HBA_FC ]; then
	if [ ! -d ${QL_PROC_SCSI}/qla4* ] && [ ! -d /sys/module/qla4* ]; then
		echo " No FC/ISCSI host is found... "
		exit 1
	fi
fi

#scan input parameters
if [ $# -ne 0 ]; then
	# need to loop thru the  args
	while [ $# -gt 0 ]; 
	do
		case "$1" in
			-p | --proc )
				QL_FS=${QL_PROCFS}
				# Make QL_SCAN=0 for any combination like -i -p/-p -i  
				if [ $QL_INTERACTIVE == 1 ]; then
					QL_SCAN=0
				else
					QL_SCAN=1
				fi
			;;

			-h | --help | \? )
				QL_HELP=$(($QL_HELP+1))
				QL_SCAN=0
			;;

			-i | --interactive )
				QL_INTERACTIVE=$((QL_INTERACTIVE+1))
				QL_SCAN=0
			;;

			-r | --refresh )
				QL_REFRESH=$(($QL_REFRESH+1))
				QL_SCAN=1
			;;	

                       -cl | --current-luns )
				QL_CURRENT_LUNS=$((QL_CURRENT_LUNS+1))
				QL_SCAN=0
			;;

			-s | --scan )
				QL_SCAN=1
			;;

			-m | --max-lun )
				shift
				if [ $QL_INTERACTIVE == 0 ]; then
					QL_SCAN=1
				fi
				qlu_set_max_lun $1
			;;
		
			-is | --iscsi )
				QL_HBA_SCAN=${QL_ISCSI_SCAN} 
				QL_SCAN=1
			;;
			
			-e | --extended-scan )
				QL_EXTENDED_SCAN=1
				echo $@ | grep "\-p" >& /dev/null
				if [ $? -eq 0 ] || [ $QL_FS -eq $QL_PROCFS ]; then
					echo " Proc based extended scanning is not allowed "
					QL_EXTENDED_SCAN=2
				fi
			;;

			-al | --allow-lip )
				QL_HBA_LIP=1
				# Make QL_SCAN=0 for any combination like -i -al/-al -i  
				if [ $QL_INTERACTIVE == 1 ]; then
					QL_SCAN=0
				else
					QL_SCAN=1
				fi
			;;

			* )
				echo "$1 Option not supported"
				exit 1
			;;

		esac
   	    shift   #Check next parameter.
	done

else
	#by default do the scan
	QL_SCAN=1
fi

#Validate kernel version
case ${QL_K_MAJ_MIN} in
	2.4)
		if [ "${QL_HBA_SCAN}" -eq "${QL_FC_SCAN}" ]; then
			QL_DRIVER="qla2300"
		else
			QL_DRIVER="qla4032"
		fi
		QL_FS=$QL_PROCFS
	;;
	2.6 | 3.* | 4.* | 5.* | 6.*)
		if [ "${QL_HBA_SCAN}" -eq "${QL_FC_SCAN}" ]; then
			QL_DRIVER=qla2xxx
			SYS_DRIVER=qla2		
		else
			QL_DRIVER=qla4xxx
			SYS_DRIVER=qla4
		fi
	;;
	* )
		echo "Kernel ${QL_KERNEL_VERSION} not yet supported.";
		exit 1
	;;
esac

QLSCAN_OR_EXTENDEDSCAN=$(($QL_SCAN | $QL_EXTENDED_SCAN))
QL_OPT_TOTAL=$(($QL_HELP+$QL_INTERACTIVE+$QLSCAN_OR_EXTENDEDSCAN+$QL_CURRENT_LUNS))
if [ $QL_OPT_TOTAL != "1" ]; then
	echo "Please select valid combination of option/s"
	echo "see $0 -h for help"
elif [ $QL_SCAN == 1 ]; then
	qlu_main
elif [ $QL_HELP == 1 ]; then
	clear
	qlu_help
elif [ $QL_CURRENT_LUNS == 1 ]; then
	if [ $QL_FS == $QL_PROCFS ]; then
        	qlu_find_all_host
	        if [ ${QL_TOTAL_HOSTS} -eq 0 ]; then
        	        echo "QLogic Host not found..."
	                echo "Please check if QLogic module is loaded or not..."
	                exit 1
                else
                     qlu_proc_display_current_luns | more
	        fi
	else
	        qlu_sys_find_all_host
	        if [ ${QL_TOTAL_HOSTS} -eq 0 ]; then
	                echo "QLogic Host not found..."
	                echo "Please check if QLogic module is loaded or not..."
	                exit 1
                else
	                qlu_display_current_luns | more
                fi   
        fi
elif [ $QL_INTERACTIVE == 1 ]; then
	STATUS=$QL_CALL_AGAIN
	QL_REFRESH=0 # ignore refresh if user has selected along with -i
	clear
	while [ $STATUS -eq $QL_CALL_AGAIN ]
	do
		qlu_main_screen
		STATUS=$?
	done				
	exit 0
fi

if [ $QL_EXTENDED_SCAN -eq 1 ];then
	if [ $QL_FS -eq $QL_PROCFS ]; then
		echo "ERROR-Extended scan not supported in proc based scanning"
	else
		qlu_sys_find_all_host
		if [ ${QL_TOTAL_HOSTS} -eq 0 ]; then
			echo "QLogic Host not found..."
			echo "Please check if QLogic module is loaded or not..."
			exit 1
		fi
		qlu_sys_rescan_scsi_devices "`echo ${QL_HOST[@]}`"
	fi
fi	

