:
#	@(#) ida.sh 25.4 93/02/10 
#
#	Copyright (C) 1990-1993 The Santa Cruz Operation, Inc.
#		All Rights Reserved.
#	The information in this file is provided for the exclusive use of
#	the licensees of The Santa Cruz Operation, Inc.  Such users have the
#	right to use, modify, and incorporate this code into other products
#	for purposes authorized by the license agreement provided they include
#	this notice and the associated copyright notice with any such product.
#	The information in this file is provided "AS IS" without warranty.
#
#	Copyright (C) Compaq Computer Corp. 1990.
#
#	mkdev/ida - IDA Hard Disk Configuration
#

# set the standard exit values
: ${OK=0} ${FAIL=1} ${STOP=10}

# set the environment variables
PATH=/etc:/bin:/usr/bin:/etc/conf/bin
export PATH
umask 0

#pick up 'mkdev hd' back-end functions
. /usr/lib/mkdev/.hdfuncs
# cd to root
cd /

# define some numbers and flags here
dmin=0			# minimum number of drive
dmax=13			# maximum number of drive
cmin=0			# minimum number of controller
cmax=6			# maximum number of controller
ctrlnum=`expr $cmax + 1`	# set to illegal value
drivenum=`expr $dmax + 1`	# set to illegal value
no_args=
tmp=/tmp/ida$$
ROOT=

# mkdev ida functions

# set a trap so that if the user dels out, a value of $STOP
# is passed to the calling program
settrap() {
	trap 'echo Interrupted: enter "mkdev ida $drivenum $ctrlnum" to restart >&2
	cleanup $FAIL'	1 2 3 15
}

# unset the traps
unsettrap() {
	trap '' 1 2 3 15
}

ida_error () {
      case $1 in
 	  bad_arg) a="Command line argument is invalid.\nInvoke mkdev ida -u\
 for a usage message."							    ;;
     esac
     echo "\nError: $a\nInstallation exiting." 
     cleanup $FAIL
}


# this function used when adding IDA disks
get_drivenum () {
	while [ "$drivenum" -lt "$dmin" -o "$drivenum" -gt "$dmax" ]
	do
	   	echo "Enter the logical drive number: \c"
	 	 
	   read num
	   case $num in
		1|2|3|4|5|6|7|8|9|10|11|12|13|14) drivenum=`expr $num - 1`   ;;	
		q|Q) cleanup $FAIL		;;
		  *) 
		   echo "Error. Not a valid number. Try again"  ;;
	   esac
	done
}

get_ctrlnum () {
	while [ "$ctrlnum" -lt "$cmin" -o "$ctrlnum" -gt "$cmax" ]
	do
	   echo "\nWhich controller will this logical disk attach to?"
	   echo "Enter 1 (first controller), 2 (second controller), etc. \c"
	 	 
	   read cnum
	   case $cnum in
		1|2|3|4|5|6) ctrlnum=`expr $cnum - 1` ;;
		q|Q) cleanup $FAIL	      ;;
		  *) echo "Error. Not a valid number. Try again"  ;;
	   esac
	done

	get_booting_slot
  	get_root_type
  	[ "$rootdisk" = "I" ] && root_ida=1
	cur_ctrl=$ctrlnum
	if [ -n "$root_ida" -a $booting_slot -ne 0 ] 
	then
		if [ $ctrlnum = 0 ]
		then
			cur_ctrl=$booting_slot
		fi
	     	if  [ $ctrlnum -le $booting_slot -a $ctrlnum -ne 0 ]
		then
			cur_ctrl=`expr $ctrlnum - 1`
		fi
	fi
	find_device

	if [ $ida -eq 0 -a $ida2 -eq 0 -a $ida3 -eq 0 -a $idaex -eq 0 ]
	then
		echo "Invalid controller number entered. Try again."
		valid_drive=0
		drivenum=`expr $dmax + 1`   # set to illegal value
		ctrlnum=`expr $cmax + 1`    # set to illegal value
		cd $savedir
		return
	fi

        valid_drive=1
        if [ $ida3 -eq 1 ]
	then
	  if [ $drivenum -ge 14 ]
	  then
	    echo "Invalid logical drive number entered for IDA3. Try again."
            valid_drive=0
	    drivenum=`expr $dmax + 1`	# set to illegal value
	    ctrlnum=`expr $cmax + 1`	# set to illegal value
	  fi
        fi
        if [ $ida2 -eq 1 ]
	then
	  if [ $drivenum -ge 3 ]
	  then
	    echo "Invalid logical drive number entered for IDA2. Try again."
            valid_drive=0
	    drivenum=`expr $dmax + 1`	# set to illegal value
	    ctrlnum=`expr $cmax + 1`	# set to illegal value
	  fi
        fi
        if [ $ida -eq 1 ]
	then
	  if [ $drivenum -ge 2 ]
	  then
	    echo "Invalid logical drive number entered for IDA. Try again."
            valid_drive=0
	    drivenum=`expr $dmax + 1`	# set to illegal value
	    ctrlnum=`expr $cmax + 1`	# set to illegal value
	  fi
        fi
        if [ $idaex -eq 1 ]
	then
	  if [ $drivenum -ge 2 ]
	  then
	    echo "Invalid logical drive number entered for IDAEX. Try again."
            valid_drive=0
	    drivenum=`expr $dmax + 1`	# set to illegal value
	    ctrlnum=`expr $cmax + 1`	# set to illegal value
	  fi
        fi
	newtype=I	
	cd $savedir
}

