#!/bin/bash
#
# **********************************************************************
# *                                                                    *
# *       Top Level Control of the RDA SubSystem of PCI Boards         *
# *                                                                    *
# **********************************************************************
# File: rda/kernelmod/rdasys
#
#                 COPYRIGHT (c) 2003, 2004, 2009 BY
#            VAISALA INC., WESTFORD MASSACHUSETTS, U.S.A.
# 
# THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
# ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
# INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
# COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
# OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
# TRANSFERED.
#
# chkconfig: 345 95 04
# description: rda module loader for RVP8/RCP8
#

### BEGIN INIT INFO
# Provides: rdasys
# Required-Start:
# Required-Stop:
# Default-Stop: 0 1 6
# Short-Description: Rebuilds and loads rvp kernel module
# Description:  Rebuilds and loads Vaisala rvp kernel module
### END INIT INFO

# Include utilities from functions
. /etc/init.d/functions
. /etc/sigmet/profile.conf
. /etc/profile.d/sigmet.sh

# Define variables
DEVDIR="/dev/rda"
PROC_NODEINFO="/proc/driver/rda/nodeinfo"
PROC_VERSION="/proc/driver/rda/version"
PROC_RECONFIG="/proc/driver/rda/reconfig"
PROC_CONSPACE="/proc/driver/rda/configspace"
RDA_SRC="${install_root}/src/rda"
SIG_SRC="${install_root}/src"
IRIS_INCLUDE="${IRIS_ROOT}/include"
IRIS_BIN="${install_root}/bin"
RDA_BIN="${install_root}/bin"
LOCK_FILE="rdasys"

# Function to rebuild a kernel module

rebuild_kernel() {
# If there is no kernel module found in the system
# this function will generate  one

# Check if the kernel-dev rpm is installed

/bin/rpm -qa | grep kernel | grep devel > /dev/null
 if [ $? -ne 0 ] ; then
   echo "No kernel devel rpm found"
   echo_failure
   echo
   exit 1
 fi

 if [ -d ${RDA_SRC} ]
   then
   mkdir /tmp/src
   cp  -r ${RDA_SRC} /tmp/src/rda
   cp ${SIG_SRC}/config.mk /tmp/src/
   cd /tmp/src/rda/kernelmod
   make clean > /dev/null 
   make > /dev/null 
   make install > /dev/null 
   rm -rf /tmp/src
 else
  echo "No RDA source installed"
  echo_failure
  echo
  exit 1
 fi
}

