#!/bin/bash
#
#/*******************************************************************
# * This file is part of the Emulex Linux Device Driver for         *
# * Fibre Channel Host Bus Adapters.                                *
# * Refer to the README file included with this package for         *
# * driver version and adapter support.                             *
# * Copyright (C) 2003-2005 Emulex.  All rights reserved.           *
# * www.emulex.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  *
# * of the License, 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, a copy of which    *
# * can be found in the file COPYING included with this package.    *
# *******************************************************************/
#
# install script for Emulex Linux Fibre Channel Driver RPMs
#
INSTALLER_VERSION='$Id: lpfc-install 509 2006-04-05 14:31:19Z sf_support $'
INSTALLER_VERSION=`echo ${INSTALLER_VERSION} | perl -pe '/\s+([\d\.]*)\s+/;$_="$1\n"'`

# Exit codes:
#   0   Success.
#   1   Unable to determine distribution type.
#   2   Unknown error.
#   5   Invalid command line parameter.
#   6   The Multipulse kit must be removed prior to the installation
#        of the LPFC driver kit.
#  10   Failure to uninstall old driver and applications.
#  12   Other package(s) depend(s) upon packages to be removed.
#  13   The Multipulse kit must be removed prior to the removal of the
#        LPFC driver kit.
#  15   One or more Emulex Linux LPFC packages already installed.
#  20   Success, system requires reboot to complete installation.
#  25   Success, system requires reboot to complete uninstallation.
#  30   Error installing ramdisk image to LILO configuration.
#  40   Error creating initial ramdisk to load Emulex driver during boot.
#  45   Error creating initial ramdisk to not load Emulex driver during boot.
#  47   Error creating initial ramdisk.
#  60   Kernel source is not installed, scripted RPM cannot continue.
#  70   Compilers are not installed, scripted RPM cannot continue.
#  75   Neither kernel source nor compilers are installed, RPM cannot
#        continue.
#  80   User specified an invalid lpfc.conf configuration file.
#  81   Error copying user-specified lpfc.conf file to ${LPFC_CONF_TEMP}.
#  82   Error removing ${LPFC_CONF_TEMP} file after driver RPM installation.
#  95   Error copying init script during driver RPM installation.
#  97   Error configuring init script during driver RPM installation.
# 120   Unable to unload old Emulex driver.
# 125   Unable to back up old Emulex driver.
# 127   Unable to uninstall old Emulex driver.
# 130   Error backing up /etc/modules.conf.
# 140   Error updating /etc/modules.conf.

DRIVER_NAME=lpfc
DFCDRIVER_NAME=lpfcdfc
RPM_BASENAME=${DRIVER_NAME}driver
SMB_RPM_BASENAME=${RPM_BASENAME}-smb
SMB_DRIVER_NAME=${DRIVER_NAME}dd
DFCRPM_BASENAME=${DFCDRIVER_NAME}driver
IOCTLRPM_BASENAME=${DRIVER_NAME}_2.4_ioctl_module
MULTIPULSE_RPM_BASENAME=lpfc_2.4_mpl_module
INITSCRIPT_NAME=elxlpfc
DRIVER_VERSION=7.3.6
DFCDRIVER_VERSION=1.2.3
DRIVER_DESCRIPTION="LPFC Driver source RPM"
DFCDRIVER_DESCRIPTION="LPFC DFC Driver source RPM"
SCRIPT_RPM_RELEASE=1
DFC_RPM_RELEASE=2
SAVEDFILESDIR="/usr/src/lpfc/savedfiles"

DRIVER_DIR=.
INSTALL_SCRIPT=$0

let MAX_SCSI_LUNS=256
let SCSI_ALLOW_GHOST_DEVICES=1
MODULES_CONF_ENTRY="options scsi_mod"
MODULES_CONF_GHOST="scsi_allow_ghost_devices=${SCSI_ALLOW_GHOST_DEVICES}"
MODULES_CONF_LUNS="max_scsi_luns=${MAX_SCSI_LUNS}"
MODULES_CONF_BACKUP=/etc/modules.elx
MODULES_CONF_TEMP=/etc/modules.conf.elxinstall
MODULES_CONF_TEMP2=/etc/modules.conf.elxinstall2
KERNEL_CONF_BACKUP=/etc/sysconfig/kernel.elx
KERNEL_CONF_TEMP=/etc/sysconfig/kernel.elxinstall
LPFC_CONF_TEMP="/tmp/lpfc.conf.linuxinstaller"

GENERIC_MESSAGE="Please contact Emulex Technical Support"
HELP_MESSAGE="Please execute '$0 --help' for usage information."

let NEED_SOURCE_PACKAGE=0
let NEED_GCC_PACKAGE=0
let DRIVER_INSTALLED=0

exec_command()
{
    local TEMPFILE
    RETURNVALUE=0
    TEMPFILE=`mktemp /tmp/elx-lpfc-install.XXXXXX`
    if [ "$2" = background ] ; then
	(eval $1 ; echo "RETURNVALUE=$?" >> ${TEMPFILE}) &
	while [ -e ${TEMPFILE} ] && [ ! -s ${TEMPFILE} ] ; do
	    sleep 3
	    echo -en "."
	done
	. ${TEMPFILE}
	rm -f ${TEMPFILE}
    else
	eval $1
	RETURNVALUE=$?
    fi
    echo -en "\n"
    return ${RETURNVALUE}
}

get_distribution ()
{
    ARCH=$(uname -m | sed "s/i686/i386/")
    KERNEL=$(rpm -qf /lib/modules/$(uname -r) --qf "%{VERSION}_%{RELEASE}\n")
    UNAME=$(uname -r)
    DRIVER_RPM=${RPM_BASENAME}-${DRIVER_VERSION}-${SCRIPT_RPM_RELEASE}.noarch.rpm
    DFCDRIVER_RPM=${DFCRPM_BASENAME}-${DFCDRIVER_VERSION}-${DFC_RPM_RELEASE}.noarch.rpm
    INITSCRIPT_SOURCE=${DRIVER_DIR}/${INITSCRIPT_NAME}
    if [ -f /etc/asianux-release ]; then
	# This is an Asianux Linux install
	DISTRIBUTION=asianux
        DIST_VERSION=$(rpm -qf /etc/asianux-release --qf "%{VERSION}" | sed "s/[^0-9\.]//g")
        RELEASE=asianux${DIST_VERSION}_${KERNEL}
	BOOT_FILE=/etc/rc.d/rc.local
	INITSCRIPT_DESTINATION=/etc/rc.d/init.d/${INITSCRIPT_NAME}
	if [ ${ARCH} = "ia64" ] ; then
	    KERNEL_IMAGE_PATH="/boot/efi/efi/asianux/vmlinuz-${UNAME}"
	    INITRDFILE="/boot/efi/efi/asianux/initrd-${UNAME}.img"
	else
	    KERNEL_IMAGE_PATH="/boot/vmlinuz-${UNAME}"
	    INITRDFILE="/boot/initrd-${UNAME}.img"
	fi
	return 0
    elif [ -f /etc/redflag-release ]; then
	# This is a Red Flag Linux install
	DISTRIBUTION=redflag
        DIST_VERSION=$(rpm -qf /etc/redflag-release --qf "%{VERSION}" | sed "s/[^0-9\.]//g")
        RELEASE=redflag{DIST_VERSION}_${KERNEL}
	BOOT_FILE=/etc/rc.d/rc.local
	INITSCRIPT_DESTINATION=/etc/rc.d/init.d/${INITSCRIPT_NAME}
	if [ ${ARCH} = "ia64" ] ; then
	    KERNEL_IMAGE_PATH="/boot/efi/efi/asianux/vmlinuz-${UNAME}"
	    INITRDFILE="/boot/efi/efi/asianux/initrd-${UNAME}.img"
	else
	    KERNEL_IMAGE_PATH="/boot/vmlinuz-${UNAME}"
	    INITRDFILE="/boot/initrd-${UNAME}.img"
	fi
	return 0
    elif [ -f /etc/miraclelinux-release ]; then
	# This is a Miracle Linux install
	DISTRIBUTION=miraclelinux
        DIST_VERSION=$(rpm -qf /etc/miraclelinux-release --qf "%{VERSION}" | sed "s/[^0-9\.]//g")
        RELEASE=miraclelinux{DIST_VERSION}_${KERNEL}
	BOOT_FILE=/etc/rc.d/rc.local
	INITSCRIPT_DESTINATION=/etc/rc.d/init.d/${INITSCRIPT_NAME}
	if [ ${ARCH} = "ia64" ] ; then
	    KERNEL_IMAGE_PATH="/boot/efi/efi/asianux/vmlinuz-${UNAME}"
	    INITRDFILE="/boot/efi/efi/asianux/initrd-${UNAME}.img"
	else
	    KERNEL_IMAGE_PATH="/boot/vmlinuz-${UNAME}"
	    INITRDFILE="/boot/initrd-${UNAME}.img"
	fi
	return 0
    elif [ -f /etc/redhat-release ]; then
        # this is a Red Hat install
	DISTRIBUTION=redhat
        RH_VERSION=$(rpm -qf /etc/redhat-release --qf "%{VERSION}" | sed "s/[^0-9\.]//g")
        RELEASE=rhel${RH_VERSION}_${KERNEL}
	BOOT_FILE=/etc/rc.d/rc.local
	INITSCRIPT_DESTINATION=/etc/rc.d/init.d/${INITSCRIPT_NAME}
	if [ ${ARCH} = "ia64" ] ; then
	    KERNEL_IMAGE_PATH="/boot/efi/efi/redhat/vmlinuz-${UNAME}"
	    INITRDFILE="/boot/efi/efi/redhat/initrd-${UNAME}.img"
	else
	    KERNEL_IMAGE_PATH="/boot/vmlinuz-${UNAME}"
	    INITRDFILE="/boot/initrd-${UNAME}.img"
	fi
	return 0
    elif [ -f /etc/SuSE-release ]; then
        # this is a Suse install
	DISTRIBUTION=suse
        SUSE_VERSION=$(rpm -qf /etc/SuSE-release --qf "%{VERSION}" | sed "s/[^0-9\.]//g")
        RELEASE=sles${SUSE_VERSION}_${KERNEL}
	BOOT_FILE=/etc/rc.d/boot.local
	INITSCRIPT_DESTINATION=/etc/rc.d/${INITSCRIPT_NAME}
	SLES_KERNEL_IMAGE=vmlinuz
	if [ ${ARCH} = "ppc64" ] ; then
	    KERNEL_IMAGE_PATH="/boot/vmlinuz"
	    INITRDFILE="/boot/initrd"
	else
	    KERNEL_IMAGE_PATH="/boot/vmlinuz-${UNAME}"
	    INITRDFILE="/boot/initrd /boot/initrd.shipped"
	fi
	return 0
    else
        echo ""
        echo "Unable to determine distribution type"
        return 1
    fi
}