set_config_vars () {
	savedir=`pwd`
	cd /etc/conf/cf.d
	# not the major number as stored in mdevice for the requested
	# controller.  This must be done to compensate for the patching
	# that hd.c doesn't at run time.

	# This test assumes that if an IDA is root, it is controller 0.
	if [ -n "$root_ida" -a "$ctrlnum" = "0" ] 
	then
		major=1
	else	
		major=`./configure -j ida$cur_ctrl`
	fi
	newtype=I	
	cd $savedir
}

# chk_disk_comm(node_name)
#
# After we have created the disk device nodes, see if we can communicate
# with the drive.  If not, exit gracefully.  
# Uses fdisk to check communications.
chk_disk_comm() {
	/etc/fdisk -p -f $1 >/dev/null 2>&1 || {
		echo "
Error: Cannot communicate with the IDA drive you specified.
       Make sure that this drive (and controller) are properly
       connected AND properly configured according to the Compaq
       EISA configuration utility.  
       After this is done, just rerun \"mkdev ida\"."

		cleanup 1
	}
}

# usage and help
usage () {
	echo "
Usage: $0 drivenum ctrlnum [-u ]

	-u	display this usage message

Selecting the arguments 'drivenum' and 'ctrlnum' is
dependent on the type of hard disk being installed. 

Following is a section describing installation."

echo "\nPress return to continue: \c"
read x

echo "\n
Installation of a disk on to a IDA (Intelligent Disk Array) controller 
----------------------------------------------------------------------
drivenum	is the logical number of the disk drive.  The first disk array
		on a controller is disk 0; the second disk is disk 1.

ctrlnum		is the controller number. Six controllers are supported.
		The first controller is ctrlnum 0, the second controller is
		ctrlnum 1 and so on.

IDA disks will install with one of the following commands:

mkdev ida 0 0  for the first disk on first controller
mkdev ida 1 0  for the second disk on first controller
mkdev ida 0 1  for the first disk on second controller
mkdev ida 1 1  for the second disk on second controller \n"

echo "\nPress return to continue: \c"
read x
}

# determine current kernel disk support. If configure call fails, just return
# check value of kernel NDISK parameter to warn user if maximum 
# number of disks is exceeded. 
echo_ndisk () {
	get_ndisk && echo "
Note: This kernel is configured to support $ndisk hard disks.
If your system will have more than $ndisk disks, the kernel 
must be reconfigured."
	cd /
}

#### IDA hardware verification procedures ####

eisa_running() {
	# This will tell you if the EISA NVM Driver is running.
	[ -c /dev/eisa0 ] && { 
		< /dev/eisa0 1> /dev/null 2>&1
		return $? 
	}
	return 1
}

# Compare the information in Non-Volatile memory with the information in
# /etc/conf/sdevice.d.  If necessary add or remove drivers from the kernel.

