#!/bin/bash
#
#  configure
#  Shell script to configure the NI-KAL kernel build, creates Makefile.in
#  This script must be run before compiling the NI-KAL kernel module
#
#   Copyright 2003-2005,
#  National Instruments Corporation.
#  All Rights reserved.
#
#  originated:  17 March 2003
#

statusFail=1
statusSuccess=0

# Get useful functions to help with install
. ../../bin/installerUtility.sh

# Set local to "C" or Posix so grep -w will work on Mandriva 2007
export LC_ALL=C

nikalInstallationCheck
if [ $? -ne $statusSuccess ]; then
   exit $statusFail
fi

echo " "
echo "Configuring for linux kernel version $kernelVersion."
echo " "

niModulePath=$INSTALL_MOD_PATH/lib/modules/$kernelVersion/kernel/natinst

echo "********************************* NOTE *********************************"
echo "Using kernel headers found in $headersDir."
echo "If this does not correspond to the location of the $kernelVersion headers,"
echo "then define KERNELHEADERS in your environment to point to the location"
echo "of the kernel headers, define KERNELTARGET as the version of the"
echo "kernel for which to compile, and then rerun $0."
echo "********************************* NOTE *********************************"
echo " "

### Determining kernel version code ###
if [ -e $headersDir/include/generated/uapi/linux/version.h ]; then
   LINUX_VERSION_CODE=`$CAT $headersDir/include/generated/uapi/linux/version.h | $GREP LINUX_VERSION_CODE | $CUT -d " " -f 3`
   VERSION_DIR=$headersDir/include/generated/uapi/linux/version.h
elif [ -e $headersDir/include/linux/version.h ]; then
   LINUX_VERSION_CODE=`$CAT $headersDir/include/linux/version.h | $GREP LINUX_VERSION_CODE | $CUT -d " " -f 3`
   VERSION_DIR=$headersDir/include/linux/version.h
elif [ -e $headersDir/Makefile ]; then
   LINUX_VERSION=`$CAT $headersDir/Makefile | $GREP "^VERSION" | $SED 's/.*= *//'`
   LINUX_PATCHLEVEL=`$CAT $headersDir/Makefile | $GREP "^PATCHLEVEL" | $SED 's/.*= *//'`
   LINUX_SUBLEVEL=`$CAT $headersDir/Makefile | $GREP "^SUBLEVEL" | $SED 's/.*= *//'`
   LINUX_VERSION_CODE=`$EXPR $LINUX_VERSION * 65536 + $LINUX_PATCHLEVEL * 256 + $LINUX_SUBLEVEL `
else
   LINUX_VERSION_CODE=`$EXPR $kernelMajor * 65536 + $kernelMinor * 256 + $kernelPatchLevel `
fi
LINUX_260_VERSION_CODE=132608
LINUX_270_VERSION_CODE=132864

### Determining kernel variant ###

echo -n "Kernel has version.h in include/generated/uapi/: "
VERSION_VARIANT=""
if [ "$VERSION_DIR" = "$headersDir/include/generated/uapi/linux/version.h" ]; then
   echo "yes"
   VERSION_VARIANT="-DnNIKAL250_kUAPIVersion"
else
   echo "no"
fi

echo -n "Kernel has reparent_to_init(): "
REPARENT_VARIANT=""
reparent_to_init=`$GREP reparent_to_init $headersDir/kernel/* 2>/dev/null | $GREP -wc reparent_to_init`
if [ $reparent_to_init -ne 0 ]; then
   echo "yes"
   REPARENT_VARIANT="-DnNIKAL100_kReparentToInit"
else
   echo "no"
fi

echo -n "Number of arguments for do_munmap(): "
MUNMAP_VARIANT=""
munmap_fourth=`$GREP do_munmap $headersDir/include/linux/mm.h | $GREP -wc "int acct"`
if [ $munmap_fourth -eq 1 ]; then
   echo "4"
   MUNMAP_VARIANT="-DnNIKAL100_kFourParameterDoMunmap"
else
   echo "3"
fi

