#!/bin/sh /etc/rc.common
# Copyright (c) 2018, 2021, The Linux Foundation. All rights reserved.
# Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

START=16

#!/bin/sh
ruletype="ip4 ip6"
side="wan lan"
qwan="1 3 2 0 5 7 6 4"
qlan="0 1 2 3 4 5 6 7"

function create_war_acl_rules(){
	for lw in $side
	do
		#echo $lw
		if [ "$lw" == "wan" ];then
			listid=254
			queue=$qwan
			portmap=0x20
		else
			listid=255
			queue=$qlan
			portmap=0x1e
		fi
		#echo $queue
		#echo "creating list $listid"
		ssdk_sh acl list create $listid 255
		ruleid=0
		for rt in $ruletype
		do
			for qid in $queue
			do
				cmd="ssdk_sh acl rule add $listid $ruleid  1 n 0 0"
				#echo $cmd
				if [ "$rt" == "ip4" ];then
					cmd="$cmd ip4 n n n n n n n n n n n n n n n n n n n n n n n n n n n n n"
					#echo $cmd
				else
					cmd="$cmd ip6 n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n"
					#echo $cmd
				fi
				if [ $ruleid -le 3 ];then
					#non-zero dscp
					cmd="$cmd y 0x0 0xff"
				elif [ $ruleid -le 7 ];then
					#zero dscp
					cmd="$cmd n"
				elif [ $ruleid -le 11 ];then
					#non-zero dscp
					cmd="$cmd y 0x0 0xff"
				else
					#zero dscp
					cmd="$cmd n"
				fi
				p=$((ruleid/2))
				cmd="$cmd y mask $((ruleid%2)) 0x1 y mask $((p%2)) 0x1 n n n n n n n n n n n n n n n y n n n n n n n y $qid n n 0 0 n n n n n n n n n n n n n n n n n n n n 0"
				#echo $cmd
				$cmd
				ruleid=`expr $ruleid + 1`
			done
		done
		ssdk_sh acl list bind $listid 0 1 $portmap
	done
}

function create_war_cosmap(){
	ssdk_sh cosmap pri2q set 0 0
	ssdk_sh cosmap pri2q set 1 0
	ssdk_sh cosmap pri2q set 2 0
	ssdk_sh cosmap pri2q set 3 0
	ssdk_sh cosmap pri2q set 4 1
	ssdk_sh cosmap pri2q set 5 1
	ssdk_sh cosmap pri2q set 6 1
	ssdk_sh cosmap pri2q set 7 1
	ssdk_sh cosmap pri2ehq set 0 0
	ssdk_sh cosmap pri2ehq set 1 0
	ssdk_sh cosmap pri2ehq set 2 0
	ssdk_sh cosmap pri2ehq set 3 0
	ssdk_sh cosmap pri2ehq set 4 1
	ssdk_sh cosmap pri2ehq set 5 1
	ssdk_sh cosmap pri2ehq set 6 1
	ssdk_sh cosmap pri2ehq set 7 1
}

function create_acl_byp_egstp_rules(){
	chip_ver=$1
	cmd="ssdk_sh servcode config set 1 n 0 0xfffefc7f 0xffbdff 0 0 0 0 0 0"
	if [ "$chip_ver" == "0x2000" ] || [ "$chip_ver" = "0x2001" ] || [ "$chip_ver" = "0x2100" ]; then
		cmd="$cmd 0"
	fi
	#echo $cmd
	$cmd

	ssdk_sh acl list create 56 48
	#action bypass eg stp check
	action="y n n n n n n n n n n 0 0 n n n n n n n n n n n n n y n n n n n n n n n n n n y n n n n n n n n n n n n n n n n n n"
	if [ "$chip_ver" == "0x2000" ]; then
		action="$action n n 0"
	elif [ "$chip_ver" = "0x2001" ] || [ "$chip_ver" = "0x2100" ]; then
		action="$action n n n 0"
	else
		action="$action 0"
	fi

	for ruleid in $( seq 0 2 )
	do
		if [ "$ruleid" == "0" ];then
			cmd="ssdk_sh acl rule add 56 0 1 n 0 0 mac n n n n n y 01-80-c2-00-00-00 ff-ff-ff-ff-ff-ff n n n n n n n n n n n n n n n n n n n n n n n"
		elif [ "$ruleid" == "1" ];then
			cmd="ssdk_sh acl rule add 56 1 1 n 0 0 mac n n n n n n n yes 0x8809 0xffff n n n n n n n n n n n n n n n n n n n n n"
		else
			cmd="ssdk_sh acl rule add 56 2 1 n 0 0 mac n n n n n n n yes 0x888e 0xffff n n n n n n n n n n n n n n n n n n n n n"
		fi
		if [ "$chip_ver" == "0x2000" ] || [ "$chip_ver" = "0x2001" ] || [ "$chip_ver" = "0x2100" ]; then
			cmd="$cmd n $action"
		else
			cmd="$cmd $action"
		fi
		#echo $cmd
		$cmd
	done
	ssdk_sh acl list bind 56 0 2 1
}

