:
#       @(#) parallel.sh 25.5 92/12/07 
#
#       Copyright (C) 1991-1992 The Santa Cruz Operation, Inc.
#               All Rights Reserved.
#       The information in this file is provided for the exclusive use of
#       the licensees of The Santa Cruz Operation, Inc.  Such users have the
#       right to use, modify, and incorporate this code into other products
#       for purposes authorized by the license agreement provided they include
#       this notice and the associated copyright notice with any such product.
#       The information in this file is provided "AS IS" without warranty.
#
#       mkdev/parallel - Parallel Port Configuration
#

DRIVER=pa

# Function Definitions
#########################
SYSTEM=/etc/conf/sdevice.d/pa
MCA_interrupt=7
TMP2=/tmp/sdev.$$
stub_port=""
stub_ent=0

# Define return values
: ${OK=0} ${FAIL=1} ${STOP=10} ${HALT=11}

# Define traps for critical and non critical code.
set_trap()  {   
        trap 'echo "\nInterrupted! Exiting ..."; cleanup 1' 1 2 3 15
}

unset_trap()  {
        trap '' 1 2 3 15
}

# clear the screen if it is supported
clearscr() {
        # check if the terminal environment is set up
        [ "$TERM" ] && clear 2> /dev/null
}
 
# Remove temp files and exit with the status passed as argument
cleanup() {
        trap '' 1 2 3 15
        # make sure that the System is removed 
        rm -f System $TMP2 /tmp/pa$$ /tmp/pa1$$ /tmp/pa2$$ /tmp/$$tmp /tmp/System.$$
        [ "$tmp" ] && rm -f $tmp*
        exit $1
}

# Prompt for yes or no answer - returns non-zero for no
getyn() {
        while   echo "$* (y/n) \c">&2
        do      read yn rest
                case $yn in
                [yY])   return $OK                      ;;
                [nN])   return $FAIL                    ;;
                *)      echo "Please answer y or n" >&2 ;;
                esac
        done
}

# Prompt with mesg, return non-zero on q
prompt() {
        while   echo "\n${mesg}or enter q to quit: \c" >&2
        do      read cmd
                case $cmd in
                +x|-x)  set $cmd                                        ;;
                Q|q)    return $FAIL                                    ;;
                !*)     eval `expr "$cmd" : "!\(.*\)"`                  ;;
                "")     # If there is an argument use it as the default
                        # else loop until 'cmd' is set
                        [ "$1" ] && { 
                                cmd=$1
                                return $OK
                        }
                        : continue
                        ;;
                *)      return $OK                                      ;;
                esac
        done
}

# Print an error message
error() {
        echo "\nError: $*" >&2
        return $FAIL
}

# Configure error message
conferr()  {
        error "configure failed to update system configuration.
Check /etc/conf/cf.d/conflog for details."
}

# perms list needed if link kit must be installed
permschk () {
        if [ -f /etc/perms/extmd ]; then
                PERM=/etc/perms/extmd
        else
                error "Cannot locate /etc/perms/extmd. This file
is needed to verify Link Kit installation."
                cleanup $FAIL
        fi
}

# test to see if link kit is installed
linkchk()  {
        cd /
        until   fixperm -i -d LINK $PERM
        do      case $? in
                4)  echo "\nThe Link Kit is not installed." >&2 ;;
                5)  echo "\nThe Link Kit is only partially installed." >&2  ;;
                *)  echo "\nError testing for Link Kit.  Exiting." >&2; cleanup $FAIL  ;;
                esac

                # Not fully installed. Do so here
                getyn "\nDo you wish to install it now?" || {
                        # answered no
                        echo "
The Link Kit must be installed to run this program.  Exiting ..."
                        cleanup $OK
                }

                # answered yes, so install link kit
                echo "\nInvoking /etc/custom\n"
                /etc/custom -o -i LINK || {
                        # custom exited unsuccessfully
                        error "custom failed to install Link Kit successfully.  Please try again."
                        cleanup $FAIL
                }
        done
}

asklink()  {
        getyn "
You must create a new kernel to effect the driver change you specified.
Do you wish to create a new kernel now?"  ||  {
                echo "
To create a new kernel execute /etc/conf/cf.d/link_unix. Then you
must reboot your system by executing  /etc/shutdown -i0  before the 
changes you have specified will be implemented.\n"
                        return $FAIL 
                }
        return $OK
}

# re-link new kernel
klink() {
        cd /etc/conf/cf.d
        ./link_unix || { 
                echo "\nError: Kernel link failed."
                cleanup $FAIL
        }
        return $OK
}

