File qeth_configure of Package s390-tools

#! /bin/sh
#
# qeth_configure
#
# Configures a qeth device
#
# Usage:
#   qeth_configure <read chan> <write chan> <ctrl chan> <online>
#
# Return values:
#   1  sysfs not mounted
#   2  Invalid status for <online>
#   3  No device found for read channel
#   4  No device found for write channel
#   5  No device found for control channel
#   6  Invalid device type
#   7  Could not load module
#   8  CCW devices grouped different devices
#   9  Could not group devices
#   10 Could not set device online
#   11 Could not set device offline
#

DEBUG=no

mesg () {
    echo "$@"
}

debug_mesg () {
    case "$DEBUG" in
        yes) mesg "$@" ;;
        *) ;;
    esac
}

# Get the mount point for sysfs
while read MNTPT MNTDIR MNTSYS MNTTYPE; do
    if test "$MNTSYS" = "sysfs"; then
	SYSFS="$MNTDIR"
	break;
    fi 
done </proc/mounts

if [ -z "$SYSFS" ]; then
    exit 1
fi

while [ $# -gt 0 ] ; do
    case "$1" in
	-i)
	    # Configure IP takeover
	    QETH_IPA_TAKEOVER=1
	    ;;
	-l)
	    # Configure Layer2 support
	    QETH_LAYER2_SUPPORT=1
	    ;;
	-p*)
	    # QETH Portname to use
	    if [ "$1" = "-p" ] ; then
		QETH_PORTNAME=$2
		shift
	    else
		QETH_PORTNAME=${1#-p}
	    fi
	    ;;
        -n*)
            # QETH port number to use
            if [ "$1" = "-n" ] ; then
                QETH_PORTNO=$2
                shift
            else
                QETH_PORTNO=${1#-n}
            fi
            ;;
	-o)
	    # General QETH options, separated by spaces
	    QETH_OPTIONS=$2
	    shift
	    ;;
	*)
	    break;
	    ;;
    esac
    shift
done

QETH_READ_CHAN=$1
QETH_WRITE_CHAN=$2
QETH_CTRL_CHAN=$3
ONLINE=$4

if [ $# -lt 4 ] ; then
    echo "Usage: $0 [options] <read chan> <write chan> <control chan> <online>"
    exit 1
fi

if [ -z "$ONLINE" ] || [ "$ONLINE" -ne "1" -a "$ONLINE" -ne "0" ]; then
    debug_mesg "Invalid device status $ONLINE"
    exit 2
fi

_ccw_dir=${SYSFS}/bus/ccw/devices

debug_mesg "Configuring QETH device ${QETH_READ_CHAN}/${QETH_WRITE_CHAN}/${QETH_CTRL_CHAN}"


if test ! -d "$_ccw_dir/$QETH_READ_CHAN" ; then
    debug_mesg "No device ${QETH_READ_CHAN}"
    exit 3
fi
if test ! -d "$_ccw_dir/$QETH_WRITE_CHAN" ; then
    debug_mesg "No device ${QETH_WRITE_CHAN}"
    exit 4
fi
if test ! -d "$_ccw_dir/$QETH_CTRL_CHAN" ; then
    debug_mesg "No device ${QETH_CTRL_CHAN}"
    exit 5
fi

CCW_CHAN_GROUP=
for ccw in $_ccw_dir/$QETH_READ_CHAN $_ccw_dir/$QETH_WRITE_CHAN $_ccw_dir/$QETH_CTRL_CHAN; do

    read _cu_type < $ccw/cutype
    read _dev_type < $ccw/devtype

    case "$_cu_type" in
        1731/01|1731/02)
            # OSA/Express / Guest LAN
            CCW_DRV="qeth"
	    QETH_CARD="qeth"
            ;;
	1731/05)
            # Hipersockets
            CCW_DRV="qeth"
	    QETH_CARD="hsi"
            ;;
	1731/06)
            # OSA/N
            CCW_DRV="qeth"
	    QETH_CARD="osn"
            ;;
	*)
	    CCW_DRV=
	;;
    esac

    if [ -z "$CCW_DRV" ]; then
	mesg "No a valid QETH device (cu $_cutype, dev $_devtype)"
	exit 6
    fi
done

# Portname is only required for OSA/Express
if [ -n "$QETH_PORTNAME" -a "$QETH_CARD" != "qeth" ] ; then
    debug_mesg "No portname required for $QETH_CARD adapters"
    QETH_PORTNAME=
fi

_ccw_groupdir=${SYSFS}/bus/ccwgroup

