#!/bin/ksh

# printregs version 1.1
# http://www.bolthole.com/solaris/drivers
#
# This script prints out useful information for a device,
# where "useful" is defined as "useful for driver programming".
# Although it can also be used just to check the "compatible" list,
# which enables you to judge if you can just throw in an entry in 
# /etc/driver_aliases for it
#
# FYI: decoding this stuff is done by IEEE 1275 rules. Some docs on this:
# http://soldc.sun.com/developer/support/driver/wps/pci/html/Device_Prop.doc.html


if [[ $# -ne 1 ]] ; then
	print You need to give one pci identifier
	print 'For example, "1234,5678", or "pci802c,1a"'
	exit
fi

case $1 in
   pci*)
	ID="'${1}'"
	SHORTID="${1##pci}"
	;;
   display)
	ID="'${1}'"
	SHORTID="${1}"
	;;
   *)
	ID="'pci${1}'"
	SHORTID="${1}"
	;;
esac

print Looking for device $ID
print We will print the possible register mappings, that can be used with
print ddi_regs_map_setup, and also any physical mappings.
print The physical mappings are only to help you FIGURE OUT what they are
print '!!!!  DO NOT TRY TO ACCESS THAT ADDRESS DIRECTLY !!!!!'
print ' -------------------------'

######## NAWK SCRIPT HERE!! ###########
/usr/sbin/prtconf -pv | nawk -v ID="${ID}" -v SHORTID="${SHORTID}" '

# convert single hex 'digit' to decimal
function xtoi(achar) {
	if(achar == "a"){ return 10;}
	if(achar == "b"){ return 11;}
	if(achar == "c"){ return 12;}
	if(achar == "d"){ return 13;}
	if(achar == "e"){ return 14;}
	if(achar == "f"){ return 15;}
	if(achar > 0)   { return achar;}

	return 0;
}

# decode the "compatible" property from prtconf, if needed
function compatible(compatstr) {
	print "DEBUG: compatstr is " compatstr;
	if(compatstr == ""){
		print "compat string is empty";
		return;
	}
	# check for xxxxxxxx.yyyyyyyy.zzzzzzzz format
	if(substr(compatstr,9,1) != "."){
		print "compatible: " compatstr;
		return
	}

	printf ("compat: ");

	# This is kinda ugly. Sigh...
	# assume on intel, because sparc prtconf isnt as broken, so
	# doesnt require this hack. I think.
	split(compatstr,octs,".");

	parse=1;
	while(octs[parse]){
		val[1]=xtoi(substr(octs[parse],1,1));
		val[2]=xtoi(substr(octs[parse],2,1));
		val[3]=xtoi(substr(octs[parse],3,1));
		val[4]=xtoi(substr(octs[parse],4,1));
		val[5]=xtoi(substr(octs[parse],5,1));
		val[6]=xtoi(substr(octs[parse],6,1));
		val[7]=xtoi(substr(octs[parse],7,1));
		val[8]=xtoi(substr(octs[parse],8,1));
		char1=val[7]*16 +val[8];
		char2=val[5]*16 +val[6];
		char3=val[3]*16 +val[4];
		char4=val[1]*16 +val[2];
		if(char1==0) char1=" ";
		if(char2==0) char2=" ";
		if(char3==0) char3=" ";
		if(char4==0) char4=" ";

		printf "%c%c%c%c",char1,char2,char3,char4;

		parse++;
	}
	print "";

}

$1 == "Node"			{ addrs=""; namestr=""; regs=""; compatstr="";
				  next;
				}
$1 == "assigned-addresses:"	{ addrs=$2; }
$1 == "name:"			{ namestr=$2; }
$1 == "compatible:"		{ compatstr=$2; }
$1 == "model:"			{ modelstr=$3; }
$1 == "reg:"			{ regs=$2;
				  if (namestr==ID){
					exit;
				   }
				  if(modelstr==SHORTID){
				  exit;
				  }
				}

END	{
	# yes ignore initial set of regs
	compatible(compatstr);
	split(regs,ints,".");
	mod=1;icount=6;regcount=1
	while(ints[icount]!=""){
		if(mod>5){ mod=mod-5; regcount++;}
		if(mod==1){tag=ints[icount];}
		if(mod==5){
		   print "register set " regcount " has tag " tag " and length " ints[icount];
		   tag="";
		}
		icount=icount+1;mod=mod+1;
	}

	split(addrs,ints,".");
	mod=1;icount=1;regcount=1
	while(ints[icount]!=""){
		if(mod>5){ mod=mod-5; regcount++;}
		if(mod==1){
			tag=ints[icount];
			regspace="(configspace)";
			if(match(tag,/.1....../)!=0){
				regspace="(iospace)";
			}
			if(match(tag,/.2....../)!=0){
				regspace="(32-bit addr)";
			}
			if(match(tag,/.3....../)!=0){
				regspace="(64-bit addr)";
			}
		}
		if(mod==3){
		   print "  tag " tag " is mapped at addr " ints[icount] regspace;
		   tag="";
		}
		icount=icount+1;mod=mod+1;
	}
	} '

################END OF NAWK SCRIPT########################