get_list() {
        not_installed="
        1. Serial/Parallel adapter #1  : address = 378-37f
        2. Parallel/Monochrome adapter : address = 3bc-3be
        3. Serial/Parallel adapter #2  : address = 278-27a
        4. Other Adapter
"
        not_installed=`grep -v $not_install` > /dev/null
}

get_device() {
        case $1 in
        1) dev="/dev/lp0" break ;;
        2) dev="/dev/lp1" break ;;
        3) dev="/dev/lp2" break ;;      
        *) dev="Other device" break ;;
        esac
}

# name a card based on unit number
find_port_name() {
        stub=$FAIL
        sioa=`awk ' $1 == '$1'  { print $3 }' <  $TMP2` 
        eioa=`awk ' $1 == '$1'  { print $4 }' <  $TMP2` 
        case $sioa in
        0)      [ "$stub_port" ] || stub_port=$1
                stub=$OK ;;
        378)    if [ "$eioa" = "37f" ]
                then
                        name="Serial/Parallel adapter #1" break
                else
                        name="Other adapter" break 
                fi ;;
        3bc)    if [ "$eioa" = "3be" ]
                then
                        name="Parallel/Monochrome adapter"  
                else
                        name="Other adapter" break 
                fi ;;
        278)    if [ "$eioa" = "27a" ]
                then
                        name="Serial/Parallel adapter #2"  
                else
                        name="Other adapter" break 
                fi ;;
        *)      name="Other adapter" break ;;
        esac
}

find_name() {
   find_port_name $1 $2
   [ "$stub" -eq "$OK" ] || {
        p2=`awk ' $1 == '$1'  { printf(" : address = %s-%s\n",$3,$4) ; }' <  $TMP2` 
        get_device $1
        name="$name $p2 ($dev)"
   }
}

find_name_int() {
   find_port_name $1 $2
   [ "$stub" -eq "$OK" ] || {
        p2=`awk ' $1 == '$1'  { printf(" : address = %s-%s, interrupt = %d \n",$3,$4,$2) ; }' <  $TMP2` 
        get_device $1
        name="$name $p2 ($dev)"
   }
}

# get the pa sdevice file
get_sdevice() {
        /etc/conf/bin/idinstall -gs $DRIVER >System  || cleanup $FAIL
}

# change the state of port $1 to $2 and set interrupt if not 0
change_port() {
        awk ' 
        BEGIN { OFS = "\t"; }
        { 
        if ( $1 == "pa" && $3 == '$1' ) {
                $2 = "'$2'" ; if ( '$3' != 0 ) $6 = '$3'; print; 
        }
        else
                        print ;
        }' < System > System.$$
        mv -f System.$$ System
        /etc/conf/bin/idinstall -us $DRIVER || cleanup $FAIL
}

# update the sdevice file
update_system() {
        [ -f "$SYSTEM" ] && {
        awk ' FNR == '$1' { print ; } '<$SYSTEM >/tmp/pa$$
        }
        
        sioa=`awk '{ print $7 }' < /tmp/pa$$`
        eioa=`awk '{ print $8 }' < /tmp/pa$$`

        ed $SYSTEM << END > /dev/null
$1
s/$sioa/0
$1
s/$eioa/0
w
q
END

}

# list the installed cards
list_installed() {
        n=0 
        stub_ent=0              # the number of 'Y' entries in the sdevice
        installed=0
        installed_ports=""
        notinstalled_ports=""
 
        set `sed -e 's/..*\([YN]\)..*/\1/' <$SYSTEM`
        for x in $*
        do
           n=`expr $n + 1`
           find_name $n $x
                
                if [ "$x" = "Y" ]
                then
                    if [ "$stub" -eq "$OK" ] 
                    then
                        stub_ent=`expr $stub_ent + 1`
                    else
                        installed=`expr $installed + 1` 
                        installed_ports=$installed_ports"\n\t"$n". "$name
                    fi
                else # N
                        notinstalled_ports=$notinstalled_ports"\n\t"$n". "$name
                fi
        done
        name="Other adapter ( configurable )"
        n=`expr $n + 1`
        notinstalled_ports=$notinstalled_ports"\n\t"$n". "$name
        total=$n

        return $OK
}

# list the installed cards
show_installed() {
        n=0
        stub_ent=0
        installed=0
        installed_ports=""
 
        set `sed -e 's/..*\([YN]\)..*/\1/' <$SYSTEM`
        for x in $*
        do
           n=`expr $n + 1`
           find_name_int $n
                if [ "$x" = "Y" ]
                then
                    if [ "$stub" -eq "$OK" ] 
                    then
                        stub_ent=`expr $stub_ent + 1`
                    else
                        installed=`expr $installed + 1` 
                        installed_ports=$installed_ports"\n\t"$name
                    fi
                fi
        done
        return $OK
}

