Kernel Module E1000E Update For SL5.1
=====================================

This document is almost certainly obsolete, hence I just include the
unformatted POD source of the original::

    =head2 References
    
    =over 4
    
    =item *
    
    http://support.intel.com/support/
    
    =back
    
    =head2 Introduction
    
    The Intel Gigabit ethernet card F<82567LM>, which comes with the
    new Fujitsu Siemens computers F<Celsius W370>, F<Esprimo p7935 e80>,
    F<Esprimo e7935 e80> and F<Lifebook e8420>, contemporary does not work
    out of the box in SL51 (and for sure others) because the updated version
    of the e1000e driver is not available yet in Scientific Linux.
    
    As a consequence of this the network installation is not working for this
    kind of hardware, because
    the SL5.1 installation kernel, too, is not coming with the proper driver.
    
    This documents describes a quick workaround, Solution 1, and a more profound
    procedure, Solution 2, to solve this issue. A third alternative, Solution 3,
    is shortly mentioned, but could not be finalized.
    
    =head3 Solution 1
    
    For the network installation
    via PXE boot a second SL5 compatible network card has to be plugged in. When the
    installation has finished, an updated version of the
    e1000e driver, that supports the mentioned hardware can be downloaded
    from the Intel website (see References) and installed on the system.
    
    =head3 Solution 2
    
    Use the SL5.3 kernel, the e1000e driver of which does support the F<82567LM> hardware,
    to install the SL5.1.
    
    First, the PXE boot environment has to be setup with the SL5.3 kernel and the related
    initial ramdisk.
    
    Second, the F<.buildstamp> in the initial ramdisk of SL5.3 has to be replaced by the
    F<.buildstamp> of SL5.1. This facilitates the SL5.3 installer to use the SL5.1 installation
    tree. Therefore the ramdisk has to be unpacked, modified and
    repacked (it is a gzipped cpio archive).
    
    Third, build a kernel module e1000e RPM for SL5.1 which will be installed during the SL5.1
    installation by means of a custom key F<e1000e>.
    
    Fourth, setup the F<e1000e> custom key.
    
    =head3 Solution 3
    
    Note: This was tried but does not work yet.
    
    For the network installation compile the new e1000e driver for the installation kernel and put it into
    the corresponding initial ramdisk.
    
    For the running system build the e1000e RPMS for the current kernel/architecture combinations
    and install the RPMS during the kickstart process.
    
    When the kernel is updated the corresponding e1000e RPMS have to be rebuilt and put into
    the update repository.
    
    =head2 Procedure for Solution 1
    
    Get the tarball, extract it and build the driver following
    the instructions in the README of the tarball.
    
    Get the tarball and extract it.
    
    	# [root@pc7637]
    	# uname -a
    	Linux pc7637 2.6.18-92.1.22.el5PAE #1 SMP Tue Dec 16 07:10:07 EST 2008 i686 i686 i386 GNU/Linux
    	# cd /tmp/
    	# wget http://downloadmirror.intel.com/17069/eng/e1000e-0.4.1.7.tar.gz
    	# tar xfz e1000e-0.4.1.7.tar.gz
    
    Install the corresponding kernel source RPM.
    
    	# rpm -ivh /afs/psi.ch/software/mirror/scientific/5x/SRPMS/vendor/kernel-2.6.18-92.1.22.el5.src.rpm
    
    Build the RPM for the running kernel.
    
    	# rpmbuild -tb e1000e-0.4.1.7.tar.gz
    	...
    	Wrote: /usr/src/redhat/RPMS/i386/e1000e-0.4.1.7-1.i386.rpm
    	...
    
    Install the driver RPM.
    
    	# rpm -ivh /usr/src/redhat/RPMS/i386/e1000e-0.4.1.7-1.i386.rpm
    
    Becaus this is a newly installed host, disable older kernels in grub,
    because the kernel module e1000e is only valid for the running kernel.
    However the older kernels should be removed later, if there are no needs to run
    them.
    
    	# vi /boot/grub/grub.conf
    
    The resulting RPM e1000e-0.4.1.7-1.i386.rpm was built on a FS Celsius W370
    after Network installation via an old plugged in 3COM network card
    as 2nd network device. After installation of this RPM the 3COM
    card was removed and the on board Intel Gigabit network card
    was running with the new e1000e kernel module.
    
    =over 4
    
    =item Note:
    
    This RPM contains only the module for an SL51 PAE kernel.
    
    	/lib/modules/2.6.18-92.1.22.el5PAE/kernel/drivers/net/e1000e/e1000e.ko.new
    
    =back
    
    =for comment
    ##################################################################################3
    
    =head2 Procedure for Solution 2
    
    =head3 Setup the PXE Boot Environment for the New Kickstart Installation
    
    Add the following labels to 
    F</afs/psi.ch/service/linux/tftpboot/pxelinux.cfg/default.testing>.
    At the time of writing they are used for testing, their names will probably
    be changed later on.
    
    Note: You can take the same kickstart configuration files as for the default
    SL51 installation, under the labels sl5 and sl564.
    
    	label sl53t32
    	  kernel scientific/53for51install/i386/vmlinuz
    	  append initrd=scientific/53for51install/i386/initrd.img ksdevice=eth0 \
    		ks=nfs:129.129.190.59:/master/linux/kickstart/configs/sl51-a-ks.cfg noipv6
    
    	label sl53t64
    	  kernel scientific/53for51install/x86_64/vmlinuz
    	  append initrd=scientific/53for51install/x86_64/initrd.img ksdevice=eth0 \
    		ks=nfs:129.129.190.59:/master/linux/kickstart/configs/sl51-64-a-ks.cfg noipv6
    
    Copy the installation kernel and the initial ramdisk to the tftpboot
    location given in the respective labels above.
    
    	# cd /afs/psi.ch/service/linux/tftpboot/scientific/
    	# mkdir -p 53for51install/i386 53for51install/x86_64
    
    	# cd 53for51install/i386/
    	# wget http://ftp.scientificlinux.org/linux/scientific/5rolling/i386/images/pxeboot/vmlinuz
    	# wget http://ftp.scientificlinux.org/linux/scientific/5rolling/i386/images/pxeboot/initrd.img
    
    	# cd ../x86_64/
    	# wget http://ftp.scientificlinux.org/linux/scientific/5rolling/x86_64/images/pxeboot/vmlinuz
    	# wget http://ftp.scientificlinux.org/linux/scientific/5rolling/x86_64/images/pxeboot/initrd.img
    
    Before proceeding with the next section test whether the basic setup is working.
    Therefore boot F<sl53t32> and F<sl53t64> on a test machine.
    
    This should setup the network connections, start the kickstart
    till to the point when it runs the pre installation scripts.
    
    =head3 Modify the Initial Ramdisk, Example for x86_64
    
    Unpack the initial ramdisk image of SL5.3.
    
    	# cd /afs/psi.ch/service/linux/tftpboot/scientific/53for51install/x86_64/
    	# mkdir tmp
    	# cd tmp
    	# zcat ../initrd.img | cpio -ivd
    
    The content of the F<.buildstamp> will be something alike.
    
    	# cat .buildstamp
    	200902111740.x86_64
    	Scientific Linux
    	53
    	SL
    	your distribution provided bug reporting tool.
    
    Now replace this F<.buildstamp> file with the one
    of the SL5.1 installation tree. Therefore you also have to
    unpack the ramdisk.
    
    	# cd /afs/psi.ch/software/linux/dist/scientific/51/x86_64/images/pxeboot/
    	# mkdir tmp
    	# cd tmp
    	# zcat ../initrd.img | cpio -ivd
    
    Here we have the following F<.buildstamp>.
    
    	# cat .buildstamp
    	200801141434.x86_64
    	Scientific Linux
    	51
    	SL
    	your distribution provided bug reporting tool.
    
    	# cp -i .buildstamp \
    	#	/afs/psi.ch/service/linux/tftpboot/scientific/53for51install/x86_64/tmp/
    
    Clean up.
    
    	# cd ..
    	# rm -rf tmp
    
    Repack the initial ramdisk of SL5.3 x86_64.
    For this part the commands were taken from F</sbin/mkinitrd> of
    the SL5.1 RPM F<mkinitrd-5.1.19.6-19> and put into a script,
    because repacking the ramdisk without the same command options
    as from the F</sbin/mkinitrd> script fails.
    
    =opentwisty
    
    	#  # Function from /sbin/mkinitrd
    	#  findall() {
    	#      echo nash-find "$@" | /sbin/nash --force --quiet
    	#  }
            #   
    	#  # Architecture
    	#  ARCH="x86_64"
            #   
    	#  # Set file locations:
    	#  #   The temporary directory in the tftpboot directory
    	#  #   where the initial ramdisk is extracted to.
    	#  MNTIMAGE="/afs/psi.ch/service/linux/tftpboot/scientific/53for51install/$ARCH/tmp"
            #   
    	#  #   The name of the new ramdisk, not to overwrite the original one
    	#  target="initrd.img_new"
            #   
    	#  # Start processing
    	#  if test ! -d $MNTIMAGE 
    	#  then 
    	#          echo "Error: $MNTIMAGE does not exist."
    	#          exit
    	#  fi
            #   
    	#  if test -e ${MNTIMAGE}/../initrd.img_new.cpio
    	#  then
    	#          echo -n "${MNTIMAGE}/../initrd.img_new.cpio exists. Shall I remove it (y/N)?"
    	#          read a
    	#          if test "$a" = "y"
    	#          then
    	#          	rm -f ${MNTIMAGE}/../initrd.img_new.cpio
    	#          fi
    	#  fi
            #   
    	#  # Create the empty ramdisk file (from /sbin/mkinitrd)
    	#  IMAGE=`mktemp ${MNTIMAGE}/../initrd.img_new.cpio`
            #   
    	#  # Fill it as cpio archive (from /sbin/mkinitrd)
    	#  (cd $MNTIMAGE; findall . | cpio --quiet -c -o) >| $IMAGE || exit 1
            #   
    	#  # Compress the cpio archive (from /sbin/mkinitrd)
    	#  gzip -9 < $IMAGE >| ${MNTIMAGE}/../$target
            #   
    	#  echo "Check the new initial ramdisk at"
    	#  echo "/afs/psi.ch/service/linux/tftpboot/scientific/53for51install/$ARCH/"
    	#  echo
    
    =closetwisty
    
    Go to the tftpboot direcory and setup the new initial ramdisk.
    Make also a backup of the original one.
    
    	# cd /afs/psi.ch/service/linux/tftpboot/scientific/53for51install/x86_64/
    	# mv initrd.img initrd.img_orig
    	# ln -s initrd.img_new initrd.img
    
    Now test the PXE boot kickstart installation using the
    label F<sl53t64>.
    
    If everything looks fine clean up and go to the next section
    or repeat this part for the i386 architecture.
    
    	# rm -rf tmp/ initrd.img_new.cpio
    
    =head3 Build the e1000e Kernel Module RPM, Example for x86_64
    
    Go to the build system tux50-64 and download the e1000e sources
    and get the spec file.
    
    	# [gasser_m@tux50-64]
    	# cd /scratch/gasser_m/rpm_topdir/SOURCES/
    	# wget http://downloadmirror.intel.com/17069/eng/e1000e-0.4.1.7.tar.gz
    	# tar xfz e1000e-0.4.1.7.tar.gz
    	# cp e1000e-0.4.1.7/e1000e.spec ../SPECS/
    	# rm -rf e1000e-0.4.1.7
    	# cd ../SPECS/
    	# cp e1000e e1000e_orig
    
    Note, you can build the RPM directly from this tarball, but here we want to
    change the name of the built RPM to apply our PSI naming convention for kernel
    modules, thus we need to edit the spec file before building.
    
    	# vi e1000e.spec
    
    =opentwisty
    
    	#### begin e1000e.spec
    
    	%define driver_name e1000e
    	%define kernel 2.6.18-92.1.22.el5
    
    	%define pkg_name kernel-module-%{driver_name}-%{kernel}
    
    	Name: %{pkg_name}
    	Summary: Intel(R) Gigabit Ethernet Connection
    	Version: 0.4.1.7
    	Release: 1
    	Source: %{driver_name}-%{version}.tar.gz
    	Vendor: Intel Corporation
    	Packager: Marc Gasser <marc.gasser@psi.ch>
    	License: GPL
    	ExclusiveOS: linux
    	Group: System Environment/Kernel
    	Provides: %{driver_name}
    	URL: http://support.intel.com/support/go/linux/e1000e.htm
    	BuildRoot: %{_tmppath}/%{driver_name}-%{version}-root
    	# do not generate debugging packages by default - newer versions of rpmbuild
    	# may instead need:
    	#%define debug_package %{nil}
    	%debug_package %{nil}
    	# macros for finding system files to update at install time (pci.ids, pcitable)
    	%define find() %(for f in %*; do if [ -e $f ]; then echo $f; break; fi; done)
    	%define _pciids   /usr/share/pci.ids        /usr/share/hwdata/pci.ids
    	%define _pcitable /usr/share/kudzu/pcitable /usr/share/hwdata/pcitable /dev/null
    	%define pciids    %find %{_pciids}
    	%define pcitable  %find %{_pcitable}
    	Requires: kernel, fileutils, findutils, gawk, bash
    
    	%description
    	This package contains the Linux driver for the Intel(R) Gigabit Family of Server Adapters.
    
    	########################### begin RPM build section
    
    	%prep
    	%setup -n %{driver_name}-%{version}
    
    	%build
    	mkdir -p %{buildroot}
    
    	KV=%{kernel}
    	KA=%{_arch}
    	KV_BASE=$(echo $KV | sed '{ s/hugemem//g; s/smp//g; s/enterprise//g; }' )
    
    	if [ -e /usr/src/kernels ] && [ $(echo $KV_BASE | grep "^2.6") ]; then
    		if [ -e /etc/redhat-release ]; then
    			KSP=$(ls /lib/modules | grep $KV_BASE)
    			for K in $KSP ; do
    				if [ $KA == "x86_64" ] && \
    				   [ $(echo $K | grep hugemem) ]; then
    					# Include path for x86_64 hugemem is broken
    					# on RHEL4
    					continue
    				fi
    				make -C src clean
    				make -C src KSP=/lib/modules/$K/build \
    					INSTALL_MOD_PATH=%{buildroot} \
    					KVERSION=$k \
    					MANDIR=%{_mandir} \
    					CFLAGS_EXTRA="$CFLAGS_EXTRA" install
    			done
    		else
    			make -C src clean
    			make -C src INSTALL_MOD_PATH=%{buildroot} \
    				MANDIR=%{_mandir} install
    		fi
    	else
    		SwitchRHKernel () {
    			CFLAGS_EXTRA=""
    			for K in $2 ; do
    				if [ $K == $1 ] ; then
    					CFLAGS_EXTRA="$CFLAGS_EXTRA -D__BOOT_KERNEL_$K=1"
    				else
    					CFLAGS_EXTRA="$CFLAGS_EXTRA -D__BOOT_KERNEL_$K=0"
    				fi
    			done
    		}
    
    		KSP="/lib/modules/$KV/build
    		     /usr/src/linux-$KV
    		     /usr/src/linux-$(echo $KV | sed 's/-.*//')
    		     /usr/src/kernel-headers-$KV
    		     /usr/src/kernel-source-$KV
    		     /usr/src/linux-$(echo $KV | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/')
    		     /usr/src/linux"
    
    		KSRC=$(for d in $KSP ; do [ -e $d/include/linux ] && echo $d; echo;  done)
    		KSRC=$(echo $KSRC | awk '{ print $1 }')
    
    		if [ -e $KSRC/include/linux/rhconfig.h ] ; then
    			RHKL=$(grep 'BOOT_KERNEL_.* [01]' /boot/kernel.h |
    			       sed 's/.*BOOT_KERNEL_\(.*\) [01]/\1/')
    			if echo $RHKL | grep BIGMEM
    			then
    				RHKL=$(echo $RHKL | sed 's/ENTERPRISE//')
    			fi
    			if echo $RHKL | grep HUGEMEM
    			then
    				RHKL=$(echo $RHKL | sed 's/BIGMEM//')
    			fi
    			for K in $RHKL ; do
    				SwitchRHKernel $K "$RHKL"
    				make -C src clean
    				if [ $KA == "x86_64" ] ; then
    					CFLAGS_EXTRA="$CFLAGS_EXTRA -D__MODULE_KERNEL_x86_64=0 -D__MODULE_KERNEL_ia32e=1"
    				fi
    				make -C src INSTALL_MOD_PATH=%{buildroot} \
    					MANDIR=%{_mandir} CFLAGS_EXTRA="$CFLAGS_EXTRA" install
    			done
    		else
    			make -C src clean
    			make -C src INSTALL_MOD_PATH=%{buildroot} MANDIR=%{_mandir} install
    		fi
    	fi
    
    	%install
    	# Append .new to driver name to avoid conflict with kernel RPM
    	echo "# Going to " %{buildroot}
    	cd %{buildroot}
    	find lib -name "e1000e.*o" -exec mv {} {}.new \; \
    		 -fprintf %{_builddir}/%{driver_name}-%{version}/file.list "/%p.new\n"
    
    
    	%clean
    	rm -rf %{buildroot}
    
    	%files -f %{_builddir}/%{driver_name}-%{version}/file.list
    	%defattr(-,root,root)
    	%{_mandir}/man7/e1000e.7.gz
    	%doc COPYING
    	%doc README
    	%doc file.list
    	%doc pci.updates
    
    	########################### end RPM build section
    
    	########################### begin RPM installation section
    
    	%post
    	FL="%{_docdir}/%{name}-%{version}/file.list
    	    %{_docdir}/%{name}/file.list"
    	FL=$(for d in $FL ; do if [ -e $d ]; then echo $d; break; fi;  done)
    
    	if [ -d /usr/local/lib/%{name} ]; then
    		rm -rf /usr/local/lib/%{name}
    	fi
    	if [ -d /usr/local/share/%{name} ]; then
    		rm -rf /usr/local/share/%{name}
    	fi
    
    	echo "original pci.ids saved in /usr/local/share/%{name}";
    	if [ "%{pcitable}" != "/dev/null" ]; then
    		echo "original pcitable saved in /usr/local/share/%{name}";
    	fi
    
    	#### Save old drivers (aka .o and .o.gz) in $d_usr
    	# k is(are) the kernel version(s) extracted with sed from the full qualified
    	# kernel module name(s) in file.list
    	echo "Original drivers saved in /usr/local/share/%{name}";
    	for k in $(sed 's/\/lib\/modules\/\([0-9a-zA-Z_\.\-]*\).*/\1/' $FL) ; 
    	do
    		d_drivers=/lib/modules/$k
    		d_usr=/usr/local/share/%{name}/$k
    		mkdir -p $d_usr
    		cd $d_drivers; find . -name %{driver_name}.*o -exec cp --parents {} $d_usr \; -exec rm -f {} \;
    		cd $d_drivers; find . -name %{driver_name}_*.*o -exec cp --parents {} $d_usr \; -exec rm -f {} \;
    		cd $d_drivers; find . -name %{driver_name}.*o.gz -exec cp --parents {} $d_usr \; -exec rm -f {} \;
    		cd $d_drivers; find . -name %{driver_name}_*.*o.gz -exec cp --parents {} $d_usr \; -exec rm -f {} \;
    		cp --parents %{pciids} /usr/local/share/%{name}/
    		if [ "%{pcitable}" != "/dev/null" ]; then
    			cp --parents %{pcitable} /usr/local/share/%{name}/
    		fi
    	done
    
    	# Add driver link
    	for f in $(sed 's/\.new$//' $FL) ; do
    		ln -f $f.new $f 
    	done
    
    	# Check if kernel version rpm was built on IS the same as running kernel
    	BK_LIST=$(sed 's/\/lib\/modules\/\([0-9a-zA-Z_\.\-]*\).*/\1/' $FL)
    	MATCH=no
    	for i in $BK_LIST
    	do
    		if [ $(uname -r) == $i ] ; then
    			MATCH=yes
    			break
    		fi
    	done
    	if [ $MATCH == no ] ; then
    		echo -n "WARNING: Running kernel is $(uname -r).  "
    		echo -n "RPM supports kernels (  "
    		for i in $BK_LIST
    		do
    			echo -n "$i  "
    		done
    		echo ")"
    	fi
    
    	LD="%{_docdir}/%{name}";
    	if [ -d %{_docdir}/%{name}-%{version} ]; then
    		LD="%{_docdir}/%{name}-%{version}";
    	fi
    
    	#Yes, this really needs bash
    	bash -s %{pciids} \
    		%{pcitable} \
    		$LD/pci.updates \
    		$LD/pci.ids.new \
    		$LD/pcitable.new \
    		%{name} \
    	<<"END"
    	#! /bin/bash
    	# $1 = system pci.ids file to update
    	# $2 = system pcitable file to update
    	# $3 = file with new entries in pci.ids file format
    	# $4 = pci.ids output file
    	# $5 = pcitable output file
    	# $6 = driver name for use in pcitable file
    
    	exec 3<$1
    	exec 4<$2
    	exec 5<$3
    	exec 6>$4
    	exec 7>$5
    	driver=$6
    	IFS=
    
    	# pattern matching strings
    	ID="[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]"
    	VEN="${ID}*"
    	DEV="	${ID}*"
    	SUB="		${ID}*"
    	TABLE_DEV="0x${ID}	0x${ID}	\"*"
    	TABLE_SUB="0x${ID}	0x${ID}	0x${ID}	0x${ID}	\"*"
    
    	line=
    	table_line=
    	ids_in=
    	table_in=
    	vendor=
    	device=
    	ids_device=
    	table_device=
    	subven=
    	ids_subven=
    	table_subven=
    	subdev=
    	ids_subdev=
    	table_subdev=
    	ven_str=
    	dev_str=
    	sub_str=
    
    	# force a sub-shell to fork with a new stdin
    	# this is needed if the shell is reading these instructions from stdin
    	while true
    	do
    		# get the first line of each data file to jump start things
    		exec 0<&3
    		read -r ids_in
    		if [ "$2" != "/dev/null" ];then
    		exec 0<&4
    		read -r table_in
    		fi
    
    		# outer loop reads lines from the updates file
    		exec 0<&5
    		while read -r line
    		do
    			# vendor entry
    			if [[ $line == $VEN ]]
    			then
    				vendor=0x${line:0:4}
    				ven_str=${line#${line:0:6}}
    				# add entry to pci.ids
    				exec 0<&3
    				exec 1>&6
    				while [[ $ids_in != $VEN ||
    					 0x${ids_in:0:4} < $vendor ]]
    				do
    					echo "$ids_in"
    					read -r ids_in
    				done
    				echo "$line"
    				if [[ 0x${ids_in:0:4} == $vendor ]]
    				then
    					read -r ids_in
    				fi
    
    			# device entry
    			elif [[ $line == $DEV ]]
    			then
    				device=`echo ${line:1:4} | tr [:upper:] [:lower:]`
    				table_device=0x${line:1:4}
    				dev_str=${line#${line:0:7}}
    				ids_device=`echo ${ids_in:1:4} | tr [:upper:] [:lower:]`
    				table_line="$vendor	$table_device	\"$driver\"	\"$ven_str|$dev_str\""
    				# add entry to pci.ids
    				exec 0<&3
    				exec 1>&6
    				while [[ $ids_in != $DEV ||
    					 $ids_device < $device ]]
    				do
    					if [[ $ids_in == $VEN ]]
    					then
    						break
    					fi
    					if [[ $ids_device != ${ids_in:1:4} ]]
    					then
    						echo "${ids_in:0:1}$ids_device${ids_in#${ids_in:0:5}}"
    					else
    						echo "$ids_in"
    					fi
    					read -r ids_in
    					ids_device=`echo ${ids_in:1:4} | tr [:upper:] [:lower:]`
    				done
    				if [[ $device != ${line:1:4} ]]
    				then
    					echo "${line:0:1}$device${line#${line:0:5}}"
    				else
    					echo "$line"
    				fi
    				if [[ $ids_device == $device ]]
    				then
    					read -r ids_in
    				fi
    				# add entry to pcitable
    				if [ "$2" != "/dev/null" ];then
    				exec 0<&4
    				exec 1>&7
    				while [[ $table_in != $TABLE_DEV ||
    					 ${table_in:0:6} < $vendor ||
    					 ( ${table_in:0:6} == $vendor &&
    					   ${table_in:7:6} < $table_device ) ]]
    				do
    					echo "$table_in"
    					read -r table_in
    				done
    				echo "$table_line"
    				if [[ ${table_in:0:6} == $vendor &&
    				      ${table_in:7:6} == $table_device ]]
    				then
    					read -r table_in
    				fi
    				fi
    			# subsystem entry
    			elif [[ $line == $SUB ]]
    			then
    				subven=`echo ${line:2:4} | tr [:upper:] [:lower:]`
    				subdev=`echo ${line:7:4} | tr [:upper:] [:lower:]`
    				table_subven=0x${line:2:4}
    				table_subdev=0x${line:7:4}
    				sub_str=${line#${line:0:13}}
    				ids_subven=`echo ${ids_in:2:4} | tr [:upper:] [:lower:]`
    				ids_subdev=`echo ${ids_in:7:4} | tr [:upper:] [:lower:]`
    				table_line="$vendor	$table_device	$table_subven	$table_subdev	\"$driver\"	\"$ven_str|$sub_str\""
    				# add entry to pci.ids
    				exec 0<&3
    				exec 1>&6
    				while [[ $ids_in != $SUB ||
    					 $ids_subven < $subven ||
    					 ( $ids_subven == $subven && 
    					   $ids_subdev < $subdev ) ]]
    				do
    					if [[ $ids_in == $VEN ||
    					      $ids_in == $DEV ]]
    					then
    						break
    					fi
    					if [[ ! (${ids_in:2:4} == "1014" &&
    						 ${ids_in:7:4} == "052C") ]]
    					then
    						if [[ $ids_subven != ${ids_in:2:4} || $ids_subdev != ${ids_in:7:4} ]]
    						then
    							echo "${ids_in:0:2}$ids_subven $ids_subdev${ids_in#${ids_in:0:11}}"
    						else
    							echo "$ids_in"
    						fi
    					fi
    					read -r ids_in
    					ids_subven=`echo ${ids_in:2:4} | tr [:upper:] [:lower:]`
    					ids_subdev=`echo ${ids_in:7:4} | tr [:upper:] [:lower:]`
    				done
    				if [[ $subven != ${line:2:4} || $subdev != ${line:7:4} ]]
    				then
    					echo "${line:0:2}$subven $subdev${line#${line:0:11}}"
    				else
    					echo "$line"
    				fi
    				if [[ $ids_subven == $subven  &&
    				      $ids_subdev == $subdev ]]
    				then
    					read -r ids_in
    				fi
    				# add entry to pcitable
    				if [ "$2" != "/dev/null" ];then
    				exec 0<&4
    				exec 1>&7
    				while [[ $table_in != $TABLE_SUB ||
    					 ${table_in:14:6} < $table_subven ||
    					 ( ${table_in:14:6} == $table_subven &&
    					   ${table_in:21:6} < $table_subdev ) ]]
    				do
    					if [[ $table_in == $TABLE_DEV ]]
    					then
    						break
    					fi
    					if [[ ! (${table_in:14:6} == "0x1014" &&
    						 ${table_in:21:6} == "0x052C") ]]
    					then
    						echo "$table_in"
    					fi
    					read -r table_in
    				done
    				echo "$table_line"
    				if [[ ${table_in:14:6} == $table_subven &&
    				      ${table_in:21:6} == $table_subdev ]]
    				then
    					read -r table_in
    				fi
    				fi
    			fi
    
    			exec 0<&5
    		done
    
    		# print the remainder of the original files
    		exec 0<&3
    		exec 1>&6
    		echo "$ids_in"
    		while read -r ids_in
    		do
    			echo "$ids_in"
    		done
    
    		if [ "$2" != "/dev/null" ];then
    		exec 0>&4
    		exec 1>&7
    		echo "$table_in"
    		while read -r table_in
    		do
    			echo "$table_in"
    		done
    		fi
    
    		break
    	done <&5
    
    	exec 3<&-
    	exec 4<&-
    	exec 5<&-
    	exec 6>&-
    	exec 7>&-
    
    	END
    
    	mv -f $LD/pci.ids.new  %{pciids}
    	if [ "%{pcitable}" != "/dev/null" ]; then
    	mv -f $LD/pcitable.new %{pcitable}
    	fi
    
    	uname -r | grep BOOT || /sbin/depmod -a > /dev/null 2>&1 || true
    
    	########################### end RPM installation section
    
    	########################### begin RPM deinstallation section
    	%preun
    	# If doing RPM un-install
    	if [ $1 -eq 0 ] ; then
    		FL="%{_docdir}/%{name}-%{version}/file.list
    			%{_docdir}/%{name}/file.list"
    		FL=$(for d in $FL ; do if [ -e $d ]; then echo $d; break; fi;  done)
    
    		# Remove driver link
    		for f in $(sed 's/\.new$//' $FL) ; do
    			rm -f $f
    		done
    
    		# Restore old drivers
    		if [ -d /usr/local/share/%{name} ]; then
    			cd /usr/local/share/%{name}; find . -name '%{driver_name}.*o*' -exec cp --parents {} /lib/modules/ \;
    			cd /usr/local/share/%{name}; find . -name '%{driver_name}_*.*o*' -exec cp --parents {} /lib/modules/ \;
    			rm -rf /usr/local/share/%{name}
    		fi
    	fi
    
    	%postun
    	uname -r | grep BOOT || /sbin/depmod -a > /dev/null 2>&1 || true
    
    	########################### end RPM deinstallation section
    
    	#### end e1000e.spec
    
    =closetwisty
    
    =head3 Create the Customization Key for the e1000e Driver, Example for x86_64
    
    Go to the customization key directory for SL5.1 and create the basic
    files.
    
    	# cd /afs/psi.ch/software/linux/dist/scientific/51/kickstart/custom/
    	# mkdir e1000e
    	# cd e1000e
    	# touch custom.sh
    	# vi custom.sh
    
    =opentwisty
    
    	#!/bin/bash
    	# 
    	# KS Customization for e1000e driver
    	#
    	# marc.gasser@psi.ch
    	# 2009-02-24
    	#
    	# KSII scriplet rules apply
    	#
    	# This customization was added for the Intel Gigabit ethernet
    	# card 82567LM, which comes with the new Fujitsu Siemens computers
    	# Celsius W370, Esprimo p7935 e80, Esprimo e7935 e80 and Lifebook e8420,
    	# because the e1000e.ko version 0.2.0 coming with SL kernels <= 2.6.18-92.1.22.el5
    	# does not support this kind of hardware.
    	#
    	##############################################################
    	# Changelog:
    	# ---------
    	#
    	##############################################################
    
    	ARCH=$(uname -m)
    	DIR_E1000E=/mnt/master/linux/dist/scientific/51/psi/all
    
    	# Install the kernel-module-e1000e containing the e1000e driver
    	if test "$ARCH" = "x86_64"
    	then
    		echo "Install kernel-module-e1000e for $ARCH" >> $POSTLOG 2>&1
    		rpm -ivh $DIR_E1000E/kernel-module-e1000e-2.6.18-92.1.22.el5-0.4.1.7-1.x86_64.rpm || \
    			echo error installing kernel-module-e1000e \
    			>> $POSTLOG 2>&1
    	else
    		echo "Install kernel-module-e1000e for $ARCH" >> $POSTLOG 2>&1
    		rpm -ivh $DIR_E1000E/kernel-module-e1000e-2.6.18-92.1.22.el5-0.4.1.7-1.i386.rpm || \
    			echo error installing kernel-module-e1000e \
    			>> $POSTLOG 2>&1
    	fi
    
    =closetwisty
    
    Copy the kernel-module-e1000e RPMS to F</mnt/master/linux/dist/scientific/51/psi/all/>
    and F</mnt/master/linux/dist/scientific/51/kernel/all/>, create the symbolic links
    in the corresponding F<current> and/or F<testing> repositories, and run C<createrepo>
    within F<current> and/or F<testing>.
    
    That's it. Now you can test the installation using the custom key
    F<e1000e>.