# Check for modules
if test ! -d "${_ccw_groupdir}/drivers/${CCW_DRV}" ; then
    /sbin/modprobe $CCW_DRV

    # Re-check whether module loading has succeeded
    if test ! -d "${_ccw_groupdir}/drivers/${CCW_DRV}"; then
	debug_mesg "Could not load module ${CCW_DRV}"
	exit 7
    fi
fi

# Check for grouping
_ccwgroup_dir=
if [ -e ${_ccw_dir}/${QETH_READ_CHAN}/group_device ] ; then
    _ccwgroup_dir=$(cd -P ${_ccw_dir}/${QETH_READ_CHAN}/group_device; echo $PWD)
fi
if [ -e ${_ccw_dir}/${QETH_WRITE_CHAN}/group_device ] ; then
    _tmp_status_dir=$(cd -P ${_ccw_dir}/${QETH_READ_CHAN}/group_device; echo $PWD)
    if [ "$_ccwgroup_dir" ] && [ "$_ccwgroup_dir" != "$_tmp_status_dir" ] ; then
	mesg "CCW devices grouped to different devices"
	exit 8
    fi
    _ccwgroup_dir=$_tmp_status_dir
fi
if [ -e ${_ccw_dir}/${QETH_CTRL_CHAN}/group_device ] ; then
    _tmp_status_dir=$(cd -P ${_ccw_dir}/${QETH_CTRL_CHAN}/group_device; echo $PWD)
    if [ "$_ccwgroup_dir" ] && [ "$_ccwgroup_dir" != "$_tmp_status_dir" ] ; then
	mesg "CCW devices grouped to different devices"
	exit 8
    fi
    _ccwgroup_dir=$_tmp_status_dir
fi
if [ -z "$_ccwgroup_dir" ] ; then
    echo "$QETH_READ_CHAN,$QETH_WRITE_CHAN,$QETH_CTRL_CHAN" > ${_ccw_groupdir}/drivers/${CCW_DRV}/group
    if [ -e ${_ccw_dir}/${QETH_READ_CHAN}/group_device ] ; then
	_ccwgroup_dir=$(cd -P ${_ccw_dir}/${QETH_READ_CHAN}/group_device; echo $PWD)
    fi
fi

if [ -z "$_ccwgroup_dir" -o ! -e  "$_ccwgroup_dir" ] ; then
    mesg "Could not group $CCW_DRV devices $QETH_READ_CHAN/$QETH_WRITE_CHAN/$QETH_CTRL_CHAN"
    exit 9
fi

CCW_CHAN_ID=${_ccwgroup_dir##*/}

read _online < $_ccwgroup_dir/online

if [ "$ONLINE" -eq 1 ]; then
    # Check whether we need to do something
    # We do not check for the value of CCW_CHAN_MODE, since we
    # might want to switch back and forth between several modes
    if test "$_online" -eq "0" ; then
	# Set the portname
	if [ "$QETH_PORTNAME" ]; then
	    mesg "(portname $QETH_PORTNAME) "
	    echo "$QETH_PORTNAME" > $_ccwgroup_dir/portname
	fi
	# Enable IP address takeover
	if [ "$QETH_IPA_TAKEOVER" ]; then
	    if [ "$QETH_IPA_TAKEOVER" = "1" ]; then
		mesg "(IP takeover) "
		echo 1 > $_ccwgroup_dir/ipa_takeover/enable
	    fi
	fi
	# Activate Layer2 support
	if [ -w "$_ccwgroup_dir/layer2" ] ; then
	    if [ "$QETH_LAYER2_SUPPORT" = "1" ]; then
		mesg "(Layer2) "
		echo 1 > $_ccwgroup_dir/layer2
	    else
		echo 0 > $_ccwgroup_dir/layer2
	    fi
	else
	    QETH_LAYER2_SUPPORT=
	fi
	# Relative port number
	if [ -w "$_ccwgroup_dir/portno" ] ; then
	    if [ -n "$QETH_PORTNO" ]; then
	        mesg "(Port $QETH_PORTNO) "
	        # This may fail, but trial and error is the only way to tell.
	        echo "$QETH_PORTNO" > $_ccwgroup_dir/portno
	    fi
	else
	    unset QETH_PORTNO
	fi
	# Set additional options
	if [ "$QETH_OPTIONS" ]; then
	    for opt in $QETH_OPTIONS; do
		set -- $(IFS='='; echo $opt)
		opt_name=$1
		opt_val=$2
		case "$opt_name" in
		    portname|ipa_takeover|layer2)
	                # These options are set above
			debug_mesg "invalid option $opt_name"
			;;
		    *)
			if [ "$opt_name" -a "$opt_val" ]; then
			    if [ -w "$_ccwgroup_dir/$opt_name" ]; then
				mesg "($opt_name) "
				echo "$opt_val" > $_ccwgroup_dir/$opt_name
				if [ $? -gt 0 ] ; then
				    cur_opts="$cur_opts ${opt_name}=${opt_val}"
				fi
			    else
	                        # Skip invalid options
				debug_mesg "invalid option $opt_name"
			    fi
			fi
			;;
		esac
	    done
	    # Update options list
	    QETH_OPTIONS="$cur_opts"
	fi

	echo "1" > $_ccwgroup_dir/online 2> /dev/null
        # Re-read device status
	read _ccw_dev_status < $_ccwgroup_dir/online
	if [ "$_ccw_dev_status" -eq 0 ]; then
	    mesg "Could not set device ${CCW_CHAN_ID} online"
	    exit 10
	fi
    else
	debug_mesg "Device ${CCW_CHAN_ID} is already online"
    fi