get_ida_irqs() {
    ida_boards=0
    set -a `eisa_nvm board_id cpq4001 0x00ffffff |
    awk '{
    if ($4 > 0 && $5 == 0) print $1, $4
    }'`
    if [ "$1" != "" ]
    then
	# There are some IDA boards present in the system
	# Activate the ida driver if necessary
	cd /etc/conf/pack.d/ida$ida_boards
    	grep Y /etc/conf/sdevice.d/ida >/dev/null || {
	    echo ""
	    echo "EISA Non-Volatile memory does not match the UNIX system"
	    echo "configuration.  The following differences have been found"
	    echo ""
	    echo "Enabling ida base driver ..."
	    echo "ida	Y	0	0	0	0	0	0	0	0" > System
	    idinstall -u -s ida
	    linkit=Y
	}
        # Compare EISA NVM with sdevice.d and note it if it needs to be updated
	while : 
    	do
# For each ida in the system update the sdevice file with the proper
# interrupt vector 
	    cd /etc/conf/pack.d/ida$ida_boards
	    grep Y /etc/conf/sdevice.d/ida$ida_boards >/dev/null 
            status=$?
	    intr=`idinstall -g -s ida$ida_boards | cut -f6`
	    if [ "$intr" != "$2" -o "$status" -ne 0 ]
	    then
		echo "Installing ida$ida_boards : EISA Slot $1 at IRQ $2"
            echo "ida$ida_boards	Y	2	5	3	$2	0	0	0	0" > System
	            idinstall -u -s ida$ida_boards
	            linkit=Y
	    fi
	    ida_boards=`expr $ida_boards + 1`
	    [ "$3" = "" ] && break
 	    shift;shift
    	done
	while [ "$ida_boards" -lt 6 ]
	do
# Make sure the other ida boards are also configured in with a valid IRQ
	    # Is the driver installed
	    cd /etc/conf/pack.d/ida$ida_boards
	    grep Y /etc/conf/sdevice.d/ida$ida_boards >/dev/null 
            status=$?
	    if [ "$status" -ne 0 ]
	    then
            echo "ida$ida_boards	Y	2	5	3	$2	0	0	0	0" > System
	            idinstall -u -s ida$ida_boards
	            linkit=Y
	    fi
	    ida_boards=`expr $ida_boards + 1`
	done
    else
	echo "EISA NVM has detected no IDA Controllers in this system."
	echo "After adding IDA board run mkdev ida."
	idcheck -p ida	# Is the driver already installed.
	grep Y /etc/conf/sdevice.d/ida && { 
	    echo "Removing ida"
	    cd /etc/conf/cf.d
	    major=`./configure -j ida`
	    ./configure -c -d -m $major -Y -R >conflog 2>&1
	    linkit=Y
	}
	count=0
	while [ "$count" -lt 6 ]
	do
	    # Is the driver installed
	    grep Y /etc/conf/sdevice.d/ida$count > /dev/null && {
  		echo "Removing ida$count"
  		cd /etc/conf/cf.d
		major=`./configure -j ida$count`
  		./configure -c -d -m $major -Y -R >conflog 2>&1
		linkit=Y
	    }
	    count=`expr $count + 1`
	done
	return $FAIL
    fi
# end get_ida_irqs
}

# Prompt the user for an interrupt vector.  Sets global variable ivect.
verify_ida() {
	eisa_running
	if [ "$?" -eq 0 ]
	then
	  get_ida_irqs || return $FAIL
	else
	  #configure the eisarom driver
	  sed 's/N/Y/' $ROOT/etc/conf/sdevice.d/eisarom > $tmp
	  mv $tmp $ROOT/etc/conf/sdevice.d/eisarom 
	  linkit=Y
	  echo "\nThe Compaq EISA NVM Driver must be running in order to"
	  echo "configure the IDA Driver.  Please relink the unix kernel"
	  echo "and reboot and then run mkdev IDA again."
	  return $FAIL
	fi
}

