# Copyright (C) 1993 Advanced Micro Devices # # (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. # # Script for installing PCNET Family driver # # 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; BRAM="0" ERAM="0" # # Prompt the user for a hex value, it must be within a given range # Usage: # prompt_range "Message" default min max [step] # prompt_range() { mesg=$1 default=$2 range_min=$3 range_max=$4 step="1" if [ $# -eq 5 ] then step=$5 fi while : do echo "${mesg} (${range_min}..${range_max}) [${default}] or 'q' to quit: \c" read result case $result in Q|q) return $FAIL ;; "") result=$default ;; esac hc $result $range_min $range_max $step case $? in 0) return $OK;; 1) cleanup $FAIL;; 2) cleanup $FAIL;; esac done } # # Prompt the user to make a selection a list of values # Usage: # prompt_select "Message" default "value_list" prompt_select() { mesg=$1 default=$2 values=$3 while : do if [ "$default" = "" ] then echo "${mesg} (${values}) or 'q' to quit: \c" else echo "${mesg} (${values}) [${default}] or 'q' to quit: \c" fi read result case $result in Q|q) return $FAIL ;; "") result=$default ;; esac for i in $values do if [ "$i" = "$result" ] then return $OK fi done echo "Illegal value, must be one of (${values})" done } # # 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}] or 'q' to quit: \c" read result case $result in q|Q) return $FAIL;; 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 # Do not remove $base if called with an argument... # makedevs() { dir=`pwd` rm -fr /tmp/dev$$ mkdir /tmp/dev$$ cd /etc/conf/cf.d cp mdevice /tmp/dev$$ cd ../sdevice.d cat * > /tmp/dev$$/sdevice [ $1 ] && { # remove driver being reconfigured from sdevice & mdevice files. sed -e "/^$base/d" < /tmp/dev$$/sdevice > /tmp/bog$$ mv /tmp/bog$$ /tmp/dev$$/sdevice sed -e "/^$base/d" < /tmp/dev$$/mdevice > /tmp/bog$$ mv /tmp/bog$$ /tmp/dev$$/mdevice } cd $dir } cleanup() { cd / rm -fr /tmp/dev$$ rm -fr /tmp/$base exit $1 } # Removes the given interrupt vector for the $clash device. rmvector() { clash=$1 vec=$2 cd $confdir echo "\nRemoving interrupt vector $vec for the $clash device ..." [ "$vec" = "2" ] && vec=9 major=`./configure -j $clash` && { # remove device but leave it required ./configure -d -c -m $major -v $vec -Y >> conflog 2>&1 || { cd $currdir cleanup $FAIL } # remove required setting if no more left if grep "Y" ../sdevice.d/$clash > /dev/null 2>&1 then true else ./configure -d -c -m $major -v $vec -R -Y >> conflog 2>&1 || { cd $currdir cleanup $FAIL } fi } cd $currdir return $OK } # On unix, we must check the files in sdevice.d. # Sets the variable $clash to the driver code name if there is a driver that # has already been allocated the given vector. Uses awk. dointclash() { driver=$1 vec=$2 [ "$vec" = "2" ] && vec=9 cd $confdir/../sdevice.d clash=`cat * | awk '{ if ( $6 == intr && $2 == "Y" ) exit } \ END { print $1 }' intr=$vec` cd $currdir [ "$clash" = "" -o "$clash" = "$driver" ] && return $FAIL # found a clash return $OK } checkvec() { driver=$1 vector=$2 clash= currdir=`pwd` confdir=/etc/conf/cf.d while dointclash $driver $vector do prompt_select "Interrupt vector $vector is already in use for the $clash device.\n\n\ The alternatives available to you are:\n\n\ \t1. Continue the installation and remove vector $vector for the $clash device.\n\ \t2. Select a different interrupt vector.\n\n\ Select an option" 1 "1 2" || { cleanup $FAIL } case $result in 1) rmvector $clash $vector || { echo "Failed to remove vector $vector" cleanup $FAIL } makedevs return $OK ;; 2) return $FAIL ;; esac done return $OK } doaddrclash() { driver=$1 addr1=$2 addr2=$3 cd $confdir clash=`../bin/idcheck -ar -l $addr1 -u $addr2 -i /tmp/dev$$` cd $currdir [ "$clash" = "" -o "$clash" = "$driver" ] && return $FAIL # found a clash return $OK } # Removes the $clash device. rmaddr() { clash=$1 cd $confdir echo "\nRemoving the $clash device ..." major=`./configure -j $clash` && { # remove device but leave it required if [ "$major" != "0" ] then ./configure -d -c -m $major -Y >> conflog 2>&1 || { cd $currdir cleanup $FAIL } else sed -e "s/Y/N/" ../sdevice.d/$clash > /tmp/bog$$ mv /tmp/bog$$ ../sdevice.d/$clash fi # remove required setting if no more left if grep "Y" ../sdevice.d/$clash > /dev/null 2>&1 then true elif [ "$major" != "0" ] then ./configure -d -c -m $major -R -Y >> conflog 2>&1 || { cd $currdir cleanup $FAIL } fi } cd $currdir return $OK } checkaddr() { driver=$1 addr1=$2 addr2=$3 clash= currdir=`pwd` confdir=/etc/conf/cf.d while doaddrclash $driver $addr1 $addr2 do if [ "$clash" = "ad" ] then echo "\n\nWARNING: Do not remove the $clash device \c" echo "if you are using an Adaptec disk controller" fi prompt_select "Addresses $addr1-$addr2 are already in use by the $clash device.\n\n\ The alternatives available to you are:\n\n\ \t1. Continue the installation and remove the $clash device.\n\ \t2. Select a different address.\n\n\ Select an option" 1 "1 2" || { cleanup $FAIL } case $result in 1) rmaddr $clash || { echo "Failed to remove $clash device" cleanup $FAIL } makedevs return $OK ;; 2) return $FAIL ;; esac done return $OK } doramclash() { driver=$1 addr1=$2 addr2=$3 cd $confdir clash=`../bin/idcheck -cr -l $addr1 -u $addr2 -i /tmp/dev$$` cd $currdir [ "$clash" = "" -o "$clash" = "$driver" ] && return $FAIL # found a clash return $OK } checkram() { driver=$1 addr1=$2 addr2=$3 clash= currdir=`pwd` confdir=/etc/conf/cf.d while doramclash $driver $addr1 $addr2 do prompt_yn " Ram addresses $addr1-$addr2 is already in use for the $clash device. You must choose a unique address for this device to work. Do you wish to choose another address now?" y || cleanup $FAIL if [ "$result" = "Y" ] then return $FAIL else cleanup $FAIL fi done return $OK } # On unix, we must check the lines in mdevice file. # Sets the variable $clash to the driver code name if there is a driver that # has already been allocated the given channel. Uses awk. dodmaclash() { driver=$1 chan=$2 clash= # -1 is never a clash [ "$chan" = "-1" ] && return $FAIL cd $confdir clash=`awk '{ if ( $1 != driver && $9 == dma ) print $1 }' dma=$chan driver=$driver mdevice` [ "$clash" = "" ] && { cd $currdir return $FAIL } cd ../sdevice.d cat $clash | awk '{ if ( $2 == "Y" ) exit 1 }' || return $OK if [ "$rel" = "3.2.0" -o "$rel" = "3.2.1" -o "$rel" = "3.2.2" ] then prompt_yn " DMA channel ${chan} is already in use by the $clash device. However, the $clash device is not currently configured into the kernel. Do you wish to remove DMA channel ${chan} from the $clash device?" y || cleanup $FAIL if [ "$result" = "Y" ] then sed -e "s/Y/N/" $clash > /tmp/bog$$ mv /tmp/bog$$ $clash cd $currdir return $FAIL else cd $currdir return $FAIL fi fi # Should be release >3.2.2, clash driver not installed if we get here. cd $currdir return $FAIL } # # Check if there is a clash of DMA channels # checkdma() { driver=$1 channel=$2 clash= currdir=`pwd` confdir=/etc/conf/cf.d while dodmaclash $driver $channel do prompt_yn " DMA channel ${channel} is already in use by the $clash device. You must choose a unique channel for this device to work. Do you wish to choose another channel now?" y || cleanup $FAIL if [ "$result" = "Y" ] then return $FAIL else cleanup $FAIL fi done return $OK } check_args() { name=$1 bd=$2 case $name in pnt) echo "Configuring PCNET Family board $bd"; PREFIX="pnt"; MAX_BD=3; ;; *) echo "ERROR: Unknown LLI driver being configured ($name$bd)"; cleanup $FAIL; ;; esac if [ $bd -gt $MAX_BD ] then echo "ERROR: Only boards 0..$MAX_BD are supported by this driver"; cleanup $FAIL fi echo } # # restorevector check for sio (vecs 3-4) and pa drivers (vec 7) # if these are being released by lli then let us restore them to sio or pa restorevector() { currdir=`pwd` cd /etc/conf/cf.d intvector=$1 test="0" [ "$intvector" = "3" -o "$intvector" = "4" ] && { prompt_yn "Restore vector $intvector to sio driver" y [ "$result" = "Y" ] && { echo "Restoring vector $intvector to sio driver" siomajor=`./configure -j sio` ./configure -m $siomajor -c -v $intvector -a -Y return $OK } } [ "$intvector" = "7" ] && { prompt_yn "Restore vector $intvector to pa driver" y [ "$result" = "Y" ] && { echo "Restoring vector $intvector to pa driver" pamajor=`./configure -j pa` ./configure -m $pamajor -c -v $intvector -a -Y return $OK } } return $OK } # # determine release, and AT or MCA bus - set rel and type variables accordingly. # os_type() { rel=`sed -n 's/^#rel=\(.*\).$/\1/p' /etc/perms/rts` if [ "$rel" = "3.2.0" -o "$rel" = "3.2.1" -o "$rel" = "3.2.2" ] then type=`sed -n 's/^#typ=\(.*\)$/\1/p' /etc/perms/inst` else # 3.2.4 - one release supports AT, MCA, and EISA. uname -X | grep "BusType = MCA" >/dev/null 2>&1 if [ $? -eq 0 ] then type=386MC else type=386GT fi fi } system_pnt() { bd=$1 IRQ=0; DMA=-1; BIO=0; EIO=0; mech=0; status=1; lastbus=256; /usr/lib/lli/pciinfo -p > /tmp/pci.log 2>&1 status=`awk '{ if($3~/AH/) print $4}' /tmp/pci.log` if [ "$status" = "0x00" ] then mech=`awk '{ if($3~/AL/) print $4}' /tmp/pci.log` ed -s /etc/conf/pack.d/pnt0/space.c << TOAST > /dev/null /ACCESS_TYPE_$bd/ d i #define ACCESS_TYPE_$bd $mech . w q TOAST lastbus=`awk '{ if($5~/CL/) print $6}' /tmp/pci.log` ed -s /etc/conf/pack.d/pnt0/space.c << TOAST > /dev/null /LAST_BUS_$bd/ d i #define LAST_BUS_$bd $lastbus . w q TOAST fi prompt_yn "Detect PCNET hardware automatically?" y || cleanup $FAIL if [ "$result" = "Y" ] then DMACHAN=-1 BIO=0 IRQ=0 else prompt_yn " Do you wish to specify I/O Base Address?" y || cleanup $FAIL if [ "$result" = "Y" ] then while : do prompt_range "Enter I/O base address" $BIO "0" "3e0" "20" || cleanup $FAIL bio=$result EIO=`ha $bio 1f` checkaddr $name$bd $bio $EIO && break done BIO=$bio else BIO=0 fi prompt_yn " Do you wish to specify IRQ?" y || cleanup $FAIL if [ "$result" = "Y" ] then while : do prompt_select "Enter IRQ" $IRQ "0 3 4 5 9 10 11 12 15" || cleanup $FAIL irq=$result checkvec $name$bd $irq && break done IRQ=$irq else IRQ=0 fi prompt_yn " Do you wish to specify DMA Channel?" y || cleanup $FAIL if [ "$result" = "Y" ] then while : do prompt_select "Enter DMA channel ( 0 if NONE ) " $DMA "0 3 5 6 7" || cleanup $FAIL dma=$result checkdma $name$bd $dma && break done DMACHAN=$dma else DMACHAN=-1 fi fi NMINORS="1" } # 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 configure=$5 fi base=`basename $0` drv=`echo $base | sed -e 's/[0-9]*$//` bd=`expr $base : '.*\(.\)'` makedevs $OK check_args $drv $bd # # verify the driver is in the kernel link-kit # idcheck -p $base -i /tmp/dev$$ if [ $? -le 16 ] then echo "Error: $base driver is not installed" cleanup $FAIL fi echo "Reconfiguring the $drv driver" cd /usr/lib/lli/$drv makedevs # # create the temporary directory for installing the driver # cd /tmp; rm -rf $base mkdir $base; cd $base DMACHAN="-1" # # set rel, type variables. # os_type # get the interrupt vector & Base I/O address for the board that we are removing currdir=`pwd` cd /etc/conf/sdevice.d ivec=`awk '{ if ( $1 != "*" ) print $6 }' < $base` OBIO=`awk '{ if ( $1 != "*" ) print $7 }' < $base` cd $currdir # # Do special board dependent processing # system_$drv $bd echo if [ "$IRQ" = "2" ] then IRQ=9 fi echo "$base\tY\t$NMINORS\t5\t0\t$IRQ\t$BIO\t$EIO\t$BRAM\t$ERAM" >./System # # All the drivers support more than one board. In fact all the code to # support all the boards is in the Driver.o for the board for the 1st board # (eg the e3A0 driver acually contains enough code for the e3A1, e3A2 & e3A3 # boards). As we need a Driver.o to be associated with 2nd, 3rd or 4th board # we install a dummy Driver.o, and a Master and Node which will actually cause # calls into the base driver. # if [ $bd -gt 0 ] then echo "$base - iScH $PREFIX$bd 0 0 1 256 $DMACHAN" >./Master echo "clone $base c $base" >./Node idinstall -u -m -s -n -e -k $base else echo "$base I iScH $PREFIX 0 0 1 256 $DMACHAN" >./Master idinstall -u -m -s -e -k $base fi # delete any potential BASE I/O address conflicts with the sio driver [ "$rel" = "3.2.0" -o "$rel" = "3.2.1" -o "$rel" = "3.2.2" ] && sio_conflict if [ "$ivec" = "3" -o "$ivec" = "4" -o "$ivec" = "7" ] then [ ${ivec} != ${IRQ} ] && restorevector $ivec fi cleanup $RELINK