else
    if [ "$_online" -eq 1 ]; then
        # Set the device offline
	debug_mesg "Setting device offline"
	echo "$ONLINE" > $_ccwgroup_dir/online

        # Re-read to check whether we have succeeded
	_online=$(cat $_ccwgroup_dir/online)
	if [ "$_online" -ne "$ONLINE" ]; then
	    debug_mesg "Could not set device ${CCW_CHAN_ID} offline"
	    exit 11
	fi
    else
	debug_mesg "Device ${CCW_CHAN_ID} is already offline"
    fi
    echo 1 > $_ccwgroup_dir/ungroup
fi

RULES_DIR=/etc/udev/rules.d
RULES_FILE=51-${QETH_CARD}-${CCW_CHAN_ID}.rules

if [ -d "$RULES_DIR" ]; then
    if [ -f ${RULES_DIR}/${RULES_FILE} ]; then
	rm -f ${RULES_DIR}/${RULES_FILE}
    fi

    if [ "$ONLINE" -eq "1" ]; then
        # Write a new udev rules file
	cat > ${RULES_DIR}/${RULES_FILE} <<EOF
# Configure ${QETH_CARD} device at ${QETH_READ_CHAN}/${QETH_WRITE_CHAN}/${QETH_CTRL_CHAN}
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="$CCW_DRV", IMPORT{program}="collect $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_CTRL_CHAN $CCW_DRV"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$QETH_READ_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_CTRL_CHAN $CCW_DRV"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$QETH_WRITE_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_CTRL_CHAN $CCW_DRV"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$QETH_CTRL_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_CTRL_CHAN $CCW_DRV"
ACTION=="remove", SUBSYSTEM=="drivers", KERNEL=="$CCW_DRV", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_CTRL_CHAN $CCW_DRV"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$QETH_READ_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_CTRL_CHAN $CCW_DRV"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$QETH_WRITE_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_CTRL_CHAN $CCW_DRV"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$QETH_CTRL_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_CTRL_CHAN $CCW_DRV"
TEST=="[ccwgroup/${CCW_CHAN_ID}]", GOTO="${QETH_CARD}-${CCW_CHAN_ID}-end"
ACTION=="add", SUBSYSTEM=="ccw", ENV{COLLECT_$CCW_CHAN_ID}=="0", ATTR{[drivers/ccwgroup:$CCW_DRV]group}="$QETH_READ_CHAN,$QETH_WRITE_CHAN,$QETH_CTRL_CHAN"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="$CCW_DRV", ENV{COLLECT_$CCW_CHAN_ID}=="0", ATTR{[drivers/ccwgroup:$CCW_DRV]group}="$QETH_READ_CHAN,$QETH_WRITE_CHAN,$QETH_CTRL_CHAN"
LABEL="${QETH_CARD}-${CCW_CHAN_ID}-end"
EOF
	if [ "$QETH_PORTNAME" ]; then
	    cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{portname}="$QETH_PORTNAME"
EOF
	fi
        if [ "$QETH_PORTNO" ]; then
            cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{portno}="$QETH_PORTNO"
EOF
        fi
	if [ "$QETH_IPA_TAKEOVER" ]; then
	    cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{ipa_takeover/enable}="1"
EOF
	fi
	if [ "$QETH_LAYER2_SUPPORT" ]; then
	    cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{layer2}="1"
EOF
	else
	    cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{layer2}="0"
EOF
	fi
	for opt in $QETH_OPTIONS; do
	    set -- $(IFS='='; echo $opt)
	    opt_name=$1
	    opt_val=$2
	    cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{$opt_name}="$opt_val"
EOF
	done
	cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{online}="1"
EOF
    fi
fi