function delete_war_acl_rules(){
	for lw in $side
	do
		#echo $lw
		if [ "$lw" == "wan" ];then
			listid=254
			queue=$qwan
			portmap=0x20
		else
			listid=255
			queue=$qlan
			portmap=0x1e
		fi
		ssdk_sh acl list unbind $listid 0 1 $portmap
		for rt in $ruletype
		do
			for qid in $queue
			do
				cmd="ssdk_sh acl rule del $listid 0 1"
				echo $cmd
				$cmd
			done
		done
		#echo "deleting list $listid"
		ssdk_sh acl list destroy $listid
	done
}

function delete_war_cosmap(){
	ssdk_sh cosmap pri2q set 0 0
	ssdk_sh cosmap pri2q set 1 0
	ssdk_sh cosmap pri2q set 2 1
	ssdk_sh cosmap pri2q set 3 1
	ssdk_sh cosmap pri2q set 4 2
	ssdk_sh cosmap pri2q set 5 2
	ssdk_sh cosmap pri2q set 6 3
	ssdk_sh cosmap pri2q set 7 3
	ssdk_sh cosmap pri2ehq set 0 1
	ssdk_sh cosmap pri2ehq set 1 0
	ssdk_sh cosmap pri2ehq set 2 2
	ssdk_sh cosmap pri2ehq set 3 2
	ssdk_sh cosmap pri2ehq set 4 3
	ssdk_sh cosmap pri2ehq set 5 3
	ssdk_sh cosmap pri2ehq set 6 4
	ssdk_sh cosmap pri2ehq set 7 5
}

function delete_acl_byp_egstp_rules(){
	chip_ver=$1
	cmd="ssdk_sh servcode config set 1 n 0 0xfffefcff 0xffbfff 0 0 0 0 0 0"
	if [ "$chip_ver" == "0x2000" ] || [ "$chip_ver" = "0x2001" ] || [ "$chip_ver" = "0x2100" ]; then
		cmd="$cmd 0"
	fi
	#echo $cmd
	$cmd
	ssdk_sh acl list unbind 56 0 2 1
	ssdk_sh acl rule del 56 0 1
	ssdk_sh acl rule del 56 1 1
	ssdk_sh acl rule del 56 2 1
	ssdk_sh acl list destroy 56
}

function edma_war_config_add(){
	create_war_cosmap
	ssdk_sh acl status set enable
	create_war_acl_rules
}

function edma_war_config_del(){
	delete_war_acl_rules
	delete_war_cosmap
}

