# -*- shell-script -*-

# 21sysfs_hotplug - Definitions and routines relating to sysfs and hotplug.

# This file is part of the Linux lsvpd package.

# (C) Copyright IBM Corp. 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: 21sysfs_hotplug,v 1.9 2004/11/18 23:17:28 martins Exp $

[ -n "$sysfs_dir" ] || return 0

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

add_device_hooks="${add_device_hooks} sysfs_add_device_bus_alias"

sysfs_add_device_bus_alias ()
{
    # Uses: bus_info

    local bus_info="${bus_info%=*}"
    local bus_type="${bus_info%/*}"
    local bus_addr="${bus_info#*/}"

    local d="${sysfs_dir}/bus/${bus_type}/devices/${bus_addr}"

    local bl="${d}/block"
    if [ -L "$bl" ] ; then
	if cd -P "$bl" ; then
	    local sysfs_node="$PWD"
	    cd "$OLDPWD"
	    bus_alias_set "${sysfs_node#/}" "${device_bus_dir#${db_bus_dir}/}"
	fi
    fi
}    

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

hotplug_add_device ()
{
#set -x
#exec 2>/tmp/lsvpd.hotplug.log

    # Uses: DEVPATH (set by hotplug)

    type="$1"

    local dl="${sysfs_dir}${DEVPATH}/device"
    
    wait_for_node "$dl"
    
    if [ -L "$dl" ] && cd -P "$dl" ; then
	local cu="${PWD##*/}"  # basename
	cd "$OLDPWD"
	add_device "$type" "$cu"
    else
	echo "$0: ${dl} did not appear" >&2
    fi
}

hotplug_remove_device ()
{
#set -x
#exec 2>/tmp/lsvpd.hotplug.log

    # Uses: DEVPATH (set by hotplug)

    type="$1"

    local sysfs_bus_info="${sysfs_dir#/}${DEVPATH}"

    local bus_alias
    bus_alias_get "$sysfs_bus_info"
    local device_bus_dir="$bus_alias"

    bus_alias_clear "$sysfs_bus_info"

    if [ -n "$device_bus_dir" ] ; then
	local bus_info t
	remove_device_hook "$type"
	bus_alias_clear "$bus_info"

	# Remove device OS dir - contains overkill to avoid serious errors.
	t="${device_bus_dir}/lsvpd,os-node"
	if [ -L "$t" ] && cd -P "$t" ; then
	    t="$PWD"
	    cd "$OLDPWD"
	else
	    t=""
	fi

	if [ "$t" = "${t#${db_os_dir}}" ] ; then
	    debug "hotplug_remove_device: bad OS directory \"${t}\"" 
	else
	    rm -rf "$t"
	fi
    
	# Remove $device_bus_dir - contains overkill to avoid serious errors.
	t="$device_bus_dir"
	if [ "$t" = "${t#${db_bus_dir}}" ] ; then
	    debug "hotplug_remove_device: bad bus directory \"${t}\"" 
	else
	    rm -rf "$t"
	fi
    fi
}

hotplug_name_and_crosslink ()
{
#set -x
#exec 2>/tmp/lsvpd.crosslink.log
    # Uses: DEVPATH

    type="$1"

    local dl="${sysfs_dir}${DEVPATH}/device"
    
    wait_for_node "$dl"
	
    if [ -L "$dl" ] && cd -P "$dl" ; then
	local cu="${PWD##*/}" # basename
	cd "$OLDPWD"

	local device_name
	get_device_name "$type" "$cu"
	if [ -n "$device_name" ] ; then
	    local bus_alias
	    bus_alias_get "${sysfs_dir#/}${DEVPATH}"
	    device_add_name_and_crosslink_basic "$bus_alias" "$device_name"
	fi
    else
	echo "$0: ${dl} did not appear" >&2
    fi
}

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

wait_for_node ()
{
    local node="$1"
    local timeout="${2:-10}" # optional, default = 10 seconds

    local n=0
    while [ $n -lt $timeout -a ! -e "$node" ] ; do
	sleep 1
	n=$(($n + 1))
    done
}