echo -n "Kernel has vm_mmap(): "
VMMMAP_VARIANT=""
vm_mmap=`$GREP -wc vm_mmap $headersDir/include/linux/mm.h`
if [ $vm_mmap -ne 0 ]; then
   echo "yes"
   VMMMAP_VARIANT="-DnNIKAL240_kHasVmMmap"
else
   echo "no"
fi

echo -n "Kernel has vm_munmap(): "
VMMUNMAP_VARIANT=""
vm_munmap=`$GREP -wc vm_munmap $headersDir/include/linux/mm.h`
if [ $vm_munmap -ne 0 ]; then
   echo "yes"
   VMMUNMAP_VARIANT="-DnNIKAL240_kHasVmMunmap"
else
   echo "no"
fi

echo -n "Kernel has VM_RESERVED: "
VM_RESERVED_VARIANT=""
vm_rsvd=`$GREP -wc VM_RESERVED $headersDir/include/linux/mm.h`
if [ $vm_rsvd -ne 0 ]; then
   echo "yes"
   VM_RESERVED_VARIANT="-DnNIKAL240_kHasVM_RESERVED"
else
   echo "no"
fi

echo -n "Kernel struct pci_dev has busn_res member: "
BUSNRES_VARIANT=""
busnres=`$GREP 'struct[[:space:]]\+resource' $headersDir/include/linux/pci.h | $GREP -wc 'busn_res'`
if [ $busnres -ne 0 ]; then
   echo "yes"
   BUSNRES_VARIANT="-DnNIKAL240_kHasPciBusnRes"
else
   echo "no"
fi


echo -n "pte_offset function: "
OFFSET_VARIANT=""
pte_offset_kernel_path=""
if [ -d $headersDir/arch/x86/include/asm ]; then
   pte_offset_kernel_path="$headersDir/arch/x86/include/asm/*"
elif [ -d $headersDir/arch/arm/include/asm ]; then
   pte_offset_kernel_path="$headersDir/arch/arm/include/asm/*"
fi
if [ -d $headersDir/include/asm ]; then
   pte_offset_kernel_path="$pte_offset_kernel_path $headersDir/include/asm/*"
fi
pte_offset_kernel=`$GREP pte_offset_kernel $pte_offset_kernel_path 2>/dev/null | $GREP -wc pte_offset_kernel`
if [ $pte_offset_kernel -ne 0 ]; then
   echo "pte_offset_kernel()"
   OFFSET_VARIANT="-DnNIKAL100_kPTEOffsetKernel"
else
   echo "pte_offset()"
fi

echo -n "Levels in page table: "
PAGE_TABLE_LEVEL_VARIANT=""
if [ -e $headersDir/include/asm-generic ]; then
   pud_offset_exists=`$GREP pud_offset $headersDir/include/asm-generic/* 2>/dev/null | $GREP -wc pud_offset`
   if [ $pud_offset_exists -ne 0 ]; then
      echo "4"
      PAGE_TABLE_LEVEL_VARIANT="-DnNIKAL100_kFourLevelPageTable"
   else
      echo "3"
   fi
else
   echo "3"
fi

echo -n "Kernel has remap_pfn_range: "
REMAP_PFN_RANGE_VARIANT=""
REMAP_ARGS_VARIANT=""
remap_pfn_range=`$GREP -wc remap_pfn_range $headersDir/include/linux/mm.h`
if [ $remap_pfn_range -ne 0 ]; then
   echo "yes"
   REMAP_PFN_RANGE_VARIANT="-DnNIKAL100_kRemapPFNRange"
else
   echo "no"
   echo -n "Number of arguments for remap_page_range(): "
   remap_fifth=`$GREP remap_page_range $headersDir/include/linux/mm.h | $GREP -wc "vm_area_struct"`
   if [ $remap_fifth -eq 1 ]; then
      echo "5"
      REMAP_ARGS_VARIANT="-DnNIKAL100_kFiveParameterRemapPageRange"
   else
      echo "4"
   fi
fi

echo -n "Kernel has kzalloc: "
KZALLOC_VARIANT=""
kzalloc=`$GREP -wc kzalloc $headersDir/include/linux/slab.h`
if [ $kzalloc -ne 0 ]; then
   echo "yes"
   KZALLOC_VARIANT="-DnNIKAL200_kHasKzalloc"
