# -*- shell-script -*-

# 33adapter_dt_sysfs - Device-tree + sysfs adapter code.

# 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: 33adapter_dt_sysfs,v 1.2 2004/11/29 02:52:08 martins Exp $

# NOTE: The sysfs devspec property was introduced in Linux 2.6.3, but
# let's assume that any system with sysfs and a device-tree will have
# devspec properties.  This will probably break one day, but checking
# for the existence of devspec properties isn't trivial.

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

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

# FIXME: scsi_debug, ide_cs

set_adapter_bus_dir ()
{
    # Sets: adapter_bus_dir

    local type="$1"
    local bus_info="$2"

    local bus_alias
    bus_alias_get "$bus_info"
    adapter_bus_dir="$bus_alias"

    [ -n "$adapter_bus_dir" ] && return 0

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

    local sysfs_bus_type
    get_sysfs_bus_type "$bus_type"

    local d="${sysfs_dir}/bus/${sysfs_bus_type}/devices/${bus_addr%/*}/devspec"

    if [ -r "$d" ] ; then
	local suffix
        read suffix <"$d"

        if [ -n "$suffix" ] ; then
	    local channel=""
	    case "$bus_addr" in
		(*/*) channel="${bus_addr#*/}" ;;
	    esac

	    if [ -n "$channel" ] ; then
		local ch_hex=$channel
		[ $channel -gt 9 ] && \
		    ch_hex=$(dec2hex "$channel")

		local dt_adapter_types dt_type
		get_dt_adapter_types "$type"
		for dt_type in $dt_adapter_types ; do
		    local maybe="${suffix}/${dt_type}@${ch_hex}"
		    if [ -d "${source_device_tree}${maybe}" ] ; then
			suffix="$maybe"
			break
		    fi
		done
	    fi

	    if [ -n "$suffix" ] ; then
		bus_alias_set "$bus_info" "${db_bus_dt_subdir}${suffix}"
		adapter_bus_dir="${db_bus_dt_dir}/${suffix}"
	    fi
	fi
    fi
}

sysfs_last_chance_pci_channels_hooks="${sysfs_last_chance_pci_channels_hooks} \
    dt_sysfs_add_channels"

dt_sysfs_add_channels ()
{
    # Sets: adapter_list

    local adapter_info="$1"

    local type="${adapter_info%%@*}"
    local bus_info="${adapter_info#*@}"

    local adapter_bus_dir
    set_adapter_bus_dir "$type" "$bus_info"
    [ -n "$adapter_bus_dir" ] || return 1

    local dt_adapter_types dt_type ch_dir found
    get_dt_adapter_types "$type"
    found=false
    for dt_type in $dt_adapter_types ; do
	for ch_dir in "${adapter_bus_dir}/${dt_type}@"* ; do
	    local t="${adapter_info}/$((0x${ch_dir##*@}))"
	    adapter_list="${adapter_list} ${t}"
	    found=true
	done
	$found && return 0
    done

    return 1    
}