# Function:  num_adapters()
#
# Description:
#   Determine the number of adapters installed on this system.  Dual
#   channel adapters will be reported as the number of channels on the
#   adapter.
#
# Parameters:
#   none.
#
# Returns:
#   The number of adapters installed on this system.
num_adapters()
{
    local NUM_ADAPTERS
    local TEMPFILE
    let NUM_ADAPTERS=0
    TEMPFILE=`mktemp /tmp/elx-lpfc-install-pciids.XXXXXX`

    # First, create a temp file with the PCI IDs of the adapters
    # supported by this driver.
    echo -n "10df  Emulex Corporation" > ${TEMPFILE}
    echo -n "\t1ae5  LP6000 Fibre Channel Host Adapter" >> ${TEMPFILE}
    echo -n "\tf085  LP850 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tf095  LP952 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tf098  LP982 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tf0a1  LP101 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tf0a5  LP1050 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tf700  LP7000 Fibre Channel Host Adapter" >> ${TEMPFILE}
    echo -n "\tf800  LP8000 Fibre Channel Host Adapter" >> ${TEMPFILE}
    echo -n "\tf900  LP9000 Fibre Channel Host Adapter" >> ${TEMPFILE}
    echo -n "\tf980  LP9802 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tfa00  LP10000 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tfb00  LPx1000 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tfd00  LP11000 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tf0d5  LP1150 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tf0d1  LP111 Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tfe00  LP11000e Fibre Channel Adapter" >> ${TEMPFILE}
    echo -n "\tf0e5  LP1150e Fibre Channel Adapter" >> ${TEMPFILE}

    # Now, execute lspci to determine the number of adapters in the
    # system.
    let NUM_ADAPTERS=$((`/sbin/lspci -d 10df: -i ${TEMPFILE} | wc -l`))

    # Remove the tempfile, since it is no longer needed.
    rm -f ${TEMPFILE}

    return ${NUM_ADAPTERS}
}

# Function:  check_for_driver_kit()
#
# Description:
#   Verifies that a version of the Emulex Linux LPFC driver kit is not
#   already installed.
#
# Parameters:
#   none.
#
# Returns:
#   0 - no driver kit is installed.
#   1 - a driver kit is already installed.
#   2 - this version of the driver kits is already installed.
check_for_driver_kit()
{
    local INSTALLEDVERSION
    local retval
    local message
    let message=0

    # Check for an SMB kit.
    INSTALLEDVERSION=$(rpm -q --qf %{VERSION} ${SMB_RPM_BASENAME} 2>/dev/null)
    if [ $? -eq 0 ] ; then
	echo -e "\n${SMB_RPM_BASENAME} package is installed."
	let message=$((${message} | 1))
	let retval=1
    fi

    # Check for the 'lpfc_2.4_ioctl_module' package.
    INSTALLEDVERSION=$(rpm -q --qf %{VERSION} ${IOCTLRPM_BASENAME} 2>/dev/null)
    if [ $? -eq 0 ] ; then
	echo "${DFCRPM_BASENAME} package is installed."
	let message=$((${message} | 16))
	let retval=1
    fi
    
    # Check for the 'lpfcdfcdriver' package.
    INSTALLEDVERSION=$(rpm -q --qf %{VERSION} ${DFCRPM_BASENAME} 2>/dev/null)
    if [ $? -eq 0 ] ; then
	if [ "${INSTALLEDVERSION}" = "${DFCDRIVER_VERSION}" ] ; then
	    echo "Version ${DFCDRIVER_VERSION} of the ${DFCRPM_BASENAME} package is already installed."
	    let retval=2
	else
	    echo "${DFCRPM_BASENAME} package is installed."
	    let message=$((${message} | 2))
	    let retval=1
	fi
    fi

    # Check for the 'lpfcdriver' package.
    INSTALLEDVERSION=$(rpm -q --qf %{VERSION} ${RPM_BASENAME} 2>/dev/null)
    if [ $? -eq 0 ] ; then
	if [ ${INSTALLEDVERSION} = ${DRIVER_VERSION} ] ; then
	    echo "Version ${DRIVER_VERSION} of the ${RPM_BASENAME} package is already installed."
	    let retval=2
	else
	    echo "${RPM_BASENAME} package is installed."
	    let local major=$(echo ${INSTALLEDVERSION} | sed 's/^\([[:digit:]]*\)\..*/\1/g')
	    if [ ${major} -lt 7 ] ; then
		let message=$((${message} | 4))
	    else
		let message=$((${message} | 8))
	    fi
	    let retval=1
	fi
    fi

    # Print all appropriate messages.
    if [ $((${message} & 1)) -ne 0 ] ; then
	echo -e "Please uninstall by running the lpfc-install script"
	echo -e "before continuing to install any new driver kits."
    elif [ $((${message} & 2)) -ne 0 ] ; then
	echo "Please uninstall by running '$0 --uninstall'."
    elif [ $((${message} & 4)) -ne 0 ] ; then
	echo "Please uninstall this package using the lpfc-install"
	echo "script that was used to install that version of the Emulex"
	echo "Linux LPFC driver kit."
    elif [ $((${message} & 8)) -ne 0 ] ; then
	echo "Please uninstall by running '$0 --uninstall'."
    elif [ $((${message} & 16)) -ne 0 ] ; then
	echo "Please uninstall the Emulex IOCTL Application Helper Module"
	echo "using the ioctl-install script from the installation directory"
	echo "of this module's kit:"
	echo "   'ioctl-install --uninstall'"
    fi

    return ${retval}
}

# Function:  backup_file_to_savedfiles()
#
# Description:
#   Move each file passed as a parameter to the directory specified by
#   the SAVEDFILESDIR shell variable, preserving the original path
#   information under the SAVEDFILESDIR directory.
#
# Parameters:
#   A list of filenames to save.
#
# Returns a bit pattern with the following values:
#   0 on success.
#   1 if the ${SAVEDFILESDIR} does not exist and cannot be created.
#   2 if one or more files could not be saved to ${SAVEDFILESDIR}.
#   4 if one or more original files could not be removed after they were saved.
backup_file_to_savedfiles()
{
    local i
    local RETURNVALUE
    let RETURNVALUE=0

    if [ ! -d ${SAVEDFILESDIR} ] ; then
	mkdir -p ${SAVEDFILESDIR}
	if [ $? -ne 0 ] ; then
	    echo "Error creating ${SAVEDFILESDIR}!"
	    return 1
	fi
    fi

    for i in $@ ; do
	cp --parents $i ${SAVEDFILESDIR}
	if [ $? -ne 0 ] ; then
	    echo "Error copying $i to a safe location!"
	    let RETURNVALUE=$((${RETURNVALUE} | 2))
	fi
	rm -f $i
	if [ $? -ne 0 ] ; then
	    echo "Error removing $i after backup!"
	    let RETURNVALUE=$((${RETURNVALUE} | 4))
	fi
    done

    return ${RETURNVALUE}
}

# Function:  restore_files_from_savedfiles()
#
# Description:
#   Move each file passed as a parameter back to its original
#   location.
#
# Parameters:
#   A list of filenames to restore.
#
# Returns a bit pattern with the following values:
#   0 on success.
#   1 if no files are available to restore.
#   2 if one or more files could not be restored.
#   4 if one or more backup files could not be removed after they were restored.
restore_files_from_savedfiles()
{
    local DIRECTORY
    local BACKUPFILE
    local RETURNVALUE
    let RETURNVALUE=0

    # Return immediately if no files are available to be restored.
    if [ ! -d "${SAVEDFILESDIR}/$1" ] ; then
	if [ -d ${SAVEDFILESDIR} ] ; then
	    rmdir --ignore-fail-on-non-empty -p ${SAVEDFILESDIR}
	fi
	return 1
    fi

    for i in `find ${SAVEDFILESDIR}/$1 -regex "$2"` ; do
	echo -en "\n"
	BACKUPFILE=$(echo $i | sed "s|^${SAVEDFILESDIR}/||")
	DIRECTORY=$(echo ${BACKUPFILE} | sed "s/\(.*\/\)[^\/]*/\1/")
	pushd ${SAVEDFILESDIR} 2>/dev/null 1>/dev/null
	cp --parents ${BACKUPFILE} /
	if [ $? -ne 0 ] ; then
	    echo "Error restoring /${BACKUPFILE}!"
	    let RETURNVALUE=$((${RETURNVALUE} | 2))
	fi
	rm -f ${BACKUPFILE}
	if [ $? -ne 0 ] ; then
	    echo "Error removing backup file ${SAVEDFILESDIR}/${BACKUPFILE}"
	    let RETURNVALUE=$((${RETURNVALUE} | 4))
	fi
	popd 2>/dev/null 1>/dev/null
	rmdir --ignore-fail-on-non-empty -p ${SAVEDFILESDIR}/${DIRECTORY}
    done

    return ${RETURNVALUE}
}