# Re-link new kernel
do_relink() {
    cd $ROOT/etc/conf/cf.d
    echo "\nRe-linking the kernel ... " >&2
    ./link_unix -y || {
	    echo "Error:  Kernel link failed." >&2
	    cleanup $FAIL
    }
    return $OK
}
#
#	Get the slot of booting IDA
#
get_booting_slot() {
	set -a `eisa_nvm "board_id sub_type" 'CPQ40??' CTL1 |
					awk '{
						 print $1, $2
					}'`
	real_slot=$1

	set -a `eisa_nvm "BOARD_ID" 'CPQ40??' |
		awk '{
			if ($4 > 0 && $5 == 0) print $1, $2
		}'`
	booting_slot=0
	this_slot=0
	slot=$1
	while [ "$slot" != "" ] ;
	do
		board_id=$2
		case $board_id in
			CPQ4002)
			eisa_nvm "board_id sub_type" CPQ4002 0xffffffff CTL1 |
						 grep CPQ4002 > /dev/null
			if [ $? -eq 0 ] ; then

				if [ $slot -eq $real_slot ] 
				then
					return 0
				fi
			fi
				;;
			CPQ400*)
			eisa_nvm "board_id sub_type" cpq4001 0xffffffff CTL1 |
						 grep CPQ4001 > /dev/null
			if [ $? -eq 0 ] ; then
				if [ $slot -eq $real_slot ] 
				then
					return 0
				fi
			fi
				;;
			CPQ401*)
            		eisa_nvm "board_id sub_type" cpq4010 0xffffffff CTL1 |
						 grep CPQ4010 > /dev/null
			if [ $? -eq 0 ] ; then
				if [ $slot -eq $real_slot ] 
				then
					return 0
				fi
			fi
				;;
			CPQ402*)
            		eisa_nvm "board_id sub_type" 'cpq402?' CTL1 |
						 grep CPQ4020 > /dev/null
			if [ $? -eq 0 ] ; then
				if [ $slot -eq $real_slot ] 
				then
					return 0
				fi
			fi
				;;
		esac
		booting_slot=`expr $booting_slot + 1`
		this_slot=`expr $this_slot + 1`
		shift;shift
		slot=$1
	done
		booting_slot=0
	
}
# End of get_booting_slot

#
#	Find out what kind of controller
#
find_device() {
	set -a `eisa_nvm "BOARD_ID" 'CPQ40??' |
		awk '{
			if ($4 > 0 && $5 == 0) print $1, $2
		}'`
	cur_board_num=0
	slot=$1
	ida2=0
	idaex=0
	ida=0
	ida3=0

	while [ "$slot" != "" ] ;
	do
		board_id=$2
		case $board_id in
			CPQ4002)
			if [ $cur_ctrl -eq $cur_board_num ]
			then
			ida2=1
			fi
				;;
			CPQ400*)
			if [ $cur_ctrl -eq $cur_board_num ]
			then
			ida=1
			fi
				;;
			CPQ401*)
			if [ $cur_ctrl -eq $cur_board_num ]
			then
			idaex=1
			fi
				;;
			CPQ402*)
			if [ $cur_ctrl -eq $cur_board_num ]
			then
			ida3=1
			fi
				;;
		esac
		cur_board_num=`expr $cur_board_num + 1`
		shift;shift
		slot=$1
	done
	
}
# End of find_device


#---------------------------------------------------------------------
#  get major number for ida
#---------------------------------------------------------------------
#
# get_major (root_ida, board_num, ida_ctrl)
#
get_major () {
	savedir=`pwd`
	cd /etc/conf/cf.d
	if [ -n "$1" -a $2 -eq $booting_slot ] ; then
		major_num=1
	else
		major_num=`./configure -j ida$2`
	fi
	cd $savedir
}