else
   echo "no"
fi

echo -n "Kernel has chained SGL support: "
CHAINED_SGL_VARIANT=""
chained_sgl=`$GREP -wc sg_alloc_table $headersDir/include/linux/scatterlist.h`
if [ $chained_sgl -ne 0 ]; then
   # TODO: CAR 450729.  There's a better way to do this.
   if [ -d $headersDir/arch/arm/include/asm ]; then
      echo "limited"
      CHAINED_SGL_VARIANT="-DnNIKAL220_kHasSGLPageAPI"
   else
      echo "yes"
      CHAINED_SGL_VARIANT="-DnNIKAL220_kHasChainedSGL"
   fi
else
   echo "no"
fi

echo -n "USB altsetting name: "
USB_ALTSETTINGS_PTR_VARIANT=""
cur_altsetting=`$GREP -wc cur_altsetting $headersDir/include/linux/usb.h`
if [ $cur_altsetting -ne 0 ]; then
   echo "cur_altsetting"
   USB_ALTSETTINGS_PTR_VARIANT="-DnNIKAL100_kCurrentAlternateSetting"
else
   echo "act_altsetting"
fi

echo -n "Kernel has usb_get_intf(): "
USB_INTERFACE_REFCOUNT_VARIANT=""
usb_get_intf=`$GREP -wc usb_get_intf $headersDir/include/linux/usb.h`
if [ $usb_get_intf -ne 0 ]; then
   echo "yes"
   USB_INTERFACE_REFCOUNT_VARIANT="-DnNIKAL100_kUSBReferenceCountFunctions"
else
   echo "no"
fi

echo -n "Kernel has intf_cache member in usb_host_config: "
USB_INTERFACE_CACHE_VARIANT=""
usb_interface_cache=`$AWK '/struct usb_host_config \{/, /}/' $headersDir/include/linux/usb.h | $GREP -wc intf_cache`
if [ $usb_interface_cache -ne 0 ]; then
   echo "yes"
   USB_INTERFACE_CACHE_VARIANT="-DnNIKAL100_kUSBInterfaceCacheMember"
else
   echo "no"
fi

echo -n "Kernel has ep[] members in usb_device: "
USB_DEVICE_EP_ARRAY_VARIANT=""
usb_device_ep_array=`$AWK '/struct usb_device \{/, /}/' $headersDir/include/linux/usb.h | $GREP -wc ep_out`
if [ $usb_device_ep_array -ne 0 ]; then
   echo "yes"
   USB_DEVICE_EP_ARRAY_VARIANT="-DnNIKAL100_kUSBDeviceEndpointArray"
else
   echo "no"
fi

echo -n "Kernel exports usb_set_configuration(): "
USB_SET_CONFIGURATION_VARIANT=""
usb_set_configuration=`$GREP -wc usb_set_configuration $headersDir/include/linux/usb.h`
if [ $usb_set_configuration -ne 0 ]; then
   echo "yes"
   USB_SET_CONFIGURATION_VARIANT="-DnNIKAL100_kUSBSetConfiguration"
else
   echo "no"
fi

echo -n "Units of USB_CTRL_GET_TIMEOUT: "
USB_TIMEOUT_UNITS_VARIANT=""
usb_timeout_units=`$GREP -B 7 USB_CTRL_GET_TIMEOUT $headersDir/include/linux/usb.h | $GREP -wc milliseconds`
if [ $usb_timeout_units -ne 0 ]; then
   echo "msec"
   USB_TIMEOUT_UNITS_VARIANT="-DnNIKAL100_kUSBmsecTimeout"
else
   echo "sec"
fi

echo -n "Kernel has owner member in usb_driver: "
USB_OWNER_VARIANT=""
usb_owner=`$AWK '/struct usb_driver \{/, /}/' $headersDir/include/linux/usb.h | $GREP -wc owner`
if [ $usb_owner -ne 0 ]; then
   echo "yes"
   USB_OWNER_VARIANT="-DnNIKAL130_kUSBOwnerMember"
