:
#		(C) 1989-1990 The Santa Cruz Operation, Inc.  All Rights
#		Reserved.  The user has unlimited right to use, modify
#		and incorporate this code into other products provided
#		it is used with SCO products and the user includes
#		this notice and the associated copyright notices with
#		any such application.
# This is a script for removing an LLI driver using netconfig
# 
# The name it is called with will cause different operation.
# e3A0 e3A1 e3A2 e3A3		== 3Com501 boards 0 - 3
# e3B0 .....     e3B3		== 3Com503 boards 0 - 3
# e3C0 .....     e3C3		== 3Com523 boards 0 - 3
# wdn0 .....     wdn3		== Western Digital boards 0 - 3
# tok0 tok1			== Token Ring Adapter 0, 1
LIB=/usr/lib/lli
CONF=/etc/conf
PATH=/bin:/usr/bin:/etc/:$CONF/bin:$LIB
#
# Set possible return codes for this script
#
OK=0;	FAIL=1;	RELINK=2; DRIVERINUSE=3;

#
# prompt the user to answer a yes no question or 'q' to quit
# Usage:
#	prompt_yn "Message" default
prompt_yn() {
	mesg=$1
	default=$2

	while :
	do
		echo "${mesg} (y/n) [${default}] : \c"
		read result

		case $result in
		y|Y) result="Y"; return $OK;;
		n|N) result="N"; return $OK;;
		"") result=`echo $default | tr "yn" "YN"`; return $OK;;
		esac

		echo "Illegal value, please type 'y' 'n' or 'q'"
	done
}

#
# Fake up an mdevice and an sdevice for idcheck
#
makedevs() {
	rm -fr /tmp/dev$$
	mkdir /tmp/dev$$
	cd /etc/conf/cf.d
	cp mdevice /tmp/dev$$
	cd ../sdevice.d
	cat * > /tmp/dev$$/sdevice
}

# cleanup removes stuff and exits - if $1 = $DRIVERINUSE, exits value is $2
cleanup() {
	tmp=$1

	if [ $tmp -ne $DRIVERINUSE ]
	then
		# disallow configuring greater than board zero
		netconfigdir=/usr/lib/netconfig
		nextbd=`expr $bd + 1`
		rm ${netconfigdir}/info/${drv}${nextbd} > /dev/null 2>&1
		rm ${netconfigdir}/init/${drv}${nextbd} > /dev/null 2>&1
                # hrf (10/94), remove reconf script
		rm ${netconfigdir}/reconf/${drv}${nextbd} > /dev/null 2>&1
		rm ${netconfigdir}/remove/${drv}${nextbd} > /dev/null 2>&1
	else
		tmp=$2
	fi
	cd /
	rm -fr /tmp/dev$$
	rm -fr /tmp/$base
	exit $tmp
}

#
# The "eisa_nvm" process returns an abbreviated board configuration
#	string for each board found in EISA non-volatile memory.
# For a synopsis of the "eisa_nvm" function, type "eisa_nvm<Enter>".
#
eisa_cfg_get() {
	eisa_cfg=`eisa_nvm "board_id type" $board_id 0xfeffffff NET 2>/dev/null`
}

unit_cfg_get() {
	ucg_status=$FAIL	# Return code unless we succeed.

	[ "$eisa_cfg" ] && {
		# 1 or more units are configured in EISA non-volatile ram.
		set $eisa_cfg   # Assign board configuration data to $1 thru $n

		# This provides for configuring a single unit.
		[ `expr $# \/ $eisa_args` -gt $bd ] && {
			[ $bd -eq 0 ] || shift `expr $bd \* $eisa_args`
			unit_cfg="$1 $2 $3 $4 $5 $6 $7 $8"
			ucg_status=$OK
		} || :
	}
	return $ucg_status
}

#
# slot_irq_get - Sets the shell variables "eisa_cfg", "unit_cfg", "slot" and
#		 "irq" using "eisa_cfg_get" and "unit_cfg_get".
# inputs -	 The "bd" variable is assumed to have been set elsewhere.
# outputs -	 return code for success or failure.
 