# Function:  unload_old_drivers()
#
# Description:
#   Unload any old lpfc, lpfcdfc, and/or lpfcdd drivers that may be
#   loaded.
#
# Parameters:
#   none.
#
# Returns a bit pattern with the following values:
#   0 - all old drivers unloaded, or no old drivers were loaded.
#   1 - an error occurred while unloading one or more drivers.
#   2 - old driver is being used and cannot be unloaded.
#   4 - old driver is being referenced by another module and cannot be unloaded.
unload_old_drivers()
{
    local drivers
    local retval
    let retval=0

    echo "Checking for old Emulex driver ..."
    drivers=(${DFCDRIVER_NAME} ${DRIVER_NAME} ${DRIVER_NAME}_703 ${SMB_DRIVER_NAME})
    for i in ${drivers[@]} ; do
	unload_driver ${i}
	case "$?" in
	    0) echo "Module '${i}' successfully unloaded." ;;
	    1) echo "An error occurred while unloading ${i}."
		let retval=$((${retval} | 1)) ;;
	    2) echo "The ${i} driver is being used and cannot be unloaded."
		let retval=$((${retval} | 2)) ;;
	    3) echo "The ${i} driver is being referenced by other"
		echo "modules and cannot be unloaded."
		let retval=$((${retval} | 4)) ;;
	    4) ;;
	    *) echo "An unknown error occurred while unloading ${i}."
		let retval=$((${retval} | 1)) ;;
	esac
    done

    return ${retval}
}

# Function:  backup_old_driver()
#
# Description:
#   Move any old drivers from the /lib/modules/${UNAME} directory to a
#   location where they will not be referenced by 'depmod -a', but
#   where they will be available if they need to be restored by the
#   '--uninstall' option to the install script.
#
# Parameters:
#   none.
#
# Returns:
#   0 on success.
backup_old_driver()
{
    # Move old copies of the driver module out of the way.
    backup_file_to_savedfiles `find /lib/modules/${UNAME}/kernel/drivers/ -regex '.*lpf[cn]\(dd\|dfc\)?\.k?o'`
    if [ $? -ne 0 ] ; then
	echo "Unable to backup old drivers."
	exit 125
    fi
    backup_file_to_savedfiles `find /lib/modules/${UNAME}/kernel/drivers/ -regex '.*lpfc_[0-9]*.k?o'`
    if [ $? -ne 0 ] ; then
	echo "Unable to backup old drivers."
	exit 125
    fi

    return 0
}

# Function:  restore_old_driver()
#
# Description:
#   Move any old drivers saved by the backup_old_driver() function to
#   their original locations.
#
# Parameters:
#   none.
#
# Returns:
#   0 on success.
#   nonzero on failure.
restore_old_driver()
{
    local RETURNVALUE

    echo "Restoring old Emulex drivers..."
    restore_files_from_savedfiles "lib/modules/${UNAME}/kernel/drivers/" '.*lpf[cn]\(dd\|dfc\)?\.k?o'
    restore_files_from_savedfiles "lib/modules/${UNAME}/kernel/drivers/" '.*lpfc_[0-9]*.k?o'
    let RETURNVALUE=$?

    # This function might be called even if no old drivers are
    # available to be restored, so don't fail if the search for files
    # to restore fails.
    case "${RETURNVALUE}" in
	0|1)  let RETURNVALUE=0 ;;
	*)    let RETURNVALUE=${RETURNVALUE} ;;
    esac
    return ${RETURNVALUE}
}

# Function:  configure_sles_sysconfig_kernel()
#
# Description:
#   Configure the /etc/sysconfig/kernel file on SLES installations to
#   load the lpfc driver on boot.
#
# Parameters:
#   none.
#
# Returns:
#   0 - /etc/sysconfig/kernel file not modified.
#   1 - /etc/sysconfig/kernel file modified.
configure_sles_sysconfig_kernel()
{
    local RETURN_VALUE
    let RETURN_VALUE=0

    if [ ${DISTRIBUTION} = "suse" ] ; then
	echo "Configuring /etc/sysconfig/kernel ..."
	if [ $(grep -c -e "^[[:space:]]*INITRD_MODULES[[:space:]]*=[[:space:]]*.*[\"[:space:]]${1}[\"[:space:]]" /etc/sysconfig/kernel) -eq 0 ] ; then
	    cp /etc/sysconfig/kernel ${KERNEL_CONF_BACKUP}
	    echo "Original saved as ${KERNEL_CONF_BACKUP}"
	    sed "s/INITRD_MODULES=\"\(.*\)\"/INITRD_MODULES=\"\1 ${DRIVER_NAME}\"/" /etc/sysconfig/kernel > ${KERNEL_CONF_TEMP}
	    mv -f ${KERNEL_CONF_TEMP} /etc/sysconfig/kernel
	    let RETURN_VALUE=1
	fi
    fi

    return ${RETURN_VALUE}
}

# Function:  unconfigure_sles_sysconfig_kernel()
#
# Description:
#   Configure the /etc/sysconfig/kernel file on SLES installations to
#   not load the lpfc driver on boot.
#
# Parameters:
#   none.
#
# Returns:
#   0 - /etc/sysconfig/kernel file not modified.
#   1 - /etc/sysconfig/kernel file modified.
unconfigure_sles_sysconfig_kernel()
{
    local MODIFIED_FILE
    local RETURN_VALUE
    let MODIFIED_FILE=0
    let RETURN_VALUE=0

    if [ ${DISTRIBUTION} = "suse" ] ; then
	echo "Configuring /etc/sysconfig/kernel ..."
	cp -f /etc/sysconfig/kernel ${KERNEL_CONF_BACKUP}
	while [ -n "$1" ] ; do
	    if [ $(grep -c -e "^[[:space:]]*INITRD_MODULES[[:space:]]*=[[:space:]]*.*[\"[:space:]]${1}[\"[:space:]]" /etc/sysconfig/kernel) -ne 0 ] ; then
		sed "/^[[:space:]]*INITRD_MODULES[[:space:]]*=.*\".*/ {s/\([\"[:space:]]\)${1}\([\"[:space:]]\)/\1\2/g}" /etc/sysconfig/kernel > ${KERNEL_CONF_TEMP}
		mv -f ${KERNEL_CONF_TEMP} /etc/sysconfig/kernel
		let MODIFIED_FILE=$((${MODIFIED_FILE}+1))
		let RETURN_VALUE=1
	    fi
	    shift
	done

	if [ ${MODIFIED_FILE} -ne 0 ] ; then
	    echo "Original saved as ${KERNEL_CONF_BACKUP}"
	else
	    rm ${KERNEL_CONF_BACKUP}
	fi
    fi

    return ${RETURN_VALUE}
}

# Function:  backup_modules_conf()
#
# Description:
#   Copy the file /etc/modules.conf to the file specified by the the
#   first positional parameter, failing with exit code 130 if the copy
#   fails.
#
# Parameters:
#   File to which /etc/modules.conf should be copied.
#
# Returns:
#   0 on success,
#   exit code 130 on failure.
backup_modules_conf()
{
    # Make a working copy of /etc/modules.conf.
    cp -f /etc/modules.conf $1
    if [ $? -ne 0 ] ; then
	echo ""
	echo "Error backup up /etc/modules.conf"
	echo ${GENERIC_MESSAGE}
	exit 130
    fi

    return 0
}