function ipq50xx_serdes_monitor () {
	#if qca808x phy exist, need to monitor the serdes to avoid the effect for WIFI
	port_id=2
	old_linkstatus="DISABLE"
	phy_id_info=`ssdk_sh port phyid get $port_id | grep Org | awk -F '!' '{print $2}'`
	if [ "$phy_id_info" = "[Org ID]:0x004d[Rev ID]:0xd101" ]; then
		ssdk_sh debug phy set 29 0xb 0x300d
		ssdk_sh debug uniphy set 0 0x7ac 0x300d 4

		while true
		do
			cur_linkstatus=`ssdk_sh port linkstatus get $port_id | grep Status | awk -F ':' '{print $2}'`
			#when qca808x phy link status is from down to up, serdes tx would be enabled
			if [ "$cur_linkstatus" = "ENABLE" ] && [ "$old_linkstatus" = "DISABLE" ]; then
				ssdk_sh debug phy set 29 0xb 0xb00d
				ssdk_sh debug uniphy set 0 0x7ac 0xb00d 4
			fi
			#when qca808x phy link status is from up to down, serdes tx would be disabled
			if [ "$cur_linkstatus" = "DISABLE" ] && [ "$old_linkstatus" = "ENABLE" ]; then
				ssdk_sh debug phy set 29 0xb 0x300d
				ssdk_sh debug uniphy set 0 0x7ac 0x300d 4
			fi
			old_linkstatus=$cur_linkstatus
		done
	fi
}

function ipq50xx_phy_amplitude_set () {
	#for qca808x phy sgmii, set half amplitude with src_half_swing register
	port_id=2
	phy_id_info=`ssdk_sh port phyid get $port_id | grep Org | awk -F '!' '{print $2}'`
	if [ "$phy_id_info" = "[Org ID]:0x004d[Rev ID]:0xd101" ]; then
		ssdk_sh debug phy set 29 0x40010087 0xa08a
		ssdk_sh debug phy set 29 0x40010067 0xb910
	fi
}

function ipq50xx_uniphy_amplitude_set () {
	#for ipq50xx sgmii, set half amplitude with tx_emp_lvl/margin_index and tx_margin
	ssdk_sh debug uniphy set 0 0x24 0x54 4
	ssdk_sh debug uniphy set 0 0x21c 0x288a 4
	ssdk_sh debug uniphy set 0 0x19c 0xbea0 4
}

ssdk_dependency() {
	counter=0
	[ -e /lib/modules/$(uname -r)/qca-ssdk.ko ] && [ ! -d /sys/module/qca_ssdk ] && {
		insmod qca-ssdk.ko
	}
	while [ ! -d /sys/ssdk ] && [ "$counter" -le 5 ]
	do
		sleep 1
		counter=$((counter+1))
	done
}

start() {
	ssdk_dependency
	chip_ver=`ssdk_sh debug reg get 0 4 | grep Data | tr -d 'SSDK Init OK![Data]:'`
	#The following commands should be uncommented to enable EDMA WAR
	if [ "$chip_ver" = "0x1401" ]; then
		#edma_war_config_add
		echo ''
	fi
	#The following commands should be uncommented to add acl egress stp bypass rules
	if [ "$chip_ver" = "0x1500" ] || [ "$chip_ver" = "0x1501" ] || [ "$chip_ver" = "0x2000" ] || [ "$chip_ver" = "0x2001" ] || [ "$chip_ver" = "0x2100" ]; then
		#create_acl_byp_egstp_rules $chip_ver
		echo ''
	fi
	#The following commands should be uncommented to enable WAR for ipq50xx
	chip_type_info=`cat tmp/sysinfo/model`
	result=$(echo $chip_type_info | grep "IPQ5018")
	if [ "$result" != "" ]; then
		#ipq50xx_serdes_monitor &
		#ipq50xx_uniphy_amplitude_set
		#ipq50xx_phy_amplitude_set
		echo ''
	fi
	echo starting
}

stop() {
	chip_ver=`ssdk_sh debug reg get 0 4 | grep Data | tr -d 'SSDK Init OK![Data]:'`
	#The following commands should be uncommented to disable EDMA WAR
	if [ "$chip_ver" = "0x1401" ]; then
		#edma_war_config_del
		echo ''
	fi
	#The following commands should be uncommented to delete acl egress stp bypass rules
	if [ "$chip_ver" = "0x1500" ] || [ "$chip_ver" = "0x1501" ] || [ "$chip_ver" = "0x2000" ] || [ "$chip_ver" = "0x2001" ] || [ "$chip_ver" = "0x2100" ]; then
		#delete_acl_byp_egstp_rules $chip_ver
		echo ''
	fi
	echo stoping
}
