#!/bin/sh

UPD_PID=/var/run/updspice3_init.pid
ERROR=0

export PATH="${PATH:+$PATH:}/usr/sbin:/sbin:/opt/RAYLASE/SPICE3/bin"

die(){
	local message=$1
	[ -z "$message" ] && message="Died"
	echo "$message at ${BASH_SOURCE[1]}:${FUNCNAME[1]} line ${BASH_LINENO[0]}." >&2
	ERROR=1
}

_setWatchdogTimeout() {
	# Set WD timeout for retriggers = (1 << (12+16)) / 25 MHz = 11 seconds: Value C
	rawmem32 0xffd03004 0xfc >/dev/null
}

_triggerWatchdog(){
	rawmem32 0xffd0300c 0x76 >/dev/null
}

_macIncrement(){
	local CONST_BYTES="3"
	local pos=$1
	if (( ${pos} < ${CONST_BYTES} ))
		then
		# Only the last 3 bytes of the MAC can be changed
		echo "Unable to calculate MAC. Maximum reached!"
		exit 1
		fi
		addr[pos]=`echo "ibase=16;${addr[pos]}+1" | bc`
		if [[ "${addr[pos]}" == "256" ]]
			then
			addr[pos]="00"
			_hexIncrement $[$1-1]
			fi
			addr[pos]=$(printf "%02X\n" ${addr[pos]});
}

_moduleInit(){
	local modName=$1
	local sysPath=$2
	# insert the module
	modprobe $modName || die
	# make sure the pseudo files are writable...
	for f in `ls -l $sysPath/* | gawk -F' ' '/-?w/ { print $9 }'`
	do
		chmod a+w $f || die
	done
}

_fpgaInit(){
	# Enable fpga bridges because vanilla bootloader
	echo 1 > /sys/class/fpga_bridge/br0/enable || die
	echo 1 > /sys/class/fpga_bridge/br1/enable || die
	echo 1 > /sys/class/fpga_bridge/br2/enable || die
}

_rtcInit(){
	# Register rtc on i2c bus0 so that it is recognized
	# as rtc. In that way it can be accessed by /dev/rtc0
	# if mcp7940m module is loaded
	echo mcp7940m 0x6F > /sys/class/i2c-dev/i2c-0/device/new_device || die

	# insert the module
	modprobe mcp7940m || die
	# make sure the pseudo file is writable for normal users...
	chmod a+rw /dev/rtc0 || die
}

_engineInit(){
	# create minor devices for all our engines (wo)
	for i in `seq 0 7`
	do
		if [ ! -c /dev/spice3/engine$i ]; then
			mknod /dev/spice3/engine$i c 240 $i || die
			chmod 222 /dev/spice3/engine$i || die
		fi

	done

	# create minor device for pcu (ro)
	if [ ! -c /dev/spice3/pcu0 ]; then
		mknod /dev/spice3/pcu0 c 241 0 || die
		chmod 444 /dev/spice3/pcu0 || die
	fi

	# create minor devices for each correction (rw)
	for i in `seq 0 4`
	do
		if [ ! -c /dev/spice3/corr$i ]; then
			mknod /dev/spice3/corr$i c 242 $i || die
			chmod 666 /dev/spice3/corr$i || die
		fi

	done

	if [ ! -c /dev/spice3/fcorr0 ]; then
		ln -s /dev/spice3/corr0 /dev/spice3/fcorr0 || die
	fi
	if [ ! -c /dev/spice3/fcorr1 ]; then
		ln -s /dev/spice3/corr1 /dev/spice3/fcorr1 || die
	fi
	if [ ! -c /dev/spice3/fcorr2 ]; then
		ln -s /dev/spice3/corr2 /dev/spice3/fcorr2 || die
	fi
	if [ ! -c /dev/spice3/fcorr3 ]; then
		ln -s /dev/spice3/corr3 /dev/spice3/fcorr3 || die
	fi
	if [ ! -c /dev/spice3/pcorr ]; then
		ln -s /dev/spice3/corr4 /dev/spice3/pcorr || die
	fi

	# create minor devices for power calibration (rw)
	if [ ! -c /dev/spice3/powercal0 ]; then
		mknod /dev/spice3/powercal0 c 243 0 || die
		chmod 666 /dev/spice3/powercal0 || die
	fi
	if [ ! -c /dev/spice3/powercal1 ]; then
		mknod /dev/spice3/powercal1 c 247 0 || die
		chmod 666 /dev/spice3/powercal1 || die
	fi

	# create minor devices for the head communication (ro)
	for i in `seq 0 1`
	do
		if [ ! -c /dev/spice3/headcomm$i ]; then
			mknod /dev/spice3/headcomm$i c 244 $i || die
			chmod 444 /dev/spice3/headcomm$i || die
		fi
	done

	# create minor devices for tracebuffer
	if [ ! -c /dev/spice3/trace ]; then
		mknod /dev/spice3/trace c 245 0 || die
		chmod 666 /dev/spice3/trace || die
	fi

	# create minor devices for the spi (rw)
	for i in `seq 0 3`
	do
		if [ ! -c /dev/spice3/spi$i ]; then
			mknod /dev/spice3/spi$i c 246 $i || die
			chmod 666 /dev/spice3/spi$i || die
		fi
	done

	_moduleInit fpga "/sys/class/engine/engine/"
}