else
   echo "no"
fi

echo -n "Kernel has put_page_testzero(): "
PUT_PAGE_TESTZERO_VARIANT=""
put_page_testzero=`$GREP -wc put_page_testzero $headersDir/include/linux/mm.h`
if [ $put_page_testzero -ne 0 ]; then
   echo "yes"
   PUT_PAGE_TESTZERO_VARIANT="-DnNIKAL100_kPutPageTestzero"
else
   echo "no"
fi

echo -n "Kernel has mutex method: "
MUTEX_VARIANT=""
if [ -e $headersDir/include/linux/mutex.h ]; then
   echo "yes"
   MUTEX_VARIANT="-DnNIKAL150_kMutexMethod"
else
   echo "no"
fi

echo -n "Kernel has wait_for_completion_interruptible: "
COMPLETION_VARIANT=""
completion_interruptible=`$GREP -wc wait_for_completion_interruptible $headersDir/include/linux/completion.h`
if [ $completion_interruptible -ne 0 ]; then
   echo "yes"
   COMPLETION_VARIANT="-DnNIKAL200_kCompletion"
else
   echo "no"
fi

echo -n "Kernel has config.h: "
CONFIG_VARIANT=""
if [ -e $headersDir/include/linux/config.h ]; then
   echo "yes"
   CONFIG_VARIANT="-DnNIKAL160_kConfig"
else
   echo "no"
fi

echo -n "Kernel has ioctl32.h: "
IOCTL32_VARIANT=""
if [ -e $headersDir/include/linux/ioctl32.h ]; then
   echo "yes"
   IOCTL32_VARIANT="-DnNIKAL170_kIoctl32"
else
   echo "no"
fi

echo -n "IRQ handlers have pt_regs: "
IRQ_REGS_VARIANT=""
pt_regs=`$GREP -wc pt_regs $headersDir/include/linux/interrupt.h`
if [ $pt_regs -ne 0 ]; then
   echo "yes"
   IRQ_REGS_VARIANT="-DnNIKAL160_kIRQRegs"
else
   echo "no"
fi

echo -n "Kernel has work_struct and delayed_work: "
WORKQUEUE_VARIANT=""
work_struct_timer=`$AWK '/struct work_struct \{/, /}/' $headersDir/include/linux/workqueue.h | $GREP -wc timer`
if [ $work_struct_timer -eq 0 ]; then
   echo "yes"
   WORKQUEUE_VARIANT="-DnNIKAL160_kWorkqueueNonDelay"
else
   echo "no"
fi

echo -n "Kernel supports fault method in vm_operations_struct: "
VM_OPS_VARIANT=""
fault=`$AWK '/struct vm_operations_struct \{/, /}/' $headersDir/include/linux/mm.h | $GREP -wc fault`
if [ $fault -ne 0 ]; then
   echo "yes"
   VM_OPS_VARIANT="-DnNIKAL190_kVmFaultMethod"
else
   echo "no"
fi

echo -n "Kernel has ioremap_wc: "
IOREMAP_WC_VARIANT=""
ioremap_wc=`$GREP -wc ioremap_wc $headersDir/include/asm-generic/iomap.h`
if [ $ioremap_wc -ne 0 ]; then
   echo "yes"
   IOREMAP_WC_VARIANT="-DnNIKAL230_kHas_ioremap_wc"
else
   echo "no"
fi

echo -n "Kernel has pgprot_writecombine: "
PGPROT_WC_VARIANT=""
pgprot_wc=`$GREP -wc pgprot_writecombine $headersDir/include/asm-generic/pgtable.h`
if [ $pgprot_wc -ne 0 ]; then
   echo "yes"
   PGPROT_WC_VARIANT="-DnNIKAL230_kHas_pgprot_writecombine"
else
   echo "no"
fi

echo -n "Kernel has cred.h: "
CRED_VARIANT=""
if [ -e $headersDir/include/linux/cred.h ]; then
   echo "yes"
   CRED_VARIANT="-DnNIKAL230_kHasCred"
else
   echo "no"
fi

