File ctc_configure of Package s390-tools

#! /bin/sh
#
# ctc_configure
#
# Configures a CTC device
#
# Usage:
#   ctc_configure <read channel> <write channel> <online> [<protocol>]
#
# 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  Invalid device type
#   6  Device type mismatch
#   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

if [ $# -lt 3 ] ; then
    echo "Usage: $0 <read channel> <write channel> <online> [<protocol>]"
    exit 1
fi

CTC_READ_CHAN=$1
CTC_WRITE_CHAN=$2
ONLINE=$3
CTC_MODE=$4

[ -z "$CTC_MODE" ] && CTC_MODE=0

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 CTC device ${CTC_READ_CHAN}/${CTC_WRITE_CHAN}"


if test ! -d "$_ccw_dir/$CTC_READ_CHAN" ; then
    debug_mesg "No device ${CTC_READ_CHAN}"
    exit 3
fi
if test ! -d "$_ccw_dir/$CTC_WRITE_CHAN" ; then
    debug_mesg "No device ${CTC_WRITE_CHAN}"
    exit 4
fi

CCW_CHAN_GROUP=
for ccw in $_ccw_dir/$CTC_READ_CHAN $_ccw_dir/$CTC_WRITE_CHAN; do

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

    case "$_cu_type" in
        3088/01)
            # P/390 network adapter
            CCW_CHAN_NAME="cu3088"
            CCW_CHAN_GROUP="lcs"
            ;;
        3088/08)
            # Channel To Channel
            CCW_CHAN_NAME="cu3088"
            CCW_CHAN_GROUP="ctcm"
            ;;
        3088/1e)
            # FICON adapter
            CCW_CHAN_NAME="cu3088"
            CCW_CHAN_GROUP="ctcm"
            ;;
        3088/1f)
            # ESCON adapter (I.e. hardware CTC device)
            CCW_CHAN_NAME="cu3088"
            CCW_CHAN_GROUP="ctcm"
            ;;
        3088/60)
            # Lan Control Station
            CCW_CHAN_NAME="cu3088"
            CCW_CHAN_GROUP="lcs"
            ;;
	*)
	    CCW_CHAN_NAME=
	;;
    esac

    if [ -z "$CCW_CHAN_NAME" ]; then
	mesg "No a valid CTC device (cu $_cutype, dev $_devtype)"
	exit 5
    fi

    [ -z "$tmp_chan" ] && tmp_chan=$CCW_CHAN_GROUP
done

if [ "$tmp_chan" != "$CCW_CHAN_GROUP" ] ; then
    mesg "CTC type mismatch (read: $tmp_chan, write: $CCW_CHAN_GROUP)"
    exit 6
fi

_ccw_groupdir=${SYSFS}/bus/ccwgroup

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

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

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

if [ -z "$_ccw_status_dir" -o ! -e  "$_ccw_status_dir" ] ; then
    mesg "Could not group $CCW_CHAN_GROUP devices $CTC_READ_CHAN/$CTC_WRITE_CHAN"
    exit 9
fi

CCW_CHAN_ID=${_ccw_status_dir##*/}

read _ccw_dev_status < $_ccw_status_dir/online

if [ "$ONLINE" -eq 1 ]; then
    # Check whether we need to do something
    if [ "$_ccw_dev_status" -eq 0 ]; then
	if [ "$CTC_MODE" -gt 0 ]; then
	    echo $CTC_MODE > $_ccw_status_dir/protocol
	fi
	# Set the device online
	debug_mesg "Setting device online"
	echo "1" > $_ccw_status_dir/online
        # Re-read device status
	read _ccw_dev_status < $_ccw_status_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 [ "$_ccw_dev_status" -eq 1 ]; then
        # Set the device offline
	debug_mesg "Setting device offline"
	echo "$ONLINE" > $_ccw_status_dir/online

        # Re-read to check whether we have succeeded
	_ccw_dev_status=$(cat $_ccw_status_dir/online)
	if [ "$_ccw_dev_status" -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
    # Always reset CTC Protocol
    echo 0 > $_ccw_status_dir/protocol
fi

RULES_DIR=/etc/udev/rules.d
RULES_FILE=51-${CCW_CHAN_GROUP}-${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 ${CCW_CHAN_GROUP} device at ${CTC_READ_CHAN}/${CTC_WRITE_CHAN} (Protocol ${CTC_MODE})
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_READ_CHAN", RUN+="/sbin/modprobe --quiet $CCW_CHAN_GROUP"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_READ_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_WRITE_CHAN", RUN+="/sbin/modprobe --quiet $CCW_CHAN_GROUP"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_WRITE_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="$CCW_CHAN_GROUP", IMPORT{program}="collect $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$CTC_READ_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$CTC_WRITE_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
ACTION=="remove", SUBSYSTEM=="drivers", KERNEL=="$CCW_CHAN_GROUP", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
TEST=="[ccwgroup/${CCW_CHAN_ID}]", GOTO="ctc-${CCW_CHAN_ID}-end"
ACTION=="add", SUBSYSTEM=="ccw", ENV{COLLECT_$CCW_CHAN_ID}=="0", ATTR{[drivers/ccwgroup:$CCW_CHAN_GROUP]group}="$CTC_READ_CHAN,$CTC_WRITE_CHAN"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="$CCW_CHAN_GROUP", ENV{COLLECT_$CCW_CHAN_ID}=="0", ATTR{group}="$CTC_READ_CHAN,$CTC_WRITE_CHAN"
LABEL="ctc-${CCW_CHAN_ID}-end"
EOF
	if [ "$CTC_MODE" -gt 0 ]; then
	    cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{protocol}="$CTC_MODE"
EOF
	fi
	cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{online}="1"
EOF
    fi
fi