#!/bin/ksh
#
# **********************************************************************
# *                                                                    *
# *       Top Level Control of the RDA SubSystem of PCI Boards         *
# *                                                                    *
# **********************************************************************
# File: rda/kernelmod/rdasys
#
#                    COPYRIGHT (c) 2003, 2004 BY
#          SIGMET INCORPORATED, 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 5
# description: rda module loader for RVP8/RCP8
#
if [ -r /usr/sigmet/config/profile ] ; then . /usr/sigmet/config/profile ; fi

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"

# See how we were called
#
case "$1" in
  # ==================================================
  # =============== Startup Routine ==================
  # ==================================================
  start|startNoBoot)
    # 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, or for 'rda.o'.  If not
    # found, then check IRIS_BIN/rda.
    #
    KERNVER="`uname -r`" ; RDANAME="rda-${KERNVER}.o"
    if   [ -r ./${RDANAME}              ] ; then RDAPATH="./${RDANAME}"
    elif [ -r ./rda.o                   ] ; then RDAPATH="./rda.o"
    elif [ -r ${IRIS_BIN}rda/${RDANAME} ] ; then RDAPATH="${IRIS_BIN}rda/${RDANAME}"
    elif [ -r ${IRIS_BIN}rda/rda.o      ] ; then RDAPATH="${IRIS_BIN}rda/rda.o"
    else
      echo "Can not locate kernel module ${RDANAME}" 1>&2 ; exit 1
    fi

    TMP="/tmp/tmprda" ; rm -f ${TMP}
    /sbin/insmod -f ${RDAPATH} -o rda 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 ; 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 ; 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 ; exit 1
    else
      LBOOTPAGE="false"
      rm -rf ${DEVDIR} ; mkdir ${DEVDIR} ; chmod 775 ${DEVDIR}
      for ITEM in `cat ${PROC_NODEINFO} | tr ' ' '~'` ; do
        NODENAME="${ITEM%~*}" ; MINOR="${ITEM#*~}" ; BOARDTYPE="${NODENAME%%-*}"

	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
	  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 ; exit 1
    else
      echo "Loaded `cat ${PROC_VERSION}`"
    fi
    ;;

  # ==================================================
  # ============== Shutdown Routine ==================
  # ==================================================
  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 ; exit 1
      fi
    fi
    rm -rf ${DEVDIR}
    ;;

  # =========================================================
  # ============== ReConfiguration Routine ==================
  # =========================================================
  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
    else
      echo "reconfig" > ${PROC_RECONFIG}
    fi
    ;;

  # =========================================================
  # ================ Test for Cards Busy ====================
  # =========================================================
  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.
    #
    egrep 'Opens:[^0]' ${PROC_CONSPACE} > /dev/null 2>/dev/null
    ;;

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

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