#---------------------------------------------------------------------
# Create diagnostic IDA nodes 
#---------------------------------------------------------------------
#
get_cpqmon_devs() {
  	get_root_type
  	[ "$rootdisk" = "I" ] && root_ida=1
	get_booting_slot
	set -a `eisa_nvm "BOARD_ID" 'CPQ40??' |
		awk '{
			if ($4 > 0 && $5 == 0) print $1, $2
		}'`
	rm -f /dev/rida*
	uidstr="uid\tsysinfo\t11"
	gidstr="gid\tsysinfo\t11"
	permstr="cpqmon\tc600\tsysinfo/sysinfo\t1\t/dev/rida"
	if [ -f /usr/lib/mkdev/perms/HD_cpq ] 
        then
	rm -f /usr/lib/mkdev/perms/HD_cpq
        fi
	echo  $uidstr >> /usr/lib/mkdev/perms/HD_cpq
	echo  $gidstr >> /usr/lib/mkdev/perms/HD_cpq
	ida_ctlr=0
	ida_ext_ctlr=0
	ida_enh_ctlr=0
	ida_3_ctlr=0
	board_num=0
	slot=$1
	while [ "$slot" != "" ] ;
	do
		board_id=$2
		case $board_id in
			#
			# Board id for IDA-2 is CPQ4002
			#
			CPQ4002)
				get_major "$root_ida" $board_num $ida_enh_ctlr
				p="${permstr}-2$ida_enh_ctlr\t${major_num}/47"
				echo  $p >> /usr/lib/mkdev/perms/HD_cpq
				ida_enh_ctlr=`expr $ida_enh_ctlr + 1`
				;;
			#
			# Board id for IDA is CPQ4001
			#
			CPQ400*)
				get_major "$root_ida" $board_num $ida_ctlr
				p="${permstr}$ida_ctlr\t${major_num}/47"
				echo  $p >> /usr/lib/mkdev/perms/HD_cpq
				ida_ctlr=`expr $ida_ctlr + 1`
				;;
			#
			# Board id for IDA-EX is CPQ4010
			#
			CPQ401*)
				get_major "" $board_num -1
				p="${permstr}e$ida_ext_ctlr\t${major_num}/47"
				echo $p >> /usr/lib/mkdev/perms/HD_cpq
				ida_ext_ctlr=`expr $ida_ext_ctlr + 1`
				;;
			#
			# Board id for IDA-3 is CPQ402X
			#
			CPQ402*)
				get_major "$root_ida" $board_num $ida_3_ctlr
				p="${permstr}-3$ida_3_ctlr\t${major_num}/47"
				echo  $p >> /usr/lib/mkdev/perms/HD_cpq
				ida_3_ctlr=`expr $ida_3_ctlr + 1`
				;;
		esac
		board_num=`expr $board_num + 1`
		shift;shift
		slot=$1
	done
	fixperm -c -dcpqmon /usr/lib/mkdev/perms/HD_cpq
	
} # End of get_cpqmon_devs & get_major


#### begin main ####

#Are we even on an EISA machine?
is_eisa || {
	echo  "IDA disks apply to EISA machines only." >&2 
	exit $FAIL
}

# parse command line args
case "$#" in
	  0) no_args=true
	     echo_ndisk
	     ;;
	  1) case $1 in
		-u) usage
		    exit $OK 		;;
		 *) ida_error bad_arg	;;
	     esac
	     ;;
	2|3) # make sure the drivenum and ctrlnum args are legal
	     [ $1 -ge $dmin -a $1 -le $dmax ] && drivenum=$1 || ida_error bad_arg
	     [ "$2" -ge $cmin -a "$2" -lt $cmax ] && ctrlnum=$2 || ida_error bad_arg
             cur_ctrl=$ctrlnum
	     echo_ndisk
	     ;;
	*)   ida_error bad_arg  
	     ;;	
esac

# set the traps
settrap

# make sure sed is installed for use by this script
  [ -x "/bin/sed" ] || error no_sed

# Create the IDA nodes for diagnostic purpose
  get_cpqmon_devs

# if no command line args given, get configuration info
  [ "$no_args" ] && {
 	valid_drive=0 
	while [ "$valid_drive" -eq 0 ]
	do
	 get_drivenum    
	 get_ctrlnum    
	done
  }

# check if hardware is consistent with UNIX settings
verify_ida

if [ "$linkit" = "Y" ]
then

    # Relink the kernel with the new driver information 
    if getyn "\nDo you wish to relink the kernel now?"
    then
	do_relink || cleanup $FAIL
    else
	echo "\nThe kernel must be re-linked before proceeding."
    fi
    cleanup $OK
fi

# determine if root device is an IDA.
  get_root_type
  [ "$rootdisk" = "I" ] && root_ida=1
# set some variables
  set_config_vars
# set minor numbers
  set_minors
# determine disk number for use in perms list
  set_disknum
if [ "$relink" -gt 0 ] ; then
    # We've added extended minors
    # Relink the kernel with the new driver information 
    cleanval=$OK
    if getyn "\nDo you wish to relink the kernel now?"
    then
	do_relink && {
	    echo "\nYou must now reboot the new kernel."
	    echo "After rebooting, enter \"mkdev ida $drivenum $ctrlnum\" to complete"
	    echo "the addition of this disk."
	    cleanup $OK
	} || cleanval=$FAIL
    else
	echo "\nWARNING: The kernel must be re-linked before proceeding."
	echo "Attempts to configure the disk before doing so will fail."
    fi
    cleanup $cleanval
fi
# last chance to bail out
  quitnow
# create devices 
  fix
# check if we can communicate with the drive.
  chk_disk_comm $cdev
# run fdisk 
  diskprep
# divide the disk into file systems
  rundivvy
  echo "\nHard disk initialization procedure completed.\n"
  cleanup $OK