show_config()   {
        nentries=`awk '$1 == "pa" {print $1}' < $SYSTEM | wc -l `
        installed=`awk '$1 == "pa" && $2 == "Y" {print $1}' < $SYSTEM | wc -l `
        # get index for serial board from System file
        # show start i/o address and end i/o address
        awk ' $1 == "pa" {printf("%d %d %s %s\n",$3,$6,$7,$8) }' < $SYSTEM > $TMP2
        if [ $nentries -eq 0 ] ||  [ $installed -eq 0 ] 
        then
                no_ports=true
                echo "\nThere are no parallel ports configured."
                #return $FAIL;
        else 
                no_ports=false
                get_sdevice 
                show_installed
                echo "\nThe following cards are currently configured:"
                echo $installed_ports

                return $OK
        fi
}

# manually configure the adapter
manadd() {
        while   mesg="Please specify the start base address in hexadecimal "
        do      prompt || cleanup $OK
                case $cmd in
                [0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]|\
                [0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])
                        sioa=$cmd break;;
                *) echo "\nBase address must be a hexadecimal value or press 'q'"
                esac
        done
        while   mesg="Please specify the end base address in hexadecimal "
        do      prompt || cleanup $OK
                case $cmd in
                [0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]|\
                [0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])
                        eioa=$cmd break;;
                *) echo "\nBase address must be a hexadecimal value or press 'q'"
                esac
        done
}

check_it() {
        for i in $list
        do
                [ "$i" = "$1" ] && return $OK
        done
        return $FAIL
}

chk_installed() {
        grep Y $SYSTEM | grep $1 | grep $2 > /dev/null
        if [ $? = 0 ]
        then #already installed
                echo "This adapter is already configured in the kernel\n"
                return $FAIL
        else # not installed yet
                return $OK
        fi
}

# stub_add() will change the first stub 'Y' entry with 0's address 
stub_add() {
        awk '
        BEGIN { OFS = "\t"; }
        {
        if ( $1 == "pa" && $3 == '$stub_port' ) {
                $6 = '$1'; $7 = "'$2'"; $8 = "'$3'"; print;
        }
        else
                        print ;
        }' < System > System.$$
        mv -f System.$$ $SYSTEM

}

# add a parallel port
add() {
        get_sdevice
        [ $installed -gt 1 ] && list_installed
        if [ $installed -eq 3 ]
        then
                echo "\nAll three parallel ports are already configured."
                cleanup $OK
        else
                while   mesg="Please select the I/O address for the adapter:

        1. Serial/Parallel adapter #1  : address = 378-37f
        2. Parallel/Monochrome adapter : address = 3bc-3be
        3. Serial/Parallel adapter #2  : address = 278-27a
        4. Other configuration

Select an option "
                do      prompt || cleanup $OK
                        case $cmd in
                        1)      sioa=378
                                eioa=37f
                                toadd=$cmd 
                                current_irq=7
                                chk_installed $sioa $eioa && break;;
                        2)      sioa=3bc
                                eioa=3be
                                toadd=$cmd 
                                current_irq=5
                                chk_installed $sioa $eioa && break;;
                        3)      sioa=278
                                eioa=27a
                                toadd=$cmd 
                                current_irq=5
                                chk_installed $sioa $eioa && break;;
                        4)      manadd 
                                current_irq=5
                                break;;
                        *)      echo "\nSelection an option or press 'q'"
                        esac
                done



# if mca, interrupt is always 7, else check with user           
                if [ $ARCH -eq 0 ]
                then
                        #current_irq=`awk  '{ if ( $1 == '$cmd') {printf("%d\n",$2) ; } } ' < $TMP2 `
                        while   echo "\n 
Should this port use interrupt (default [$current_irq]): \c"
                        do      
                                read x
                                case $x in
                                        "")     interrupt=$current_irq break;;
                                     [1-9])     interrupt=$x break;;    
                                         *)     echo "\nEnter a vector or press 'q'"
                                esac
                        done
                else
                        interrupt=$MCA_interrupt
                fi

                if [ "$stub_ent" = "0" ]
                then
           	n=`expr $nentries + 1`
                echo "pa	Y	$n	2	4	$interrupt	$sioa	$eioa	0	0" >> $SYSTEM
                        get_device $n 
                else
                        stub_add $interrupt $sioa $eioa
                        get_device $stub_port 
                fi
        fi
        echo "\nThe device node is $dev\n"