_uioEepromInit(){
	for i in `seq 0 2`
	do
		if [ ! -c /dev/spice3/eeprom$i ]; then
			mknod /dev/spice3/eeprom$i c 261 $i || die
			chmod 666 /dev/spice3/eeprom$i || die
		fi
	done
	_moduleInit uio-eeprom "/sys/class/eeprom/eeprom/"
}

_usbEthGadgetEnable(){
	local usbEth=`seteeprom USBETH`
	if [ ! -z ${eth2Addr} ]
	then
		local eth2Addr=`seteeprom ETH2ADDR`
		local eth3Addr=`seteeprom ETH2ADDR`

		# If there is no ETH2ADDR and ETH3ADDR stored whe have to generate them
		if [ -z ${eth2Addr} ]
			then
			echo "No \"ETH2ADDR\" and \"ETH3ADDR\" found in eeprom. Adding now."
			echo "This may take a while!"
			local eth1addr=`seteeprom ETH1ADDR`
			IFS=':' read -r -a addr <<< $eth1addr
			_macIncrement 5
			ETH2ADDR="${addr[0]}:${addr[1]}:${addr[2]}:${addr[3]}:${addr[4]}:${addr[5]}"
			seteeprom ETH2ADDR=${eth2Addr}
			IFS=':' read -r -a addr <<< $eth2Addr
			_macIncrement 5
			ETH3ADDR="${addr[0]}:${addr[1]}:${addr[2]}:${addr[3]}:${addr[4]}:${addr[5]}"
			seteeprom ETH3ADDR=${eth3Addr}
			echo "Finished adding \"ETH2ADDR\" and \"ETH3ADDR\" to eeprom."
		fi
		# install module
		modprobe g_ether host_addr=${eth3Addr} dev_addr=${eth2Addr}
	fi
}

_doNetworkReset(){
	echo "Resetting Network settings to factory defaults."
	seteeprom -f
}

_doConfigsReset(){
	cd /home/spice3/procvarfiles
	echo "Backing up current Configs."
	tar -cjf "$(date '+configs-%Y%m%d-%H%M%S').tar.bz2" *.json
	echo "Removing config files."
	rm -f *.json
	rm -f *.bak
}