slot_irq_get() {
	sig_status=$FAIL	# Return code unless we succeed.

	# Attempts to get the EISA configuration data for this unit.
	eisa_cfg_get && {
		unit_cfg_get && {
			# EISA configuration data is in $unit_cfg, as follows:
			# 1st = slot, 2nd - 3rd not used, 4th = irq,
			# 5th - 8th not used

			# Extracts only the slot number and irq.
			slot=`expr "$unit_cfg" : "\([0-$max_slot]\{1,\}\) .*"`
			[ "$slot" ] && {
				irq=`expr "$unit_cfg" : "[0-$max_slot]\{1,\} [^ ]\{7\}* -1 \([0-9]\{1,\}\) .*"`
				[ "$irq" ] && sig_status=$OK
			} || :
		} || :
	} || :
	return $sig_status
}

system_ne() {
	SB=/etc/conf/pack.d/${drv}0

	[ $bd -eq 0 ] && {
		rm -f /etc/rc2.d/S39neth_dl
		idinstall -d -e ${drv}_d
	}

	sed "s/NE3200_SLOT$bd .*$/NE3200_SLOT$bd 0/" ${SB}/space.c > temp
	mv temp ${SB}pace.c
	sed "s/NE3200_IRQ$bd  .*$/NE3200_IRQ$bd  0/" ${SB}/space.c > temp
	mv temp ${SB}pace.c
}

system_ctr() {
	eisa_cfg=
	unit_cfg=
	slot=
	board_id="cpq6000"
	eisa_args=8
	max_slot=8
	MAX_BD=3

	slot_irq_get && {
		IRQ=$irq
	} || {
		echo "\n\tCouldn't get EISA configuration for $drv unit $bd"
		echo "\tproceeding with removal anyways...\n"
		cd /etc/conf/sdevice.d
		slot=`cat ${drv}${bd} | awk '{ print $3 }'`
		IRQ=`cat ${drv}${bd} | awk '{ print $6 }'`
	}

	NMINORS=$slot
	IPL=5
	TYPE=1
	MIN_UNITS=0
	MAX_UNITS=`expr ${max_slot} + 1`
	BIO=`expr ${slot} \* 1000`
	EIO=`ha $BIO fff`
	BRAM=0
	ERAM=0

	[ ! -x /tmp/$base ] && mkdir /tmp/$base
	cd /tmp/$base

	[ $bd -eq 0 ] && copy -m /usr/lib/lli/$drv/Driver.o Driver.o

	echo "clone	$drv$bd		c	$drv$bd" >./Node

	echo "#include	<sys/types.h>\n#include	<sys/stream.h>\n" >./Space.c
	echo "extern struct qinit ${drv}nrinit, ${drv}winit;\n" >>./Space.c
	echo "struct streamtab ${drv}0info =\n   {\n   &${drv}nrinit, &${drv}winit, (struct qinit *)0, (struct qinit *)0\n   };\n" >>./Space.c
	echo "extern void ${drv}intr();\n" >>./Space.c

	#
	# Gets the slots, irqs and groups actually configured. The driver "init"
	# routine will use these to recognize configuration differences with
	# respect to EISA non-volatile memory.
	#
	slot_units=		# List of slot numbers actually configured.
	intrs=			# List of irq group dummy interrupt handlers.
	ext_units=		# List of external unit numbers for start_stop.
	ivecs=			# interrupt vectors used

	cd /etc/conf/pack.d
	for unit_device in ${drv}[0-$MAX_BD]
	do
		unit_inst=`cat ../sdevice.d/${unit_device} | awk '{ print $2 }'`
		[ "$unit_inst" = "Y" -a "$unit_device" != ${drv}${bd} ] && { 

			echo "void ${unit_device}intr() {}" >>/tmp/${base}/Space.c
			echo "void (*${unit_device}_intr)() = ${unit_device}intr;\n" >>/tmp/${base}/Space.c
			[ "$unit_device" = "$drv$bd" ] && {
				unit_slot=$slot
			} || {
				unit_slot=`sed -n "s/$unit_device	Y	\([1-$max_slot]\)	.*/\1/p" ../sdevice.d/$unit_device`
			}
			ext_unit=`expr "$unit_device" : "$drv\([0-$MAX_BD]\{1\}\)"`
				[ "$slot_units" ] && slot_units="${slot_units}, {$unit_slot, $ext_unit}" || slot_units="{$unit_slot, $ext_unit}"
			echo "Configuring $drv$ext_unit in slot $unit_slot"
			ext_units="$ext_units $ext_unit"
			[ "$intrs" ] && intrs="$intrs, &${unit_device}_intr" || intrs="&${unit_device}_intr"

		}
		[ "$unit_inst" = "Y" ] && { 
			i=`echo ${unit_device} | sed -e "s/$drv//"`
			[ "$i" -lt $bd ] && ivecs="$ivecs "`cat ../sdevice.d/${unit_device} | awk '{ print $6 }'`
		}
	done

	cd /tmp/${base}
	echo "void (**${drv}_ints[])() = {$intrs};\n" >>./Space.c
	echo "struct {
	unsigned short slot;
	unsigned short unit;
} ${drv}_slots[] = { $slot_units };