# Function:  configure_modules_conf()
#
# Description:
#   Add /etc/modules.conf scsihostadapter references to each driver
#   passed as a parameter.  If the distribution is not SLES, then add
#   the text contained in MODULES_CONF_ENTRY to the /etc/modules.conf
#   file, as well.
#
# Parameters:
#   A list of driver modules.
#
# Returns a bit pattern with the following values:
#  0 if the /etc/modules.conf file is not modified,
#  1 if the /etc/modules.conf file is modified.
#  2 if the scsi_mod options contains an invalid value for scsi_allow_ghost_devices.
#  4 if multiple scsi_mod option lines exist in modules.conf.
#  8 if an "alias scsi_hostadapter off" entry exists in modules.conf.
configure_modules_conf()
{
    local RETURN_VALUE
    local MAX_REF
    let RETURN_VALUE=0

    echo "Configuring /etc/modules.conf ..."
    backup_modules_conf ${MODULES_CONF_TEMP}

    MAX_REF=$(grep -e "^[[:space:]]*alias[[:space:]]\+scsi_hostadapter[[:digit:]]\+[[:space:]]\+" /etc/modules.conf | sed 's/^.*[[:space:]]scsi_hostadapter\([[:digit:]]\+\)[[:space:]].*$/\1/' | awk '{if (s < $1) s=$1} END {print s}')
    let MAX_REF=$((${MAX_REF}+1))

    # Check for the presence of "alias scsi_hostadapter off" entry.
    local SCSI_OFF
    let SCSI_OFF=$(grep -c -e "^[[:space:]]*alias[[:space:]]\+scsi_hostadapter[[:space:]]\+off[[:space:]]*" /etc/modules.conf)
    if [ ${SCSI_OFF} -ne 0 ] ; then
	let RETURN_VALUE=$((${RETURN_VALUE}|8))
    fi

    # Add apppropriate number of references for each driver passed to
    # this function.
    while [ -n "$1" ] && [ -n "$2" ] ; do
	local NUM_REFS
	let NUM_REFS=$(grep -c -e "^[[:space:]]*alias[[:space:]]\\+scsi_hostadapter[[:digit:]]\\+[[:space:]]\\+${1}[[:space:]]*\$" ${MODULES_CONF_TEMP})
	while [ ${NUM_REFS} -lt $2 ] ; do
	    echo "alias scsi_hostadapter${MAX_REF} ${1}" >> ${MODULES_CONF_TEMP}
	    let MAX_REF=$((${MAX_REF}+1))
	    let NUM_REFS=$((${NUM_REFS}+1))
	    let RETURN_VALUE=$((${RETURN_VALUE}|1))
	done
	shift
	shift
    done

    # Add or modify the 'options scsi_mod' line in /etc/modules.conf
    # file if necessary.
    local SCSI_MOD_COUNT
    local SCSI_MOD_ENTRY
    local SCSI_MOD_ENTRY_ORIGINAL
    let SCSI_MOD_COUNT=$(grep -c -e "^[[:space:]]*options[[:space:]]\\+scsi_mod[[:space:]]\\+" ${MODULES_CONF_TEMP})
    SCSI_MOD_ENTRY=$(grep -e "^[[:space:]]*options[[:space:]]\\+scsi_mod[[:space:]]\\+" ${MODULES_CONF_TEMP})
    SCSI_MOD_ENTRY_ORIGINAL=${SCSI_MOD_ENTRY}
    if [ ${SCSI_MOD_COUNT} -eq 1 ] ; then
	# An 'options scsi_mod' line already exists.  Make sure it
        # meets the needs of the lpfc module.
	local CHANGES
	let CHANGES=0
	# First, check the "max_scsi_luns" entry.
	local LUNS_ENTRY
	LUNS_ENTRY=$(echo ${SCSI_MOD_ENTRY} | grep -e 'max_scsi_luns=[[:digit:]]\+')
	if [ -n "${LUNS_ENTRY}" ] ; then
	    LUNS_ENTRY=$(echo ${LUNS_ENTRY} | sed 's/.*\(max_scsi_luns=[[:digit:]]\+\).*/\1/')
	fi
	if [ -z "${LUNS_ENTRY}" ] ; then
	    SCSI_MOD_ENTRY="${SCSI_MOD_ENTRY} max_scsi_luns=${MAX_SCSI_LUNS}"
	    let CHANGES=1
	elif [ $(echo ${LUNS_ENTRY} | sed "s/max_scsi_luns=//") -lt ${MAX_SCSI_LUNS} ] ; then
	    SCSI_MOD_ENTRY=$(echo ${SCSI_MOD_ENTRY} | sed "s/max_scsi_luns=[[:digit:]]\+/max_scsi_luns=${MAX_SCSI_LUNS}/")
	    let CHANGES=1
	fi
	# Next, check the "scsi_allow_ghost_devices" entry."
	if [ ${DISTRIBUTION} = "redhat" ] || [ ${DISTRIBUTION} = "asianux" ] ||
	    [ ${DISTRIBUTION} = "redflag" ] || [ ${DISTRIBUTION} = "miraclelinux" ]; then
	    local GHOST_ENTRY
	    GHOST_ENTRY=$(echo ${SCSI_MOD_ENTRY} | grep -e 'scsi_allow_ghost_devices=[[:digit:]]\+')
	    if [ -n "${GHOST_ENTRY}" ] ; then
		GHOST_ENTRY=$(echo ${GHOST_ENTRY} | sed 's/.*\(scsi_allow_ghost_devices=[[:digit:]]\+\).*/\1/')
	    fi
	    if [ -z "${GHOST_ENTRY}" ] ; then
		SCSI_MOD_ENTRY="${SCSI_MOD_ENTRY} scsi_allow_ghost_devices=${SCSI_ALLOW_GHOST_DEVICES}"
		let CHANGES=1
	    elif [ $(echo ${GHOST_ENTRY} | sed s/scsi_allow_ghost_devices=//) -ne ${SCSI_ALLOW_GHOST_DEVICES} ] ; then
		let RETURN_VALUE=$((${RETURN_VALUE}|2))
	    fi
	fi
	if [ ${CHANGES} -ne 0 ] ; then
	    grep -v "${SCSI_MOD_ENTRY_ORIGINAL}" ${MODULES_CONF_TEMP} > ${MODULES_CONF_TEMP2}
	    echo ${SCSI_MOD_ENTRY} >> ${MODULES_CONF_TEMP2}
	    mv -f ${MODULES_CONF_TEMP2} ${MODULES_CONF_TEMP}
	    let RETURN_VALUE=$((${RETURN_VALUE}|1))
	fi

    elif [ ${SCSI_MOD_COUNT} -eq 0 ] ; then
	# No 'options scsi_mod' line exists.  Write one that meets
        # the needs of the lpfc module.
	local LINE_TO_WRITE
	LINE_TO_WRITE=$(echo "${MODULES_CONF_ENTRY} ${MODULES_CONF_LUNS}")
	if [ ${DISTRIBUTION} = "redhat" ] || [ ${DISTRIBUTION} = "asianux" ] ||
	    [ ${DISTRIBUTION} = "redflag" ] || [ ${DISTRIBUTION} = "miraclelinux" ]; then
	    LINE_TO_WRITE=$(echo "${LINE_TO_WRITE} ${MODULES_CONF_GHOST}")
	fi
	echo "${LINE_TO_WRITE}" >> ${MODULES_CONF_TEMP}
	let RETURN_VALUE=$((${RETURN_VALUE}|1))
    else
	# Multple 'options scsi_mod' lines exist.  Bail.
	let RETURN_VALUE=$((${RETURN_VALUE}|4))
    fi

    # Back up and then update /etc/modules.conf if changes are
    # necessary.
    if [ ${RETURN_VALUE} -ne 0 ] ; then
	# Save one pre-existing backup.
	if [ -e /etc/modules.elx ] ; then
	    mv -f ${MODULES_CONF_BACKUP} ${MODULES_CONF_BACKUP}.old
	fi

	# Backup up /etc/modules.conf.
	cp -f /etc/modules.conf ${MODULES_CONF_BACKUP}
	if [ $? -ne 0 ] ; then
	    echo ""
	    echo "Error backing up /etc/modules.conf"
	    echo ${GENERIC_MESSAGE}
	    exit 130
	fi
	echo "Original saved as ${MODULES_CONF_BACKUP}"

	# Update /etc/modules.conf with the changes.
	mv -f ${MODULES_CONF_TEMP} /etc/modules.conf
	if [ $? -ne 0 ] ; then
	    echo ""
	    echo "Error updating /etc/modules.conf"
	    echo ${GENERIC_MESSAGE}
	    exit 140
	fi
    else
	# Remove the unmodified temp file.
	rm -f ${MODULES_CONF_TEMP}
    fi

    return ${RETURN_VALUE}
}

# Function:  unconfigure_modules_conf()
#
# Description:
#   Remove any references in /etc/modules.conf to all driver modules
#   passed as parameters to this function.  If any references are
#   removed on a non-SLES system, also check for a line matching
#   MODULES_CONF_ENTRY and remove it if it exists.
#
# Parameters:
#   A list of driver modules.
#
# Returns a bit pattern with the following values:
#   0 if the /etc/modules.conf file is not modified,
#   1 if the /etc/modules.conf file is modified.
#   4 if multiple scsi_mod option lines exist in modules.conf.
#   8 if the "options scsi_mod" entry could not be unconfigured.
unconfigure_modules_conf()
{
    local RETURN_VALUE
    let RETURN_VALUE=0

    echo "Configuring /etc/modules.conf ..."
    backup_modules_conf ${MODULES_CONF_TEMP}

    # Remove references to all drivers passed to this function.
    while [ -n "$1" ] ; do
	if [ $(grep -c -e "^alias[[:space:]]\+scsi_hostadapter[[:digit:]]*[[:space:]]\+${1}[[:space:]]*\$" /etc/modules.conf) -ne 0 ] ; then
	    grep -v -e "^alias[[:space:]]\+scsi_hostadapter[[:digit:]]*[[:space:]]\+${1}[[:space:]]*\$" ${MODULES_CONF_TEMP} > ${MODULES_CONF_TEMP2}
	    mv -f ${MODULES_CONF_TEMP2} ${MODULES_CONF_TEMP}
	    let RETURN_VALUE=$((${RETURN_VALUE}|1))
	fi
	shift
    done

    # Remove or modify the 'options scsi_mod' line in
    # /etc/modules.conf.
    local SCSI_MOD_COUNT
    local SCSI_MOD_ENTRY
    local SCSI_MOD_ENTRY_ORIGINAL
    let SCSI_MOD_COUNT=$(grep -c -e "^[[:space:]]*options[[:space:]]\\+scsi_mod[[:space:]]\\+" ${MODULES_CONF_TEMP})
    SCSI_MOD_ENTRY=$(grep -e "^[[:space:]]*options[[:space:]]\\+scsi_mod[[:space:]]\\+" ${MODULES_CONF_TEMP})
    SCSI_MOD_ENTRY_ORIGINAL=${SCSI_MOD_ENTRY}
    if [ ${SCSI_MOD_COUNT} -eq 1 ] ; then
	# An 'options scsi_mod' line already exists.  Make sure it
        # matches the one written by lpfc-install during installation.
	local TEMP
	TEMP=$(grep -e "^options[[:space:]]\+scsi_mod[[:space:]]\+" /etc/modules.conf)
	TEMP=$(echo ${TEMP} | sed "s/options[[:space:]]\+scsi_mod[[:space:]]\+//")
	TEMP=$(echo ${TEMP} | sed "s/max_scsi_luns=${MAX_SCSI_LUNS}//")
	if [ ${DISTRIBUTION} = "redhat" ] || [ ${DISTRIBUTION} = "asianux" ] ||
	    [ ${DISTRIBUTION} = "redflag" ] || [ ${DISTRIBUTION} = "miraclelinux" ]; then
	    TEMP=$(echo ${TEMP} | sed "s/scsi_allow_ghost_devices=${SCSI_ALLOW_GHOST_DEVICES}//")
	fi
	TEMP=$(echo ${TEMP} | sed "s/[[:space:]]*//g")
	if [ -z "${TEMP}" ] ; then
	    # The "options scsi_mod" line matches the default that
	    # is written by lpfc-install during installation.
	    # Completely remove it.
	    grep -v -e "^options[[:space:]]\+scsi_mod[[:space:]]\+" ${MODULES_CONF_TEMP} > ${MODULES_CONF_TEMP2}
	    mv -f ${MODULES_CONF_TEMP2} ${MODULES_CONF_TEMP}
	    let RETURN_VALUE=$((${RETURN_VALUE}|1))
	else
	    # The "options scsi_mod" line does not match the
	    # default written by lpfc-install on installation; it
	    # was either modified by lpfc-install during
	    # installation or edited by the user afterwards.
	    # Prompt the user to manually edit the
	    # /etc/modules.conf file.
	    let RETURN_VALUE=$((${RETURN_VALUE}|8))
	fi
    elif [ ${SCSI_MOD_COUNT} -ne 0 ] ; then
	# Multple 'options scsi_mod' lines exist.  Bail.
	let RETURN_VALUE=$((${RETURN_VALUE}|4))
    fi

    if [ $((${RETURN_VALUE} & 1)) -ne 0 ] ; then
	if [ -e /etc/modules.elx ] ; then
	    mv -f ${MODULES_CONF_BACKUP} ${MODULES_CONF_BACKUP}.old
	fi
	cp -f /etc/modules.conf ${MODULES_CONF_BACKUP}
	if [ $? -ne 0 ] ; then
	    echo ""
	    echo "Error backing up /etc/modules.conf"
	    echo ${GENERIC_MESSAGE}
	    exit 130
	fi
	echo "Original saved as ${MODULES_CONF_BACKUP}"
	mv -f ${MODULES_CONF_TEMP} /etc/modules.conf
	if [ $? -ne 0 ] ; then
	    echo ""
	    echo "Error updating /etc/modules.conf"
	    echo ${GENERIC_MESSAGE}
	    exit 140
	fi
    else
	rm -f ${MODULES_CONF_TEMP}
    fi

    return ${RETURN_VALUE}
}

configure_ramdisk()
{
    local RETURN_VALUE
    local NUM_ADAPTERS
    let RETURN_VALUE=0

    echo "Configuring ramdisk..."
    num_adapters
    let NUM_ADAPTERS=$?
    configure_modules_conf ${DRIVER_NAME} ${NUM_ADAPTERS}
    let RETURN_VALUE=$((${RETURN_VALUE} | $?))

    configure_sles_sysconfig_kernel ${DRIVER_NAME}
    let RETURN_VALUE=$((${RETURN_VALUE} | $?))

    return ${RETURN_VALUE}
}

unconfigure_ramdisk()
{
    local RETURN_VALUE
    let RETURN_VALUE=0

    unconfigure_modules_conf ${DRIVER_NAME} ${SMB_DRIVER_NAME}
    let RETURN_VALUE=$((${RETURN_VALUE} | $?))

    unconfigure_sles_sysconfig_kernel ${DRIVER_NAME} ${SMB_DRIVER_NAME}
    let RETURN_VALUE=$((${RETURN_VALUE} | $?))

    return ${RETURN_VALUE}
}

update_lilo()
{
    echo "Updating LILO configuration ..." 
    /sbin/lilo 2>/dev/null 1>/dev/null
    if [ $? -ne 0 ] ; then
	echo "Error installing ramdisk image into LILO configuration file."
	echo ${GENERIC_MESSAGE}
	exit 30;
    fi
}

# Function:  backup_files_to_elx()
#
# Description:
#   Copy each file passed as a parameter to filename.elx.
#
# Parameters:
#   A list of filenames to back up.
#
# Returns:
#   Nothing.
backup_files_to_elx()
{
    for i in $@ ; do
	cp -f $i $i.elx
	if [ $? -ne 0 ] ; then
	    echo "Error $? copying $i to $i.elx"
	else
	    echo "Original ramdisk image $i saved as $i.elx"
	fi
    done
}

# Function:  create_ramdisk()
#
# Description:
#   Creates a ramdisk image for the currently running kernel.
#
# Parameters:
#   none.
#
# Returns:
#   Nothing.
create_ramdisk()
{
    if [ ${DISTRIBUTION} = "redhat" ] || [ ${DISTRIBUTION} = "asianux" ] ||
	[ ${DISTRIBUTION} = "redflag" ] || [ ${DISTRIBUTION} = "miraclelinux" ]; then
	# Configure ramdisk for Red Hat Linux.
	backup_files_to_elx ${INITRDFILE}
	echo -n "Creating ramdisk ."
	exec_command "/sbin/mkinitrd -f ${INITRDFILE} ${UNAME}" background
	if [ $? -ne 0 ] ; then
	    echo "Could not create ramdisk image.  Restoring original ramdisk ..."
	    cp -f /boot/initrd-${UNAME}.img.elx /boot/initrd-${UNAME}.img
	    echo "Original ramdisk restored."
	    echo ""
	    echo "Please run '${INSTALL_SCRIPT} --uninstall' to remove any partially"
a	    echo "installed components of the Emulex driver and utility applications."
	    exit 40
	fi
    else
	# Configure ramdisk configuration file for SuSE Linux Enterprise Server.
	backup_files_to_elx ${INITRDFILE}

	echo -n "Creating ramdisk ."
	if [ ${ARCH} = "i386" ] ; then
	    exec_command "/sbin/mk_initrd -i initrd-${UNAME} -k ${SLES_KERNEL_IMAGE}-${UNAME} >/dev/null 2>&1" background
	else
	    exec_command "/sbin/mk_initrd -i initrd -k ${SLES_KERNEL_IMAGE} >/dev/null 2>&1" background
	fi
	if [ $? -ne 0 ] ; then
	    echo "Could not create ramdisk image.  Restoring original ramdisk ..."
	    cp -f /boot/initrd.shipped.elx /boot/initrd.shipped && cp -f /boot/initrd.elx /boot/initrd
	    if [ $? -ne 0 ] ; then
		echo "Original ramdisks restored."
	    else
		echo "Original ramdisks could not be restored - error $?"
	    fi
	    echo ""
	    echo "Please run '${INSTALL_SCRIPT} --uninstall' to remove any partially"
	    echo "installed components of the Emulex driver and utility applications."
	    exit 40
	fi
    fi
    depmod
    if [ ${ARCH} = "ppc64" ] && [ ${DISTRIBUTION} = "suse" ] ; then
	update_lilo
    fi

    return 0
}

# Function:  examine_build_configuration()
#
# Description:
#   Examines the system to verify that source package for the
#   currently running kernel and the gcc package are installed.
#
# Parameters:
#   none.
#
# Returns:
#   0 - The system is ready for installation of the LPFC driver.
#   1 - The kernel source needs to be installed.
#   2 - The gcc compiler package needs to be installed.
#   3 - Both the kernel source and gcc need to be installed.
examine_build_configuration()
{
    echo "Looking for kernel source ..."
    let ERRORCONDITION=0
    KERNELVERSION=$(rpm -qf ${KERNEL_IMAGE_PATH} --qf %{VERSION}-%{RELEASE})
    if [ $? -ne 0 ] ; then
	let ERRORCONDITION=4
    else
	KERNELSOURCEVERSION=$(rpm -q kernel-source-${KERNELVERSION} 2>/dev/null)
	if [ $? -ne 0 ]
	    then
	    let ERRORCONDITION=1
	fi
    fi

    echo "Looking for compilers ..."
    GCCVERSION=$(rpm -q --qf %{VERSION}-%{RELEASE} gcc)
    if [ $? -ne 0 ]
	then
	if [ ${ERRORCONDITION} -eq 0 ]
	    then
	    let ERRORCONDITION=2
	else
	    let ERRORCONDITION=3
	fi
    fi

    if [ ${ERRORCONDITION} -eq 1 ] ; then
	echo ""
	echo "RPM cannot be installed: kernel source package is required."
	let NEED_SOURCE_PACKAGE=1
        return 1
    elif [ ${ERRORCONDITION} -eq 2 ] ; then
	echo ""
	echo "RPM cannot be installed: gcc package is required."
	let NEED_GCC_PACKAGE=1
	return 2
    elif [ ${ERRORCONDITION} -eq 3 ] ; then
	echo "RPM cannot be installed ; kernel source and gcc packages are required."
	let NEED_SOURCE_PACKAGE=1
	let NEED_GCC_PACKAGE=1
	return 3
    elif [ ${ERRORCONDITION} -eq 4 ] ; then
	echo "RPM cannot be installed: kernel version could not be determined."
	return 4
    fi

    return 0
}

# Function:  install_rpm()
#
# Description:
#   Installed the specified RPM package.
#
# Parameters:
#   $1 - Package description.
#   $2 - Package Directory.
#   $3 - Package file name.
#   $4 - Package name.
#
# Returns:
#    0 - RPM successfully installed.
#    2 - A version of the package is already installed.
#    4 - An error occurred during RPM test.
#    5 - An error occurred during RPM installation.
#    6 - Could not find RPM file in specified path.
install_rpm()
{
    INSTALLEDVERSION=$(rpm -q --qf %{VERSION} $4 2>/dev/null)
    if [ $? -eq 0 ] ; then
	return 2
    fi
    echo "Searching for $1 from $2 ..."
    if [ ! -e $2/$3 ] ; then
	echo "Could not find $1 in path $2/$3!"
	return 6
    fi
    rpm -Uhv $2/$3 --test 2>/dev/null 1>/dev/null
    if [ $? -ne 0 ]; then
	echo ""
	echo "Error during RPM test"
	return 4
    else
	echo "Installing package ..."
	rpm -Uhv $2/$3
	if [ $? -ne 0 ]; then
	    echo ""
	    echo "Error during RPM installation"
	    return 5
	else
	    depmod -a
	    DRIVER_INSTALLED=1
	fi
    fi

    return 0
}

# Function:  load_driver()
#
# Description:
#   Load the specified driver.
#
# Parameters:
#   $1 - name of the driver to be loaded.
#   $2 - description of the driver to be loaded.
load_driver()
{
    echo -en "Loading $2 ."
    exec_command "modprobe $1" background
    if [ $? -ne 0 ]; then
	echo ""
	echo "Error loading $2"
	return 1
    fi
}

# Function:  install_dfcdriver_rpm()
#
# Description:
#   Install the ioctl driver RPM.
#
# Parameters:
#   $1 = 0  if driver is to be loaded after installation,
#   $1 != 0 if driver is not to be loaded after installation.
#
# Returns:
#    0 - RPM installed, or version of package currently installed
#         matches version of package to be installed.
#    1 - Error during RPM installation.
#    2 - Old package already installed.
#    3 - The current version of this package is already isntalled.
install_dfcdriver_rpm()
{
    install_rpm "${DFCDRIVER_DESCRIPTION}" "`pwd`/${DRIVER_DIR}" ${DFCDRIVER_RPM} ${DFCRPM_BASENAME}
    RETURNVALUE=$?
    if [ ${RETURNVALUE} -eq 2 ] ; then
	if [ ${INSTALLEDVERSION} = ${DFCDRIVER_VERSION} ] ; then
	    echo "${DFCDRIVER_DESCRIPTION} version ${DFCDRIVER_VERSION} already installed."
	    return 3
	else
	    echo "Another version of the ${DFCDRIVER_DESCRIPTION} is already installed."
	    echo "Please execute '$0 --uninstall' to remove old versions of the"
	    echo "Emulex driver kit."
	    return 2
	fi
    elif [ ${RETURNVALUE} -ne 0 ] ; then
	echo "Error installing LPFC DFC RPM."
	echo ${GENERIC_MESSAGE}
	return 1
    fi
    if [ $1 -eq 0 ] ; then
	load_driver ${DFCDRIVER_NAME} "LPFC DFC Driver"
    fi
    if [ $? -ne 0 ] ; then
	echo "Error loading LPFC DFC driver."
	echo ${GENERIC_MESSAGE}
	return 1
    fi
    return 0
}

setup_custom_config_file()
{
    echo "Using ${CUSTOM_CONFIG_FILE} for lpfc.conf ..."
    cp ${CUSTOM_CONFIG_FILE} ${LPFC_CONF_TEMP}
    if [ $? -ne 0 ] ; then
	echo "Error copying ${CUSTOM_CONFIG_FILE} to ${LPFC_CONF_TEMP}."
	exit 81
    fi
}

remove_custom_config_file()
{
    rm -f ${LPFC_CONF_TEMP}
    if [ $? -ne 0 ] ; then
	echo "Error removing ${LPFC_CONF_TEMP}."
	exit 82
    fi
}

# Function:  install_basedriver_rpm()
#
# Description:
#   Install the base driver RPM.
#
# Parameters:
#   $1 = 0  if driver is to be loaded after installation,
#   $1 != 0 if driver is not to be loaded after installation.
#
# Returns:
#    0 - RPM installed, or version of package currently installed
#         matches version of package to be installed.
#    1 - Error during RPM installation.
#    2 - Old package already installed.
#    3 - The current version of this package is already installed.
install_basedriver_rpm()
{
    if [ -n "${CUSTOM_CONFIG_FILE}" ] ; then
	setup_custom_config_file
    fi
    install_rpm "${DRIVER_DESCRIPTION}" "`pwd`/${DRIVER_DIR}" ${DRIVER_RPM} ${RPM_BASENAME}
    RETURNVALUE=$?
    if [ -n "${CUSTOM_CONFIG_FILE}" ] ; then
	remove_custom_config_file
    fi
    if [ ${RETURNVALUE} -eq 2 ] ; then
	if [ ${INSTALLEDVERSION} = ${DRIVER_VERSION} ] ; then
	    echo "${DRIVER_DESCRIPTION} version ${DRIVER_VERSION} already installed."
	    return 3
	else
	    echo "Another version of the ${DRIVER_DESCRIPTION} is already installed."
	    echo "Please execute '$0 --uninstall' to remove old versions of the"
	    echo "Emulex driver kit."
	    return 2
	fi
    fi
    if [ $1 -eq 0 ] ; then
	load_driver ${DRIVER_NAME} "LPFC Driver"
    fi
    if [ $? -ne 0 ] ; then
	echo ${GENERIC_MESSAGE}
	return 1
    fi
    return 0
}

# Function:  remove_rpm_package()
#
# Description:
#   Remove the specified RPM package if it is installed and if no
#   other packages depend on the virtual packages it provides.
#
# Returns:
#   0 - RPM removed.
#   1 - Error during RPM removal.
#   2 - Other packages depend on the package to be removed.
remove_rpm_package()
{
    local retval

    while [ -n "$1" ]; do
	rpm -q $1 2>/dev/null 1>/dev/null
	if [ $? -eq 0 ] ; then
	    PACKAGES=$(rpm -q --whatrequires $1 2>&1)
	    if [ $? -ne 0 ] ; then
		echo "Removing $2 ..."
		rpm -e $1
		if [ $? -ne 0 ] ; then
		    echo "An error occurred while uninstalling $1"
		    return 1
		fi
	    else
		echo "The following packages depend on $1:"
		echo "${PACKAGES}"
		return 2
	    fi
	fi
	shift
	shift
    done

    return 0
}

remove_file()
{
    if [ -e $1 ] ; then
	rm -f $1
	if [ $? -ne 0 ] ; then
	    echo "An error occurred while removing $1"
	    return 1
	fi
    fi

    return 0
}

remove_dir()
{
    if [ -d $1 ] ; then
	rmdir $1
	if [ $? -ne -0 ] ; then
	    echo "An error occurred while removing $1"
	    return 1
	fi
    fi

    return 0
}

# Function:  unload_driver()
#
# Description:
#   Unload the specified driver if it is loaded and unused.
#
# Parameters:
#   $1 - Name of module to be unloaded.
#
# Returns:
#   0 - module successfully unloaded
#   1 - an error occurred while unloading the module.
#   2 - module is being used and cannot be unloaded.
#   3 - module is being referenced by other modules and cannot be
#       unloaded.
#   4 - module was not loaded.
#   
unload_driver()
{
    LSMOD=$(lsmod | grep -e "^$1\?[[:space:]]\+[[:digit:]]\+[[:space:]]\+[[:digit:]]\+")
    if [ $? -ne 0 ] || [ -z "${LSMOD}" ] ; then
	return 4
    fi

    AWK_MODULE=`echo ${LSMOD} | awk -F '[[:space:]]+' '{ print $1; }'`
    let AWK_USECOUNT=`echo ${LSMOD} | awk -F '[[:space:]]+' '{ print $3; }'`
    AWK_REFERENCES=`echo ${LSMOD} | awk -F '[[:space:]]+' '{ print $4; }'`

    if [ ${AWK_MODULE} != $1 ] ; then
	echo "ERROR - module found is not the module we're looking for."
	echo "AWK_MODULE=${AWK_MODULE}"
	echo "MODULE=$1"
	exit 5150
    fi

    if [ ${AWK_USECOUNT} -eq 0 ] ; then
	if [ -z ${AWK_REFERENCES} ] || [ ${AWK_REFERENCES} = "(unused)" ] ; then
	    rmmod $1
	    if [ $? -ne 0 ] ; then
		echo "An error occurred while unloading $1"
		return 1
	    fi
	else
	    return 3
	fi
    else
	return 2
    fi

    return 0
}

initscript_install()
{
    echo "Installing Emulex DFC driver startup script ..."
    cp ${INITSCRIPT_SOURCE} ${INITSCRIPT_DESTINATION}
    if [ $? -eq 0 ]; then
	if [ ${DISTRIBUTION} = "redhat" ] || [ ${DISTRIBUTION} = "asianux" ] ||
	    [ ${DISTRIBUTION} = "redflag" ] || [ ${DISTRIBUTION} = "miraclelinux" ]; then
	    chkconfig --add ${INITSCRIPT_NAME} && \
		chkconfig --level 2345 ${INITSCRIPT_NAME} on
	else
	    chkconfig --add ${INITSCRIPT_NAME} && \
		chkconfig ${INITSCRIPT_NAME} on
	fi
	if [ $? -eq 0 ] ; then
	    DRIVER_INSTALLED=1
	else
	    echo ""
	    echo "Error installing elxlpfc startup script"
	    echo ${GENERIC_MESSAGE}
	    exit 97
	fi
    else
	echo ""
	echo "Error copying startup script to ${INITSCRIPT_DESTINATION}"
	echo ${GENERIC_MESSAGE}
	exit 95
    fi
}

initscript_uninstall()
{
    if [ -e ${INITSCRIPT_DESTINATION} ] ; then
	echo "Removing Emulex DFC driver startup script ..."
	chkconfig --del ${INITSCRIPT_NAME}
	remove_file "${INITSCRIPT_DESTINATION}" || return 1
    fi

    return 0
}

print_help()
{
    echo ""
    echo "$0 will by default install version ${DRIVER_VERSION} of the"
    echo "Emulex Linux Fibre Channel drivers.  The following options may"
    echo "also be used:"
    echo ""
    echo "-c,--configfile      - Specify lpfc.conf file to use during installation."
    echo "   --configramdisk   - Configure and build a ramdisk image that loads the"
    echo "                        Emulex driver when the system is booted with the"
    echo "                        current kernel."
    echo "   --createramdisk   - Create a new ramdisk image.  Use this option after"
    echo "                        you have modified driver parameters in the"
    echo "                        lpfc.conf file and rebuilt the driver."
    echo "-u,--uninstall       - Uninstall previously installed driver kit."
    echo "   --unconfigramdisk - Configure and build a ramdisk image that does not"
    echo "                        load the Emulex driver when the system is booted"
    echo "                        with the current kernel."
}

get_custom_config_file()
{
    if [ ! -e $2 ] ; then
	echo "Valid LPFC configuration file does not exist at $2."
	echo ${HELP_MESSAGE}
	exit 80
    else
	CUSTOM_CONFIG_FILE=$2
    fi
}

uninstall_kit()
{
    let UNINSTALL_ERRORS=0
    let REBOOT_REQUIRED=0
    let NOREBOOT_REQUIRED=0

    echo "Checking for Emulex driver packages ..."
    rpm -q --quiet ${MULTIPULSE_RPM_BASENAME}
    if [ $? -eq 0 ] ; then
	echo "Please remove the Emulex Multipulse kit and then run"
	echo "'$0 --uninstall' again."
	exit 13
    fi
    remove_rpm_package "${DFCRPM_BASENAME}" 'LPFC DFC Driver source RPM' \
	"${RPM_BASENAME}" "LPFC Driver source RPM" \
	"${SMB_RPM_BASENAME}" "LPFC SMB Driver source RPM"
    case "$?" in
	0)  ;;
	1)  let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1 ;;
	2)  echo "Please remove the dependent packages and then"
	    echo "run '$0 --uninstall' again."
	    exit 12 ;;
	*)  let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1 ;;
    esac

    initscript_uninstall || let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1

    # Remove a bunch of files.
    files=( "/lib/modules/${UNAME}/kernel/drivers/scsi/lpfc/lpfc.o" \
	    "/lib/modules/${UNAME}/kernel/drivers/scsi/lpfc/lpfcdfc.o" \
	    "/lib/modules/${UNAME}/kernel/drivers/scsi/lpfcdfc.o")
    for i in ${files[@]} ; do
	remove_file $i || let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1
    done
