# -*- shell-script -*-

# 07device_scsi_sg_inq - SCSI device inquiry support using sg3_utils.

# This file is part of the Linux lsvpd package.

# (C) Copyright IBM Corp. 2002, 2003, 2004

# Maintained by Martin Schwenke <martins@au.ibm.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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
    
# $Id: 07device_scsi_sg_inq,v 1.1 2004/02/18 04:37:48 martins Exp $

sg_inq=$(type -p sg_inq)
[ -n "$sg_inq" ] || return 0

######################################################################

function do_device_scsi ()
{
    local dev="$1"

    local num='\([0-9][0-9]*\)'
    local y="\1 \2 \3 \4"
    case "$dev" in
	/dev/sg*)
	    local x="^${dev}  *${num} ${num} ${num} ${num} .*"
	    set -f
	    set -- $(sed -n -e "s@${x}@${y}@p" "${db_misc_dir}/sg_map-x")
	    set +f
	    ;;
	/dev/scsi/*/generic)
	    local x="^.*/host${num}/bus${num}/target${num}/lun${num}.*\$"
	    set -f
	    set -- $(echo "$dev" | sed -n -e "s@${x}@${y}@p")
	    set +f
	    ;;
	*)
	    debug "scsi_do_device: not implemented - sg device name: \"${dev}\""
	    return 1
    esac

    local host="$1"
    local bus="$2"
    local target="$3"
    local lun="$4"

    if [ -z "$host" -o -z "$bus" -o -z "$target" -o -z "$lun" ] ; then
	debug "scsi_do_device: unable to parse SCSI information from device \"${dev}\""
	return 1
    fi

    local subdir=$(get_adapter_subdir "$type")
    # Get the disk (or whatever) name if available, not just /dev/sg*.
    local dev_node=$(scsi_hbtl_to_dev "$host" "$bus" "$target" "$lun")
    local name=$(basename "$dev_node")
    local d="${db_os_dir}/${subdir}/host${host}/${name}/tmp"
    mkdir -p "$d"
    if scsi_vpd_inquire "$dev" "$d" ; then

	local outdir="${d}/vpd"
	mkdir -p "$outdir"

	scsi_vpd_std    "$d" "$outdir"
	scsi_vpd_custom "$d" "$outdir"

	# Create AX field.
	local ax="${outdir}/AX"
	if [ ! -f "$ax" ] ; then
	    echo "$dev_node" >"$ax"
	    if [ ! -s "$ax" ] ; then
		debug "scsi_do_device: internal error - no device name for \"${d}\"" 1>&2
		return 1
	    fi
	fi

	# Used by hook.
	local device_type
	if [ -f "${d}/type" ] ; then
	    read device_type < "${d}/type"
	fi
	local adapter="host${host}"

	# Hook sets these variables.
	local vpdprop yl
	local adapter="host${host}"
	do_device_hook "scsi"

	# Render.
	if [ -n "$vpdprop" ]  ; then
	    local yl_file="${outdir}/YL"
	    if [ -n "$yl" -a ! -f "$yl_file" ] ; then
		echo "$yl" >"$yl_file"
	    fi
	    scsi_vpd_render "$outdir" "$vpdprop"
	    rmdir "$outdir" 2>/dev/null || true
	fi

	# By default, leave $outdir, since we might want to debug.
    fi
}

######################################################################

function scsi_hbtl_to_dev ()
{
    # Args: (host, bus, target, lun)

    # Use non-sg name (at $) if available, otherwise use sg name (at $).
    sed -n -e "/ $1 $2 $3 $4  *[0-9][0-9]*  *\/dev\//s/.* \([^ ]*\)$/\1/p" \
	   -e "/^\/dev\/[^ ]*  *$1 $2 $3 $4  */s/ .*//p" \
	   "${db_misc_dir}/sg_map-x"
}

function scsi_vpd_inquire ()
{
    local dev="$1"
    local outd="$2"

    # Retrieve VPD data via SG interface.
    local t="$outd/inquiry"
    if debug_cmd "$sg_inq" -r "$dev" >"$t"  ; then
	t="$outd/0x00"
	if debug_cmd "$sg_inq" -r -e -o=0x00 "$dev" >"$t" ; then
	    for i in $(tdump "$t" | (read x x x x rest ; echo $rest)) ; do
		j="0x${i}"
		if [ "$j" != "0x00" ] ; then
		    t="$outd/$j"
		    if debug_cmd "$sg_inq" -r -e -o=$j "$dev" >"$t" ; then
			:
		    else
			rm -f "$t"
		    fi
		fi
	    done
	else
	    rm -f "$t"
	fi
    else
	rm -f "$t"
	debug "scsi_vpd_inquire: Standard inquiry on ${dev} failed"
	return 1
    fi

    return 0
}

# This is destructive.
function scsi_vpd_render ()
{
    local dir="$1"
    local vpdprop="$2"

    local sort_order="DS AX PL MF TM CD LL YL FN RL SN EC PN"

    local oldpwd=$(pwd)
    cd "$dir"

    {
	do_fc_field $(dirname "$vpdprop")

	local i
	for i in $sort_order ; do
	    if [ -f "$i" ] ; then
		echo "*${i} $(cat ${i})"
		rm -f "$i"
	    fi
	done

	for i in * ; do
	    echo "*${i} $(cat ${i})"
	    rm -f "$i"
	done
    }  >"$vpdprop"

    cd "$oldpwd"
}