echo -n "Kernel has uidgid.h: "
UIDGID_VARIANT=""
if [ -e $headersDir/include/linux/uidgid.h ]; then
   echo "yes"
   UIDGID_VARIANT="-DnNIKAL1400_kHasUidGid"
else
   echo "no"
fi

echo -n "Kernel has UMH constants: "
UMH_VARIANT=""
umh_constants=`$GREP -wc UMH_NO_WAIT $headersDir/include/linux/kmod.h`
if [ $umh_constants -ne 0 ]; then
   echo "yes"
   UMH_VARIANT="-DnNIKAL240_kHasUMHConstants"
else
   echo "no"
fi

echo -n "Kernel has create_proc_read_entry: "
HAS_CREATE_PROC_READ_ENTRY=""
proc_create_data=`$GREP -wc create_proc_read_entry $headersDir/include/linux/proc_fs.h`
if [ $proc_create_data -ne 0 ]; then
   echo "yes"
   HAS_CREATE_PROC_READ_ENTRY="-DnNIKAL1400_kHasCreateProcReadEntry"
else
   echo "no"
fi

echo -n "Kernel has namespaced generic netlink API: "
NAMESPACED_GENETLINK_VARIANT=""
namespaced_genetlink=`$AWK '/genlmsg_unicast\(/, /\)/' $headersDir/include/net/genetlink.h | $GREP -c 'struct net'`
if [ $namespaced_genetlink -ne 0 ]; then
   echo "yes"
   NAMESPACED_GENETLINK_VARIANT="-DnNIKAL250_kHasNamespacedGenetlink"
else
   echo "no"
fi

echo -n "Kernel has genlmsg_new: "
GENLMSG_NEW_VARIANT=""
genlmsg_new=`$GREP -wc genlmsg_new $headersDir/include/net/genetlink.h`
if [ $genlmsg_new -ne 0 ]; then
   echo "yes"
   GENLMSG_NEW_VARIANT="-DnNIKAL250_kHasGenlmsgNew"
else
   echo "no"
fi

echo -n "Kernel has family genlmsg_put: "
FAMILY_GENLMSG_PUT_VARIANT=""
family_genlmsg_put=`$AWK '/genlmsg_put\(/, /\)/' $headersDir/include/net/genetlink.h | $GREP -c 'struct genl_family'`
if [ $family_genlmsg_put -ne 0 ]; then
   echo "yes"
   FAMILY_GENLMSG_PUT_VARIANT="-DnNIKAL250_kHasFamilyGenlmsgPut"
else
   echo "no"
fi

echo -n "Kernel has family genl_ops_groups: "
FAMILY_GENLOPS_GROUPS_VARIANT=""
family_genlops_groups=`$GREP -wc genl_register_family_with_ops_groups $headersDir/include/net/genetlink.h`
if [ $family_genlops_groups -ne 0 ]; then
   echo "yes"
   FAMILY_GENLOPS_GROUPS_VARIANT="-DnNIKAL1400_kHasFamilyGenlOpsGroups"
else
   echo "no"
fi

echo -n "Kernel has usleep_range(): "
HIGHRES_TIMER_VARIANT=""
usleep_range=`$GREP -wc usleep_range $headersDir/include/linux/delay.h`
if [ $usleep_range -ne 0 ]; then
   echo "yes"
   HIGHRES_TIMER_VARIANT="-DnNIKAL100_kHighresTimerAvailable"
else
   echo "no"
fi

echo -n "Kernel has RS-485 serial_core support: "
HAS_RS485_SUPPORT=""
txvr_ops=`$GREP -wc txvr_ops $headersDir/include/linux/serial_core.h`
if [ $txvr_ops -ne 0 ]; then
   echo "yes"
   HAS_RS485_SUPPORT="-DnNIKAL100_kHasRS485Support"
else
   echo "no"
fi

echo -n "Kernel struct uart_ops has set_wake(): "
UART_SET_WAKE_VARIANT=""
uart_set_wake=`$GREP -wc set_wake $headersDir/include/linux/serial_core.h`
if [ $uart_set_wake -ne 0 ]; then
   echo "yes"
   UART_SET_WAKE_VARIANT="-DnNIKAL1400_kHasUartSetWake"