#    remove_dir  "/lib/modules/${UNAME}/kernel/drivers/scsi/lpfc/" || let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1

    # Unload a bunch of drivers.
    drivers=(${DFCDRIVER_NAME} ${DRIVER_NAME} ${SMB_DRIVER_NAME})
    for i in ${drivers[@]} ; do
	unload_driver ${i}
	case "$?" in
	    0|4) ;;
	    1)  echo "An error occurred while unloading ${i}."
		let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1 ;;
	    2)  MESGS="${MESGS}\no The ${i} driver is being used and cannot be unloaded."
		let REBOOT_REQUIRED=${REBOOT_REQUIRED}+1 ;;
	    3)  MESGS="${MESGS}\no The ${i} driver is being referenced by other"
		MESGS="${MESGS}\n  modules and cannot be unloaded."
		let REBOOT_REQUIRED=${REBOOT_REQUIRED}+1 ;;
	    *)  echo "An unknown error occurred while uninstalling ${i}."
		let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1 ;;
	esac
    done

    # Perform some SLES-specific processing.
    if [ ${DISTRIBUTION} = "suse" ]; then
	TMPFILE=/tmp/lpfc-uninstall-$$
	cp ${BOOT_FILE} ${TMPFILE}
	sed -e "/# load Emulex lpfcdd driver/d" -e "/modprobe ${DRIVER_NAME}/d"\
	    ${TMPFILE} > ${BOOT_FILE}
	rm ${TMPFILE}
	chmod a+x ${BOOT_FILE}
    fi
    restore_old_driver

    # Rebuild the ramdisk, if necessary.
    local TEMPVALUE
    unconfigure_ramdisk
    let TEMPVALUE=$?
    if [ $((${TEMPVALUE} & 1)) -ne 0 ] ; then
	create_ramdisk
	case "$?" in
	    0) echo "The ramdisk for this kernel has been updated." ;;
	    *) let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1 ;;
	esac
    fi
    if [ $((${TEMPVALUE} & 4)) -ne 0 ] ; then
	MESGS="${MESGS}\no Multiple 'options scsi_mod' lines exist in /etc/modules.conf."
	MESGS="${MESGS}\n  Please remove the redundant lines and then execute:"
	MESGS="${MESGS}\n  ${0} --configramdisk"
	let NOREBOOT_REQUIRED=$((${NOREBOOT_REQUIRED}+1))
    fi
    if [ $((${TEMPVALUE} & 8)) -ne 0 ] ; then
	MESGS="${MESGS}\no The 'options scsi_mod' line in /etc/modules.conf does not"
	MESGS="${MESGS}\n  match the default line that is written by lpfc-install"
	MESGS="${MESGS}\n  when installing the Emulex LPFC Linux driver.  The options"
	MESGS="${MESGS}\n  that the uninstallation process attempted to remove are:"
	MESGS="${MESGS}\n     max_scsi_luns=${MAX_SCSI_LUNS}"
	if [ ${DISTRIBUTION} = "redhat" ] || [ ${DISTRIBUTION} = "asianux" ] ||
	    [ ${DISTRIBUTION} = "redflag" ] || [ ${DISTRIBUTION} = "miraclelinux" ]; then
	    MESGS="${MESGS}\n     scsi_allow_ghost_devices=${SCSI_ALLOW_GHOST_DEVICES}"
	fi
	MESGS="${MESGS}\n  These entries have not been removed because they may be"
	MESGS="${MESGS}\n  used by other modules.  The entries will not negatively"
	MESGS="${MESGS}\n  affect normal performance of the system if they are not"
	MESGS="${MESGS}\n  used; however, if no other modules are using these options,"
	MESGS="${MESGS}\n  then the entries can safely be removed manually."
	let NOREBOOT_REQUIRED=$((${NOREBOOT_REQUIRED}+1))
    fi

    # Check for any uninstall errors.
    local TOTAL_MESSAGES
    let TOTAL_MESSAGES=$((${REBOOT_REQUIRED}+${NOREBOOT_REQUIRED}))
    if [ ${UNINSTALL_ERRORS} -ne 0 ] ; then
	echo ""
	echo "Uninstallation of Emulex drivers was not successful."
	echo "${GENERIC_MESSAGE}"
	exit 10
    elif [ ${TOTAL_MESSAGES} -ne 0 ] ; then
	echo -en "\n${TOTAL_MESSAGES} message"
	if [ ${TOTAL_MESSAGES} -ne 1 ] ; then
	    echo -n "s"
	fi
	echo -e " generated during uninstallation:\n${MESGS}\n"
	if [ ${REBOOT_REQUIRED} -gt 0 ] ; then
	    echo "Please reboot this system to complete the uninstallation"
	    echo "of the Emulex LPFC driver kit."
	    exit 25
	fi
	exit 0
    else
	echo "Uninstallation complete."
	exit 0
    fi
}