unsigned short ${drv}_units = sizeof(${drv}_slots) / sizeof(${drv}_slots[0]);
	" >>./Space.c

	[ $bd -gt 0 ] && {
		cp Space.c /etc/conf/pack.d/${drv}0/space.c

		cd /etc/conf/sdevice.d
		old_type=`cat ${base} | awk '{ print $5 }'`
		[ "$old_type" = "1" ] && {
			for i in ${drv}[$bd-$MAX_BD]
			do
				clash=`cat $i | awk '{ if ( $6 == intr && $5 == "0" && $2 == "Y" ) exit } \
						END { print $1 }' intr=$IRQ`
				[ $clash ] && {
					cat $i | awk '{ printf "%s\t%s\t%s\t%s\t1\t%s\t%s\t%s\t%s\t%s\n", $1, $2, $3, $4, $6, $7, $8, $9, $10 }' > /tmp/bog$$
					mv /tmp/bog$$ $i
					break
				}
			done
		}
		cp /usr/lib/lli/ctr/S39ctr /tmp/bog 2>/dev/null
		sed -e "s/mac380.bin 0.*/mac380.bin ${ext_units}/" < /tmp/bog > /tmp/bog$$
		sed -e "s/stop 0.*/stop ${ext_units}/" < /tmp/bog$$ > /etc/ctr
		chown root /etc/ctr
		chgrp root /etc/ctr
		chmod 744 /etc/ctr
		rm -f /tmp/bog /tmp/bog$$
		cp /etc/ctr /etc/rc2.d/S39ctr 2>/dev/null
		chown root /etc/rc2.d/S39ctr
		chgrp root /etc/rc2.d/S39ctr
		chmod 744 /etc/rc2.d/S39ctr
	} || {
		[ -x /etc/rc0.d/K86ctr stop ] && /etc/rc0.d/K86ctr stop
		rm -f /etc/ctr /etc/rc2.d/S39ctr /etc/rc0.d/K86ctr
	}
}

system_btok() {

	# decrease the number of boards recognized in the boot-time microcode
	# file.
	awk 'BEGIN { FS = "=" } /^NBOARDS/ {
		NEW=$2-1
		if (NEW < 0) NEW=0
		printf "%s=%s\n",$1,NEW
		next
	}
	{ print } ' < /usr/lib/lli/btok/S25btok > /tmp/Sbt$$
	mv /tmp/Sbt$$ /usr/lib/lli/btok/S25btok
	cp /usr/lib/lli/btok/S25btok /etc/rc2.d
	[ "$bd" = "0" ] && rm /etc/rc2.d/S25btok
}

#
# function to remove address conflicts in the sio driver
#
sio_conflict() {
	currdir=`pwd`
	cd /etc/conf/pack.d/sio
	if [ "$BIO" != "0" ]
	then
		grep "/* LLI {.*$BIO" space.c > /dev/null && {
			echo "Restoring serial cards using base address 0x$BIO into link kit..."
			sed -e /"LLI.*$BIO,/s/^\/\* LLI //" space.c >/tmp/bog$$
			if [ "$base" = "tok0" ] 
			then
				sed -e /"ibm COM3/s/^\/\* LLI //" /tmp/bog$$ >/tmp/foo$$
				mv /tmp/foo$$ /tmp/bog$$
			fi
			mv /tmp/bog$$ space.c
		}
	fi
	cd $currdir
}

#
# function to produce the information for the System file for the token ring
#
# if tcp is installed we remove the board from /etc/tcp and /etc/strcf
#
cleantcp() {
	driver=$1

	[ -f /etc/tcp ] && {
		sed "/$driver/d" /etc/tcp > /tmp/bog$$
		cp /tmp/bog$$ /etc/tcp
	}
	[ -f /etc/strcf ] && {
		sed "/$driver/d" /etc/strcf > /tmp/bog$$
		cp /tmp/bog$$ /etc/strcf
	}
	rm -f /tmp/bog$$
}

