# -*- shell-script -*-

# 30device-tree - device-tree related lscfg routines.

# This file is part of the Linux lsvpd package.

# (C) Copyright IBM Corp. 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: 30device-tree,v 1.6 2004/02/17 05:17:53 martins Exp $

[ -f "${db_bus_dir}/model" ] || return 0

if [ -f "${db_bus_dir}/device_type" ] ; then
    device_tree_device_type=$(cat "${db_bus_dir}/device_type")
fi

function get_cpus ()
{
    if [ -d "${db_bus_dir}/cpus" ] ; then
	if [ -f "${db_bus_dir}/cpus/smp-enabled" ] ; then
	    echo "Multiple Processor"
	else
	    echo "Uni-Processor"
	fi
    else
	get_cpus_basic
	fi
}

#---------------------------------------------------------------------

function dt_platform_specific_header ()
{
    local node="$1"
    local prop="$2"
    local label="$3"

    local p="${node}/${prop}"
    if [ -f "$p" ] ; then
	# Subshell strips NULs. :-)
	local t=$(cat "$p")
	echo "    ${label}:  ${t}"
    fi
}

#---------------------------------------------------------------------

function dt_platform_specific_vpd_line ()
{
    local k="$1"
    shift
    local v="$*"

    case "$k" in
	CI) formatvpd     "$k" "$v" "Controlling CEC ID"          ;;
	RD) formatvpd     "$k" "$v" "Power Domain ID"             ;;
	RM) formatvpd     "$k" "$v" "ROM Level.(alterable)"       ;;

	Y?) formatvpd     "$k" "$v" "System Info Specific.(${k})" ;;

	*)  formatvpdline "$k" "$v";;
    esac
}

# FIXME: The YL handling here is a bad hack, but is easier than
# parsing the ibm,loc-code prop.  Also the generation of
# "Version=RS6K" is hardcoded and needs to be looked at.
function dt_platform_specific_vpd ()
{
    local nodebase="$1"
    local k rest yl
    while read k rest ; do
	k=$(stripkey "$k")
	[ -n "$k" ] || continue

	case "$k" in
	    FC) [ -n "$yl" ] && echo "      Physical Location: ${yl}"
		echo
		;; 
	    DS) printf '      %-16s:\n' "${rest}" ;;
	    YL) [ "$nodebase" = "/" ] && yl="$rest"
		echo "        Version.....................RS6K"
		dt_platform_specific_vpd_line "$k" "$rest"
		;;
	    AX) : # Suppress.
		;;
	    *)  dt_platform_specific_vpd_line "$k" "$rest"
		;;
	esac
    done
    [ -n "$yl" ] && echo "      Physical Location: ${yl}"
}

function dt_platform_specific_node ()
{
    local node="$1"
    local nodebase="$2"
    local vpd_file="$3"
    local ax="$4"

    if $first ; then
	echo
	echo "  PLATFORM SPECIFIC"
	first=false
    fi

    echo

    # Subshell strips NULs. :-)
    local nodename=$(cat "${node}/name")
    echo "  Name:  ${nodename}"

    dt_platform_specific_header "$node" "model" "Model"
    echo "    Node:  ${nodebase}"
    
    if [ -f "${node}/device_type" ] &&
	[ "$nodename" != "$(cat ${node}/device_type)" ] ; then
	dt_platform_specific_header "$node" "device_type" "Device Type"
    fi

    local loc="${node}/ibm,loc-code"
    if [ "$nodebase" != "/" -a -f "$loc" ] ; then
	echo "    Physical Location: $(cat ${loc})"
    fi

    if $dovpd && [ -f "$vpd_file" -a -z "$ax" ] ; then
	dt_platform_specific_vpd "$nodebase" <"$vpd_file"
    fi
}

function dt_platform_specific_node_maybe ()
{
    local node="$1"

    local ax
    local vpd_file="${node}/linux,vpd"
    if [ -f "$vpd_file" ] ; then
	ax=$(sed -n -e 's/^\*AX \(.*\)$/\1/p' "$vpd_file")
    fi

    local nodebase=$(basename "$node")
    if [ -z "$nodebase" -o "$nodebase" = "." ] ; then
	nodebase="/"
    fi

    if [ -n "$name" ] ; then
	case "$name" in
	    mem*)
		case "$nodebase" in
		    *memory-module*)
			dt_platform_specific_node \
			    "$node" "$nodebase" "$vpd_file" "$ax"
			;;
		esac
		;;
	    *)
		case "$ax" in
		    $name)
			dt_platform_specific_node \
			    "$node" "$nodebase" "$vpd_file" "$ax"
			;;
		esac
		;;
	esac
    else
	case "$nodebase" in
	    (memory@*) : ;;
	    *)
		dt_platform_specific_node \
		    "$node" "$nodebase" "$vpd_file" "$ax"
		;;
	esac
    fi
}

function do_platform_specific_section ()
{
    local first=true

    # There's probably a nicer way of doing this, rather than
    # excluding all this junk on the "find".  However, this gains us a
    # bit of efficiency due to the -prune.
    find "${db_bus_dir}/." -type d \
	\( \( -name IBM,sp -o -name ibm,serial -o \
	      -name aliases  -o -name chosen -o -name options -o \
	      -name packages -o -name rtas -o \
	      -name sd -o -name st -o -name vdevice -o \
	      -name "reserved@*" -o -name "rtc@*" -o -name "vty@*" \) \
	   -prune -o -print \) |
    sort |
    while read node ; do
	if [ -f "${node}/name" -a \
	     \( -f "${node}/model" -o \
		-f "${node}/device_type" -o \
		-f "${node}/ibm,loc-code" \) ] ;then
	    dt_platform_specific_node_maybe "$node"
	fi
    done
}
