# -*- shell-script -*-

# 03adapter_scsi_proc - SCSI adapter support using /proc/scsi.

# This file is part of the Linux lsvpd package.

# (C) Copyright IBM Corp. 2002, 2003

# 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: 03adapter_scsi_proc,v 1.4 2003/12/22 04:55:31 martins Exp $

[ -d "/proc/scsi" ] || return 0

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

function adapter_setup_scsi ()
{
    local subdir=$(get_adapter_subdir "scsi")
    db_scsi_dir="${db_os_dir}/${subdir}"
    mkdir -p "$db_scsi_dir"
}

function list_os_adapters_scsi ()
{
    # Use external command for systems without sysfs.
    scsi_host_pci_info
    local i
    for i in "${db_scsi_dir}/host"* ; do
	basename "$i"
    done
}

function get_pci_info_scsi ()
{
    local name="$1"

    # Will have been collected during call to "list_os_adapters scsi".

    # Although this function should be callable for an individual
    # device as part of a hotplug event, we assume that a non-sysfs
    # system will never be expected to handle hotplug events.
    local f="${db_scsi_dir}/${name}/pci-data"
    [ -f "$f" ] && cat "$f"
}

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

function scsi_get_host_frag ()
{
    local file="$1"
    local sedpat="$2"
    local prefix="$3"

    local tmp=$(sed -n -e "s/${sedpat}/\1/" \
		       -e 's/^\([0-9A-Fa-f][0-9A-Fa-f]*\)$/\1/p' "$file")
    [ -n "$tmp" ] && echo "${prefix}${tmp}"
}

function scsi_host_pci_info ()
{
    local d
    local info
    local conf="${libdir}/scsihost.conf"
    # Possibly 1 too many loops here, but it lets us handle specific
    # drivers only, and we don't get mixed up by things like "sg".
    for d in $(sed -e '/^#/d' -e 's/:.*$//' "$conf") ; do
	for info in /proc/scsi/${d}/*; do

	    local num=$(basename "$info" | \
			sed -n -e 's/^\([0-9][0-9]*\)$/\1/p')
	    if [ -z "$num" ] ; then
		continue
	    fi

	    local prefix="${db_scsi_dir}/host${num}"
	    mkdir -p "$prefix"

	    IFS=":"
	    set -f
	    set -- $(grep "^${d}:" "$conf")
	    set +f
	    unset IFS
	    local buspat="$2"
	    local devpat="$3"
	    local funpat="$4"
	    local irqpat="$5"
	    local buspref="$6"
	    local devpref="$7"
	    local funpref="$8"
	    local irqpref="$9"

	    local bus=$(scsi_get_host_frag "$info" "$buspat" "$buspref")
	    local dev=$(scsi_get_host_frag "$info" "$devpat" "$devpref")
	    local fun=$(scsi_get_host_frag "$info" "$funpat" "$funpref")
	    local irq=$(scsi_get_host_frag "$info" "$irqpat" "$irqpref")

	    if [ -n "$irq" ] ; then
		# This is the only place where get_real_bus is called.
		# This is a workaround, since $bus is only a u_char in
		# some of the SCSI drivers I know about.  Hopefully a
		# future kernel patch will fix this, so the functions
		# can go away.
		bus=$(get_real_bus "scsi" \
				   $(printf "%02x:%02x.%x-%d" \
					    "$bus" "$dev" "$fun" "$irq"))
	    fi

	    local dom=$(( ($bus >> 8) & 0xffffff ))
	    bus=$(($bus & 0xff))

	    printf "0x%x 0x%x 0x%x 0x%x\n" \
		    "$dom" "$bus" "$dev" "$fun" >"${prefix}/pci-data"
	done
    done
}