# relink and reboot if called for
asklink && klink

}

# remove a parallel port
del() {
        get_sdevice || error Cannot get sdevice file
        [ $installed -gt 0 ] && list_installed
        echo $installed_ports > /tmp/$$tmp
        list=`awk -F. '{print $1}'</tmp/$$tmp `
        if [ $installed -eq 0 ]
        then
                echo "\nThere are no parallel ports configured."
                cleanup $OK
        else
                while   mesg="Which port would you like to remove ?
        $installed_ports

Select an option from above "
                do      prompt || cleanup $OK
                        case $cmd in
                        [1-3])  toadd=$cmd 
                                check_it $cmd && break;;
                        *)      echo "\nSelection an option from above or press 'q'"
                        esac
                done
                entry=`grep Y $SYSTEM | wc -l`
                if [ `expr $entry - $stub_ent` -eq "1" ]
                then
                        # If it is the last configured entry
                        rm -f $SYSTEM
                        touch $SYSTEM
                elif [ "$installed" -eq "$cmd" ]
                then
                        # if it is the last entry
        ed $SYSTEM << END > /dev/null
$cmd
d
w
q
END
                else
                        update_system $cmd
                fi
        fi
# relink and reboot if called for
asklink && klink

}

# help option in mkdev parallel
help() {
echo "
1. Adding parallel adapter
   The first, second and third parallel ports configured in the system 
   will have device nodes /dev/lp0, /dev/lp1 and /dev/lp2 respectively.

   If your parallel port is not being recognized at boot up, then
   you need to determine the card's address and interrupt. Perform
   the following steps:

	- Shut down the system and switch it off. 
	- Run the hardware configuration program to determine the address
	  and interrupt. If the card does not have a configuration program,
	  remove the card from the computer and make a note of the address 
	  and interrupt on the card.  

   Restart the system and invoke \"mkdev parallel\" to configure the parallel
   ports.

Hit return to continue
"
        read key

echo "
2. Deleting parallel adapter
   If one parallel adapter is removed, the device nodes that are connected
   to other configured parallel adapters will remain the same. For example,
   suppose the following adapters are configured in the system,

        adapter #1, address=378-37f, /dev/lp0
        adapter #2, address=3bc-3be, /dev/lp1
  
   If adapter #1 is removed, the configuration is 

        adapter #2, address=3bc-3be, /dev/lp1

   If a new adapter is added into the system, the configuration becomes

        new adapter, address=4bc-4be, /dev/lp0
        adapter #2, address=3bc-3be, /dev/lp1

Hit return to continue
"
        read key
}

choose_action() {
while   mesg="Do you wish to:

        1. Add a parallel port
        2. Remove a parallel port
        3. Show configuration
        4. Help

Select an option "
do      prompt || cleanup $OK
        case $cmd in
        1)      add; break      ;;
        2)      del; break      ;;
        3)      show_config     
                echo "\nHit return to continue"
                read key
                clearscr        ;;
        4)      help; clearscr  ;;
        *) echo "\nEnter 1, 2, 3, 4 or q" >&2 ;;
        esac
done
}

# remove all the "N" entries in the sdevice.d/pa file
clean_sdevice() {
[ -f $SYSTEM ] && {
    grep "N" $SYSTEM > /tmp/pa$$ 2>&1
    [ $? = 0 ] && {
	grep "	Y	" $SYSTEM > /tmp/pa$$ 2>&1
	if [ $? != 0 ]
        then
                # remove all the entries if no pa is configured.
                cp /tmp/pa$$ $SYSTEM
        else
                # change the sdevice.d/pa such that all "N" entries
                # are deleted and "Y" entries unit numbers are in
                # sequence.
                [ `wc -l < /tmp/pa$$` -gt 0 ] && {
                        awk '
                        BEGIN { OFS = "\t"; entry = 0 }
                        {
                                $3=++entry
                                print
                        }' < /tmp/pa$$ > $SYSTEM
                }
        fi
        rm -f /tmp/pa$$
    }
}


}

# main
#
set trap

# check if machine is mca or not, so we can ignore interrupts
cd /
if cat /dev/mcapos 1>/dev/null 2>/dev/null 
then ARCH=1
else ARCH=0
fi

clearscr
echo "\n\nParallel Port Initialization \n"
permschk
linkchk

# remove all the "N" entries first
clean_sdevice

# print out current config, and ask questions
(show_config && choose_action) 

cleanup $OK