start() {  
    # Try to locate the driver and insert it into the kernel.  First
    # preference is to check the current directory, either for the
    # fully qualified (versioned) module name.  If not
    # found, then check IRIS_BIN.
    #
    KERNVER="`uname -r`" ; KERNMAJOR="`echo ${KERNVER} | cut -d. -f -2`"

    RDANAME="`lsmod | egrep '^rda-|^rda ' | sed 's/ .*//'`"
    if [ "${RDANAME}" != "" ] ; then
	echo "Driver rda is loaded already!"
	echo_failure
	echo
	touch /var/lock/subsys/${LOCK_FILE}
	exit 1	
    fi

    if [ -f /var/lock/subsys/${LOCK_FILE} ] ; then
	rm /var/lock/subsys/${LOCK_FILE}
    fi

    RDANAME="rda-${KERNVER}.ko"

    if   [ -r ./${RDANAME}           ] ; then RDAPATH="./${RDANAME}"
    elif [ -r ${IRIS_BIN}/${RDANAME} ] ; then RDAPATH="${IRIS_BIN}/${RDANAME}"
    else
      rebuild_kernel
      RDAPATH="${IRIS_BIN}/${RDANAME}"
    fi

    TMP="/tmp/tmprda" ; rm -f ${TMP}
    DASHO=""
    /sbin/insmod -f ${RDAPATH} ${DASHO} 2>${TMP} ; EXITSTS="$?"
    grep -v "taint the kernel" < ${TMP} 1>&2 ; rm -f ${TMP}
    if [ "${EXITSTS}" != "0" ] ; then
      echo "INSMOD failed on ${RDAPATH}" 1>&2
      echo_failure
      echo
      exit 1
    fi

    # Get the major number of the driver by locating the RDA entry in
    # the list of character devices.  This allows us to use dynamic
    # major numbers in the driver.
    #
    MAJOR=`cat /proc/devices | awk "\\$2==\"rda\" {print \\$1}"`
    if [ "${MAJOR}" = "" ] ; then
      echo "Could not get major number of RDA driver" 1>&2 
      echo_failure
      echo
      exit 1
    else
      echo "Using RDA kernel module: ${RDAPATH}"
    fi

    # Verify that the /proc filesystem was properly created, and use
    # the NODEINFO entry to create all of the device files for the RDA
    # subsystem.  This is how dynamic minor numbers are assigned.
    #
    if [ ! -r ${PROC_NODEINFO} ] ; then
      echo "Could not locate ${PROC_NODEINFO} entry" 1>&2
      echo_failure
      echo
      exit 1
    else
      LBOOTPAGE="false"
      /bin/rm -rf ${DEVDIR} ; mkdir ${DEVDIR} ; chmod 775 ${DEVDIR}
      for ITEM in `cat ${PROC_NODEINFO} | tr ' ' '~'` ; do
        NODENAME="${ITEM%~*}" ; MINOR="${ITEM#*~}" ; BOARDTYPE="${NODENAME%%-*}"

	/bin/mknod --mode=666 "${DEVDIR}/${NODENAME}" c ${MAJOR} ${MINOR}

	# Also create TTY FIFO entries for certain types of boards
	#
	# if [ "${BOARDTYPE}" = "io62" ] ; then
	#   for SUFFIX in 0-x 0-y 0-info 1-x 1-y 1-info ; do
	#     mkfifo --mode=666 "${DEVDIR}/${NODENAME}-tty${SUFFIX}"
	#   done
	# fi

	# By default, reboot the FPGA chips on all of the PCI cards.
	# The "startNoBoot" option still allows us to start up in a
	# development setting without reloading the FPGAs.
	#
	if [ "$1" != "startNoBoot" -a "${BOARDTYPE}" = "slot" ] ; then
	  ${RDA_BIN}/rdaport -bootPage ${NODENAME} 0 ; LBOOTPAGE="true"
	fi
      done

      # If we've reconfigured the PCI cards, then sleep briefly just
      # to make sure they are all fully functional.  Then reload the
      # PCI bus information that the kernel retrieved from the card
      # when it was first opened, but which has now been blown away.
      #
      if [ "${LBOOTPAGE}" = "true" ] ; then
        sleep 1.0 ; echo "reconfig" > ${PROC_RECONFIG}
      fi
    fi

    # Print the version of the module that was just installed
    #
    if [ ! -r ${PROC_VERSION} ] ; then
      echo "Could not locate ${PROC_VERSION} entry" 1>&2
      echo_failure
      echo
      exit 1
    else
      echo_success
      echo "Loaded `cat ${PROC_VERSION}`"
      touch /var/lock/subsys/${LOCK_FILE}
      echo
    fi
}

stop() {
    # Remove the RDA driver from the kernel (if, indeed, it is loaded
    # now), and delete all of the device nodes.
    #
    RDANAME="`lsmod | egrep '^rda-|^rda ' | sed 's/ .*//'`"
    if [ "${RDANAME}" != "" ] ; then
      /sbin/rmmod ${RDANAME}
      if [ "$?" != "0" ] ; then
        echo "RMMOD failed to remove '${RDANAME}'" 1>&2
        echo_failure
        echo
        exit 1
      else
      echo_success
      echo "Stop RDA ...."
      echo
     fi
    rm -f /var/lock/subsys/${LOCK_FILE}
    rm -rf ${DEVDIR}
    fi
}

testbusy() {
    # Test whether any of the PCI cards are busy right now, i.e.,
    # whether any of them have a nonzero open count.  Exit status is
    # zero if busy.
    #
    RETVAL=`egrep 'Opens:[^0]' ${PROC_CONSPACE}`
    if [ ! -z "$RETVAL" ] ; then
    echo "Busy PCI card(s):"
    echo "${RETVAL}"
    else
    echo "No Busy PCI card(s)"
    fi 
}

reconfig() {
    # Reload the volatile PCI configuration space of all RDA devices,
    # to match the values that were seen when the driver was first
    # started.  This permits power cycling and dynamic reconfiguration
    # of the FPGA chips without the need to reboot each time.
    #
    if [ ! -w ${PROC_RECONFIG} ] ; then
      echo "Could not locate ${PROC_RECONFIG} entry" 1>&2 ; exit 1
      echo_failure
      echo
    else
      echo "reconfig" > ${PROC_RECONFIG}
      echo_success
      echo
    fi
}

version() {
    if [ ! -r ${PROC_VERSION} ] ; then
      echo "Could not locate ${PROC_VERSION} entry" 1>&2 ; exit 1
    else
      cat ${PROC_VERSION}
    fi
}




# See how we were called
#
case "$1" in
  start|startNoBoot)
    start
    ;;

  stop)
    stop
    ;;

  reconfig)
    reconfig
    ;;

  testbusy)
    testbusy
    ;;

  version)
    version
    ;;

  *)
    echo $"Usage: $0 {start|stop|reconfig|version|startNoBoot|testbusy}"
    exit 1
esac