else
   echo "no"
fi

echo -n "Kernel uses tty_port instead of tty_struct for tty helper functions: "
USE_TTY_PORT_PARAM=""
tty_port_param=`$GREP -wc 'tty_insert_flip_char[[:blank:]]*([[:blank:]]*struct tty_port' $headersDir/include/linux/tty_flip.h`
if [ $tty_port_param -ne 0 ]; then
   echo "yes"
   USE_TTY_PORT_PARAM="-DnNIKAL100_kUseTtyPortParam"
else
   echo "no"
fi

DEBUG_VARIANT=""
if [ "$1" = "debug" ]; then
   echo " "
   echo "NI-KAL will be compiled in debug mode."
   DEBUG_VARIANT="-DnNIKAL100_kDebuggingIsActive"
fi

# JAH 2013/10/30: NOTE: Going forward, please try to use negative logic when
# adding preprocessor defines here.  So instead of setting kHasChainedSGL for newer
# kernels, set kNoChainedSGL for older kernels.  Doing things that way favors
# newer kernels over old outdated ones, which makes long-term maintenance easier,
# and will in most cases eliminate the need for us to add a static PP_DEFINE for
# our Linux RT build (as Linux RT typically uses fairly new kernels).

# Echo all variables to concatenate the strings
KERNEL_VARIANTS="`echo $REPARENT_VARIANT $MUNMAP_VARIANT $VMMMAP_VARIANT \
$VMMUNMAP_VARIANT $BUSNRES_VARIANT $OFFSET_VARIANT $REMAP_ARGS_VARIANT \
$USB_ALTSETTINGS_PTR_VARIANT $USB_INTERFACE_REFCOUNT_VARIANT \
$USB_INTERFACE_CACHE_VARIANT $USB_SET_CONFIGURATION_VARIANT $DEBUG_VARIANT \
$REMAP_PFN_RANGE_VARIANT $USB_DEVICE_EP_ARRAY_VARIANT $PAGE_TABLE_LEVEL_VARIANT \
$USB_TIMEOUT_UNITS_VARIANT $USB_OWNER_VARIANT $PUT_PAGE_TESTZERO_VARIANT \
$MUTEX_VARIANT $CONFIG_VARIANT $IRQ_REGS_VARIANT $WORKQUEUE_VARIANT \
$IOCTL32_VARIANT $VM_OPS_VARIANT $COMPLETION_VARIANT $KZALLOC_VARIANT \
$GENERATED_DIR_VARIANT $CHAINED_SGL_VARIANT $IOREMAP_WC_VARIANT $PGPROT_WC_VARIANT \
$CRED_VARIANT $UIDGID_VARIANT $VM_RESERVED_VARIANT $UMH_VARIANT \
$GENLMSG_NEW_VARIANT $NAMESPACED_GENETLINK_VARIANT $FAMILY_GENLMSG_PUT_VARIANT \
$FAMILY_GENLOPS_GROUPS_VARIANT $HIGHRES_TIMER_VARIANT $VERSION_VARIANT \
$HAS_CREATE_PROC_READ_ENTRY $HAS_RS485_SUPPORT $USE_TTY_PORT_PARAM \
$UART_SET_WAKE_VARIANT`"

echo " "
echo "Storing configuration in Makefile.in"
echo "If the values stored are incorrect they can be changed before running make."
echo " "

dumpTools > ./Makefile.in
echo "KERNELTARGET=$kernelVersion
KERNELDIRECTORY=$headersDir
MODPATH=$niModulePath
LINUX_VERSION_CODE=$LINUX_VERSION_CODE
LINUX_260_VERSION_CODE=$LINUX_260_VERSION_CODE
LINUX_270_VERSION_CODE=$LINUX_270_VERSION_CODE
MIN_SUPPORTED_VERSION_CODE=$LINUX_260_VERSION_CODE
MAX_SUPPORTED_VERSION_CODE=$LINUX_270_VERSION_CODE
KERNEL_VARIANTS=\"$KERNEL_VARIANTS\"" >> ./Makefile.in
