SHA256
1
0
forked from pool/s390-tools
s390-tools/qeth_configure

453 lines
14 KiB
Plaintext
Raw Normal View History

#! /bin/sh
#
# qeth_configure
#
# Configures a qeth device
#
# Usage:
# qeth_configure [-i] [-l] [-f -t <CARDTYPE> ] [-o "Values"] -n <portno> -p <portname> <read chan> <write chan> <data chan> <online>
#
# -i Configure IP takeover
# -l Configure Layer2 support
# -f force creation of udev rules, do not check values in /sys
# -t Valid cardtypes are: qeth, hsi, osn
# -o General QETH options, separated by spaces
# -n QETH port number to use, 0 or 1. Only needed for real, not virtual devices.
# -p QETH Portname to use. Only needed if sharing a real OSA with z/OS.
# read/write/data chan = x.y.ssss where
# x is always 0 until IBM creates something that uses that number
# y is the logical channel subsystem (lcss) number. Most often this is 0, but it could be non-zero
# ssss is the four digit subchannel address of the device, in hexidecimal, with leading zeros.
# online = 0 to take the device offline
# 1 to bring the device 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 data 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
#
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
QETH_FORCE=0
mesg () {
echo "$@"
}
DATUM=$(date)
add_channel_for_cio() {
echo "$* # $DATUM" >> /boot/zipl/active_devices.txt
}
remove_channel_for_cio() {
[ -w /boot/zipl/active_devices.txt ] && sed -i -e "/^$1/d" /boot/zipl/active_devices.txt
}
debug_mesg () {
case "$DEBUG" in
yes) mesg "$@" ;;
*) ;;
esac
}
while [ $# -gt 0 ] ; do
case "$1" in
-i)
# Configure IP takeover
QETH_IPA_TAKEOVER=1
;;
-f) # force creation of udev rules, do not check values in /sys
QETH_FORCE=1
;;
-l)
# Configure Layer2 support
QETH_LAYER2_SUPPORT=1
;;
-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
;;
-p*)
# QETH Portname to use
if [ "$1" = "-p" ] ; then
QETH_PORTNAME=$2
shift
else
QETH_PORTNAME=${1#-p}
fi
;;
-t*) # Card type. Must be provided if -f is used.
if [ "$1" = "-t" ] ; then
if [ "$2" = "qeth" -o "$2" = "hsi" -o "$2" = "osn" ]; then
QETH_CARD=$2
shift
else
mesg "Only qeth, hsi and osn are supported."
exit 6
fi
fi
CCW_DRV="$QETH_CARD"
;;
*)
break;
;;
esac
shift
done
if [ $QETH_FORCE -eq 0 ]; then
# 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
mesg "/sysfs not present"
exit 1
fi
fi
QETH_READ_CHAN=$1
QETH_WRITE_CHAN=$2
QETH_DATA_CHAN=$3
ONLINE=$4
if [ $# -lt 4 ] ; then
echo "Usage: $0 [options] <read chan> <write chan> <data chan> <online>"
echo " -i Configure IP takeover"
echo " -l Configure Layer2 support"
echo " -f force creation of udev rules, do not check values in /sys"
echo " -t Valid cardtypes are: qeth, hsi, osn"
echo " -o General QETH options, separated by spaces"
echo " -n QETH port number to use, 0 or 1. Only needed for real, not virtual devices."
echo " -p QETH Portname to use. Only needed if sharing a real OSA with z/OS."
echo " read/write/data chan = x.y.ssss where"
echo " x is always 0 until IBM creates something that uses that number"
echo " y is the logical channel subsystem (lcss) number. Most often this is 0, but it could be non-zero"
echo " ssss is the four digit subchannel address of the device, in hexidecimal, with leading zeros."
echo " online = 0 to take the device offline"
echo " 1 to bring the device online"
exit 1
fi
if [ -z "$ONLINE" ] || [ "$ONLINE" -ne "1" -a "$ONLINE" -ne "0" ]; then
mesg "Invalid device status $ONLINE"
exit 2
fi
if [ $QETH_FORCE -eq 0 ]; then
_ccw_dir=${SYSFS}/bus/ccw/devices
# Convert any hexidecimal numbers to lower case
QETH_READ_CHAN=$(echo ${QETH_READ_CHAN} | tr "[A-Z]" "[a-z]")
QETH_WRITE_CHAN=$(echo ${QETH_WRITE_CHAN} | tr "[A-Z]" "[a-z]")
QETH_DATA_CHAN=$(echo ${QETH_DATA_CHAN} | tr "[A-Z]" "[a-z]")
debug_mesg "Configuring QETH device ${QETH_READ_CHAN}/${QETH_WRITE_CHAN}/${QETH_DATA_CHAN}"
if test ! -d "$_ccw_dir/$QETH_READ_CHAN" ; then
mesg "No device ${QETH_READ_CHAN}"
exit 3
fi
if test ! -d "$_ccw_dir/$QETH_WRITE_CHAN" ; then
mesg "No device ${QETH_WRITE_CHAN}"
exit 4
fi
if test ! -d "$_ccw_dir/$QETH_DATA_CHAN" ; then
mesg "No device ${QETH_DATA_CHAN}"
exit 5
fi
CCW_CHAN_GROUP=
for ccw in $_ccw_dir/$QETH_READ_CHAN $_ccw_dir/$QETH_WRITE_CHAN $_ccw_dir/$QETH_DATA_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 "Not a valid QETH device (cu $_cutype, dev $_devtype)"
exit 6
fi
done
fi # end QETH_FORCE
# 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
if [ $QETH_FORCE -eq 0 ]; then
_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
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_DATA_CHAN}/group_device ] ; then
_tmp_status_dir=$(cd -P ${_ccw_dir}/${QETH_DATA_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_DATA_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_DATA_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
# 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
# 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
# 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 [ $? -eq 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
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
else
CCW_CHAN_ID=$QETH_READ_CHAN
fi # QETH_FORCE
if [ $DEBUG = "no" ]; then
RULES_DIR=/etc/udev/rules.d
else
RULES_DIR=.
fi
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
remove_channel_for_cio "${QETH_READ_CHAN}"
remove_channel_for_cio "${QETH_WRITE_CHAN}"
remove_channel_for_cio "${QETH_DATA_CHAN}"
if [ "$ONLINE" -eq "1" ]; then
add_channel_for_cio "${QETH_READ_CHAN},${QETH_WRITE_CHAN},${QETH_DATA_CHAN}"
# Write a new udev rules file
cat > ${RULES_DIR}/${RULES_FILE} <<EOF
# Configure ${QETH_CARD} device at ${QETH_READ_CHAN}/${QETH_WRITE_CHAN}/${QETH_DATA_CHAN}
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="$CCW_DRV", IMPORT{program}="collect $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_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_DATA_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_DATA_CHAN $CCW_DRV"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$QETH_DATA_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_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_DATA_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_DATA_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_DATA_CHAN $CCW_DRV"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$QETH_DATA_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_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_DATA_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_DATA_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_LAYER2_SUPPORT" ]; then
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{layer2}="1"
EOF
elif [ "${QETH_CARD}" != "osn" ]; then
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{layer2}="0"
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
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
udevadm settle
exit 0