#!/bin/sh
# Copyright (c) 2005 Dieter Jurzitza, Germany.
#
# Author: Dr. Ing. Dieter Jurzitza <dieter.jurzitza@t-online.de>
#
# /etc/init.d/framebufferset
#
#   and symbolic its link
#
# /usr/sbin/rcframebufferset
#
### BEGIN INIT INFO
# Provides:       framebuffer
# Required-Stop:
# Default-Start:  2 3 5
# Default-Stop:   0 1 6
# Description:    framebuffer
### END INIT INFO

# source rc functions
. /etc/rc.status

# some variables we need in the script
AWK=/bin/awk
SED=/bin/sed
GREP=/bin/grep
CAT=/bin/cat

LSPCI="/sbin/lspci"
LSPCIOPTS="-v"
MTRR="/proc/mtrr"
CONFIGFILE=/etc/sysconfig/framebuffer

declare -a RETVAL
declare -a RESULT

# First reset status of this service
rc_reset

echo -n "Verify the apropriate mtrr setting"

if [ ! -f ${MTRR} ]; then
	echo -n " ${MTRR} not found "
	echo "${rc_failed}"
	exit 1
fi

if [ ! -f ${CONFIGFILE} ];then
    echo -n " ${CONFIGFILE} not found "
    echo "${rc_failed}"
    exit 2
fi

# source config file
. ${CONFIGFILE}

# Analyze the output of lspci with regard to the graphics card's attributes. We search for " VGA ". Having found this
# we search for the String "Memory at ", what in turn gives the address value. K-Byte values (/K/) are ignored.
# For everything valid we get a printout 0xBASEADDR MEMSZ, what gets stored into RETVAL. num is our eventcounter: each
# time we find a valid Memory entry num is increased by two. At the very end we print num. So our array contains pairs of
# addresses and memory sizes until the last value which represents the total size of the array RETVAL.
# The final sed removes the [size= XXX] from the actual XXX-size values.

RETVAL=(`${LSPCI} ${LSPCIOPTS} |\
	   ${AWK} '{if (match($0, " VGA ")){					\
			 num=0;								\
			 A=getline;							\
			 while(A != ""){						\
				if (match(A, "Memory at ")){			\
				    split(A,B, " ");				\
				    sub(/M/, "", B[6]);				\
				    if (sub(/K/, "", B[6])){			\
					   break;						\
				    }							\
				    printf("0x%s %s ", B[3], B[6]);	\
				    num+=2;						\
				};								\
				getline A;						\
			 }									\
			 printf(" %d END", num);					\
		  }										\
	   }' |										\
sed 's/\[size=//g; s/\]//g'`)

#
# Now let us search for the END entry in RETVAL[i]. END marks the end of the array. Since the mtrr's cannot be that many ones we
# do not search for more than 100 entries (will never be reached).
#
for (( i=0 ; $i != 100 ; i=`expr $i + 1` )) ; do
	if [ "${RETVAL[$i]}" = "END" ]; then
		if [ $i != "0" ]; then
			i=`expr $i - 1`;
		fi
		break;
	fi
done

# Now we have to look into $MTRR. There are settings for the graphics card we find by looking at the address values.
# Those addresses that are identical to the ones from the graphics card are the ones we need.
# However, one cannot rely on the return value for memory of lspci. Therefore we introduced an environment variable
# defined in /etc/sysconfig/framebuffer that needs to be set by the user. It is called FRAMEBUFFERSIZE and can have values
# from 16 to 2048 [MB].

for (( j=0 ; "$j" != "$i" ; j=`expr $j + 2` )) ; do
	RESULT=(`${CAT} ${MTRR} | ${GREP} ${RETVAL[$j]} | $SED 's/://g; s/[a-z]//g; s/[A-Z]//g' | ${AWK} '{printf("%d %d", $1, $5)}'`)
	if [ "${RESULT[1]}" != "${RETVAL[`expr $j + 1`]}" ]; then
		if [ "${FRAMEBUFFERSIZE}" = "16" ]; then
			MEMSIZE=1000000
		elif [ "${FRAMEBUFFERSIZE}" = "32" ]; then
			MEMSIZE=2000000
		elif [ "${FRAMEBUFFERSIZE}" = "64" ]; then
			MEMSIZE=4000000
		elif [ "${FRAMEBUFFERSIZE}" = "128" ]; then
			MEMSIZE=8000000
		elif [ "${FRAMEBUFFERSIZE}" = "256" ]; then
			MEMSIZE=10000000
		elif [ "${FRAMEBUFFERSIZE}" = "512" ]; then
			MEMSIZE=20000000
		elif [ "${FRAMEBUFFERSIZE}" = "1024" ]; then
			MEMSIZE=40000000
		elif [ "${FRAMEBUFFERSIZE}" = "2048" ]; then
			MEMSIZE=80000000
		else
			MEMSIZE=INVALID
		fi
	fi

	if [ "${MEMSIZE}" != "INVALID" -a "${MEMSIZE}" != "" ]; then
		echo "disable=${RESULT[0]}" > ${MTRR}
		echo "base=${RETVAL[$j]} size=0x${MEMSIZE} type=write-combining" > ${MTRR}
		echo "${rc_done}"
	fi
done

if [ "${MEMSIZE}" = "INVALID" ]; then
	echo -n " no valid memory size has been found!"
	echo ${rc_failed}
elif [ "${MEMSIZE}" = "" ]; then
	echo -n " nothing to do on this system, sizes are identical!"
	echo "${rc_done}"
fi