# main()
#

#
# get the name of the init script being run, since one script
# is used for multiple drivers; get the number at the end of the
# script's name
#
if [ $# -gt 1 ]
then
	name_below=$1; if_below=$2
	name_above=$3; if_above=$4
fi

base=`basename $0`
drv=`echo $base | sed -e 's/[0-9]*$//`
bd=`expr $base : '.*\(.\)'`

case $drv in
btok) PREFIX="btok";;
ctr) PREFIX="ctr";;
e3A) PREFIX="e3c";;
e3B) PREFIX="e503";;
e3C) PREFIX="emc";;
e3D) PREFIX="e3d";;
e3m) PREFIX="e3m$bd";;
wdn) PREFIX="wdn";;
tok) PREFIX="tok";;
exos) PREFIX="exos";;
hpi) PREFIX="hpi";;
hpe) PREFIX="hpe";;
i3B) PREFIX="i3B";;
i6E) PREFIX="i6E";;
nat) PREFIX="nat$bd";;
ne) PREFIX="ne";;
*) echo "ERROR: Unknown LLI driver being configured ($drv$bd)";
	cleanup $FAIL;
	;;
esac
[ "$bd" -gt "0" ] && {
	PREFIX="$PREFIX$bd"
}

echo "NODE=/etc/conf/node.d/$base" >/tmp/$base.src
chmod 777 /tmp/$base.src

#
# check to see if the driver is already in the kernel link-kit so we can
# either add it or update it later on
#
makedevs
idcheck -p $base
if [ $? -gt 16 ]
then
	installed="TRUE"
else
	installed="FALSE"
fi

if [ "$installed" = "FALSE" ]
then
	cleanup $OK
fi

#
# Check and Manage our internal chains file.
#
# if our board (base) is not in the chain then we always remove the board
# if our board is in the chain then we check for the chain and remove it.
# if after our chain is removed from the chains file the board is still there
#    then we do not remove it.
#
chains=/usr/lib/lli/chains
chain=$base:$name_above
if grep $base: $chains > /dev/null 2>& 1
then 
	grep $chain $chains > /dev/null 2>& 1 || {
		cleanup $OK
	}
	# remove our chain
	awk '{
		if ($1 == CHAIN && found != 1) {
			found = 1
			next
		}
		print $0
	}' CHAIN=$chain < $chains > /tmp/bog$$
	cp /tmp/bog$$ $chains
	rm -f /tmp/bog$$
	# Check if it is there in another chain
	grep $base: $chains > /dev/null 2>& 1 && {
		cleanup $DRIVERINUSE $OK
	}
else
	cleanup $OK
fi

echo "Removing $base..."

# Check if we are board zero that no other boards of this type are configured
[ "$bd" -eq "0" ] && {
	grep ${drv}[1-3] $chains > /dev/null 2>& 1 && {
		echo "Warning, You are removing board 0 before other boards"
		echo "You must remove the other $drv boards next"
		echo "or your link-kit will be left in an invalid state"
	}
}

#
# Do board dependent processing
#
case $drv in
	btok)	system_btok;;
	ctr)	system_ctr;;
	ne)	system_ne;;
esac

#if [ $bd -gt 0 ]
#then
#	idinstall -d -e $base
#	cleanup $RELINK
#fi

# get the interrupt vector for the board that we are removing
cd /etc/conf/sdevice.d
ivec=`awk '{ if ( $1 != "*" ) print $6 }' < $base`
BIO=`awk '{ if ( $1 != "*" ) print $7 }' < $base`

cd /tmp; rm -rf $base
mkdir $base; cd $base

echo "${base}\tN\t1\t5\t1\t9\t0\t0\t0\t0" >System
if [ $bd -gt 0 ]
then
	echo "$base	-	iScH	$PREFIX	0	0	1	256	-1" >./Master
else
	cp $LIB/${drv}/Master ./Master
fi
idinstall -u -e -s -m $base

# restore sio space.c file
sio_conflict

cleantcp $base
[ "$ivec" = "4" ] && echo "Please use 'mkdev serial' to restore interrupt 4 to the sio driver"
# Check to see if driver for next board is configured
grep ${drv}`expr ${bd} + 1`: $chains > /dev/null 2>& 1 && {
	cleanup $DRIVERINUSE $RELINK
}
cleanup $RELINK
