#!/bin/sh
#
# ioscan_fc.sh
#
# Ioscan wrapper for fiber channel devices. Tested with an EVA array.
#
# The latest version can be found at:
# http://www.mayoxide.com/toolbox
#
# (c) 2006 Olivier S. Masse, omasse ~at~ mayoxide ~dot~ 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
#
# Updates:
# 2006/07/06 Olivier S. Masse
# - added limited support for Emulex Lightpulse Fiber channel adapters (lpfc driver)
#

tempfile=/tmp/$(basename $0).$$

show_vg=1
show_size=1
human=1

usage()
{
	echo "usage: $(basename $0) -V -l [lun]"
	echo
	exit 1
}

make_report()
{
	typeset type=${1}
	typeset ioscan
	
	case ${type} in 
		"hp")		ioscan="ioscan -kFC fc";;
		"emulex")	ioscan="ioscan -kFd lpfc";;
	esac
	
	eval ${ioscan} | while read adapter
	do
		adapter_hwpath=$(echo $adapter | cut -d ":" -f 11)
		
		case ${type} in
			"hp")		adapter_desc=$(echo $adapter | cut -d ":" -f 18);
					adapter_dev=$(ioscan -kfH ${adapter_hwpath} -C fc -n | tail -1 | sed 's/^[[:space:]]*//g');
					adapter_wwn=$(fcmsutil ${adapter_dev} | grep "N_Port Port World Wide Name" | cut -d "=" -f 2);;
			"emulex")	adapter_desc="Emulex Lightpulse FC card $(echo $adapter | cut -d ":" -f 18)";
					adapter_dev="(none)";
					adapter_wwn="(Check with lputil)";;
		esac
	
		if [ ${human} -eq 1 ]
		then
			echo
			echo "Hardware Path: ${adapter_hwpath}"
			echo "Description: ${adapter_desc}"
			echo "Device: ${adapter_dev}"
			echo "World Wide Name: ${adapter_wwn}"
		fi
	
		>${tempfile}
		[ ${human} -eq 1 ] && echo "Visible luns:"
		ioscan -kFH ${adapter_hwpath} -C disk | while read disk
		do
			disk_hwpath=$(echo ${disk} | cut -d ":" -f 11)
			disk_status=$(echo ${disk} | cut -d ":" -f 16)
			disk_desc=$(echo ${disk} | cut -d ":" -f 18)
			disk_lun=$(echo ${disk_hwpath} | cut -d "." -f 6-7)
	
			if [ "${show_lun}" ]
			then
				echo ${disk_lun} | grep -q ${show_lun}
				[ $? -eq 0 ] && echo ${disk_lun} ${disk_status} ${disk_hwpath} ${disk_desc} >>${tempfile}
			else
				echo ${disk_lun} ${disk_status} ${disk_hwpath} ${disk_desc} >>${tempfile}
			fi
		done
		
			
		cat ${tempfile} | sort -k 1,1 | while read disk_lun disk_status disk_hwpath disk_desc
		do
			if [ ${human} -eq 1 ]
			then
				echo ${disk_lun} ${disk_status} ${disk_hwpath} ${disk_desc}
			else
				echo "${disk_lun}:${disk_status}:${disk_hwpath}:${disk_desc}:\c"
			fi
		
			grep ${disk_hwpath} ${tempfile}.lssf.dsk | awk '{print $16}' | while read dsk
			do
				if [ ${show_vg} -eq 1 ]
				then
					vg=$(pvdisplay ${dsk} 2>/dev/null | awk '/VG Name/ {print $3}')
					[ "${vg}" = "" ] && vg="(unknown_vg)"
				else
					vg=""
				fi
	
				if [ ${human} -eq 1 ]
				then
					echo "    ------- ${dsk} ${vg}"
				else
					printf " %s" ${dsk}
				fi
			done
			
			grep ${disk_hwpath} ${tempfile}.lssf.rdsk | awk '{print $16}' | while read rdsk
			do
				if [ ${show_size} -eq 1 ]
				then
					size=$(diskinfo ${rdsk} 2>/dev/null | awk '/size:/ {print $2}')
					[ "${size}" = "" ] && size="(unknown_size)" || size="$((${size}/1024))Mb"
				else
					size=""
				fi
				if [ ${human} -eq 1 ]
				then
					echo "    ------- ${rdsk} ${size}"
				else
					printf ":%s" ${rdsk}
				fi
			done
			[ ${human} -eq 0 ] && printf "\n"
		done
	
	done
}

while [ ! "$1" = "" ]
do
	case "$1" in
		"-V")	human=0;;
		"-l")	shift; show_lun="$1";;
		*)	usage;;
	esac
	shift
done

lssf /dev/dsk/* > ${tempfile}.lssf.dsk
lssf /dev/rdsk/* > ${tempfile}.lssf.rdsk

make_report hp		# Honest-to-goodness HP fiber channel devices
make_report emulex	# Emulex third-party devices


[ -f ${tempfile} ] && rm ${tempfile}
[ -f ${tempfile}.lssf.dsk ] && rm ${tempfile}.lssf.dsk
[ -f ${tempfile}.lssf.rdsk ] && rm ${tempfile}.lssf.rdsk