_doFactoryReset(){
	_do_networkReset
	cd /home/spice3
	echo "Resetting everything to factory defaults."
	rm -f /home/webuser/user.config
	for d in *files autostart ; do
		[ -d $d ] && rm -f ${d}/*
	done
	rm -f /home/spice3/log/*
}

_checkForResets(){
	local fatDir="/media/fat"
	local legacyNetworkResetFile="factoryreset"
	local networkResetFile="resetnetwork"
	local configsResetFile="resetconfigs"
	local factoryResetFile="resetfactory"
	echo -n "Checking for reset to default triggers..."
	if [ "$(mount | grep "${fatDir}" | cut -d' ' -f1)" == "/dev/mmcblk0p1" ]
	then
		echo ""
		for tf in "${factoryResetFile}" "${configsResetFile}" "${networkResetFile}" "${legacyNetworkResetFile}" ; do
			if [ -f "${fatDir}/${tf}" ]
			then
				echo " found ${fatDir}/${tf}"
				rm -d "${fatDir}/${tf}"

				case "${tf}" in 
					( "${factoryResetFile}" )
						_doFactoryReset
						return 0
					;;

					( "${configsResetFile}" )
						_doConfigsReset
						return 0
					;;

					( "${networkResetFile}" | "${legacyNetworkResetFile}" )
						_doNetworkReset
						return 0
					;;
				esac
			else
				echo " ${fatDir}/${tf} not found."
			fi
		done
		return 0
	fi
	echo " '${fatDir}' apparently not mounted."
	return 0
}

_checkEepromAddrEntries() {
	local ipv4Addr0="$(seteeprom IPV4ADDR0)"
	if [ -z "$ipv4Addr0" ]
	then
		echo "Replacing old-style IPV4ADDR settings in EEPROM!"
		local ipv4Addr="$(seteeprom IPV4ADDR)"

		if [ -n "$ipv4Addr" ]
		then
			seteeprom IPV4ADDR0="$ipv4Addr"
			seteeprom IPV4ADDR=
		else
			seteeprom IPV4ADDR0=DHCP
		fi
		seteeprom IPV4ADDR1=DHCP
	fi
	return 0
}

#
# startup
#
start(){

	_triggerWatchdog

	# create a 'spice3' subfolder for all our devices
	[ -d /dev/spice3 ] || mkdir /dev/spice3
	_fpgaInit &
	pids="$pids $!"
	_rtcInit &
	pids="$pids $!"
	_engineInit &
	pids="$pids $!"

	_usbEthGadgetEnable &
	pids="$pids $!"

	_uioEepromInit

	# Wait for all threads to finish
	wait $pids

	_triggerWatchdog

	# Check whether a settings reset (network, configs, factory) was requested.
	_checkForResets

	# Fixup any legacy Eeprom IPAddr entries made by Ancient firmware.
	_checkEepromAddrEntries

	# revert to the normal 11s timout (see fsck)
	_setWatchdogTimeout
	_triggerWatchdog

	return $?
}

#
# shutdown
#
stop(){
	modprobe -rf mcp7940m
	modprobe -rf uio-eeprom
	modprobe -rf fpga

	modprobe -rf g_ether
	modprobe -rf usb_f_eem
	modprobe -rf u_ether
	modprobe -rf libcomposite
}

case "$1" in
  start)
	echo "Starting spice3 devices and services..."
	start
	res=$?
	if [ ERROR == 1 ]
	then
		echo "Error occurred during initialization, watchdog daemon will not start!"
		exit 1
	fi
	echo "Setting system time via hwclock"
	/etc/init.d/hwclock.sh start
	echo "done."

	echo "Starting watchdog daemon: watchdog"
	start-stop-daemon -S -N -1 -x watchdogDaemon -- 10 0xffd0300c 0x76
	echo "done."

	. /opt/RAYLASE/SPICE3/bin/upd_functions.sh
	logecho_init
	
	echo "Starting update daemon: update"
	start-stop-daemon -S -b -p $UPD_PID -m -x upd_daemon.sh
	# After a factoryreset we reboot again to set correct ips during startup
	if [ "$res" == "1" ]
	then
		reboot
	fi
	echo "done."
	;;
  stop)
	stop
	
	#DW: Don't stop the watchdogDaemon by this script. If it really should be stopped, then only manually
	#echo "Stopping watchdog daemon: watchdog"
	#start-stop-daemon -K -x watchdogDaemon
	#echo "."
	
	echo "Stopping update daemon: update"
	start-stop-daemon -K -p $UPD_PID upd_daemon.sh
	echo "."
	;;
  *)
	echo "Usage: /etc/init.d/spice3 {start|stop}"
	exit 1
esac

exit 0