install_kit()
{
    check_for_driver_kit || exit 15

    let DRIVER_UNLOADED=0
    let REBOOT_REQUIRED=0
    let NOREBOOT_REQUIRED=0
    let CREATE_RAMDISK=0
    unload_old_drivers
    case "$?" in
	0)
	    ;;
	1|3|5|7)
	    echo ""
	    echo ${GENERIC_MESSAGE}
	    exit 127 ;;
	2|4|6)
	    MESGS="${MESGS}\no An old Emulex Linux LPFC driver could not be unloaded"
	    MESGS="${MESGS}\n  prior to the installation of the new driver kit."
	    let REBOOT_REQUIRED=$((${REBOOT_REQUIRED}+1))
	    let DRIVER_UNLOADED=1
	    ;;
	*)
	    echo ""
	    echo ${GENERIC_MESSAGE}
	    exit 127 ;;
    esac

    backup_old_driver

    examine_build_configuration || {
	if [ ${NEED_SOURCE_PACKAGE} == 1 ] && [ ${NEED_GCC_PACKAGE} == 1 ]
	    then
	    echo ""
	    echo "${INSTALL_SCRIPT} was unable to successfully build and load a driver."
	    echo "Please install the appropriate kernel source code and development"
	    echo "environment, and then re-run ${INSTALL_SCRIPT}"
	    exit 75
	elif [ ${NEED_SOURCE_PACKAGE} == 1 ]
	    then
	    echo ""
	    echo "${INSTALL_SCRIPT} was unable to successfully build and load a driver."
	    echo "Please install the appropriate kernel source code and then re-run"
	    echo "${INSTALL_SCRIPT}"
	    exit 60
	elif [ ${NEED_GCC_PACKAGE} == 1 ]
	    then
	    echo ""
	    echo "${INSTALL_SCRIPT} was unable to successfully build and load a driver."
	    echo "Please install the appropriate development environment, and then"
	    echo "re-run ${INSTALL_SCRIPT}"
	    exit 70
	else
	    echo ${GENERIC_MESSAGE}
	fi
	exit 2    
    }

    # Check if the Multipulse driver is installed before proceeding
    # with the installation of the LPFC driver.
    rpm -q --quiet ${MULTIPULSE_RPM_BASENAME}
    if [ $? -eq 0 ] ; then
	echo "Please remove the Emulex Multipulse kit and then run"
	echo "'$0' again."
	exit 6
    fi

    install_basedriver_rpm ${DRIVER_UNLOADED}
    let RETVAL=$?
    if [ ${RETVAL} -eq 0 ] ; then
	let CREATE_RAMDISK=1
    elif [ ${RETVAL} -ne 3 ] ; then
	exit 2
    fi

    install_dfcdriver_rpm ${DRIVER_UNLOADED}
    let RETVAL=$?
    if [ ${RETVAL} -ne 0 ] && [ ${RETVAL} -ne 3 ] ; then
	exit 2
    fi

    initscript_install || {
	echo ${GENERIC_MESSAGE}
	exit 2
    }

    echo "Package installation complete"

    if [ ${DRIVER_INSTALLED} -ne 0 ] || [ ${CREATE_RAMDISK} -ne 0 ] ; then
	local TEMPVALUE
	configure_ramdisk
	let TEMPVALUE=$?
	if [ $((${TEMPVALUE} & 1)) -ne 0 ] || [ ${CREATE_RAMDISK} -ne 0 ] ; then
	    create_ramdisk
	    case "$?" in
		0)  MESGS="${MESGS}\no The ramdisk for this kernel has been updated."
		    let REBOOT_REQUIRED=$((${REBOOT_REQUIRED}+1)) ;;
		*)  echo "Error creating the ramdisk."
		    exit 40 ;;
	    esac
	fi
	if [ $((${TEMPVALUE} & 2)) -ne 0 ] ; then
	    MESGS="${MESGS}\no The 'options scsi_mod' line in /etc/modules.conf contains"
	    MESGS="${MESGS}\n  an invalid value for the 'scsi_allow_ghost_devices' option."
	    MESGS="${MESGS}\n  The lpfc driver requires this option to have a value of 1."
	    MESGS="${MESGS}\n  Please adjust the configuration of any drivers that require"
	    MESGS="${MESGS}\n  the current value of this option, set this option to '1', and"
	    MESGS="${MESGS}\n  then execute:"
	    MESGS="${MESGS}\n  ${0} --createramdisk"
	    let NOREBOOT_REQUIRED=$((${NOREBOOT_REQUIRED}+1))
	fi
	if [ $((${TEMPVALUE} & 4)) -ne 0 ] ; then
	    MESGS="${MESGS}\no Multiple 'options scsi_mod' lines exist in /etc/modules.conf."
	    MESGS="${MESGS}\n  Please remove the redundant lines and then execute:"
	    MESGS="${MESGS}\n  ${0} --configramdisk"
	    let NOREBOOT_REQUIRED=$((${NOREBOOT_REQUIRED}+1))
	fi
	if [ $((${TEMPVALUE} & 8)) -ne 0 ] ; then
	    MESGS="${MESGS}\no An 'alias scsi_hostadapter off' entry exists in the"
	    MESGS="${MESGS}\n  /etc/modules.conf file.  Please resolve any configuration"
	    MESGS="${MESGS}\n  that depends on this entry, remove the entry, and then"
	    MESGS="${MESGS}\n  execute:"
	    MESGS="${MESGS}\n  ${0} --configramdisk"
	fi
	chmod a+x ${BOOT_FILE}
    fi

    # Installation complete.  Print reboot messages if necessary.
    local TOTAL_MESSAGES
    let TOTAL_MESSAGES=$((${REBOOT_REQUIRED}+${NOREBOOT_REQUIRED}))
    if [ ${TOTAL_MESSAGES} -ne 0 ] ; then
	echo -en "\n${TOTAL_MESSAGES} message"
	if [ ${TOTAL_MESSAGES} -ne 1 ] ; then
	    echo -n "s"
	fi
	echo -e " generated during installation:\n${MESGS}"
	if [ ${REBOOT_REQUIRED} -gt 0 ] ; then
	    echo -e "\nPlease reboot this system to complete the installation"
	fi
	echo "of the Emulex LPFC driver kit."
    else
	echo ""
	echo "Installation complete."
    fi
    if [ ${REBOOT_REQUIRED} -gt 0 ] ; then
	exit 20
    else
	exit 0
    fi
}

