#!/bin/sh

# (C) Copyright 2000-2005 Hewlett-Packard Development Company, L.P.

chatter() {
	if test "$1" = "verbose"; then
		echo $2
	fi
}

startup_helper() {
	if [ -f /opt/compaq/cpqci/driver/$1.${MOD_EXT} ]; then
		log_msg "Loading the hp ProLiant Channel Interface Driver . . ."
		/sbin/insmod /opt/compaq/cpqci/driver/$1.${MOD_EXT} >> $HPRSM_LOGFILE 2>&1
		chatter $2 "..$1 started."
	fi
}

stopit_helper() {
	log_msg "Stopping the hp ProLiant Channel Interface Driver"
	if eval "/sbin/rmmod $1 > /dev/null 2> /dev/null"; then
		chatter $2 "..$1 stopped."
		log_msg "..$1 stopped."
	else
		LS_MOD=`lsmod | fgrep $1`
		if [ ${#LS_MOD} -eq 0 ]; then
			exit 0
		fi
		chatter $2 "..$1 busy."
		log_msg "..$1 busy."
		exit -1
	fi
}

stopit() {
	stopit_helper ${DRIVER_NAME} $1
	rm -f /var/lock/subsys/cpqci
	rm -rf /dev/cpqci
}

startup() {
	startup_helper ${DRIVER_NAME} $1
	touch /var/lock/subsys/cpqci
	mknod /dev/cpqci c 10 209 >/dev/null 2>&1
	chatter $1 "...done. Please type 'man cpqci' for more information."
}

kernel_src_avail() {
	THIS_KERNEL=`uname -r`
	echo "Looking for sources to build ${THIS_KERNEL}"
	ls -ld /lib/modules/${THIS_KERNEL}/build > /dev/null
	[ $? != 0 ] && {
		echo "/lib/modules/${THIS_KERNEL}/build does not exist"
		echo "This is an indication that the sources for this kernel (${THIS_KERNEL}) are not loaded."
		echo "Please load the appropriate sources to rebuild module."
		exit 1
	}

#
# We need to make sure that "version.h" exists.  This is a problem on SLES7
#
        ls /lib/modules/${THIS_KERNEL}/build/include/linux/version.h > /dev/null
	[ $? != 0 ] && {
                ls /boot/vmlinuz.version.h > /dev/null
                [ $? -eq 0 ] && {
                        cp /boot/vmlinuz.version.h /lib/modules/${THIS_KERNEL}/build/include/linux/version.h
                } || {
                        echo "/lib/modules/${THIS_KERNEL}/build/include/linux/version.h does not exist"
                        echo "Please load the appropriate sources to rebuild module".
                        exit 1
                }

        }

#
# We need to make sure that "autoconf.h" exists.  This is a problem on SLES7
#
   ls /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h > /dev/null
   [ $? != 0 ] && {
      ls /boot/vmlinuz.autoconf.h > /dev/null
      [ $? -eq 0 ] && {
                        cp /boot/vmlinuz.autoconf.h /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h
                } || {
                        echo "/lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h does not exist"
                        echo "Please load the appropriate sources to rebuild module".
                        exit 1
                }

        }
#
# We now need to make sure that the version.h file matches the kernel
# we are trying to build.
#
        fgrep ${THIS_KERNEL} /lib/modules/${THIS_KERNEL}/build/include/linux/version.h > /dev/null
        [ $? != 0 ] && {
                echo "/lib/modules/${THIS_KERNEL}/build/include/linux/version.h does not match"
                echo "the version of this kernel (${THIS_KERNEL})."
                echo "This is an indication that a patch has been loaded but not the sources"
                echo "to match the running kernel.  This driver requires the sources to all"
                echo "kernel patches to be loaded in order to relink to the kernel symbols"
# 
#       We will now try to see if this is a SLES 7 system that might have
#  been patched.
#
                ls /boot/vmlinuz.version.h > /dev/null
                [ $? -eq 0 ] && {
                        fgrep ${THIS_KERNEL} /boot/vmlinuz.version.h > /dev/null
                        [ $? -eq 0 ] && {
                                echo "This appears to be a patched kernel and the correct files are located in the \"/boot\" directory"
                                echo "Making a backup of /lib/modules/${THIS_KERNEL}/build/include/linux/version.h to"
                                echo "                   /lib/modules/${THIS_KERNEL}/build/include/linux/version.h.ORIGINAL"
                                mv /lib/modules/${THIS_KERNEL}/build/include/linux/version.h /lib/modules/${THIS_KERNEL}/build/include/linux/version.h.ORIGINAL
                                echo "Making a backup of /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h to"
                                echo "                   /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h.ORIGINAL"
                                mv /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h.ORIGINAL
                                echo "Copying /boot/vmlinuz.version.h to /lib/modules/${THIS_KERNEL}/build/include/linux/version.h"
                                cp /boot/vmlinuz.version.h /lib/modules/${THIS_KERNEL}/build/include/linux/version.h

                                echo "Copying /boot/vmlinuz.autoconf.h to /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h"
                                cp /boot/vmlinuz.autoconf.h /lib/modules/${THIS_KERNEL}/build/include/linux/autoconf.h

                        } || {
                                echo "There does not appear to be kernel sources which match the current booting Linux kernel"
                                echo "There must be a directory named \"/lib/modules/${THIS_KERNEL}\" and there must be a"
                                echo "valid directory linked to \"/lib/modules/${THIS_KERNEL}/build\"."
                                echo "Please load the appropriate Linux sources to rebuild module".
                                exit 1
                        }

                } || {
                        exit 1
                }

        }

}

rebuild() {
	MACH=`uname -m`
	if [ "$MACH" = "x86_64" ]; then
		export OS_MEM="-mcmodel=kernel"
	fi
	if [ "$K_VER" = "6" ]; then
		echo "Building custom cpqci driver"
		cd /opt/compaq/cpqci/custom

		if [ -f /lib/modules/${OS_VER}/build/include/linux/mm.h ]; then
			F=/lib/modules/${OS_VER}/build/include/linux/mm.h 
		elif [ -f /lib/modules/${OS_VER}/source/include/linux/mm.h ]; then
			F=/lib/modules/${OS_VER}/source/include/linux/mm.h 
		fi
		if [ -n "$F" ]
		then
			D=`cat $F | grep remap_pfn_range`
		fi
		if [ -n "$D" ]
		then
        		export EXTRA_CFLAGS="-DMREMAP_PFN_RANGE"
		fi
		make clean > /dev/null 2>/dev/null
		make > /dev/null 2>/dev/null
		if [ "$MACH" = "x86_64" ]; then
			make -e LD_OPT=elf_x86_64 TARGETDIR=./ all > /dev/null 2>/dev/null
		else
			make -e TARGETDIR=./ all > /dev/null 2>/dev/null
		fi
	else
		kernel_src_avail
		cd /opt/compaq/cpqci/custom
		A=`cat /lib/modules/${OS_VER}/build/include/linux/mm.h | grep do_munmap | cut -f 4 -d ','`
		if [ -n "$A" ]
		then
        		export OS_MUNMAP4="-DMUNMAP4"
		fi
		B=`cat /lib/modules/${OS_VER}/build/include/linux/mm.h | grep remap_page_range | cut -f 5 -d ','`
		if [ -n "$B" ]
		then
        		export OS_MREMAP5="-DMREMAP_PAGE_RANGE"
		fi

		C=`cat /lib/modules/${OS_VER}/build/include/linux/timer.h | grep entry`
		if [ -n "$C" ]
		then
        		export OS_TIMER2_6="-DCPQCI_TIMER_FLAG"
		fi

	
		make -f linux.mk TARGETDIR=./ clean all > /dev/null 2> /dev/null
	fi
}



copyorfixup() {
	if [ "$REBUILD_MODULE" = "FALSE" ]; then
		if [ "$MOD_EXT" = "o" ]; then
			if eval "insmod -p /opt/compaq/cpqci/driver/${OS_SMP}/$1.${MOD_EXT} > /dev/null 2> /dev/null"; then
				cp /opt/compaq/cpqci/driver/${OS_SMP}/$1.${MOD_EXT} /opt/compaq/cpqci/driver/$1.${MOD_EXT} >/dev/null 2>&1
				echo "$OS_VER" > /opt/compaq/cpqci/driver/kernel.txt
			elif eval "insmod -p /opt/compaq/cpqci/custom/$1.${MOD_EXT} > /dev/null 2> /dev/null"; then
				cp /opt/compaq/cpqci/custom/$1.${MOD_EXT} /opt/compaq/cpqci/driver/$1.${MOD_EXT}
				echo "$OS_VER" > /opt/compaq/cpqci/driver/kernel.txt
			else
				LS_MOD=`lsmod | fgrep $1`
				if [ ${#LS_MOD} -eq 0 ]; then
					echo "Linux Kernel Symbol Conflict - Attempting to rebuild to resolve"
					log_msg "Linux Kernel Symbol Conflict - Attempting to rebuild cpqci to resolve"
					REBUILD_MODULE=TRUE
				fi
			fi
		else
			/sbin/insmod /opt/compaq/cpqci/driver/${OS_SMP}/$1.${MOD_EXT} > /dev/null 2> /dev/null
			LS_MOD=`lsmod | fgrep $1`
			if [ ${#LS_MOD} -eq 0 ]; then
				/sbin/insmod /opt/compaq/cpqci/custom/${OS_SMP}/$1.${MOD_EXT} > /dev/null 2> /dev/null
				LS_MOD=`lsmod | fgrep $1`
				if [ ${#LS_MOD} -eq 0 ]; then
					echo "Linux Kernel Symbol Conflict - Attempting to rebuild to resolve"
					log_msg "Linux Kernel Symbol Conflict - Attempting to rebuild cpqci to resolve"
					REBUILD_MODULE=TRUE
				else
					cp /opt/compaq/cpqci/custom/$1.${MOD_EXT} /opt/compaq/cpqci/driver/$1.${MOD_EXT}
					echo "$OS_VER" > /opt/compaq/cpqci/driver/kernel.txt
				fi
			else
				cp /opt/compaq/cpqci/driver/${OS_SMP}/$1.${MOD_EXT} /opt/compaq/cpqci/driver/$1.${MOD_EXT} >/dev/null 2>&1
				echo "$OS_VER" > /opt/compaq/cpqci/driver/kernel.txt
			fi
		fi
		MODINFO="`modinfo -d /opt/compaq/cpqci/driver/$1.${MOD_EXT} 2>/dev/null`"
		if [[ ! -z "$MODINFO" && "$MODINFO" != "<none>" && "${REBUILD_MODULE}" = "FALSE" ]]
		then
			echo "$MODINFO" | tr -d '"' | md5sum --check --status 2> /dev/null > /dev/null
			if [ $? -ne 0 ]
			then
				log_msg "Linux Kernel Checksum Conflict - Attempting rebuild to resolve."
				echo "Linux Kernel Checksum Conflict - Attempting rebuild to resolve."
				rm -f /opt/compaq/cpqci/driver/$1.${MOD_EXT}
				REBUILD_MODULE=TRUE
			fi
		fi
	fi

        if [ "${REBUILD_MODULE}" = "TRUE" ]
        then
		rebuild
		if [ -f /opt/compaq/cpqci/custom/$1.${MOD_EXT} ]; then
			if eval "insmod -p /opt/compaq/cpqci/custom/$1.${MOD_EXT} > /dev/null 2> /dev/null"; then
				echo "Rebuild successful."
				log_msg "Rebuild of cpqci successful."
				cp /opt/compaq/cpqci/custom/$1.${MOD_EXT} /opt/compaq/cpqci/driver/$1.${MOD_EXT}
				echo "$OS_VER" > /opt/compaq/cpqci/driver/kernel.txt
			else
				LS_MOD=`lsmod | fgrep $1`
				if [ ${#LS_MOD} -eq 0 ]; then
					echo "cpqci rebuilt, but failed to load."
					log_msg "cpqci failed to load after rebuild."
				else
					echo "Rebuild successful."
					log_msg "Rebuild of cpqci successful."
					cp /opt/compaq/cpqci/custom/$1.${MOD_EXT} /opt/compaq/cpqci/driver/$1.${MOD_EXT}
				fi
			fi
		else
			echo "Failed to rebuild for custom kernel."
			log_msg "Rebuild of cpqci failed."
		fi
	fi
}

log_msg() {
        echo "$*" >> $HPRSM_LOGFILE
}

HPRSM_LOGFILE=/opt/compaq/hprsm/hprsm_boot.log
DRIVER_NAME="cpqci"
OS_VER=`uname -r`
K_VER=`uname -r | awk -F. '{ print $2 }'`
REBUILD_MODULE=FALSE
OS_SMP=""
OS_RUN=""

# There is now the possibility of the open source version
# of the channel driver being present.  If so, we simply
# exit.
LS_MOD=`lsmod | fgrep hpqci`
if [ ${#LS_MOD} -ne 0 ]; then
	log_msg "The GPL version of the Channel Interface Driver is loaded."
	exit 0
fi

# The module matching the runtime kernel was saved here 
if [ -f /opt/compaq/cpqci/driver/kernel.txt ]; then
	CUSTOM_KERN=`cat /opt/compaq/cpqci/driver/kernel.txt`
else
	CUSTOM_KERN=""
fi

# Figure out what type of module is to be loaded (2.4 vs 2.6 kernel)
if [ "$K_VER" = "6" ]; then
	MOD_EXT="ko"
else
	MOD_EXT="o"
fi

# Rebuild if the saved module does not exist or match the runtime kernel
if [ "$CUSTOM_KERN" != "$OS_VER" ]; then
	REBUILD_MODULE=TRUE
fi

# Figure out if the prebuilt binaries match the running kernel
for DIR in `ls /opt/compaq/cpqci/driver`; do
	if [ -f /opt/compaq/cpqci/driver/$DIR/kernel.txt ]; then
		VER=`cat /opt/compaq/cpqci/driver/$DIR/kernel.txt`
		if [ "$VER" = "$OS_VER" ]; then
			OS_SMP="$DIR"
			REBUILD_MODULE=FALSE
			break
		fi
	fi
done

if test "$1" = "stop"; then
	stopit $2
	exit 0
fi

if test "$1" = "start"; then
	if [ ! -f /opt/compaq/cpqci/driver/${DRIVER_NAME}.${MOD_EXT} ]; then
		OS_RUN="init"
	elif [ "$CUSTOM_KERN" != "$OS_VER" ]; then
		OS_RUN="init"
	else
		startup $2
		LS_MOD=`lsmod | fgrep ${DRIVER_NAME}`
		if [ ${#LS_MOD} -eq 0 ]; then
			OS_RUN="init"
		else
			exit 0
		fi
	fi
fi

if test "$1" = "rebuild"; then
	rebuild
	cp /opt/compaq/cpqci/custom/${DRIVER_NAME}.${MOD_EXT} /opt/compaq/cpqci/driver/${DRIVER_NAME}.${MOD_EXT}
	echo "$OS_VER" > /opt/compaq/cpqci/driver/kernel.txt
fi

if test "$OS_RUN" != "init"; then
	if test "$1" != "init"; then
		exit -1	
	fi
fi

copyorfixup ${DRIVER_NAME}
if [ "`echo $CMANOSTARTINSTALL | tr [a-z] [A-Z]`" != "YES" ]; then
	startup_helper ${DRIVER_NAME} $2
fi

touch /var/lock/subsys/cpqci
/sbin/depmod -a -e  > /dev/null 2> /dev/null