echo "Emulex LPFC Driver Installer Version ${INSTALLER_VERSION}"

# Process the parameters
SCRIPT_COMMAND="install"
while [ $# -ne 0 ] ; do
    case "$1" in
	-c|--configfile)
	    get_custom_config_file $1 $2
	    shift
	    ;;
	--configramdisk|configureramdisk)
	    SCRIPT_COMMAND="configramdisk"
	    ;;
	--createramdisk)
	    SCRIPT_COMMAND="createramdisk"
	    ;;
	-h|--help)
	    print_help
	    exit 0
	    ;;
	-u|--uninstall)
	    SCRIPT_COMMAND="uninstall"
	    ;;
	--unconfigramdisk|unconfigureramdisk)
	    SCRIPT_COMMAND="unconfigramdisk"
	    ;;
	--)
	    break
	    ;;
	*)
	    echo "Invalid option - $1"
	    SCRIPT_COMMAND="badoption"
	    ;;
    esac
    shift
done

# Exit if an invalid parameter was specified by the user.
if [ -n "${SCRIPT_COMMAND}" ] && [ ${SCRIPT_COMMAND} = "badoption" ] ; then
    echo ${HELP_MESSAGE}
    exit 5
fi
    
echo "Determining distribution type and kernel version ..."

if ! get_distribution; then
   echo ${GENERIC_MESSAGE}
   exit 1
fi

# cd to the package directory
cd ${0%/*}

if [ -z "${SCRIPT_COMMAND}" ] ; then
    echo "Fatal error - SCRIPT_COMMAND has no value."
    exit 255
elif [ ${SCRIPT_COMMAND} = "uninstall" ] ; then
    uninstall_kit
elif [ ${SCRIPT_COMMAND} = "install" ] ; then
    install_kit
elif [ ${SCRIPT_COMMAND} = "createramdisk" ] ; then
    create_ramdisk
    case "$?" in
	0)
	    echo "The ramdisk for this kernel has been updated."
	    ;;
	*)
	    echo "Error creating a ramdisk image for the running kernel."
	    exit 47
	    ;;
    esac
elif [ ${SCRIPT_COMMAND} = "configramdisk" ] ; then
    configure_ramdisk
	let TEMPVALUE=$?
	if [ $((${TEMPVALUE} & 1)) -ne 0 ] ; then
	    create_ramdisk
	    case "$?" in
		0)
		    echo "The ramdisk for this kernel has been updated."
		    ;;
		*)
		    echo "Error creating ramdisk image for the running kernel."
		    exit 40
		    ;;
	    esac
	fi
	if [ $((${TEMPVALUE} & 2)) -ne 0 ] ; then
	    echo "The 'options scsi_mod' line in /etc/modules.conf contains"
	    echo "an invalid value for the 'scsi_allow_ghost_devices' option."
	    echo "The lpfc driver requires this option to have a value of 1."
	    echo "Please adjust the configuration of any drivers that require"
	    echo "the current value of this option, set this option to '1', and"
	    echo "then execute:"
	    echo "${0} --createramdisk"
	fi
	if [ $((${TEMPVALUE} & 4)) -ne 0 ] ; then
	    echo "Multiple 'options scsi_mod' lines exist in /etc/modules.conf."
	    echo "Please remove the redundant lines and then execute:"
	    echo "  ${0} --configramdisk"
	fi
	if [ $((${TEMPVALUE} & 8)) -ne 0 ] ; then
	    echo "An 'alias scsi_hostadapter off' entry exists in the"
	    echo "/etc/modules.conf file.  Please resolve any configuration"
	    echo "that depends on this entry, remove the entry, and then"
	    echo "execute:"
	    echo "  ${0} --configramdisk"
	fi
elif [ ${SCRIPT_COMMAND} = "unconfigramdisk" ] ; then
    unconfigure_ramdisk
    let TEMPVALUE=$?
    if [ $((${TEMPVALUE} & 1)) -ne 0 ] ; then
	create_ramdisk
	case "$?" in
	    0) echo "The ramdisk for this kernel has been updated." ;;
	    *) let UNINSTALL_ERRORS=${UNINSTALL_ERRORS}+1 ;;
	esac
    fi
    if [ $((${TEMPVALUE} & 4)) -ne 0 ] ; then
	echo "Multiple 'options scsi_mod' lines exist in /etc/modules.conf."
	echo "Please remove the redundant lines and then execute:"
	echo "  ${0} --configramdisk"
    fi
    if [ $((${TEMPVALUE} & 8)) -ne 0 ] ; then
	echo "The 'options scsi_mod' line in /etc/modules.conf does not"
	echo "match the default line that is written by lpfc-install"
	echo "when installing the Emulex LPFC Linux driver.  The options"
	echo "that the uninstallation process attempted to remove are:"
	echo "    max_scsi_luns=${MAX_SCSI_LUNS}"
	if [ ${DISTRIBUTION} = "redhat" ] || [ ${DISTRIBUTION} = "asianux" ] ||
	    [ ${DISTRIBUTION} = "redflag" ] || [ ${DISTRIBUTION} = "miraclelinux" ]; then
	    echo "    scsi_allow_ghost_devices=${SCSI_ALLOW_GHOST_DEVICES}"
	fi
	echo "These entries have not been removed because they may be"
	echo "used by other modules.  The entries will not negatively"
	echo "affect normal performance of the system if they are not"
	echo "used; however, if no other modules are using these options,"
	echo "then the entries can safely be removed manually."
    fi
else
    echo "Fatal error - invalid value for SCRIPT_COMMAND."
    exit 255
fi

exit 0
